From 2409a1fec88aec38ea7b70be0420990220c1a232 Mon Sep 17 00:00:00 2001 From: Frank Stellmacher <171614930+Psychotoxical@users.noreply.github.com> Date: Thu, 14 May 2026 14:06:31 +0200 Subject: [PATCH] refactor(i18n): split locale files into per-namespace modules (Phase K) (#688) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Each src/locales/.ts (~1800 LOC) becomes a folder src/locales// with one module per i18n namespace (44 each) plus an index.ts barrel that reassembles Translation in the original key order. Mechanical, script-driven split with a JSON round-trip check: every locale object is byte-identical to its pre-split form. i18n.ts is unchanged — './locales/' now resolves to the folder index. The per-namespace settings.ts files land ~440-460 LOC; a single i18n namespace is the natural, non-arbitrary split unit for a flat string table, so they are intentionally left whole. --- src/locales/de.ts | 1870 ----------------------------- src/locales/de/albumDetail.ts | 47 + src/locales/de/albums.ts | 32 + src/locales/de/artistDetail.ts | 41 + src/locales/de/artists.ts | 18 + src/locales/de/changelog.ts | 5 + src/locales/de/common.ts | 66 ++ src/locales/de/composerDetail.ts | 11 + src/locales/de/composers.ts | 10 + src/locales/de/connection.ts | 28 + src/locales/de/contextMenu.ts | 33 + src/locales/de/deviceSync.ts | 79 ++ src/locales/de/entityRating.ts | 9 + src/locales/de/favorites.ts | 19 + src/locales/de/folderBrowser.ts | 4 + src/locales/de/genres.ts | 12 + src/locales/de/help.ts | 115 ++ src/locales/de/hero.ts | 6 + src/locales/de/home.ts | 19 + src/locales/de/index.ts | 91 ++ src/locales/de/licenses.ts | 13 + src/locales/de/login.ts | 22 + src/locales/de/losslessAlbums.ts | 5 + src/locales/de/luckyMix.ts | 6 + src/locales/de/miniPlayer.ts | 9 + src/locales/de/mostPlayed.ts | 13 + src/locales/de/nowPlaying.ts | 47 + src/locales/de/nowPlayingInfo.ts | 24 + src/locales/de/orbit.ts | 200 ++++ src/locales/de/player.ts | 56 + src/locales/de/playlists.ts | 101 ++ src/locales/de/queue.ts | 45 + src/locales/de/radio.ts | 35 + src/locales/de/randomAlbums.ts | 4 + src/locales/de/randomLanding.ts | 9 + src/locales/de/randomMix.ts | 39 + src/locales/de/search.ts | 29 + src/locales/de/settings.ts | 442 +++++++ src/locales/de/sharePaste.ts | 18 + src/locales/de/sidebar.ts | 37 + src/locales/de/smartPlaylists.ts | 41 + src/locales/de/songInfo.ts | 23 + src/locales/de/statistics.ts | 65 + src/locales/de/tracks.ts | 15 + src/locales/de/tray.ts | 8 + src/locales/de/whatsNew.ts | 8 + src/locales/en.ts | 1876 ----------------------------- src/locales/en/albumDetail.ts | 47 + src/locales/en/albums.ts | 32 + src/locales/en/artistDetail.ts | 41 + src/locales/en/artists.ts | 18 + src/locales/en/changelog.ts | 5 + src/locales/en/common.ts | 66 ++ src/locales/en/composerDetail.ts | 11 + src/locales/en/composers.ts | 10 + src/locales/en/connection.ts | 28 + src/locales/en/contextMenu.ts | 33 + src/locales/en/deviceSync.ts | 80 ++ src/locales/en/entityRating.ts | 9 + src/locales/en/favorites.ts | 19 + src/locales/en/folderBrowser.ts | 4 + src/locales/en/genres.ts | 12 + src/locales/en/help.ts | 115 ++ src/locales/en/hero.ts | 6 + src/locales/en/home.ts | 19 + src/locales/en/index.ts | 91 ++ src/locales/en/licenses.ts | 13 + src/locales/en/login.ts | 22 + src/locales/en/losslessAlbums.ts | 5 + src/locales/en/luckyMix.ts | 6 + src/locales/en/miniPlayer.ts | 9 + src/locales/en/mostPlayed.ts | 13 + src/locales/en/nowPlaying.ts | 47 + src/locales/en/nowPlayingInfo.ts | 24 + src/locales/en/orbit.ts | 200 ++++ src/locales/en/player.ts | 56 + src/locales/en/playlists.ts | 101 ++ src/locales/en/queue.ts | 45 + src/locales/en/radio.ts | 35 + src/locales/en/randomAlbums.ts | 4 + src/locales/en/randomLanding.ts | 9 + src/locales/en/randomMix.ts | 39 + src/locales/en/search.ts | 29 + src/locales/en/settings.ts | 445 +++++++ src/locales/en/sharePaste.ts | 18 + src/locales/en/sidebar.ts | 39 + src/locales/en/smartPlaylists.ts | 41 + src/locales/en/songInfo.ts | 23 + src/locales/en/statistics.ts | 65 + src/locales/en/tracks.ts | 15 + src/locales/en/tray.ts | 8 + src/locales/en/whatsNew.ts | 8 + src/locales/es.ts | 1828 ----------------------------- src/locales/es/albumDetail.ts | 47 + src/locales/es/albums.ts | 33 + src/locales/es/artistDetail.ts | 41 + src/locales/es/artists.ts | 18 + src/locales/es/changelog.ts | 5 + src/locales/es/common.ts | 56 + src/locales/es/composerDetail.ts | 11 + src/locales/es/composers.ts | 10 + src/locales/es/connection.ts | 28 + src/locales/es/contextMenu.ts | 33 + src/locales/es/deviceSync.ts | 73 ++ src/locales/es/entityRating.ts | 9 + src/locales/es/favorites.ts | 19 + src/locales/es/folderBrowser.ts | 4 + src/locales/es/genres.ts | 12 + src/locales/es/help.ts | 105 ++ src/locales/es/hero.ts | 6 + src/locales/es/home.ts | 19 + src/locales/es/index.ts | 91 ++ src/locales/es/licenses.ts | 13 + src/locales/es/login.ts | 22 + src/locales/es/losslessAlbums.ts | 5 + src/locales/es/luckyMix.ts | 6 + src/locales/es/miniPlayer.ts | 9 + src/locales/es/mostPlayed.ts | 13 + src/locales/es/nowPlaying.ts | 47 + src/locales/es/nowPlayingInfo.ts | 24 + src/locales/es/orbit.ts | 200 ++++ src/locales/es/player.ts | 56 + src/locales/es/playlists.ts | 101 ++ src/locales/es/queue.ts | 45 + src/locales/es/radio.ts | 35 + src/locales/es/randomAlbums.ts | 4 + src/locales/es/randomLanding.ts | 9 + src/locales/es/randomMix.ts | 39 + src/locales/es/search.ts | 29 + src/locales/es/settings.ts | 442 +++++++ src/locales/es/sharePaste.ts | 18 + src/locales/es/sidebar.ts | 38 + src/locales/es/smartPlaylists.ts | 41 + src/locales/es/songInfo.ts | 23 + src/locales/es/statistics.ts | 47 + src/locales/es/tracks.ts | 15 + src/locales/es/tray.ts | 8 + src/locales/es/whatsNew.ts | 8 + src/locales/fr.ts | 1824 ----------------------------- src/locales/fr/albumDetail.ts | 47 + src/locales/fr/albums.ts | 32 + src/locales/fr/artistDetail.ts | 41 + src/locales/fr/artists.ts | 18 + src/locales/fr/changelog.ts | 5 + src/locales/fr/common.ts | 56 + src/locales/fr/composerDetail.ts | 11 + src/locales/fr/composers.ts | 10 + src/locales/fr/connection.ts | 28 + src/locales/fr/contextMenu.ts | 33 + src/locales/fr/deviceSync.ts | 73 ++ src/locales/fr/entityRating.ts | 9 + src/locales/fr/favorites.ts | 19 + src/locales/fr/folderBrowser.ts | 4 + src/locales/fr/genres.ts | 12 + src/locales/fr/help.ts | 105 ++ src/locales/fr/hero.ts | 6 + src/locales/fr/home.ts | 19 + src/locales/fr/index.ts | 91 ++ src/locales/fr/licenses.ts | 13 + src/locales/fr/login.ts | 22 + src/locales/fr/losslessAlbums.ts | 5 + src/locales/fr/luckyMix.ts | 6 + src/locales/fr/miniPlayer.ts | 9 + src/locales/fr/mostPlayed.ts | 13 + src/locales/fr/nowPlaying.ts | 47 + src/locales/fr/nowPlayingInfo.ts | 24 + src/locales/fr/orbit.ts | 200 ++++ src/locales/fr/player.ts | 56 + src/locales/fr/playlists.ts | 101 ++ src/locales/fr/queue.ts | 45 + src/locales/fr/radio.ts | 35 + src/locales/fr/randomAlbums.ts | 4 + src/locales/fr/randomLanding.ts | 9 + src/locales/fr/randomMix.ts | 39 + src/locales/fr/search.ts | 29 + src/locales/fr/settings.ts | 440 +++++++ src/locales/fr/sharePaste.ts | 18 + src/locales/fr/sidebar.ts | 37 + src/locales/fr/smartPlaylists.ts | 41 + src/locales/fr/songInfo.ts | 23 + src/locales/fr/statistics.ts | 47 + src/locales/fr/tracks.ts | 15 + src/locales/fr/tray.ts | 8 + src/locales/fr/whatsNew.ts | 8 + src/locales/nb.ts | 1823 ----------------------------- src/locales/nb/albumDetail.ts | 47 + src/locales/nb/albums.ts | 32 + src/locales/nb/artistDetail.ts | 41 + src/locales/nb/artists.ts | 18 + src/locales/nb/changelog.ts | 5 + src/locales/nb/common.ts | 56 + src/locales/nb/composerDetail.ts | 11 + src/locales/nb/composers.ts | 10 + src/locales/nb/connection.ts | 28 + src/locales/nb/contextMenu.ts | 33 + src/locales/nb/deviceSync.ts | 73 ++ src/locales/nb/entityRating.ts | 9 + src/locales/nb/favorites.ts | 19 + src/locales/nb/folderBrowser.ts | 4 + src/locales/nb/genres.ts | 12 + src/locales/nb/help.ts | 105 ++ src/locales/nb/hero.ts | 6 + src/locales/nb/home.ts | 19 + src/locales/nb/index.ts | 91 ++ src/locales/nb/licenses.ts | 13 + src/locales/nb/login.ts | 22 + src/locales/nb/losslessAlbums.ts | 5 + src/locales/nb/luckyMix.ts | 6 + src/locales/nb/miniPlayer.ts | 9 + src/locales/nb/mostPlayed.ts | 13 + src/locales/nb/nowPlaying.ts | 47 + src/locales/nb/nowPlayingInfo.ts | 24 + src/locales/nb/orbit.ts | 200 ++++ src/locales/nb/player.ts | 56 + src/locales/nb/playlists.ts | 101 ++ src/locales/nb/queue.ts | 45 + src/locales/nb/radio.ts | 35 + src/locales/nb/randomAlbums.ts | 4 + src/locales/nb/randomLanding.ts | 9 + src/locales/nb/randomMix.ts | 39 + src/locales/nb/search.ts | 29 + src/locales/nb/settings.ts | 439 +++++++ src/locales/nb/sharePaste.ts | 18 + src/locales/nb/sidebar.ts | 37 + src/locales/nb/smartPlaylists.ts | 41 + src/locales/nb/songInfo.ts | 23 + src/locales/nb/statistics.ts | 47 + src/locales/nb/tracks.ts | 15 + src/locales/nb/tray.ts | 8 + src/locales/nb/whatsNew.ts | 8 + src/locales/nl.ts | 1823 ----------------------------- src/locales/nl/albumDetail.ts | 47 + src/locales/nl/albums.ts | 32 + src/locales/nl/artistDetail.ts | 41 + src/locales/nl/artists.ts | 18 + src/locales/nl/changelog.ts | 5 + src/locales/nl/common.ts | 56 + src/locales/nl/composerDetail.ts | 11 + src/locales/nl/composers.ts | 10 + src/locales/nl/connection.ts | 28 + src/locales/nl/contextMenu.ts | 32 + src/locales/nl/deviceSync.ts | 73 ++ src/locales/nl/entityRating.ts | 9 + src/locales/nl/favorites.ts | 19 + src/locales/nl/folderBrowser.ts | 4 + src/locales/nl/genres.ts | 12 + src/locales/nl/help.ts | 105 ++ src/locales/nl/hero.ts | 6 + src/locales/nl/home.ts | 19 + src/locales/nl/index.ts | 91 ++ src/locales/nl/licenses.ts | 13 + src/locales/nl/login.ts | 22 + src/locales/nl/losslessAlbums.ts | 5 + src/locales/nl/luckyMix.ts | 6 + src/locales/nl/miniPlayer.ts | 9 + src/locales/nl/mostPlayed.ts | 13 + src/locales/nl/nowPlaying.ts | 47 + src/locales/nl/nowPlayingInfo.ts | 24 + src/locales/nl/orbit.ts | 200 ++++ src/locales/nl/player.ts | 56 + src/locales/nl/playlists.ts | 101 ++ src/locales/nl/queue.ts | 45 + src/locales/nl/radio.ts | 35 + src/locales/nl/randomAlbums.ts | 4 + src/locales/nl/randomLanding.ts | 9 + src/locales/nl/randomMix.ts | 39 + src/locales/nl/search.ts | 29 + src/locales/nl/settings.ts | 440 +++++++ src/locales/nl/sharePaste.ts | 18 + src/locales/nl/sidebar.ts | 37 + src/locales/nl/smartPlaylists.ts | 41 + src/locales/nl/songInfo.ts | 23 + src/locales/nl/statistics.ts | 47 + src/locales/nl/tracks.ts | 15 + src/locales/nl/tray.ts | 8 + src/locales/nl/whatsNew.ts | 8 + src/locales/ro.ts | 1876 ----------------------------- src/locales/ro/albumDetail.ts | 47 + src/locales/ro/albums.ts | 32 + src/locales/ro/artistDetail.ts | 41 + src/locales/ro/artists.ts | 18 + src/locales/ro/changelog.ts | 5 + src/locales/ro/common.ts | 66 ++ src/locales/ro/composerDetail.ts | 11 + src/locales/ro/composers.ts | 10 + src/locales/ro/connection.ts | 28 + src/locales/ro/contextMenu.ts | 33 + src/locales/ro/deviceSync.ts | 80 ++ src/locales/ro/entityRating.ts | 9 + src/locales/ro/favorites.ts | 19 + src/locales/ro/folderBrowser.ts | 4 + src/locales/ro/genres.ts | 12 + src/locales/ro/help.ts | 115 ++ src/locales/ro/hero.ts | 6 + src/locales/ro/home.ts | 19 + src/locales/ro/index.ts | 91 ++ src/locales/ro/licenses.ts | 13 + src/locales/ro/login.ts | 22 + src/locales/ro/losslessAlbums.ts | 5 + src/locales/ro/luckyMix.ts | 6 + src/locales/ro/miniPlayer.ts | 9 + src/locales/ro/mostPlayed.ts | 13 + src/locales/ro/nowPlaying.ts | 47 + src/locales/ro/nowPlayingInfo.ts | 24 + src/locales/ro/orbit.ts | 200 ++++ src/locales/ro/player.ts | 56 + src/locales/ro/playlists.ts | 101 ++ src/locales/ro/queue.ts | 45 + src/locales/ro/radio.ts | 35 + src/locales/ro/randomAlbums.ts | 4 + src/locales/ro/randomLanding.ts | 9 + src/locales/ro/randomMix.ts | 39 + src/locales/ro/search.ts | 29 + src/locales/ro/settings.ts | 445 +++++++ src/locales/ro/sharePaste.ts | 18 + src/locales/ro/sidebar.ts | 39 + src/locales/ro/smartPlaylists.ts | 41 + src/locales/ro/songInfo.ts | 23 + src/locales/ro/statistics.ts | 65 + src/locales/ro/tracks.ts | 15 + src/locales/ro/tray.ts | 8 + src/locales/ro/whatsNew.ts | 8 + src/locales/ru.ts | 1888 ------------------------------ src/locales/ru/albumDetail.ts | 48 + src/locales/ru/albums.ts | 36 + src/locales/ru/artistDetail.ts | 43 + src/locales/ru/artists.ts | 20 + src/locales/ru/changelog.ts | 5 + src/locales/ru/common.ts | 56 + src/locales/ru/composerDetail.ts | 11 + src/locales/ru/composers.ts | 10 + src/locales/ru/connection.ts | 31 + src/locales/ru/contextMenu.ts | 35 + src/locales/ru/deviceSync.ts | 73 ++ src/locales/ru/entityRating.ts | 9 + src/locales/ru/favorites.ts | 21 + src/locales/ru/folderBrowser.ts | 4 + src/locales/ru/genres.ts | 14 + src/locales/ru/help.ts | 105 ++ src/locales/ru/hero.ts | 6 + src/locales/ru/home.ts | 21 + src/locales/ru/index.ts | 91 ++ src/locales/ru/licenses.ts | 13 + src/locales/ru/login.ts | 22 + src/locales/ru/losslessAlbums.ts | 5 + src/locales/ru/luckyMix.ts | 6 + src/locales/ru/miniPlayer.ts | 9 + src/locales/ru/mostPlayed.ts | 13 + src/locales/ru/nowPlaying.ts | 51 + src/locales/ru/nowPlayingInfo.ts | 26 + src/locales/ru/orbit.ts | 202 ++++ src/locales/ru/player.ts | 53 + src/locales/ru/playlists.ts | 101 ++ src/locales/ru/queue.ts | 45 + src/locales/ru/radio.ts | 35 + src/locales/ru/randomAlbums.ts | 4 + src/locales/ru/randomLanding.ts | 9 + src/locales/ru/randomMix.ts | 42 + src/locales/ru/search.ts | 29 + src/locales/ru/settings.ts | 459 ++++++++ src/locales/ru/sharePaste.ts | 20 + src/locales/ru/sidebar.ts | 38 + src/locales/ru/smartPlaylists.ts | 41 + src/locales/ru/songInfo.ts | 23 + src/locales/ru/statistics.ts | 58 + src/locales/ru/tracks.ts | 17 + src/locales/ru/tray.ts | 8 + src/locales/ru/whatsNew.ts | 8 + src/locales/zh.ts | 1816 ---------------------------- src/locales/zh/albumDetail.ts | 47 + src/locales/zh/albums.ts | 32 + src/locales/zh/artistDetail.ts | 41 + src/locales/zh/artists.ts | 18 + src/locales/zh/changelog.ts | 5 + src/locales/zh/common.ts | 56 + src/locales/zh/composerDetail.ts | 11 + src/locales/zh/composers.ts | 10 + src/locales/zh/connection.ts | 24 + src/locales/zh/contextMenu.ts | 32 + src/locales/zh/deviceSync.ts | 73 ++ src/locales/zh/entityRating.ts | 9 + src/locales/zh/favorites.ts | 19 + src/locales/zh/folderBrowser.ts | 4 + src/locales/zh/genres.ts | 12 + src/locales/zh/help.ts | 105 ++ src/locales/zh/hero.ts | 6 + src/locales/zh/home.ts | 19 + src/locales/zh/index.ts | 91 ++ src/locales/zh/licenses.ts | 13 + src/locales/zh/login.ts | 22 + src/locales/zh/losslessAlbums.ts | 5 + src/locales/zh/luckyMix.ts | 6 + src/locales/zh/miniPlayer.ts | 9 + src/locales/zh/mostPlayed.ts | 13 + src/locales/zh/nowPlaying.ts | 47 + src/locales/zh/nowPlayingInfo.ts | 24 + src/locales/zh/orbit.ts | 200 ++++ src/locales/zh/player.ts | 56 + src/locales/zh/playlists.ts | 99 ++ src/locales/zh/queue.ts | 45 + src/locales/zh/radio.ts | 35 + src/locales/zh/randomAlbums.ts | 4 + src/locales/zh/randomLanding.ts | 9 + src/locales/zh/randomMix.ts | 39 + src/locales/zh/search.ts | 29 + src/locales/zh/settings.ts | 440 +++++++ src/locales/zh/sharePaste.ts | 17 + src/locales/zh/sidebar.ts | 37 + src/locales/zh/smartPlaylists.ts | 41 + src/locales/zh/songInfo.ts | 23 + src/locales/zh/statistics.ts | 47 + src/locales/zh/tracks.ts | 15 + src/locales/zh/tray.ts | 8 + src/locales/zh/whatsNew.ts | 8 + 414 files changed, 17424 insertions(+), 16624 deletions(-) delete mode 100644 src/locales/de.ts create mode 100644 src/locales/de/albumDetail.ts create mode 100644 src/locales/de/albums.ts create mode 100644 src/locales/de/artistDetail.ts create mode 100644 src/locales/de/artists.ts create mode 100644 src/locales/de/changelog.ts create mode 100644 src/locales/de/common.ts create mode 100644 src/locales/de/composerDetail.ts create mode 100644 src/locales/de/composers.ts create mode 100644 src/locales/de/connection.ts create mode 100644 src/locales/de/contextMenu.ts create mode 100644 src/locales/de/deviceSync.ts create mode 100644 src/locales/de/entityRating.ts create mode 100644 src/locales/de/favorites.ts create mode 100644 src/locales/de/folderBrowser.ts create mode 100644 src/locales/de/genres.ts create mode 100644 src/locales/de/help.ts create mode 100644 src/locales/de/hero.ts create mode 100644 src/locales/de/home.ts create mode 100644 src/locales/de/index.ts create mode 100644 src/locales/de/licenses.ts create mode 100644 src/locales/de/login.ts create mode 100644 src/locales/de/losslessAlbums.ts create mode 100644 src/locales/de/luckyMix.ts create mode 100644 src/locales/de/miniPlayer.ts create mode 100644 src/locales/de/mostPlayed.ts create mode 100644 src/locales/de/nowPlaying.ts create mode 100644 src/locales/de/nowPlayingInfo.ts create mode 100644 src/locales/de/orbit.ts create mode 100644 src/locales/de/player.ts create mode 100644 src/locales/de/playlists.ts create mode 100644 src/locales/de/queue.ts create mode 100644 src/locales/de/radio.ts create mode 100644 src/locales/de/randomAlbums.ts create mode 100644 src/locales/de/randomLanding.ts create mode 100644 src/locales/de/randomMix.ts create mode 100644 src/locales/de/search.ts create mode 100644 src/locales/de/settings.ts create mode 100644 src/locales/de/sharePaste.ts create mode 100644 src/locales/de/sidebar.ts create mode 100644 src/locales/de/smartPlaylists.ts create mode 100644 src/locales/de/songInfo.ts create mode 100644 src/locales/de/statistics.ts create mode 100644 src/locales/de/tracks.ts create mode 100644 src/locales/de/tray.ts create mode 100644 src/locales/de/whatsNew.ts delete mode 100644 src/locales/en.ts create mode 100644 src/locales/en/albumDetail.ts create mode 100644 src/locales/en/albums.ts create mode 100644 src/locales/en/artistDetail.ts create mode 100644 src/locales/en/artists.ts create mode 100644 src/locales/en/changelog.ts create mode 100644 src/locales/en/common.ts create mode 100644 src/locales/en/composerDetail.ts create mode 100644 src/locales/en/composers.ts create mode 100644 src/locales/en/connection.ts create mode 100644 src/locales/en/contextMenu.ts create mode 100644 src/locales/en/deviceSync.ts create mode 100644 src/locales/en/entityRating.ts create mode 100644 src/locales/en/favorites.ts create mode 100644 src/locales/en/folderBrowser.ts create mode 100644 src/locales/en/genres.ts create mode 100644 src/locales/en/help.ts create mode 100644 src/locales/en/hero.ts create mode 100644 src/locales/en/home.ts create mode 100644 src/locales/en/index.ts create mode 100644 src/locales/en/licenses.ts create mode 100644 src/locales/en/login.ts create mode 100644 src/locales/en/losslessAlbums.ts create mode 100644 src/locales/en/luckyMix.ts create mode 100644 src/locales/en/miniPlayer.ts create mode 100644 src/locales/en/mostPlayed.ts create mode 100644 src/locales/en/nowPlaying.ts create mode 100644 src/locales/en/nowPlayingInfo.ts create mode 100644 src/locales/en/orbit.ts create mode 100644 src/locales/en/player.ts create mode 100644 src/locales/en/playlists.ts create mode 100644 src/locales/en/queue.ts create mode 100644 src/locales/en/radio.ts create mode 100644 src/locales/en/randomAlbums.ts create mode 100644 src/locales/en/randomLanding.ts create mode 100644 src/locales/en/randomMix.ts create mode 100644 src/locales/en/search.ts create mode 100644 src/locales/en/settings.ts create mode 100644 src/locales/en/sharePaste.ts create mode 100644 src/locales/en/sidebar.ts create mode 100644 src/locales/en/smartPlaylists.ts create mode 100644 src/locales/en/songInfo.ts create mode 100644 src/locales/en/statistics.ts create mode 100644 src/locales/en/tracks.ts create mode 100644 src/locales/en/tray.ts create mode 100644 src/locales/en/whatsNew.ts delete mode 100644 src/locales/es.ts create mode 100644 src/locales/es/albumDetail.ts create mode 100644 src/locales/es/albums.ts create mode 100644 src/locales/es/artistDetail.ts create mode 100644 src/locales/es/artists.ts create mode 100644 src/locales/es/changelog.ts create mode 100644 src/locales/es/common.ts create mode 100644 src/locales/es/composerDetail.ts create mode 100644 src/locales/es/composers.ts create mode 100644 src/locales/es/connection.ts create mode 100644 src/locales/es/contextMenu.ts create mode 100644 src/locales/es/deviceSync.ts create mode 100644 src/locales/es/entityRating.ts create mode 100644 src/locales/es/favorites.ts create mode 100644 src/locales/es/folderBrowser.ts create mode 100644 src/locales/es/genres.ts create mode 100644 src/locales/es/help.ts create mode 100644 src/locales/es/hero.ts create mode 100644 src/locales/es/home.ts create mode 100644 src/locales/es/index.ts create mode 100644 src/locales/es/licenses.ts create mode 100644 src/locales/es/login.ts create mode 100644 src/locales/es/losslessAlbums.ts create mode 100644 src/locales/es/luckyMix.ts create mode 100644 src/locales/es/miniPlayer.ts create mode 100644 src/locales/es/mostPlayed.ts create mode 100644 src/locales/es/nowPlaying.ts create mode 100644 src/locales/es/nowPlayingInfo.ts create mode 100644 src/locales/es/orbit.ts create mode 100644 src/locales/es/player.ts create mode 100644 src/locales/es/playlists.ts create mode 100644 src/locales/es/queue.ts create mode 100644 src/locales/es/radio.ts create mode 100644 src/locales/es/randomAlbums.ts create mode 100644 src/locales/es/randomLanding.ts create mode 100644 src/locales/es/randomMix.ts create mode 100644 src/locales/es/search.ts create mode 100644 src/locales/es/settings.ts create mode 100644 src/locales/es/sharePaste.ts create mode 100644 src/locales/es/sidebar.ts create mode 100644 src/locales/es/smartPlaylists.ts create mode 100644 src/locales/es/songInfo.ts create mode 100644 src/locales/es/statistics.ts create mode 100644 src/locales/es/tracks.ts create mode 100644 src/locales/es/tray.ts create mode 100644 src/locales/es/whatsNew.ts delete mode 100644 src/locales/fr.ts create mode 100644 src/locales/fr/albumDetail.ts create mode 100644 src/locales/fr/albums.ts create mode 100644 src/locales/fr/artistDetail.ts create mode 100644 src/locales/fr/artists.ts create mode 100644 src/locales/fr/changelog.ts create mode 100644 src/locales/fr/common.ts create mode 100644 src/locales/fr/composerDetail.ts create mode 100644 src/locales/fr/composers.ts create mode 100644 src/locales/fr/connection.ts create mode 100644 src/locales/fr/contextMenu.ts create mode 100644 src/locales/fr/deviceSync.ts create mode 100644 src/locales/fr/entityRating.ts create mode 100644 src/locales/fr/favorites.ts create mode 100644 src/locales/fr/folderBrowser.ts create mode 100644 src/locales/fr/genres.ts create mode 100644 src/locales/fr/help.ts create mode 100644 src/locales/fr/hero.ts create mode 100644 src/locales/fr/home.ts create mode 100644 src/locales/fr/index.ts create mode 100644 src/locales/fr/licenses.ts create mode 100644 src/locales/fr/login.ts create mode 100644 src/locales/fr/losslessAlbums.ts create mode 100644 src/locales/fr/luckyMix.ts create mode 100644 src/locales/fr/miniPlayer.ts create mode 100644 src/locales/fr/mostPlayed.ts create mode 100644 src/locales/fr/nowPlaying.ts create mode 100644 src/locales/fr/nowPlayingInfo.ts create mode 100644 src/locales/fr/orbit.ts create mode 100644 src/locales/fr/player.ts create mode 100644 src/locales/fr/playlists.ts create mode 100644 src/locales/fr/queue.ts create mode 100644 src/locales/fr/radio.ts create mode 100644 src/locales/fr/randomAlbums.ts create mode 100644 src/locales/fr/randomLanding.ts create mode 100644 src/locales/fr/randomMix.ts create mode 100644 src/locales/fr/search.ts create mode 100644 src/locales/fr/settings.ts create mode 100644 src/locales/fr/sharePaste.ts create mode 100644 src/locales/fr/sidebar.ts create mode 100644 src/locales/fr/smartPlaylists.ts create mode 100644 src/locales/fr/songInfo.ts create mode 100644 src/locales/fr/statistics.ts create mode 100644 src/locales/fr/tracks.ts create mode 100644 src/locales/fr/tray.ts create mode 100644 src/locales/fr/whatsNew.ts delete mode 100644 src/locales/nb.ts create mode 100644 src/locales/nb/albumDetail.ts create mode 100644 src/locales/nb/albums.ts create mode 100644 src/locales/nb/artistDetail.ts create mode 100644 src/locales/nb/artists.ts create mode 100644 src/locales/nb/changelog.ts create mode 100644 src/locales/nb/common.ts create mode 100644 src/locales/nb/composerDetail.ts create mode 100644 src/locales/nb/composers.ts create mode 100644 src/locales/nb/connection.ts create mode 100644 src/locales/nb/contextMenu.ts create mode 100644 src/locales/nb/deviceSync.ts create mode 100644 src/locales/nb/entityRating.ts create mode 100644 src/locales/nb/favorites.ts create mode 100644 src/locales/nb/folderBrowser.ts create mode 100644 src/locales/nb/genres.ts create mode 100644 src/locales/nb/help.ts create mode 100644 src/locales/nb/hero.ts create mode 100644 src/locales/nb/home.ts create mode 100644 src/locales/nb/index.ts create mode 100644 src/locales/nb/licenses.ts create mode 100644 src/locales/nb/login.ts create mode 100644 src/locales/nb/losslessAlbums.ts create mode 100644 src/locales/nb/luckyMix.ts create mode 100644 src/locales/nb/miniPlayer.ts create mode 100644 src/locales/nb/mostPlayed.ts create mode 100644 src/locales/nb/nowPlaying.ts create mode 100644 src/locales/nb/nowPlayingInfo.ts create mode 100644 src/locales/nb/orbit.ts create mode 100644 src/locales/nb/player.ts create mode 100644 src/locales/nb/playlists.ts create mode 100644 src/locales/nb/queue.ts create mode 100644 src/locales/nb/radio.ts create mode 100644 src/locales/nb/randomAlbums.ts create mode 100644 src/locales/nb/randomLanding.ts create mode 100644 src/locales/nb/randomMix.ts create mode 100644 src/locales/nb/search.ts create mode 100644 src/locales/nb/settings.ts create mode 100644 src/locales/nb/sharePaste.ts create mode 100644 src/locales/nb/sidebar.ts create mode 100644 src/locales/nb/smartPlaylists.ts create mode 100644 src/locales/nb/songInfo.ts create mode 100644 src/locales/nb/statistics.ts create mode 100644 src/locales/nb/tracks.ts create mode 100644 src/locales/nb/tray.ts create mode 100644 src/locales/nb/whatsNew.ts delete mode 100644 src/locales/nl.ts create mode 100644 src/locales/nl/albumDetail.ts create mode 100644 src/locales/nl/albums.ts create mode 100644 src/locales/nl/artistDetail.ts create mode 100644 src/locales/nl/artists.ts create mode 100644 src/locales/nl/changelog.ts create mode 100644 src/locales/nl/common.ts create mode 100644 src/locales/nl/composerDetail.ts create mode 100644 src/locales/nl/composers.ts create mode 100644 src/locales/nl/connection.ts create mode 100644 src/locales/nl/contextMenu.ts create mode 100644 src/locales/nl/deviceSync.ts create mode 100644 src/locales/nl/entityRating.ts create mode 100644 src/locales/nl/favorites.ts create mode 100644 src/locales/nl/folderBrowser.ts create mode 100644 src/locales/nl/genres.ts create mode 100644 src/locales/nl/help.ts create mode 100644 src/locales/nl/hero.ts create mode 100644 src/locales/nl/home.ts create mode 100644 src/locales/nl/index.ts create mode 100644 src/locales/nl/licenses.ts create mode 100644 src/locales/nl/login.ts create mode 100644 src/locales/nl/losslessAlbums.ts create mode 100644 src/locales/nl/luckyMix.ts create mode 100644 src/locales/nl/miniPlayer.ts create mode 100644 src/locales/nl/mostPlayed.ts create mode 100644 src/locales/nl/nowPlaying.ts create mode 100644 src/locales/nl/nowPlayingInfo.ts create mode 100644 src/locales/nl/orbit.ts create mode 100644 src/locales/nl/player.ts create mode 100644 src/locales/nl/playlists.ts create mode 100644 src/locales/nl/queue.ts create mode 100644 src/locales/nl/radio.ts create mode 100644 src/locales/nl/randomAlbums.ts create mode 100644 src/locales/nl/randomLanding.ts create mode 100644 src/locales/nl/randomMix.ts create mode 100644 src/locales/nl/search.ts create mode 100644 src/locales/nl/settings.ts create mode 100644 src/locales/nl/sharePaste.ts create mode 100644 src/locales/nl/sidebar.ts create mode 100644 src/locales/nl/smartPlaylists.ts create mode 100644 src/locales/nl/songInfo.ts create mode 100644 src/locales/nl/statistics.ts create mode 100644 src/locales/nl/tracks.ts create mode 100644 src/locales/nl/tray.ts create mode 100644 src/locales/nl/whatsNew.ts delete mode 100644 src/locales/ro.ts create mode 100644 src/locales/ro/albumDetail.ts create mode 100644 src/locales/ro/albums.ts create mode 100644 src/locales/ro/artistDetail.ts create mode 100644 src/locales/ro/artists.ts create mode 100644 src/locales/ro/changelog.ts create mode 100644 src/locales/ro/common.ts create mode 100644 src/locales/ro/composerDetail.ts create mode 100644 src/locales/ro/composers.ts create mode 100644 src/locales/ro/connection.ts create mode 100644 src/locales/ro/contextMenu.ts create mode 100644 src/locales/ro/deviceSync.ts create mode 100644 src/locales/ro/entityRating.ts create mode 100644 src/locales/ro/favorites.ts create mode 100644 src/locales/ro/folderBrowser.ts create mode 100644 src/locales/ro/genres.ts create mode 100644 src/locales/ro/help.ts create mode 100644 src/locales/ro/hero.ts create mode 100644 src/locales/ro/home.ts create mode 100644 src/locales/ro/index.ts create mode 100644 src/locales/ro/licenses.ts create mode 100644 src/locales/ro/login.ts create mode 100644 src/locales/ro/losslessAlbums.ts create mode 100644 src/locales/ro/luckyMix.ts create mode 100644 src/locales/ro/miniPlayer.ts create mode 100644 src/locales/ro/mostPlayed.ts create mode 100644 src/locales/ro/nowPlaying.ts create mode 100644 src/locales/ro/nowPlayingInfo.ts create mode 100644 src/locales/ro/orbit.ts create mode 100644 src/locales/ro/player.ts create mode 100644 src/locales/ro/playlists.ts create mode 100644 src/locales/ro/queue.ts create mode 100644 src/locales/ro/radio.ts create mode 100644 src/locales/ro/randomAlbums.ts create mode 100644 src/locales/ro/randomLanding.ts create mode 100644 src/locales/ro/randomMix.ts create mode 100644 src/locales/ro/search.ts create mode 100644 src/locales/ro/settings.ts create mode 100644 src/locales/ro/sharePaste.ts create mode 100644 src/locales/ro/sidebar.ts create mode 100644 src/locales/ro/smartPlaylists.ts create mode 100644 src/locales/ro/songInfo.ts create mode 100644 src/locales/ro/statistics.ts create mode 100644 src/locales/ro/tracks.ts create mode 100644 src/locales/ro/tray.ts create mode 100644 src/locales/ro/whatsNew.ts delete mode 100644 src/locales/ru.ts create mode 100644 src/locales/ru/albumDetail.ts create mode 100644 src/locales/ru/albums.ts create mode 100644 src/locales/ru/artistDetail.ts create mode 100644 src/locales/ru/artists.ts create mode 100644 src/locales/ru/changelog.ts create mode 100644 src/locales/ru/common.ts create mode 100644 src/locales/ru/composerDetail.ts create mode 100644 src/locales/ru/composers.ts create mode 100644 src/locales/ru/connection.ts create mode 100644 src/locales/ru/contextMenu.ts create mode 100644 src/locales/ru/deviceSync.ts create mode 100644 src/locales/ru/entityRating.ts create mode 100644 src/locales/ru/favorites.ts create mode 100644 src/locales/ru/folderBrowser.ts create mode 100644 src/locales/ru/genres.ts create mode 100644 src/locales/ru/help.ts create mode 100644 src/locales/ru/hero.ts create mode 100644 src/locales/ru/home.ts create mode 100644 src/locales/ru/index.ts create mode 100644 src/locales/ru/licenses.ts create mode 100644 src/locales/ru/login.ts create mode 100644 src/locales/ru/losslessAlbums.ts create mode 100644 src/locales/ru/luckyMix.ts create mode 100644 src/locales/ru/miniPlayer.ts create mode 100644 src/locales/ru/mostPlayed.ts create mode 100644 src/locales/ru/nowPlaying.ts create mode 100644 src/locales/ru/nowPlayingInfo.ts create mode 100644 src/locales/ru/orbit.ts create mode 100644 src/locales/ru/player.ts create mode 100644 src/locales/ru/playlists.ts create mode 100644 src/locales/ru/queue.ts create mode 100644 src/locales/ru/radio.ts create mode 100644 src/locales/ru/randomAlbums.ts create mode 100644 src/locales/ru/randomLanding.ts create mode 100644 src/locales/ru/randomMix.ts create mode 100644 src/locales/ru/search.ts create mode 100644 src/locales/ru/settings.ts create mode 100644 src/locales/ru/sharePaste.ts create mode 100644 src/locales/ru/sidebar.ts create mode 100644 src/locales/ru/smartPlaylists.ts create mode 100644 src/locales/ru/songInfo.ts create mode 100644 src/locales/ru/statistics.ts create mode 100644 src/locales/ru/tracks.ts create mode 100644 src/locales/ru/tray.ts create mode 100644 src/locales/ru/whatsNew.ts delete mode 100644 src/locales/zh.ts create mode 100644 src/locales/zh/albumDetail.ts create mode 100644 src/locales/zh/albums.ts create mode 100644 src/locales/zh/artistDetail.ts create mode 100644 src/locales/zh/artists.ts create mode 100644 src/locales/zh/changelog.ts create mode 100644 src/locales/zh/common.ts create mode 100644 src/locales/zh/composerDetail.ts create mode 100644 src/locales/zh/composers.ts create mode 100644 src/locales/zh/connection.ts create mode 100644 src/locales/zh/contextMenu.ts create mode 100644 src/locales/zh/deviceSync.ts create mode 100644 src/locales/zh/entityRating.ts create mode 100644 src/locales/zh/favorites.ts create mode 100644 src/locales/zh/folderBrowser.ts create mode 100644 src/locales/zh/genres.ts create mode 100644 src/locales/zh/help.ts create mode 100644 src/locales/zh/hero.ts create mode 100644 src/locales/zh/home.ts create mode 100644 src/locales/zh/index.ts create mode 100644 src/locales/zh/licenses.ts create mode 100644 src/locales/zh/login.ts create mode 100644 src/locales/zh/losslessAlbums.ts create mode 100644 src/locales/zh/luckyMix.ts create mode 100644 src/locales/zh/miniPlayer.ts create mode 100644 src/locales/zh/mostPlayed.ts create mode 100644 src/locales/zh/nowPlaying.ts create mode 100644 src/locales/zh/nowPlayingInfo.ts create mode 100644 src/locales/zh/orbit.ts create mode 100644 src/locales/zh/player.ts create mode 100644 src/locales/zh/playlists.ts create mode 100644 src/locales/zh/queue.ts create mode 100644 src/locales/zh/radio.ts create mode 100644 src/locales/zh/randomAlbums.ts create mode 100644 src/locales/zh/randomLanding.ts create mode 100644 src/locales/zh/randomMix.ts create mode 100644 src/locales/zh/search.ts create mode 100644 src/locales/zh/settings.ts create mode 100644 src/locales/zh/sharePaste.ts create mode 100644 src/locales/zh/sidebar.ts create mode 100644 src/locales/zh/smartPlaylists.ts create mode 100644 src/locales/zh/songInfo.ts create mode 100644 src/locales/zh/statistics.ts create mode 100644 src/locales/zh/tracks.ts create mode 100644 src/locales/zh/tray.ts create mode 100644 src/locales/zh/whatsNew.ts diff --git a/src/locales/de.ts b/src/locales/de.ts deleted file mode 100644 index d82db6b8..00000000 --- a/src/locales/de.ts +++ /dev/null @@ -1,1870 +0,0 @@ -export const deTranslation = { - sidebar: { - library: 'Bibliothek', - mainstage: 'Mainstage', - newReleases: 'Neueste', - allAlbums: 'Alle Alben', - randomAlbums: 'Zufallsalben', - randomPicker: 'Mix erstellen', - artists: 'Künstler', - composers: 'Komponist*innen', - randomMix: 'Zufallsmix', - favorites: 'Favoriten', - nowPlaying: 'Now Playing', - system: 'System', - statistics: 'Statistiken', - settings: 'Einstellungen', - help: 'Hilfe', - expand: 'Sidebar einblenden', - collapse: 'Sidebar ausblenden', - downloadingTracks: '{{n}} Tracks werden gecacht…', - syncingTracks: 'Synchronisiere {{done}}/{{total}}…', - cancelDownload: 'Download abbrechen', - offlineLibrary: 'Offline-Bibliothek', - genres: 'Genres', - tracks: 'Titel', - playlists: 'Playlists', - mostPlayed: 'Meistgehört', - losslessAlbums: 'Lossless', - radio: 'Internetradio', - folderBrowser: 'Ordner-Browser', - deviceSync: 'Gerätesync', - libraryScope: 'Bibliotheksumfang', - allLibraries: 'Alle Bibliotheken', - expandPlaylists: 'Playlists ausklappen', - collapsePlaylists: 'Playlists einklappen', - more: 'Mehr', - feelingLucky: 'Glücks-Mix', - }, - home: { - hero: 'Featured', - starred: 'Persönliche Favoriten', - recent: 'Zuletzt hinzugefügt', - mostPlayed: 'Meistgehört', - recentlyPlayed: 'Kürzlich gespielt', - losslessAlbums: 'Lossless-Alben', - discover: 'Entdecken', - discoverSongs: 'Titel entdecken', - loadMore: 'Mehr laden', - discoverMore: 'Mehr entdecken', - discoverArtists: 'Künstler entdecken', - discoverArtistsMore: 'Alle Künstler', - becauseYouLike: 'Weil du gehört hast…', - becauseYouLikeFor: 'Weil du {{artist}} gehört hast', - similarTo: 'Ähnlich wie {{artist}}', - becauseYouLikeTracks_one: '{{count}} Titel', - becauseYouLikeTracks_other: '{{count}} Titel' - }, - hero: { - eyebrow: 'Album des Augenblicks', - playAlbum: 'Album abspielen', - enqueue: 'Einreihen', - enqueueTooltip: 'Ganzes Album zur Warteschlange hinzufügen', - }, - search: { - placeholder: 'Suchen nach Künstler, Album oder Song…', - noResults: 'Keine Ergebnisse für „{{query}}"', - artists: 'Künstler', - albums: 'Alben', - songs: 'Songs', - clearLabel: 'Suche leeren', - addedToQueueToast: '„{{title}}" zur Warteschlange hinzugefügt', - title: 'Suche', - resultsFor: 'Ergebnisse für „{{query}}"', - album: 'Album', - advanced: 'Erweiterte Suche', - advancedSearchTerm: 'Suchbegriff', - advancedSearchPlaceholder: 'Titel, Album, Künstler…', - advancedGenre: 'Genre', - advancedAllGenres: 'Alle Genres', - advancedYear: 'Jahr', - advancedYearFrom: 'von', - advancedYearTo: 'bis', - advancedAll: 'Alle', - advancedSearch: 'Suchen', - advancedEmpty: 'Suchbegriff eingeben oder Filter wählen, um zu beginnen.', - advancedNoResults: 'Keine Ergebnisse gefunden.', - advancedGenreNote: 'Songs werden zufällig aus dem Genre gewählt.', - recentSearches: 'Zuletzt gesucht', - browse: 'Stöbern', - emptyHint: 'Was möchtest du hören?', - genres: 'Genres', - }, - nowPlaying: { - tooltip: 'Wer hört was?', - title: 'Wer hört was?', - loading: 'Lädt…', - nobody: 'Gerade hört niemand Musik.', - minutesAgo: 'vor {{n}}m', - nothingPlaying: 'Noch nichts am Laufen. Leg einen Track auf!', - aboutArtist: 'Über den Künstler', - fromAlbum: 'Aus diesem Album', - viewAlbum: 'Album öffnen', - goToArtist: 'Zum Künstler', - readMore: 'Mehr lesen', - showLess: 'Weniger anzeigen', - genreInfo: 'Genre', - trackInfo: 'Track-Info', - topSongs: 'Meistgespielt von diesem Künstler', - topSongsCredit: 'Top-Tracks von {{name}}', - trackPosition: 'Track {{pos}}', - playsCount_one: '{{count}} Wiedergabe', - playsCount_other: '{{count}} Wiedergaben', - releasedYearsAgo_one: 'vor {{count}} Jahr', - releasedYearsAgo_other: 'vor {{count}} Jahren', - discography: 'Diskografie', - lastfmStats: 'Last.fm-Statistik', - thisTrack: 'Dieser Titel', - thisArtist: 'Dieser Künstler', - listeners: 'Hörer', - scrobbles: 'Scrobbles', - yourScrobbles: 'von dir', - listenersN: '{{n}} Hörer', - scrobblesN: '{{n}} Scrobbles', - playsByYouN: '{{n}}× von dir gespielt', - openTrackOnLastfm: 'Track auf Last.fm', - openArtistOnLastfm: 'Künstler auf Last.fm', - rgTrackTooltip: 'ReplayGain (Track)', - rgAlbumTooltip: 'ReplayGain (Album)', - rgAutoTooltip: 'ReplayGain (Auto)', - showMoreTracks: '{{count}} weitere anzeigen', - showLessTracks: 'Weniger anzeigen', - hideCard: 'Karte ausblenden', - layoutMenu: 'Layout', - visibleCards: 'Sichtbare Karten', - hiddenCards: 'Ausgeblendete Karten', - noHiddenCards: 'Keine ausgeblendeten Karten', - resetLayout: 'Layout zurücksetzen', - emptyColumn: 'Karten hier ablegen', - }, - contextMenu: { - playNow: 'Direkt abspielen', - playNext: 'Als Nächstes abspielen', - addToQueue: 'Zur Warteschlange hinzufügen', - enqueueAlbum: 'Ganzes Album einreihen', - enqueueAlbums_one: '{{count}} Album einreihen', - enqueueAlbums_other: '{{count}} Alben einreihen', - startRadio: 'Radio starten', - instantMix: 'Instant Mix', - instantMixFailed: 'Instant Mix konnte nicht erstellt werden — Server- oder Pluginfehler.', - cliMixNeedsTrack: 'Es läuft nichts — starte zuerst die Wiedergabe und führe den Mix-Befehl erneut aus.', - lfmLove: 'Auf Last.fm liken', - lfmUnlove: 'Last.fm-Like entfernen', - favorite: 'Favorisieren', - favoriteArtist: 'Künstler favorisieren', - favoriteAlbum: 'Album favorisieren', - unfavorite: 'Aus Favoriten entfernen', - unfavoriteArtist: 'Künstler aus Favoriten entfernen', - unfavoriteAlbum: 'Album aus Favoriten entfernen', - removeFromQueue: 'Diesen Song entfernen', - removeFromPlaylist: 'Aus Playlist entfernen', - openAlbum: 'Album öffnen', - goToArtist: 'Zum Künstler', - download: 'Herunterladen (ZIP)', - addToPlaylist: 'Zur Playlist hinzufügen', - selectedPlaylists: '{{count}} Playlists ausgewählt', - selectedAlbums: '{{count}} Alben ausgewählt', - selectedArtists: '{{count}} Künstler ausgewählt', - songInfo: 'Song-Infos', - shareLink: 'Freigabe-Link kopieren', - shareCopied: 'Freigabe-Link wurde in die Zwischenablage kopiert.', - shareCopyFailed: 'Kopieren in die Zwischenablage fehlgeschlagen.', - }, - sharePaste: { - notLoggedIn: 'Melde dich an und füge den Server hinzu, bevor du einen Freigabe-Link einfügst.', - noMatchingServer: 'Kein gespeicherter Server passt zu diesem Link. Füge einen Server mit dieser Adresse hinzu: {{url}}', - trackUnavailable: 'Dieser Titel wurde auf dem Server nicht gefunden.', - albumUnavailable: 'Dieses Album wurde auf dem Server nicht gefunden.', - artistUnavailable: 'Dieser Künstler wurde auf dem Server nicht gefunden.', - composerUnavailable: 'Diese*r Komponist*in wurde auf dem Server nicht gefunden.', - openedTrack: 'Geteilter Titel wird abgespielt.', - openedAlbum: 'Geteiltes Album wird geöffnet.', - openedArtist: 'Geteilter Künstler wird geöffnet.', - openedComposer: 'Geteilte*r Komponist*in wird geöffnet.', - openedQueue_one: '{{count}} Titel aus Freigabe-Link wird abgespielt.', - openedQueue_other: '{{count}} Titel aus Freigabe-Link werden abgespielt.', - openedQueuePartial: - '{{played}} von {{total}} Titeln aus dem Link werden abgespielt ({{skipped}} auf diesem Server nicht gefunden).', - queueAllUnavailable: 'Keiner der Titel aus diesem Link wurde auf dem Server gefunden.', - genericError: 'Freigabe-Link konnte nicht geöffnet werden.', - }, - albumDetail: { - back: 'Zurück', - orbitDoubleClickHint: 'Doppelklick fügt diesen Titel zur Orbit-Queue hinzu', - playAll: 'Alle abspielen', - shareAlbum: 'Album teilen', - enqueue: 'Einreihen', - enqueueTooltip: 'Ganzes Album zur Warteschlange hinzufügen', - artistBio: 'Künstler-Bio', - download: 'Download (ZIP)', - downloading: 'Lade…', - cacheOffline: 'Offline verfügbar machen', - offlineCached: 'Offline verfügbar', - offlineDownloading: 'Wird gecacht… ({{n}}/{{total}})', - removeOffline: 'Offline-Cache löschen', - offlineStorageFull: 'Offline-Speicher voll (Limit: {{mb}} MB). Lösche ein Album aus der Offline-Bibliothek oder erhöhe das Limit in den Einstellungen.', - offlineStorageGoToSettings: 'Einstellungen', - offlineStorageGoToLibrary: 'Offline-Bibliothek', - favoriteAdd: 'Zu Favoriten hinzufügen', - favoriteRemove: 'Aus Favoriten entfernen', - favorite: 'Als Favorit', - noBio: 'Keine Biografie verfügbar.', - moreByArtist: 'Mehr von {{artist}}', - tracksCount: '{{n}} Tracks', - goToArtist: 'Zu {{artist}} wechseln', - moreLabelAlbums: 'Weitere Alben von {{label}} anzeigen', - trackTitle: 'Titel', - trackAlbum: 'Album', - trackArtist: 'Interpret', - trackGenre: 'Genre', - trackFormat: 'Format', - trackFavorite: 'Favorit', - trackRating: 'Bewertung', - trackDuration: 'Dauer', - trackTotal: 'Gesamt', - columns: 'Spalten', - resetColumns: 'Zurücksetzen', - notFound: 'Album nicht gefunden.', - bioModal: 'Künstler-Biografie', - bioClose: 'Schließen', - ratingLabel: 'Bewertung', - enlargeCover: 'Vergrößern', - filterSongs: 'Titel filtern…', - sortNatural: 'Reihenfolge', - sortByTitle: 'A–Z (Titel)', - sortByArtist: 'A–Z (Künstler)', - sortByAlbum: 'A–Z (Album)', - }, - entityRating: { - albumShort: 'Albumbewertung', - artistShort: 'Künstlerbewertung', - albumAriaLabel: 'Albumbewertung', - artistAriaLabel: 'Künstlerbewertung', - selectedArtistsRatingAriaLabel: 'Sternebewertung für {{count}} ausgewählte Künstler', - selectedAlbumsRatingAriaLabel: 'Sternebewertung für {{count}} ausgewählte Alben', - saveFailed: 'Bewertung konnte nicht gespeichert werden.', - }, - artistDetail: { - back: 'Zurück', - albums: 'Alben', - album: 'Album', - playAll: 'Alle abspielen', - shareArtist: 'Künstler teilen', - shuffle: 'Zufallswiedergabe', - radio: 'Radio', - loading: 'Lädt…', - noRadio: 'Keine ähnlichen Titel für diesen Künstler gefunden.', - notFound: 'Künstler nicht gefunden.', - albumsBy: 'Alben von {{name}}', - topTracks: 'Beliebteste Titel', - noAlbums: 'Keine Alben gefunden.', - trackTitle: 'Titel', - trackAlbum: 'Album', - trackDuration: 'Dauer', - favoriteAdd: 'Zu Favoriten hinzufügen', - favoriteRemove: 'Aus Favoriten entfernen', - favorite: 'Als Favorit', - albumCount_one: '{{count}} Album', - albumCount_other: '{{count}} Alben', - openedInBrowser: 'Im Browser geöffnet', - featuredOn: 'Auch enthalten auf', - similarArtists: 'Ähnliche Künstler', - cacheOffline: 'Diskografie offline speichern', - offlineCached: 'Diskografie gecacht', - offlineDownloading: 'Wird gecacht… ({{done}}/{{total}} Alben)', - uploadImage: 'Künstlerbild hochladen', - uploadImageError: 'Bild konnte nicht hochgeladen werden', - releaseTypes: { - album: 'Album', - ep: 'EP', - single: 'Single', - compilation: 'Kompilation', - live: 'Live', - soundtrack: 'Soundtrack', - remix: 'Remix', - other: 'Sonstige', - }, - }, - favorites: { - title: 'Favoriten', - empty: 'Du hast noch keine Favoriten gespeichert.', - artists: 'Künstler', - albums: 'Alben', - songs: 'Songs', - enqueueAll: 'Alle in die Warteschlange', - playAll: 'Alle abspielen', - removeSong: 'Aus Favoriten entfernen', - stations: 'Radiosender', - showingFiltered: 'Zeige {{filtered}} von {{total}} ({{artist}})', - showingCount: 'Zeige {{filtered}} von {{total}}', - clearArtistFilter: 'Künstlerfilter zurücksetzen', - noFilterResults: 'Keine Ergebnisse mit den ausgewählten Filtern.', - allArtists: 'Alle Künstler', - topArtists: 'Top-Künstler nach Favoriten', - topArtistsSongCount_one: '{{count}} Song', - topArtistsSongCount_other: '{{count}} Songs', - }, - randomLanding: { - title: 'Mix erstellen', - mixByTracks: 'Mix nach Titeln', - mixByTracksDesc: 'Zufällige Auswahl aus deiner gesamten Mediathek', - mixByAlbums: 'Mix nach Alben', - mixByAlbumsDesc: 'Zufällige Alben für neue Entdeckungen', - mixByLucky: 'Glücks-Mix', - mixByLuckyDesc: 'Smarter Instant Mix aus Top-Künstlern, Alben und Bewertungen', - }, - randomAlbums: { - title: 'Zufallsalben', - refresh: 'Neu laden', - }, - genres: { - title: 'Genres', - genreCount: 'Genres', - albumCount_one: '{{count}} Album', - albumCount_other: '{{count}} Alben', - loading: 'Genres werden geladen…', - empty: 'Keine Genres gefunden.', - albumsLoading: 'Alben werden geladen…', - albumsEmpty: 'Keine Alben in diesem Genre gefunden.', - loadMore: 'Mehr laden', - back: 'Zurück', - }, - randomMix: { - title: 'Zufallsmix', - remix: 'Neu mixen', - remixTooltip: 'Neue Songs laden', - remixGenre: '{{genre}} neu mixen', - remixTooltipGenre: 'Neue {{genre}}-Songs laden', - playAll: 'Alle abspielen', - trackTitle: 'Titel', - trackArtist: 'Künstler', - trackAlbum: 'Album', - trackFavorite: 'Favorit', - trackDuration: 'Dauer', - favoriteAdd: 'Zu Favoriten hinzufügen', - favoriteRemove: 'Aus Favoriten entfernen', - play: 'Abspielen', - trackGenre: 'Genre', - mixSettingsHeader: 'Mix-Einstellungen', - exclusionsHeader: 'Ausschlüsse', - filterPanelInexactSizeNote: 'Die Mix-Größe ist ein Ziel — bei großen Anfragen kann der Server weniger eindeutige Tracks liefern, wenn sein Zufallspool erschöpft ist.', - mixSize: 'Playlistgröße', - excludeAudiobooks: 'Hörbücher & Hörspiele ausschließen', - excludeAudiobooksDesc: 'Prüft Keywords gegen Genre, Titel, Album und Künstler — z. B. Hörbuch, Audiobook, Spoken Word, …', - genreBlocked: 'Keyword gesperrt', - genreAddedToBlacklist: 'Zur Filterliste hinzugefügt', - genreAlreadyBlocked: 'Bereits gesperrt', - artistBlocked: 'Künstler gesperrt', - artistAddedToBlacklist: 'Künstler zur Filterliste hinzugefügt', - artistClickHint: 'Klicken um diesen Künstler zu sperren', - blacklistToggle: 'Keyword-Filter', - genreMixTitle: 'Genre-Mix', - genreMixDesc: 'Top 20 Genres nach Songanzahl — klicken für einen Zufallsmix', - genreMixAll: 'Alle Songs', - genreMixLoadMore: '10 weitere laden', - genreMixNoGenres: 'Keine Genres auf dem Server gefunden.', - shuffleGenres: 'Andere Genres anzeigen', - filterPanelTitle: 'Filter', - filterPanelDesc: 'Genre-Tag oder Künstlername in der Liste anklicken, um ihn aus zukünftigen Mixes auszuschließen.', - genreClickHint: 'Genre-Tag anklicken,\num es als Filter-Keyword hinzuzufügen.\nPrüft Genre, Titel, Album & Künstler.', - }, - luckyMix: { - done: 'Glücks-Mix bereit: {{count}} Titel', - failed: 'Glücks-Mix konnte nicht erstellt werden. Bitte erneut versuchen.', - unavailable: 'Glücks-Mix ist für diesen Server nicht verfügbar.', - cancelTooltip: 'Glücks-Mix-Erstellung abbrechen', - }, - albums: { - title: 'Alle Alben', - sortByName: 'A–Z (Album)', - sortByArtist: 'A–Z (Künstler)', - sortNewest: 'Neueste zuerst', - sortRandom: 'Zufällig', - yearFrom: 'Von', - yearTo: 'Bis', - yearFilterClear: 'Jahresfilter zurücksetzen', - yearFilterLabel: 'Jahr', - compilationLabel: 'Sampler', - compilationOnly: 'Nur Sampler', - compilationHide: 'Ohne Sampler', - compilationTooltipAll: 'Alle Alben · klicken: nur Sampler', - compilationTooltipOnly: 'Nur Sampler · klicken: Sampler ausblenden', - compilationTooltipHide: 'Sampler ausgeblendet · klicken: alle zeigen', - select: 'Mehrfachauswahl', - startSelect: 'Mehrfachauswahl aktivieren', - cancelSelect: 'Abbrechen', - selectionCount: '{{count}} ausgewählt', - downloadZips: 'ZIPs herunterladen', - addOffline: 'Offline hinzufügen', - enqueueSelected_one: 'Einreihen ({{count}})', - enqueueSelected_other: 'Einreihen ({{count}})', - enqueueQueued_one: '{{count}} Album zur Warteschlange hinzugefügt', - enqueueQueued_other: '{{count}} Alben zur Warteschlange hinzugefügt', - downloadingZip: 'Lade {{current}}/{{total}} herunter: {{name}}', - downloadZipDone: '{{count}} ZIP(s) heruntergeladen', - downloadZipFailed: 'Download fehlgeschlagen: {{name}}', - offlineQueuing: '{{count}} Album(s) für Offline einreihen…', - offlineFailed: '{{name}} konnte nicht offline hinzugefügt werden', - }, - tracks: { - title: 'Titel', - subtitle: 'Stöbern. Suchen. Entdecken.', - heroEyebrow: 'Titel des Moments', - heroReroll: 'Anderen wählen', - playSong: 'Abspielen', - enqueueSong: 'Zur Warteschlange', - railRandom: 'Zufallsauswahl', - railHighlyRated: 'Hoch bewertet', - browseTitle: 'Alle Titel durchstöbern', - browseUnsupported: 'Dieser Server listet nicht die ganze Bibliothek auf einmal. Nutze die Suche oben, um bestimmte Titel zu finden.', - searchPlaceholder: 'Titel, Künstler oder Album suchen…', - count_one: '{{count}} Titel', - count_other: '{{count}} Titel', - }, - artists: { - title: 'Künstler', - search: 'Suchen…', - all: 'Alle', - gridView: 'Gitteransicht', - listView: 'Listenansicht', - imagesOn: 'Künstlerbilder aktiv — kann Netzwerk- und Systemlast erhöhen', - imagesOff: 'Künstlerbilder deaktiviert — zeigt nur Initialen', - loadMore: 'Mehr laden', - notFound: 'Keine Künstler gefunden.', - albumCount_one: '{{count}} Album', - albumCount_other: '{{count}} Alben', - selectionCount: '{{count}} ausgewählt', - select: 'Mehrfachauswahl', - startSelect: 'Mehrfachauswahl aktivieren', - cancelSelect: 'Abbrechen', - addToPlaylist: 'Zur Playlist hinzufügen', - }, - composers: { - title: 'Komponist*innen', - search: 'Suchen…', - notFound: 'Keine Komponist*innen gefunden.', - unsupported: 'Komponist-Ansicht benötigt Navidrome 0.55 oder neuer.', - loadFailed: 'Komponist*innen konnten nicht geladen werden.', - retry: 'Erneut versuchen', - involvedIn_one: 'Beteiligt an {{count}} Album', - involvedIn_other: 'Beteiligt an {{count}} Alben', - }, - composerDetail: { - back: 'Zurück', - notFound: 'Komponist*in nicht gefunden.', - about: 'Über diese*n Komponist*in', - works: 'Werke', - noWorks: 'Keine Werke gefunden.', - workCount_one: '{{count}} Werk', - workCount_other: '{{count}} Werke', - shareComposer: 'Komponist*in teilen', - unknownComposer: 'Komponist*in', - }, - login: { - subtitle: 'Dein Navidrome Desktop Player', - serverName: 'Server-Name (optional)', - serverNamePlaceholder: 'Mein Navidrome', - serverUrl: 'Server-URL', - serverUrlPlaceholder: '192.168.1.100:4533 oder https://music.example.com', - username: 'Benutzername', - usernamePlaceholder: 'admin', - password: 'Passwort', - showPassword: 'Passwort anzeigen', - hidePassword: 'Passwort verstecken', - connect: 'Verbinden', - connecting: 'Verbinde…', - connected: 'Verbunden!', - error: 'Verbindung fehlgeschlagen – bitte Daten prüfen.', - urlRequired: 'Bitte Server-URL eingeben.', - savedServers: 'Gespeicherte Server', - addNew: 'Oder neuen Server hinzufügen', - orMagicString: 'Oder Magic-String', - magicStringPlaceholder: 'Freigabe-String einfügen (psysonic1-…)', - magicStringInvalid: 'Ungültiger oder nicht lesbarer Magic-String.', - }, - connection: { - connected: 'Verbunden', - connectedTo: 'Verbunden mit {{server}}', - disconnected: 'Getrennt', - disconnectedFrom: '{{server}} nicht erreichbar — klicken für Einstellungen', - checking: 'Verbinde…', - extern: 'Extern', - offlineTitle: 'Keine Serververbindung', - offlineSubtitle: '{{server}} ist nicht erreichbar. Prüfe Netzwerk oder Server.', - offlineModeBanner: 'Offline-Modus — Wiedergabe aus lokalem Cache', - offlineNoCacheBanner: 'Keine Serververbindung — {{server}} nicht erreichbar', - offlineLibraryTitle: 'Offline-Bibliothek', - offlineLibraryEmpty: 'Noch keine Alben gecacht. Online gehen, Album öffnen und "Offline verfügbar machen" klicken.', - offlineAlbumCount: '{{n}} Album', - offlineAlbumCount_plural: '{{n}} Alben', - offlineFilterAll: 'Alle', - offlineFilterAlbums: 'Alben', - offlineFilterPlaylists: 'Playlists', - offlineFilterArtists: 'Diskografien', - retry: 'Erneut versuchen', - serverSettings: 'Server-Einstellungen', - switchServerTitle: 'Server wechseln', - switchServerHint: 'Klicken, um einen anderen gespeicherten Server zu wählen.', - manageServers: 'Server verwalten…', - switchFailed: 'Wechsel fehlgeschlagen — Server nicht erreichbar.', - lastfmConnected: 'Last.fm verbunden als @{{user}}', - lastfmSessionInvalid: 'Session ungültig — klicken zum Neu-Verbinden', - }, - common: { - albums: 'Alben', - album: 'Album', - loading: 'Lade…', - loadingMore: 'Lade…', - loadingPlaylists: 'Lade Playlists…', - noAlbums: 'Keine Alben gefunden.', - downloading: 'Lade…', - downloadZip: 'Download (ZIP)', - back: 'Zurück', - cancel: 'Abbrechen', - close: 'Schließen', - save: 'Speichern', - delete: 'Löschen', - use: 'Verwenden', - add: 'Hinzufügen', - new: 'Neu', - active: 'Aktiv', - download: 'Herunterladen', - chooseDownloadFolder: 'Download-Ordner wählen', - noFolderSelected: 'Kein Ordner ausgewählt', - rememberDownloadFolder: 'Ordner merken', - filterGenre: 'Genre-Filter', - filterSearchGenres: 'Genres suchen…', - filterNoGenres: 'Keine Genres gefunden', - filterClear: 'Zurücksetzen', - favorites: 'Favoriten', - favoritesTooltipOff: 'Nur Favoriten anzeigen', - favoritesTooltipOn: 'Alle anzeigen', - play: 'Abspielen', - bulkSelected: '{{count}} ausgewählt', - clearSelection: 'Auswahl aufheben', - bulkAddToPlaylist: 'Zur Playlist hinzufügen', - bulkRemoveFromPlaylist: 'Aus Playlist entfernen', - bulkClear: 'Auswahl aufheben', - updaterAvailable: 'Update verfügbar', - updaterVersion: 'v{{version}} verfügbar', - updaterWebsite: 'Website', - updaterModalTitle: 'Neue Version verfügbar', - updaterChangelog: 'Was ist neu', - updaterDownloadBtn: 'Jetzt herunterladen', - updaterSkipBtn: 'Version überspringen', - updaterRemindBtn: 'Später erinnern', - updaterDone: 'Download abgeschlossen', - updaterShowFolder: 'Im Ordner anzeigen', - updaterInstallHint: 'Psysonic schließen und das Installationsprogramm manuell ausführen.', - updaterAurHint: 'Update über AUR installieren:', - updaterErrorMsg: 'Download fehlgeschlagen', - updaterInstallNow: 'Jetzt installieren', - updaterMacReadyTitle: 'Bereit zur Installation', - updaterMacReady: 'Das Update wird heruntergeladen, verifiziert und direkt übernommen — keine DMG nötig. Die App startet anschließend automatisch neu.', - updaterTrustNotarized: 'Von Apple beglaubigt', - updaterTrustSignature: 'Signatur verifiziert', - updaterMacDoneTitle: 'Update installiert', - updaterRestartingIn: 'Neustart in {{n}}s …', - updaterRestarting: 'Neustart läuft …', - updaterRestartNow: 'Jetzt neu starten', - updaterRetryBtn: 'Erneut versuchen', - durationHoursMinutes: '{{hours}} Std. {{minutes}} Min.', - durationMinutesOnly: '{{minutes}} Min.', - updaterOpenGitHub: 'Auf GitHub öffnen', - filters: 'Filter', - more: 'mehr', - yearRange: 'Jahresbereich', - clearAll: 'Alles zurücksetzen', - }, - settings: { - title: 'Einstellungen', - language: 'Sprache', - languageEn: 'English', - languageDe: 'Deutsch', - languageEs: 'Español', - languageFr: 'Français', - languageNl: 'Nederlands', - languageNb: 'Norsk', - languageRu: 'Русский', - languageZh: '中文', - languageRo: 'Română', - font: 'Schriftart', - fontHintOpenDyslexic: 'Legasthenie-freundlich · keine Chinesisch-Unterstützung', - theme: 'Design', - appearance: 'Darstellung', - servers: 'Server', - serverName: 'Server-Name', - serverUrl: 'Server-URL', - serverUrlPlaceholder: '192.168.1.100:4533 oder https://music.example.com', - serverUsername: 'Benutzername', - serverPassword: 'Passwort', - addServer: 'Server hinzufügen', - addServerTitle: 'Neuen Server hinzufügen', - useServer: 'Verwenden', - deleteServer: 'Löschen', - noServers: 'Keine Server gespeichert.', - serverActive: 'Aktiv', - confirmDeleteServer: 'Server „{{name}}" löschen?', - serverConnecting: 'Verbinde…', - serverConnected: 'Verbunden!', - serverFailed: 'Verbindung fehlgeschlagen.', - testBtn: 'Verbindung testen', - testingBtn: 'Teste…', - serverCompatible: 'Für Navidrome entwickelt. Andere Subsonic-kompatible Server (Gonic, Airsonic, …) funktionieren ggf. eingeschränkt, weil Psysonic viele Navidrome-spezifische API-Endpunkte nutzt.', - userMgmtTitle: 'Benutzerverwaltung', - userMgmtDesc: 'Benutzer auf diesem Server verwalten. Erfordert Admin-Rechte.', - userMgmtNoAdmin: 'Du brauchst Admin-Rechte, um Benutzer auf diesem Server zu verwalten.', - userMgmtLoadError: 'Benutzer konnten nicht geladen werden.', - userMgmtLoadFriendly: 'Server hat nicht geantwortet — meistens ein Einzelfall.', - userMgmtRetry: 'Erneut versuchen', - userMgmtEmpty: 'Keine Benutzer gefunden.', - userMgmtYouBadge: 'Du', - userMgmtAdminBadge: 'Admin', - userMgmtAddUser: 'Benutzer hinzufügen', - userMgmtAddUserTitle: 'Neuen Benutzer anlegen', - userMgmtEditUserTitle: 'Benutzer bearbeiten', - userMgmtUsername: 'Benutzername', - userMgmtName: 'Anzeigename', - userMgmtEmail: 'E-Mail', - userMgmtPassword: 'Passwort', - userMgmtPasswordEditHint: 'Neues Passwort eingeben, um es zu ändern.', - userMgmtRoleAdmin: 'Admin', - userMgmtLibraries: 'Bibliotheken', - userMgmtLibrariesAdminHint: 'Admin-Benutzer haben automatisch Zugriff auf alle Bibliotheken.', - userMgmtLibrariesEmpty: 'Keine Bibliotheken auf diesem Server vorhanden.', - userMgmtLibrariesValidation: 'Mindestens eine Bibliothek auswählen.', - userMgmtLibrariesUpdateError: 'Benutzer gespeichert, aber Bibliothekszuweisung fehlgeschlagen', - userMgmtNoLibraries: 'Keine Bibliotheken zugewiesen', - userMgmtNeverSeen: 'Nie', - userMgmtSave: 'Speichern', - userMgmtCancel: 'Abbrechen', - userMgmtDelete: 'Löschen', - userMgmtEdit: 'Bearbeiten', - userMgmtConfirmDelete: 'Benutzer „{{username}}" löschen? Das kann nicht rückgängig gemacht werden.', - userMgmtCreateError: 'Benutzer konnte nicht angelegt werden.', - userMgmtUpdateError: 'Benutzer konnte nicht aktualisiert werden.', - userMgmtDeleteError: 'Benutzer konnte nicht gelöscht werden.', - userMgmtCreated: 'Benutzer angelegt.', - userMgmtUpdated: 'Benutzer aktualisiert.', - userMgmtDeleted: 'Benutzer gelöscht.', - userMgmtValidationMissing: 'Benutzername, Anzeigename und Passwort sind erforderlich.', - userMgmtValidationMissingIdentity: 'Benutzername und Anzeigename sind erforderlich.', - userMgmtMagicStringGenerate: 'Magic-String erzeugen', - userMgmtSaveAndMagicString: 'Speichern und Magic-String kopieren', - userMgmtMagicStringPasswordNavHint: - 'Navidrome speichert dieses Passwort für den Benutzer. Weicht es vom aktuellen ab, wird das Anmeldepasswort auf dem Server aktualisiert.', - userMgmtMagicStringPlaintextWarning: - 'Teilen Sie den Magic-String vorsichtig: Er enthält das Passwort im Klartext (Kodierung ist keine Verschlüsselung). Wer die vollständige Zeichenkette hat, kann sich als dieser Benutzer anmelden.', - userMgmtMagicStringCopied: 'Magic-String in die Zwischenablage kopiert.', - userMgmtMagicStringCopyFailed: 'Kopieren in die Zwischenablage fehlgeschlagen.', - userMgmtMagicStringLoginFailed: 'Passwortprüfung fehlgeschlagen — Anmeldedaten konnten nicht verifiziert werden.', - userMgmtMagicStringModalTitle: 'Magic-String erzeugen', - userMgmtMagicStringModalDesc: 'Subsonic-Passwort für „{{username}}" eingeben — es wird in den kopierten Magic-String übernommen.', - userMgmtMagicStringModalConfirm: 'String kopieren', - audiomuseTitle: 'AudioMuse-AI (Navidrome)', - audiomuseDesc: - 'Aktivieren, wenn dieser Server das AudioMuse-AI-Navidrome-Plugin nutzt. Schaltet Instant Mix pro Titel frei und nutzt ähnliche Künstler vom Server statt Last.fm auf Künstlerseiten.', - audiomuseIssueHint: - 'Instant Mix ist kürzlich fehlgeschlagen — Navidrome-Plugin und AudioMuse-API prüfen. Ohne Server-Treffer werden ähnliche Künstler über Last.fm geladen.', - connected: 'Verbunden', - failed: 'Fehlgeschlagen', - eqTitle: 'Equalizer', - eqEnabled: 'Equalizer aktivieren', - eqPreset: 'Preset', - eqPresetCustom: 'Benutzerdefiniert', - eqPresetBuiltin: 'Eingebaute Presets', - eqPresetCustomGroup: 'Meine Presets', - eqSavePreset: 'Als Preset speichern', - eqPresetName: 'Preset-Name…', - eqDeletePreset: 'Preset löschen', - eqResetBands: 'Auf Flat zurücksetzen', - eqPreGain: 'Vorverstärkung', - eqResetPreGain: 'Vorverstärkung zurücksetzen', - eqAutoEqTitle: 'AutoEQ Kopfhörer-Suche', - eqAutoEqPlaceholder: 'Kopfhörer / IEM Modell suchen…', - eqAutoEqSearching: 'Suche…', - eqAutoEqNoResults: 'Keine Ergebnisse gefunden', - eqAutoEqError: 'Suche fehlgeschlagen', - eqAutoEqRateLimit: 'GitHub Rate-Limit erreicht — in einer Minute erneut versuchen', - eqAutoEqFetchError: 'EQ-Profil konnte nicht geladen werden', - lfmTitle: 'Last.fm', - lfmConnect: 'Mit Last.fm verbinden', - lfmConnecting: 'Warte auf Bestätigung…', - lfmConfirm: 'Ich habe die App autorisiert', - lfmConnected: 'Verbunden als', - lfmDisconnect: 'Trennen', - lfmConnectDesc: 'Verbinde deinen Last.fm Account, um Scrobbling und Now-Playing-Updates direkt aus Psysonic heraus zu aktivieren — keine Navidrome-Konfiguration erforderlich.', - lfmOpenBrowser: 'Es öffnet sich ein Browserfenster. Autorisiere Psysonic auf Last.fm und klicke dann unten auf den Button.', - lfmScrobbles: '{{n}} Scrobbles', - lfmMemberSince: 'Dabei seit {{year}}', - scrobbleEnabled: 'Scrobbling aktiviert', - scrobbleDesc: 'Songs nach 50% Laufzeit an Last.fm senden', - behavior: 'App-Verhalten', - cacheTitle: 'Max. Speichergröße', - cacheDesc: 'Cover und Künstlerbilder. Wenn voll, werden die ältesten Einträge automatisch entfernt. Offline-Alben werden nicht automatisch gelöscht, aber beim manuellen Cache leeren entfernt.', - cacheUsedImages: 'Bilder:', - cacheUsedOffline: 'Offline-Tracks:', - cacheUsedHot: 'Belegter Speicher:', - hotCacheTrackCount: 'Titel im Cache:', - cacheMaxLabel: 'Max. Größe', - cacheClearBtn: 'Cache leeren', - cacheClearWarning: 'Alle Offline-Alben werden damit aus der Bibliothek entfernt.', - cacheClearConfirm: 'Alles löschen', - cacheClearCancel: 'Abbrechen', - offlineDirTitle: 'Offline-Bibliothek (In-App)', - offlineDirDesc: 'Speicherort für Titel, die du innerhalb von Psysonic offline verfügbar machst.', - offlineDirDefault: 'Standard (App-Daten)', - offlineDirChange: 'Verzeichnis ändern', - offlineDirClear: 'Auf Standard zurücksetzen', - offlineDirHint: 'Neue Downloads werden an diesem Ort gespeichert. Bestehende Downloads verbleiben am ursprünglichen Pfad.', - hotCacheTitle: 'Hot-Playback-Cache', - hotCacheDisclaimer: 'Lädt kommende Warteschlangen-Titel vor und behält zuletzt gespielte. Bei aktivierter Option: Speicherplatz und Netzwerk.', - hotCacheDirDefault: 'Standard (App-Daten)', - hotCacheDirChange: 'Ordner ändern', - hotCacheDirClear: 'Auf Standard zurücksetzen', - hotCacheDirHint: 'Beim Ordnerwechsel wird der App-Index zurückgesetzt; alte Dateien bleiben am alten Ort, bis Sie sie löschen.', - hotCacheEnabled: 'Hot-Playback-Cache aktivieren', - hotCacheMaxMb: 'Maximale Cache-Größe', - hotCacheDebounce: 'Debounce bei Warteschlangen-Änderungen', - hotCacheDebounceImmediate: 'Sofort', - hotCacheDebounceSeconds: '{{n}} s', - hotCacheClearBtn: 'Hot-Cache leeren', - audioOutputDevice: 'Audio-Ausgabegerät', - audioOutputDeviceDesc: 'Wähle das Audiogerät, über das Psysonic spielt. Änderungen werden sofort übernommen und starten den aktuellen Track neu.', - audioOutputDeviceDefault: 'Systemstandard', - audioOutputDeviceRefresh: 'Geräteliste aktualisieren', - audioOutputDeviceOsDefaultNow: 'aktuelle Systemausgabe', - audioOutputDeviceListError: 'Audiogeräteliste konnte nicht geladen werden.', - audioOutputDeviceNotInCurrentList: 'nicht in der aktuellen Liste', - audioOutputDeviceMacNotice: 'Auf macOS folgt die Wiedergabe aus technischen Gründen zurzeit immer dem System-Ausgabegerät. Du kannst das Ziel über Systemeinstellungen → Ton oder das Lautsprecher-Symbol in der Menüleiste wechseln. Hintergrund: CoreAudio löst beim Öffnen eines nicht-Default-Streams eine Mikrofonberechtigungsabfrage aus — wir vermeiden sie, indem wir stets den System-Default verwenden.', - hiResTitle: 'Native Hi-Res-Wiedergabe', - hiResEnabled: 'Native Hi-Res-Wiedergabe aktivieren', - hiResDesc: "Standardmäßig wird auf 44,1 kHz begrenzt (maximale Stabilität). Nur aktivieren, wenn Hardware und Netzwerk zuverlässig hohe Abtastraten (88,2 kHz+) unterstützen.", - showArtistImages: 'Künstlerbilder anzeigen', - showArtistImagesDesc: 'Lädt und zeigt Künstlerbilder in der Künstlerübersicht. Standardmäßig deaktiviert, um Server-I/O und Netzwerklast bei großen Bibliotheken zu reduzieren.', - showOrbitTrigger: '„Orbit" im Header zeigen', - showOrbitTriggerDesc: 'Der Kopfzeilen-Button zum Starten oder Beitreten einer gemeinsamen Hör-Session. Ausblenden, wenn du Orbit nicht nutzt — hier lässt er sich jederzeit wieder einschalten.', - showTrayIcon: 'Tray-Icon anzeigen', - showTrayIconDesc: 'Psysonic-Icon im System-Tray / in der Menüleiste anzeigen.', - minimizeToTray: 'Im Tray minimieren', - minimizeToTrayDesc: 'Beim Schließen des Fensters läuft Psysonic weiter im System-Tray statt zu beenden.', - preloadMiniPlayer: 'Mini-Player vorladen', - preloadMiniPlayerDesc: 'Baut das Mini-Player-Fenster beim App-Start im Hintergrund auf, damit es beim ersten Öffnen sofort Inhalt zeigt. Kostet etwas mehr RAM.', - discordRichPresence: 'Discord Rich Presence', - discordRichPresenceDesc: 'Zeigt den aktuell gespielten Titel im Discord-Profil an. Discord muss dafür geöffnet sein.', - useCustomTitlebar: 'Eigene Titelleiste', - useCustomTitlebarDesc: 'Ersetzt die System-Titelleiste durch eine eingebaute, die zum App-Theme passt. Deaktivieren, um die native GNOME/GTK-Titelleiste zu verwenden.', - linuxWebkitSmoothScroll: 'Sanftes Mausrad (Linux)', - linuxWebkitSmoothScrollDesc: 'An: mit Nachlauf. Aus: zeilenweise wie in GTK-Apps.', - discordCoverSource: 'Cover-Quelle', - discordCoverSourceDesc: 'Woher das Album-Cover für dein Discord-Profil geladen wird.', - discordCoverNone: 'Keine (nur App-Symbol)', - discordCoverServer: 'Server (über Album-Info)', - discordCoverApple: 'Apple Music', - discordOptions: 'Erweiterte Discord-Optionen', - discordTemplates: 'Benutzerdefinierte Textvorlagen', - discordTemplatesDesc: 'Passen Sie an, welche Informationen in Ihrem Discord-Profil angezeigt werden. Variablen: {title}, {artist}, {album}', - discordTemplateDetails: 'Primäre Zeile (details)', - discordTemplateState: 'Sekundäre Zeile (state)', - discordTemplateLargeText: 'Album-Tooltip (largeText)', - nowPlayingEnabled: 'Im Livefenster anzeigen', - nowPlayingEnabledDesc: 'Überträgt den aktuell gespielten Titel an die Livehörer-Ansicht des Servers. Deaktivieren, um keine Wiedergabedaten zu senden.', - enableBandsintown: 'Bandsintown-Tourdaten', - enableBandsintownDesc: 'Zeigt anstehende Konzerte des aktuellen Künstlers im Info-Tab. Daten werden über die öffentliche Bandsintown-API abgerufen.', - lyricsServerFirst: 'Server-Lyrics bevorzugen', - lyricsServerFirstDesc: 'Server-seitige Lyrics (eingebettete Tags, Sidecar-Dateien) vor LRCLIB abfragen. Deaktivieren, um LRCLIB zuerst zu verwenden.', - enableNeteaselyrics: 'Netease Cloud Music Lyrics', - enableNeteaselyricsDesc: 'Netease Cloud Music als letzte Lyrics-Quelle verwenden, wenn Server und LRCLIB nichts liefern. Besonders gut für asiatische und internationale Musik.', - lyricsSourcesTitle: 'Lyrics-Quellen', - lyricsSourcesDesc: 'Wähle, welche Quellen für Lyrics abgefragt werden und in welcher Reihenfolge. Ziehen zum Sortieren. Deaktivierte Quellen werden übersprungen.', - lyricsSourceServer: 'Server', - lyricsSourceLrclib: 'LRCLIB', - lyricsSourceNetease: 'Netease Cloud Music', - lyricsModeStandard: 'Standard', - lyricsModeStandardDesc: 'Drei Quellen mit frei wählbarer Reihenfolge: Server-Tags, LRCLIB, Netease.', - lyricsModeLyricsplus: 'YouLyPlus (Karaoke)', - lyricsModeLyricsplusDesc: 'Wort-für-Wort-Sync aus Apple Music, Spotify, Musixmatch & QQ (Community-Backend). Fällt still zurück auf die Standard-Quellen, wenn nichts gefunden wird.', - lyricsStaticOnly: 'Nur statische Lyrics anzeigen', - lyricsStaticOnlyDesc: 'Synchronisierte Lyrics werden ohne Auto-Scroll und ohne Wort-Hervorhebung als statischer Text dargestellt.', - downloadsTitle: 'ZIP-Export & Archivierung', - downloadsFolderDesc: 'Zielverzeichnis für Alben, die du als ZIP-Datei auf deinen Computer herunterlädst.', - downloadsDefault: 'Standard-Downloads-Ordner', - pickFolder: 'Auswählen', - pickFolderTitle: 'Download-Ordner auswählen', - clearFolder: 'Download-Ordner löschen', - logout: 'Abmelden', - aboutTitle: 'Über Psysonic', - aboutDesc: 'Ein moderner Desktop-Musikplayer für Navidrome. Nutzt die Subsonic-API plus Navidrome-spezifische Erweiterungen. Basiert auf Tauri v2 mit einer nativen Rust-Audio-Engine — schlank und schnell, aber vollgepackt mit Features: Wellenform-Seekbar, synchronisierte Lyrics, Last.fm-Integration, 10-Band-EQ, Crossfade, nahtlose Wiedergabe, Replay Gain, Genre-Browser und eine große Theme-Bibliothek.', - aboutLicense: 'Lizenz', - aboutLicenseText: 'GNU GPL v3 — kostenlos nutzbar, veränderbar und unter gleicher Lizenz weiterzugeben.', - aboutRepo: 'Quellcode auf GitHub', - aboutVersion: 'Version', - aboutBuiltWith: 'Gebaut mit Tauri · React · TypeScript · Rust/rodio', - aboutMaintainersLabel: 'Projektleitung', - aboutReleaseNotesLabel: 'Release Notes', - aboutReleaseNotesLink: 'Neuigkeiten dieser Version öffnen', - aboutContributorsLabel: 'Mitwirkende', - showChangelogOnUpdate: "'Was ist neu' bei Update anzeigen", - showChangelogOnUpdateDesc: 'Blendet nach einem Update einen dezenten Changelog-Banner über Now Playing ein. Klick öffnet die Release Notes, X blendet ihn aus.', - randomMixTitle: 'Zufallsmix-Blacklist', - luckyMixMenuTitle: 'Glücks-Mix im Menü anzeigen', - luckyMixMenuDesc: 'Aktiviert Glücks-Mix im "Mix erstellen"-Hub und als separaten Menüeintrag bei getrennter Navigation. Sichtbar nur bei aktiviertem AudioMuse auf dem aktiven Server.', - randomMixBlacklistTitle: 'Eigene Filter-Keywords', - randomMixBlacklistDesc: 'Songs werden ausgeschlossen, wenn ein Keyword auf Genre, Titel, Album oder Künstler zutrifft (aktiv wenn die Checkbox oben an ist).', - randomMixBlacklistPlaceholder: 'Keyword hinzufügen…', - randomMixBlacklistAdd: 'Hinzufügen', - randomMixBlacklistEmpty: 'Noch keine eigenen Keywords hinzugefügt.', - randomMixHardcodedTitle: 'Eingebaute Keywords (aktiv wenn Checkbox an)', - tabAudio: 'Audio', - tabStorage: 'Offline & Cache', - tabAppearance: 'Darstellung', - tabLibrary: 'Bibliothek', - tabServers: 'Server', - tabLyrics: 'Songtexte', - tabPersonalisation: 'Personalisierung', - tabIntegrations: 'Integrationen', - inputKeybindingsTitle: 'Tastenkombinationen', - aboutContributorsCount_one: '{{count}} Beitrag', - aboutContributorsCount_other: '{{count}} Beiträge', - searchPlaceholder: 'Einstellungen durchsuchen…', - searchNoResults: 'Keine Treffer für deine Suche.', - integrationsPrivacyTitle: 'Hinweis zum Datenschutz', - integrationsPrivacyBody: 'Alle Integrationen auf diesem Tab sind Opt-in und senden, sobald aktiviert, Daten an externe Dienste oder an deinen Navidrome-Server. Last.fm erhält deinen Wiedergabeverlauf, Discord zeigt den aktuell laufenden Track in deinem Profil an, Bandsintown wird pro Künstler für Tour-Daten abgefragt, und der „Jetzt läuft"-Hinweis veröffentlicht deinen aktuellen Titel für andere Benutzer deines Navidrome-Servers. Wer das nicht möchte, lässt den jeweiligen Abschnitt einfach deaktiviert.', - homeCustomizerTitle: 'Startseite', - queueToolbarTitle: 'Warteschlangen-Toolbar', - queueToolbarReset: 'Zurücksetzen', - queueToolbarSeparator: 'Trennlinie', - sidebarTitle: 'Seitenleiste', - sidebarReset: 'Zurücksetzen', - artistLayoutTitle: 'Künstlerseiten-Abschnitte', - artistLayoutDesc: 'Per Drag & Drop neu anordnen, einzelne Abschnitte der Künstlerseite ein- oder ausblenden. Abschnitte ohne Daten werden automatisch übersprungen.', - artistLayoutReset: 'Zurücksetzen', - artistLayoutBio: 'Künstler-Biografie', - artistLayoutTopTracks: 'Top-Tracks', - artistLayoutSimilar: 'Ähnliche Künstler*innen', - artistLayoutAlbums: 'Alben', - artistLayoutFeatured: 'Auch enthalten auf', - sidebarDrag: 'Ziehen zum Umsortieren', - sidebarFixed: 'Immer sichtbar', - randomNavSplitTitle: 'Mix-Navigation aufteilen', - randomNavSplitDesc: '"Zufallsmix", "Zufallsalben" und "Glücks-Mix" als separate Sidebar-Einträge statt als "Mix erstellen"-Hub anzeigen.', - tabInput: 'Eingabe', - tabUsers: 'Benutzer', - shortcutsReset: 'Auf Standard zurücksetzen', - shortcutListening: 'Taste drücken…', - shortcutUnbound: '—', - shortcutClear: 'Löschen', - globalShortcutsTitle: 'Globale Shortcuts', - globalShortcutsNote: 'Funktionieren systemweit, auch wenn Psysonic im Hintergrund läuft. Mindestens Ctrl, Alt oder Super als Modifier erforderlich.', - shortcutPlayPause: 'Wiedergabe / Pause', - shortcutNext: 'Nächster Titel', - shortcutPrev: 'Vorheriger Titel', - shortcutVolumeUp: 'Lautstärke erhöhen', - shortcutVolumeDown: 'Lautstärke verringern', - shortcutSeekForward: '10s vorspulen', - shortcutSeekBackward: '10s zurückspulen', - shortcutToggleQueue: 'Warteschlange ein-/ausblenden', - shortcutOpenFolderBrowser: '{{folderBrowser}} öffnen', - shortcutFullscreenPlayer: 'Vollbild-Player', - shortcutNativeFullscreen: 'Nativer Vollbildmodus', - shortcutOpenMiniPlayer: 'Mini-Player öffnen', - shortcutStartSearch: 'Suche starten', - shortcutStartAdvancedSearch: 'Erweiterte Suche starten', - shortcutToggleSidebar: 'Seitenleiste umschalten', - shortcutMuteSound: 'Stumm schalten', - shortcutToggleEqualizer: 'Equalizer öffnen / umschalten', - shortcutToggleRepeat: 'Wiederholen umschalten', - shortcutOpenNowPlaying: '„Now Playing" öffnen', - shortcutShowLyrics: 'Songtexte anzeigen', - shortcutFavoriteCurrentTrack: 'Aktuellen Titel zu Favoriten hinzufügen', - shortcutOpenHelp: 'Hilfe', - tabSystem: 'System', - loggingTitle: 'Protokollierung', - loggingModeDesc: 'Steuert die Ausführlichkeit der Backend-Protokolle im Terminal.', - loggingModeOff: 'Aus', - loggingModeNormal: 'Normal', - loggingModeDebug: 'Debug', - loggingExport: 'Protokolle exportieren', - loggingExportSuccess: 'Protokolle exportiert ({{count}} Zeilen).', - loggingExportError: 'Protokolle konnten nicht exportiert werden.', - ratingsSectionTitle: 'Bewertungen', - ratingsSkipStarTitle: 'Skip → 1 Stern', - ratingsSkipStarDesc: - 'Wird ein Titel mehrmals hintereinander übersprungen, bekommt er automatisch 1★. Nur für noch nicht bewertete Titel.', - ratingsSkipStarThresholdLabel: 'Skips', - ratingsMixFilterTitle: 'Nach Bewertung filtern', - ratingsMixFilterDesc: - 'Gering bewertete Titel in {{mix}} und {{albums}} ausblenden. Nochmals auf den gewählten Stern klicken, um den Filter zu deaktivieren.', - ratingsMixMinSong: 'Titel', - ratingsMixMinAlbum: 'Alben', - ratingsMixMinArtist: 'Interpreten', - ratingsMixMinThresholdAria: 'Mindest-Sterne: {{label}}', - backupTitle: 'Backup & Wiederherstellung', - backupExport: 'Einstellungen exportieren', - backupExportDesc: 'Speichert alle Einstellungen, Serverprofile, Last.fm-Konfiguration, Theme, EQ und Tastenkürzel in eine .psybkp-Datei. Passwörter werden im Klartext gespeichert — Datei sicher aufbewahren.', - backupImport: 'Einstellungen importieren', - backupImportDesc: 'Stellt Einstellungen aus einer .psybkp-Datei wieder her. Die App wird nach dem Import neu geladen.', - backupImportConfirm: 'Alle aktuellen Einstellungen werden überschrieben. Fortfahren?', - backupSuccess: 'Backup gespeichert', - backupImportSuccess: 'Einstellungen wiederhergestellt — wird neu geladen…', - backupImportError: 'Ungültige oder beschädigte Backup-Datei.', - playbackTitle: 'Wiedergabe', - replayGain: 'Replay Gain', - replayGainDesc: 'Lautstärke mit ReplayGain-Metadaten normalisieren', - replayGainMode: 'Modus', - replayGainAuto: 'Auto', - replayGainAutoDesc: 'Wählt Album-Gain, wenn benachbarte Tracks in der Warteschlange vom selben Album sind, sonst Track-Gain.', - replayGainTrack: 'Track', - replayGainAlbum: 'Album', - replayGainPreGain: 'Pre-Gain (getaggte Dateien)', - replayGainPreGainDesc: 'Pauschaler Boost, der auf jede ReplayGain-Berechnung aufaddiert wird. Hilft, wenn deine Bibliothek insgesamt zu leise wirkt.', - replayGainFallback: 'Fallback (ohne Tags / Radio)', - replayGainFallbackDesc: 'Wird auf Titel (und Radio-Streams) ohne ReplayGain-Tags angewendet, damit Untagged-Inhalt nicht lauter aus dem Mix springt.', - normalization: 'Normalisierung', - normalizationDesc: 'Empfundene Lautstärke über Titel, Alben und Radio angleichen.', - normalizationOff: 'Aus', - normalizationReplayGain: 'ReplayGain', - normalizationLufs: 'LUFS', - loudnessTargetLufs: 'Ziel-LUFS', - loudnessTargetLufsDesc: 'Referenz-Lautstärke, an die alle Titel angepasst werden. Niedrigere Werte = lautere Ausgabe. Streaming-Dienste liegen meist bei etwa -14 LUFS.', - loudnessPreAnalysisAttenuation: 'Dämpfung vor Messung', - loudnessPreAnalysisAttenuationDesc: - 'Zusätzliche Dämpfung, bis die Loudness des Titels gespeichert ist. Beim Streamen folgen nur grobe Schätzungen, keine volle Messung. 0 dB = aus; negativer = leiser. Rechts steht der wirksame dB-Wert für die gewählte Ziel-LUFS.', - loudnessPreAnalysisAttenuationRef: 'Wirksam {{eff}} dB bei Ziel {{tgt}} LUFS.', - loudnessPreAnalysisAttenuationReset: 'Standard', - loudnessFirstPlayNote: - 'Beim ersten Abspielen eines neuen Titels kann die Lautstärke kurz schwanken, während gemessen wird. Beim nächsten Mal greift die gespeicherte Messung und alles bleibt stabil. Kommende Queue-Titel werden meist schon während des vorherigen Songs analysiert — in der Praxis tritt das daher selten auf.', - crossfade: 'Crossfade', - crossfadeDesc: 'Überblendung zwischen Tracks', - crossfadeSecs: '{{n}} s', - notWithGapless: 'Nicht verfügbar wenn Nahtlose Wiedergabe aktiv ist', - notWithCrossfade: 'Nicht verfügbar wenn Crossfade aktiv ist', - gapless: 'Nahtlose Wiedergabe', - gaplessDesc: 'Nächsten Track vorpuffern um Lücken zwischen Songs zu vermeiden', - preservePlayNextOrder: '„Als Nächstes"-Reihenfolge bewahren', - preservePlayNextOrderDesc: 'Neu hinzugefügte „Als Nächstes"-Titel reihen sich hinten an statt sich vorn einzuschieben.', - trackPreviewsTitle: 'Track-Vorschau', - trackPreviewsToggle: 'Track-Vorschau aktivieren', - trackPreviewsDesc: 'Inline Play- und Vorschau-Buttons in den Tracklisten anzeigen für eine kurze Hörprobe mitten im Song.', - trackPreviewStart: 'Startposition', - trackPreviewStartDesc: 'Wie weit der Track schon gespielt sein soll wenn die Vorschau startet (% der Länge).', - trackPreviewDuration: 'Dauer', - trackPreviewDurationDesc: 'Wie lange jede Vorschau spielt bevor sie automatisch stoppt.', - trackPreviewDurationSecs: '{{n}} s', - trackPreviewLocationsTitle: 'Wo Vorschauen erscheinen', - trackPreviewLocationsDesc: 'Wähle aus, in welchen Listen die Vorschau-Buttons angezeigt werden.', - trackPreviewLocation_suggestions: 'In Playlist-Vorschlägen', - trackPreviewLocation_albums: 'In Album-Tracklisten', - trackPreviewLocation_playlists: 'In Playlists', - trackPreviewLocation_favorites: 'In Favoriten', - trackPreviewLocation_artist: 'In Künstler-Top-Tracks', - trackPreviewLocation_randomMix: 'In Random Mix', - preloadMode: 'Nächsten Track vorpuffern', - preloadModeDesc: 'Wann mit dem Puffern des nächsten Tracks begonnen werden soll', - nextTrackBufferingTitle: 'Pufferung', - preloadHotCacheMutualExclusive: 'Preload und Hot Cache erfüllen denselben Zweck – nur eine Methode kann gleichzeitig aktiv sein. Das Aktivieren einer deaktiviert die andere automatisch.', - preloadOff: 'Aus', - preloadBalanced: 'Ausgewogen (30 s vor Ende)', - preloadEarly: 'Früh (nach 5 s Wiedergabe)', - preloadCustom: 'Benutzerdefiniert', - preloadCustomSeconds: 'Sekunden vor Ende: {{n}}', - infiniteQueue: 'Endlose Warteschlange', - infiniteQueueDesc: 'Automatisch Zufallstitel anhängen wenn die Warteschlange leer wird', - experimental: 'Experimentell', - fsPlayerSection: 'Vollbild-Player', - fsShowArtistPortrait: 'Künstlerfoto anzeigen', - fsShowArtistPortraitDesc: 'Künstlerfoto (oder Albumcover) auf der rechten Seite des Vollbild-Players anzeigen.', - fsPortraitDim: 'Abdunkelung des Fotos', - fsLyricsStyle: 'Liedtext-Stil', - fsLyricsStyleRail: 'Schiene', - fsLyricsStyleRailDesc: 'Klassische 5-Zeilen-Schiene.', - fsLyricsStyleApple: 'Scrollen', - fsLyricsStyleAppleDesc: 'Vollbild-Scrollliste.', - sidebarLyricsStyle: 'Text-Scroll-Stil', - sidebarLyricsStyleClassic: 'Klassisch', - sidebarLyricsStyleClassicDesc: 'Aktive Zeile wird zentriert.', - sidebarLyricsStyleApple: 'Apple Music-like', - sidebarLyricsStyleAppleDesc: 'Aktive Zeile oben mit sanfter Animation.', - seekbarStyle: 'Seekbar-Stil', - seekbarStyleDesc: 'Aussehen der Wiedergabe-Seekbar auswählen', - seekbarTruewave: 'Echte Wellenform', - seekbarPseudowave: 'Pseudo-Wellenform', - seekbarLinedot: 'Linie & Punkt', - seekbarBar: 'Balken', - seekbarThick: 'Dicker Balken', - seekbarSegmented: 'Segmentiert', - seekbarNeon: 'Neonröhre', - seekbarPulsewave: 'Pulswelle', - seekbarParticletrail: 'Partikel-Spur', - seekbarLiquidfill: 'Flüssigkeit', - seekbarRetrotape: 'Retro-Band', - themeSchedulerTitle: 'Theme-Zeitplan', - themeSchedulerEnable: 'Theme-Zeitplan aktivieren', - themeSchedulerEnableSub: 'Wechselt automatisch zwischen zwei Themes basierend auf der Uhrzeit', - themeSchedulerDayTheme: 'Tages-Theme', - themeSchedulerDayStart: 'Tag beginnt um', - themeSchedulerNightTheme: 'Nacht-Theme', - themeSchedulerNightStart: 'Nacht beginnt um', - themeSchedulerActiveHint: 'Theme-Zeitplan ist aktiv - Themes werden automatisch gewechselt.', - visualOptionsTitle: 'Visuelle Optionen', - coverArtBackground: 'Cover-Hintergrund', - coverArtBackgroundSub: 'Zeigt verschwommenes Cover als Hintergrund in Album/Playlist-Kopfzeilen', - playlistCoverPhoto: 'Playlist-Coverfoto', - playlistCoverPhotoSub: 'Zeigt Coverfoto-Raster in der Playlist-Detailansicht', - showBitrate: 'Bitrate anzeigen', - showBitrateSub: 'Audio-Bitrate in Track-Listen anzeigen', - floatingPlayerBar: 'Schwebende Player-Leiste', - floatingPlayerBarSub: 'Player-Leiste über dem Inhalt schweben lassen', - uiScaleTitle: 'Interface-Skalierung', - uiScaleLabel: 'Zoom', - }, - changelog: { - modalTitle: 'Was ist neu', - dontShowAgain: 'Nicht mehr anzeigen', - close: 'Verstanden', - }, - whatsNew: { - title: 'Was ist neu', - empty: 'Für diese Version liegt noch kein Changelog-Eintrag vor.', - bannerTitle: 'Changelog', - bannerCollapsed: 'Neu in v{{version}}', - dismiss: 'Ausblenden', - close: 'Schließen', - }, - help: { - title: 'Hilfe', - searchPlaceholder: 'Hilfe durchsuchen…', - noResults: 'Keine passenden Themen. Versuche einen anderen Suchbegriff.', - // ── Section 1: Erste Schritte ────────────────────────────────────────── - s1: 'Erste Schritte', - q1: 'Welche Server sind kompatibel?', - a1: 'Psysonic ist primär für Navidrome gebaut und voll Subsonic-kompatibel — Gonic, Airsonic, LMS und andere Subsonic-API-Server funktionieren ebenfalls. Einige fortgeschrittene Features (Bewertungen, Smart Playlists, Magic-String-Sharing, User-Verwaltung) erfordern Navidrome.', - q2: 'Wie füge ich einen Server hinzu?', - a2: 'Einstellungen → Server → Server hinzufügen. URL eingeben (z. B. http://192.168.1.100:4533), Benutzername und Passwort. Psysonic testet die Verbindung vor dem Speichern — bei Fehler wird nichts gespeichert. Du kannst beliebig viele Server hinzufügen und im Header zwischen ihnen wechseln; immer ist nur einer aktiv.', - q3: 'Schnelle UI-Tour?', - a3: 'Sidebar (links) für Navigation, Mainstage / Seiten in der Mitte, Playerleiste unten, Warteschlangen-Panel rechts (über das Icon oben rechts neben dem Now-Playing-Indikator). Die Suche oben durchsucht die gesamte Bibliothek; "Now Playing" zeigt, was andere Nutzer auf dem gleichen Navidrome-Server gerade hören.', - // ── Section 2: Wiedergabe & Warteschlange ────────────────────────────── - s2: 'Wiedergabe & Warteschlange', - q4: 'Wie nutze ich die Warteschlange?', - a4: 'Warteschlangen-Panel oben rechts öffnen. Zeilen per Drag & Drop umsortieren, nach außen ziehen zum Entfernen, oder über die Toolbar mischen, als Playlist speichern oder zu einem Track springen. Zeilen lassen sich auch aus dem Panel heraus an andere Stellen ziehen.', - q5: 'Gapless vs. Crossfade — was ist der Unterschied?', - a5: 'Gapless puffert den nächsten Track vor, sodass keine Stille zwischen Songs entsteht (ideal für Live-Alben und DJ-Mixe). Crossfade blendet den aktuellen Track aus, während der nächste eingeblendet wird (1–10 s, gut für gemischte Mixe). Die zwei sind gegenseitig exklusiv — eines aktivieren deaktiviert das andere. Konfiguration in Einstellungen → Audio.', - q6: 'Was ist die Infinite Queue?', - a6: 'Wenn die Warteschlange leerläuft und Wiederholen aus ist, hängt Psysonic ähnliche / zufällige Tracks aus deiner Bibliothek hinten dran, sodass die Wiedergabe nie stoppt. Auto-hinzugefügte Tracks erscheinen unter dem Trenner „— Automatisch hinzugefügt —". Umschalten über das Unendlichkeits-Icon im Warteschlangen-Header; in Einstellungen → Warteschlange auf ein Genre einschränken.', - q7: 'Mehrfachauswahl und Shift-Klick-Bereich?', - a7: 'Im Mehrfach-Modus auf Alben / New Releases / Random Albums / Playlists: Klick toggelt einen Eintrag, dann Shift halten und einen anderen Eintrag klicken — alles dazwischen in der sichtbaren Reihenfolge wird ausgewählt. Shift-Klicks erweitern vom zuletzt geklickten Anker. Die Toolbar oben bietet Bulk-Aktionen (Queue, Download, Löschen usw.).', - q8: 'Tastenkürzel und globale Hotkeys?', - a8: 'Standard-In-App-Tasten: Leertaste = Play / Pause, Esc = Vollbild / Modal schließen, F1 = Shortcut-Spickzettel. Einstellungen → Eingabe lässt jede In-App-Aktion neu zuweisen (auch als Akkorde wie Strg+Shift+P) und systemweite globale Shortcuts setzen, die auch im Hintergrund oder minimiert funktionieren. Medientasten (Play/Pause, Weiter, Zurück) funktionieren auf allen Plattformen.', - // ── Section 3: Audio-Werkzeuge ───────────────────────────────────────── - s3: 'Audio-Werkzeuge', - q9: 'Replay-Gain-Modi?', - a9: 'Einstellungen → Audio → Replay Gain. Track-Modus normalisiert jeden Song auf einen Zielpegel. Album-Modus erhält die Lautstärke-Kurve innerhalb eines Albums. Auto-Modus wählt Track oder Album je nachdem, ob die Warteschlange aus einem einzelnen Album stammt. Tracks ohne Replay-Gain-Tags fallen auf einen konfigurierbaren Preamp zurück.', - q10: 'Was ist Smart Loudness Normalization (LUFS)?', - a10: 'Eine moderne Alternative zu Replay Gain in Einstellungen → Audio. Psysonic analysiert jeden Track nach LUFS / EBU R128 und speichert das Ergebnis, sodass die Lautstärke über die gesamte Bibliothek konsistent ist — auch bei Tracks ohne Replay-Gain-Tags. Die Cold-Cache-Analyse läuft im Hintergrund und nutzt 35–40 % CPU für ~1 Minute, danach 0. Ziel-Lautstärke (Standard −10 LUFS) einmal festlegen.', - q11: 'EQ und AutoEQ?', - a11: 'Ein 10-Band-Parametrik-EQ in Einstellungen → Audio → Equalizer mit manuellen Bändern und Presets. AutoEQ daneben holt ein gemessenes Korrekturprofil für dein Kopfhörermodell aus der AutoEQ-Datenbank und überträgt es automatisch auf die Bänder — Kopfhörer wählen, der EQ rastet auf der korrekten Kurve ein.', - q12: 'Wie wechsle ich das Audio-Ausgabegerät?', - a12: 'Einstellungen → Audio → Ausgabegerät. Psysonic listet alle verfügbaren Ausgaben und wechselt sofort beim Auswählen. Der Aktualisierungs-Button scannt nach Geräten, die nach dem Start angeschlossen wurden. Linux-ALSA-Namen wie „sysdefault" werden für die Lesbarkeit automatisch bereinigt.', - q13: 'Was ist der Hot Cache?', - a13: 'Der Hot Cache lädt den aktuellen Track plus die nächsten in den RAM und auf die Festplatte vor, sodass die Wiedergabe ohne Pufferverzögerung startet — besonders nützlich bei langsamen / entfernten Servern. Eviction greift, wenn das Größenlimit erreicht ist. Größe und Debounce-Verzögerung (damit schnelle Skips nicht überfetchen) in Einstellungen → Audio.', - // ── Section 4: Bibliothek & Discovery ────────────────────────────────── - s4: 'Bibliothek & Discovery', - q14: 'Wie funktionieren Bewertungen und Skip-to-1★?', - a14: 'Psysonic unterstützt 1–5-Sterne-Bewertungen über OpenSubsonic (Navidrome ≥ 0.53). Songs in Tracklisten, im Rechtsklick-Menü oder in der Playerleiste unter dem Künstlernamen bewerten; Alben auf der Albumseite; Künstler auf der Künstlerseite. Skip-to-1★ (Einstellungen → Bibliothek → Bewertungen) vergibt automatisch 1 Stern nach einer konfigurierbaren Anzahl aufeinanderfolgender Skips. Im selben Panel lässt sich eine Mindestbewertung als Filter für Random Mix und andere Mixes setzen.', - q15: 'Wie browse ich — Ordner, Genres, Tracks?', - a15: 'Der Ordner-Browser (Sidebar) navigiert durch das Musikverzeichnis des Servers im Miller-Column-Layout — Klick auf Ordner zum Öffnen, Klick auf Track oder Play-Icon eines Ordners zum Abspielen / Hinzufügen. Genres nutzt eine nach Track-Anzahl skalierte Tag-Cloud; Klick auf ein Genre öffnet es. Tracks ist ein flacher Library-Hub mit spaltensortierbarer virtueller Liste und Live-Suche.', - q16: 'Suche und erweiterte Suche?', - a16: 'Die Header-Suche läuft live während der Eingabe und durchsucht Künstler, Alben und Tracks. Die erweiterte Suche (Sidebar) bietet eine reichere Sicht: Filter nach Jahr, Genre, Bewertung, Format, Kanälen, Sample-Rate, BPM, Stimmung, kombinierbar. Rechtsklick auf jeden Treffer öffnet das gleiche Kontextmenü wie überall sonst in der App.', - q17: 'Was sind die Mixes (Random / Genre / Super Genre / Lucky)?', - a17: 'Random Mix erstellt eine Playlist aus zufälligen Tracks deiner Bibliothek; der Schlüsselwort-Filter schließt Hörbücher, Comedy etc. nach Genre / Titel / Album-Substrings aus. Super-Genre-Mix gruppiert deine Bibliothek in breite Stile (Rock, Metal, Electronic, Jazz, Klassik …) und erstellt einen fokussierten Mix. Lucky Mix nutzt Hörhistorie, Bewertungen und AudioMuse-AI-ähnliche Tracks, um per Klick eine sofortige Playlist zu bauen.', - q18: 'Statistik-Seite?', - a18: 'Statistik (Sidebar) zeigt Top-Künstler, Top-Alben, Top-Tracks, Genre-Verteilung, Hörzeit über die Zeit und pro Bibliothek, wenn mehrere Music Folder konfiguriert sind. Mehrere Ansichten lassen sich als teilbares Card-Bild exportieren.', - q19: 'Wie lade ich ein Album als ZIP herunter?', - a19: 'Albumseite → „Download (ZIP)". Der Server packt das Album zuerst — bei großen oder verlustfreien Alben (FLAC / WAV) erscheint der Fortschrittsbalken erst, wenn das Zippen fertig ist und der Transfer beginnt. Das ist normal.', - // ── Section 5: Lyrics ────────────────────────────────────────────────── - s5: 'Lyrics', - q20: 'Woher kommen die Lyrics?', - a20: 'Drei Quellen, konfigurierbar in Einstellungen → Lyrics: Navidrome-Server (eingebettete / OpenSubsonic-Lyrics), LRCLIB (community-gepflegte synchronisierte Texte) und NetEase Cloud Music (umfangreicher asiatischer + internationaler Katalog). Jede Quelle aktivieren / deaktivieren und per Drag & Drop priorisieren.', - q21: 'Wie zeige ich Lyrics während der Wiedergabe?', - a21: 'Klick auf das Mikrofon-Icon in der Playerleiste öffnet den Lyrics-Tab im Warteschlangen-Panel. Synchronisierte Lyrics scrollen automatisch und unterstützen Klick-zum-Springen; reine Texte scrollen als statischer Block. Den Vollbild-Player über das Cover in der Playerleiste öffnen für eine immersive Lyrics-Ansicht mit Mesh-Blob-Hintergrund.', - // ── Section 6: Sharing & Social ──────────────────────────────────────── - s6: 'Sharing & Social', - q22: 'Was sind Magic Strings?', - a22: 'Magic Strings sind kurze Copy-Paste-Tokens, die Dinge zwischen Psysonic-Nutzern ohne Drittanbieter-Server teilen. Server-Einladungs-Strings ermöglichen einem Freund das Onboarding auf deinem Navidrome mit einem Paste; Album- / Künstler- / Queue-Magic-Strings öffnen dasselbe Album / denselben Künstler / dieselbe Queue beim Empfänger. Aus dem Teilen-Menü generieren, in die Suche einfügen zum Konsumieren.', - q23: 'Was ist Orbit?', - a23: 'Orbit ist synchrones Zusammenhören: ein Host spielt einen Track, alle Gäste hören ihn synchron, und Gäste können Songs vorschlagen, die der Host in die Queue annehmen kann. Session über den Orbit-Button im Header starten, Einladungslink teilen, andere können von jeder Psysonic-Installation beitreten. Der Host kontrolliert die Wiedergabe (Skip, Seek, Queue) — Gäste sehen den Stand in Echtzeit und können Vorschläge machen. Sessions sind ephemer und enden, wenn der Host sie schließt.', - q24: 'Was ist das Now-Playing-Dropdown?', - a24: 'Das Broadcast-Symbol oben rechts im Header zeigt, was andere Nutzer auf deinem Navidrome-Server gerade hören, aktualisiert alle 10 Sekunden. Der eigene Eintrag verschwindet sofort beim Pausieren. Per-Server — Nutzer auf einem anderen aktiven Server werden nicht angezeigt.', - // ── Section 7: Personalisierung ──────────────────────────────────────── - s7: 'Personalisierung', - q25: 'Themes und der Theme-Scheduler?', - a25: 'Einstellungen → Darstellung → Theme bietet 60+ Themes in 8 Gruppen (Psysonic, Mediaplayer, Betriebssysteme, Spiele, Filme, Serien, Social Media, Open Source Classics — Catppuccin / Nord / Gruvbox / Nightfox / Dracula). Auto-Switch-Theme erlaubt das Setzen von Tag- und Nacht-Theme mit Startzeiten, sodass Psysonic automatisch wechselt.', - q26: 'Kann ich Sidebar, Home und Künstlerseite anpassen?', - a26: 'Ja — Einstellungen → Personalisierung. Der Sidebar-Customizer erlaubt das Umsortieren der Nav-Items per Drag und das Ausblenden ungenutzter. Der Home-Customizer schaltet jede Mainstage-Reihe (Hero, Recent, Discover, Recently Played, Starred …) ein/aus. Der Artist-Page-Customizer ordnet die Sektionen (Top Songs, Alben, Singles, Compilations, ähnliche Künstler usw.) um und blendet ungenutzte aus.', - q27: 'Was ist der Mini-Player?', - a27: 'Ein kleines schwebendes Fenster mit Cover, Transport-Controls und kompakter Queue. Über das Mini-Player-Icon in der Playerleiste oder das zugehörige Tastenkürzel öffnen. Das Fenster merkt sich Position und Größe zwischen Sessions. Auf Windows wird die Mini-Webview beim Start vorerstellt, sodass das Öffnen sofort geschieht; Linux / macOS aktivieren das optional über Einstellungen → Darstellung → Mini-Player vorladen.', - q28: 'Was ist die Floating Player Bar?', - a28: 'Eine optionale Playerleisten-Variante (Einstellungen → Darstellung), die sich mit themed Hintergrund, Akzent-Border, abgerundetem Cover und zentriertem Lautstärke-Bereich vom unteren Rand löst. Nützlich auf hohen Monitoren oder kompakten Themes.', - q29: 'Track-Vorschau beim Hovern?', - a29: 'Über eine Track-Zeile hovern, den kleinen Vorschau-Button auf dem Cover klicken oder die Vorschau über das Rechtsklick-Menü auslösen — Psysonic streamt die ersten ~15 s durch dieselbe Rust-Audio-Engine, sodass Loudness-Normalisierung greift. Praktisch beim Durchblättern eines neuen Albums.', - q30: 'Sleep-Timer?', - a30: 'Klick auf das Mond-Icon in der Playerleiste öffnet den Sleep-Timer. Eine Dauer wählen (oder „Ende des aktuellen Tracks") und Psysonic blendet aus und pausiert am Ende. Der Button zeigt einen Kreis-Ring und einen Countdown im Button, während der Timer läuft.', - q31: 'UI-Skalierung, Schrift, Seekbar-Stil?', - a31: 'Einstellungen → Darstellung — Anzeigeskalierung (80–125 %, ohne System-Schriftgröße zu beeinflussen), Schrift (10 UI-Schriften, u. a. IBM Plex Mono, Fira Code, Geist, Golos Text …), Seekbar-Stil (Wellenform analysiert / Pseudowave deterministisch / Linie & Punkt / Balken / Dicker Balken / Segmentiert / Neon-Glow / Pulswelle / Partikelspur / Flüssigfüllung / Retro-Tape).', - // ── Section 8: Power User ────────────────────────────────────────────── - s8: 'Power User', - q32: 'CLI-Player-Steuerung?', - a32: 'Das Psysonic-Binary kann als Fernsteuerung dienen. Beispiele: psysonic --player play / pause / next / prev, --player volume 75, --player seek 15, --player shuffle, --player repeat off|all|one, --player rating 1-5. Server, Audiogeräte, Bibliotheken wechseln; Instant Mix triggern; Künstler / Alben / Tracks suchen. Vollständige Liste mit psysonic --player --help. Shell-Completions für bash und zsh über psysonic completions.', - q33: 'Smart Playlists (Navidrome)?', - a33: 'Smart Playlists sind serverseitige dynamische Playlists, die durch Regeln definiert werden (Genre = Rock UND Jahr > 2020 etc.). Die Playlists-Seite in Psysonic erlaubt das Erstellen, Bearbeiten und Löschen mit visuellem Regel-Editor — Psysonic spricht dafür mit der Navidrome Native API. Sie verhalten sich wie normale Playlists im Rest der App und aktualisieren sich automatisch, wenn sich die Bibliothek ändert.', - q34: 'Einstellungen sichern und wiederherstellen?', - a34: 'Einstellungen → Storage → Backup & Restore exportiert Server-Profile, Themes, Tastenkürzel und andere Einstellungen in eine einzige JSON-Datei. Auf einem anderen Gerät oder nach einer Neuinstallation importieren, um alles auf einmal wiederherzustellen. Server-Passwörter sind enthalten — Datei sicher aufbewahren.', - q35: 'Wo sehe ich alle Open-Source-Lizenzen?', - a35: 'Einstellungen → System → Open Source Licenses. Die volle Abhängigkeitsliste (Cargo-Crates und npm-Pakete) wird mit gebündelten Lizenztexten ausgeliefert. Klick auf einen Eintrag öffnet den vollen Text; der kuratierte Highlight-Block oben hebt die User-bekannten Bibliotheken hervor (Tauri, React, rodio, symphonia usw.).', - // ── Section 9: Offline & Sync ────────────────────────────────────────── - s9: 'Offline & Sync', - q36: 'Offline-Modus — Alben und Playlists cachen?', - a36: 'Album oder Playlist öffnen und das Download-Icon im Header klicken — Psysonic cacht jeden Track lokal, sodass er ohne Netzwerkzugriff abspielt. Die Offline-Bibliothek (Sidebar) listet alles Gecachte, zeigt laufende Downloads und erlaubt das Entfernen über das Papierkorb-Icon (das nach Abschluss erscheint).', - q37: 'Offline-Speicherlimit?', - a37: 'Einstellungen → Bibliothek → Offline lässt eine maximale Cache-Größe setzen. Wird das Limit erreicht, zeigt die Albumseite einen Warnhinweis. Speicher freigeben durch Entfernen von Alben oder Playlists in der Offline-Bibliothek.', - q38: 'Device Sync — Musik auf USB / SD?', - a38: 'Device Sync (Sidebar) kopiert Alben, Playlists oder ganze Künstler auf ein externes Laufwerk für Offline-Hören auf anderen Geräten. Zielordner wählen, Quellen aus den Browser-Tabs auswählen, „Auf Gerät übertragen" klicken. Psysonic schreibt ein Manifest (psysonic-sync.json), sodass es weiß, welche Dateien bereits dort sind, auch beim Wieder-Öffnen unter einem anderen OS mit anderer Vorlage. Vorlagen unterstützen {artist} / {album} / {title} / {track_number} / {disc_number} / {year}-Tokens mit / als Ordner-Trennzeichen.', - // ── Section 10: Integrationen & Fehlerbehebung ───────────────────────── - s10: 'Integrationen & Fehlerbehebung', - q39: 'Last.fm-Scrobbling?', - a39: 'Einstellungen → Integrationen → Last.fm. Konto einmal verbinden, Psysonic scrobbelt direkt zu Last.fm — keine Navidrome-Konfiguration nötig. Ein Scrobble wird gesendet, wenn 50 % eines Tracks gehört wurden. Now-Playing-Pings gehen zu Beginn raus.', - q40: 'Discord Rich Presence?', - a40: 'Einstellungen → Integrationen → Discord zeigt deinen aktuellen Track auf deinem Discord-Profil. Wahl zwischen App-Icon, Cover-Art deines Servers (über getAlbumInfo2 — benötigt einen öffentlich erreichbaren Server) oder Apple-Music-Covern. Anzeige-Strings (Details, Status, Tooltip) per Token-Templates anpassen.', - q41: 'Bandsintown-Tour-Daten?', - a41: 'Opt-in unter Einstellungen → Integrationen → Now-Playing-Info. Der Now-Playing-Tab auf der Now-Playing-Seite zeigt dann kommende Tour-Daten für den laufenden Künstler über die Bandsintown-Widget-API. Standardmäßig aus — keine Anfragen, bevor aktiviert.', - q42: 'Internet Radio — Live-Streams abspielen?', - a42: 'Internet Radio (Sidebar) spielt jeden auf deinem Navidrome-Server gespeicherten Live-Stream (Sender über die Navidrome-Admin-UI hinzufügen). Wiedergabe läuft über die HTML5-Audio-Engine des Browsers — die meisten EQ- / Replay-Gain- / Loudness-Einstellungen gelten nicht für Radio, aber ICY-Metadaten (aktueller Songname) werden angezeigt. Unterstützt MP3, AAC, OGG Vorbis und die meisten HLS-Streams; Codec-Support hängt von der Plattform ab.', - q43: 'Der Verbindungstest schlägt fehl — was tun?', - a43: 'URL inklusive Port doppelt prüfen (z. B. http://192.168.1.100:4533). Im lokalen Netzwerk klappt http:// oft, wo https:// nicht funktioniert (kein Zertifikat). Sicherstellen, dass keine Firewall den Port blockiert und dass Benutzername und Passwort stimmen. Bei Servern hinter einem Reverse-Proxy zuerst die direkte URL probieren, um die Ursache einzugrenzen.', - q44: 'Cover und Künstlerbilder laden langsam.', - a44: 'Bilder werden beim ersten Aufruf vom Server geholt und dann 30 Tage lokal gecacht. Bei langsamen Server-Festplatten kann der erste Seitenaufruf einen Moment dauern; danach sind sie sofort da. Der Hot Cache hilft auch bei Tracks, der Bild-Cache ist davon unabhängig.', - q45: 'Linux-Probleme — schwarzer Bildschirm oder kein Ton?', - a45: 'Schwarzer Bildschirm ist meist ein GPU- / EGL-Treiberproblem in WebKitGTK — mit GDK_BACKEND=x11 WEBKIT_DISABLE_COMPOSITING_MODE=1 WEBKIT_DISABLE_DMABUF_RENDERER=1 starten (die AUR- / .deb- / .rpm-Installer setzen das automatisch). Für Audio sicherstellen, dass PipeWire oder PulseAudio läuft. Tonaussetzer nach Sleep / Wake werden mittlerweile vom Post-Sleep-Recovery-Hook automatisch behandelt.', - }, - queue: { - title: 'Warteschlange', - savePlaylist: 'Playlist speichern', - updatePlaylist: 'Playlist aktualisieren', - filterPlaylists: 'Playlists filtern…', - playlistName: 'Name der Playlist', - cancel: 'Abbrechen', - save: 'Speichern', - loadPlaylist: 'Playlist laden', - loading: 'Lade…', - noPlaylists: 'Keine Playlists gefunden.', - load: 'Warteschlange ersetzen & abspielen', - appendToQueue: 'An Warteschlange anhängen', - delete: 'Löschen', - deleteConfirm: 'Playlist "{{name}}" löschen?', - clear: 'Leeren', - shuffle: 'Warteschlange mischen', - gapless: 'Nahtlos', - crossfade: 'Crossfade', - infiniteQueue: 'Endlose Warteschlange', - autoAdded: '— Automatisch hinzugefügt —', - radioAdded: '— Radio —', - hide: 'Verbergen', - hideNowPlaying: 'Wiedergabeinformationen ausblenden', - showNowPlaying: 'Wiedergabeinformationen anzeigen', - close: 'Schließen', - nextTracks: 'Nächste Titel', - shareQueue: 'Warteschlangen-Link kopieren', - shareQueueEmpty: 'Die Warteschlange ist leer — nichts zu teilen.', - emptyQueue: 'Die Warteschlange ist leer.', - trackSingular: 'Titel', - trackPlural: 'Titel', - showRemaining: 'Restzeit anzeigen', - showTotal: 'Gesamtzeit anzeigen', - showEta: 'Endzeit anzeigen', - replayGain: 'ReplayGain', - rgTrack: 'T {{db}} dB', - rgAlbum: 'A {{db}} dB', - rgPeak: 'Peak {{pk}}', - sourceOffline: 'Wiedergabe aus der Offline-Bibliothek', - sourceHot: 'Wiedergabe aus dem Cache', - sourceStream: 'Wiedergabe aus dem Netzwerkstream', - clearCachedLoudnessWaveform: 'Clear cached loudness and waveform, then re-analyze this track', - recalculatingLoudnessWaveform: 'Recalculating loudness and waveform for this track…', - }, - miniPlayer: { - showQueue: 'Warteschlange einblenden', - hideQueue: 'Warteschlange ausblenden', - pinOnTop: 'Im Vordergrund halten', - pinOff: 'Vordergrund deaktivieren', - openMainWindow: 'Hauptfenster öffnen', - close: 'Schließen', - emptyQueue: 'Die Warteschlange ist leer', - }, - statistics: { - title: 'Statistiken', - recentlyPlayed: 'Zuletzt gehört', - mostPlayed: 'Meistgespielte Alben', - highestRated: 'Höchstbewertete Alben', - genreDistribution: 'Genre-Verteilung (Top 20)', - loadMore: 'Mehr laden', - statArtists: 'Künstler', - statArtistsTooltip: 'Nur Album-Künstler — Künstler, die ausschließlich als Track-Künstler vorkommen (Featured, Gast usw.) und kein eigenes Album haben, werden nicht gezählt.', - statAlbums: 'Alben', - statSongs: 'Songs', - statGenres: 'Genres', - statPlaytime: 'Gesamtspielzeit', - genreInsights: 'Genre-Einblicke', - formatDistribution: 'Format-Verteilung', - formatSample: 'Stichprobe von {{n}} Titeln', - computing: 'Wird berechnet…', - genreSongs: '{{count}} Songs', - genreAlbums: '{{count}} Alben', - recentlyAdded: 'Neu hinzugefügt', - decadeDistribution: 'Alben nach Jahrzehnt', - decadeAlbums_one: '{{count}} Album', - decadeAlbums_other: '{{count}} Alben', - decadeUnknown: 'Unbekannt', - lfmTitle: 'Last.fm Statistiken', - lfmTopArtists: 'Top-Künstler', - lfmTopAlbums: 'Top-Alben', - lfmTopTracks: 'Top-Titel', - lfmPlays: '{{count}} Plays', - lfmPeriodOverall: 'Gesamt', - lfmPeriod7day: '7 Tage', - lfmPeriod1month: '1 Monat', - lfmPeriod3month: '3 Monate', - lfmPeriod6month: '6 Monate', - lfmPeriod12month: '12 Monate', - lfmNotConnected: 'Verbinde Last.fm in den Einstellungen, um deine Statistiken zu sehen.', - lfmRecentTracks: 'Zuletzt gescrobbelt', - lfmNowPlaying: 'Läuft gerade', - lfmJustNow: 'gerade eben', - lfmMinutesAgo: 'vor {{n}} Min.', - lfmHoursAgo: 'vor {{n}} Std.', - lfmDaysAgo: 'vor {{n}} Tagen', - topRatedSongs: 'Bestbewertete Songs', - topRatedArtists: 'Bestbewertete Künstler', - noRatedSongs: 'Noch keine bewerteten Songs. Songs in Album- oder Playlist-Ansicht bewerten.', - noRatedArtists: 'Noch keine bewerteten Künstler.', - exportShare: 'Teilen', - exportTitle: 'Top-Alben teilen', - exportSubtitle: 'Ein teilbares Bild deiner meistgespielten Alben erstellen.', - exportFormat: 'Format', - exportFormatStory: 'Story', - exportFormatSquare: 'Quadrat', - exportFormatTwitter: 'Twitter-Card', - exportGrid: 'Raster', - exportGridLabel: '{{n}}×{{n}}', - exportPreview: 'Vorschau', - exportGenerate: 'Erstellen', - exportSave: 'Bild speichern…', - exportCancel: 'Abbrechen', - exportFooterLabel: 'Top-Alben', - exportNotEnough: 'Für ein {{n}}×{{n}}-Raster braucht es mindestens {{count}} Alben in der Library.', - exportSaving: 'Speichere…', - exportSaved: 'Gespeichert.', - exportSaveFailed: 'Bild konnte nicht gespeichert werden.', - }, - player: { - regionLabel: 'Musikplayer', - openFullscreen: 'Vollbild-Player öffnen', - fullscreen: 'Vollbild-Player', - closeFullscreen: 'Vollbild schließen', - closeTooltip: 'Schließen (Esc)', - noTitle: 'Kein Titel', - stop: 'Stop', - prev: 'Vorheriger Titel', - play: 'Play', - pause: 'Pause', - previewActive: 'Vorschau läuft', - previewLabel: 'Vorschau', - delayModalTitle: 'Timer', - delayPauseSection: 'Pause nach', - delayStartSection: 'Start nach', - delayPreviewPause: 'Pause um', - delayPreviewStart: 'Start um', - delaySchedulePause: 'Pause planen', - delayScheduleStart: 'Start planen', - delayCancelPause: 'Pause-Timer abbrechen', - delayCancelStart: 'Start-Timer abbrechen', - delayInactivePause: 'Nur während der Wiedergabe verfügbar.', - delayInactiveStart: 'Nur in Pause mit geladenem Titel oder Radio.', - delayCustomMinutes: 'Eigene Dauer (Minuten)', - delayCustomPlaceholder: 'z. B. 2,5', - closeDelayModal: 'Schließen', - delayIn: 'in', - delayFmtSec: '{{n}} s', - delayFmtMin: '{{n}} Min', - delayFmtHr: '{{n}} Std', - delayCancel: 'Abbrechen', - delayApply: 'Übernehmen', - next: 'Nächster Titel', - repeat: 'Wiederholen', - repeatOff: 'Aus', - repeatAll: 'Alle', - repeatOne: 'Einen', - progress: 'Songfortschritt', - volume: 'Lautstärke', - toggleQueue: 'Warteschlange umschalten', - collapseQueueResize: 'Warteschlange einklappen, Breite ändern', - moreOptions: 'Weitere Optionen', - equalizer: 'Equalizer', - miniPlayer: 'Mini-Player', - lyrics: 'Lyrics', - fsLyricsToggle: 'Lyrics im Vollbild', - lyricsLoading: 'Lyrics werden geladen…', - lyricsNotFound: 'Keine Lyrics für diesen Titel gefunden', - lyricsSourceServer: 'Quelle: Server', - lyricsSourceLrclib: 'Quelle: LRCLIB', - lyricsSourceNetease: 'Quelle: Netease', - lyricsSourceLyricsplus: 'Quelle: YouLyPlus', - showDuration: 'Dauer anzeigen', - showRemainingTime: 'Verbleibende Zeit anzeigen', - }, - nowPlayingInfo: { - tab: 'Info', - empty: 'Spiele etwas, um Infos zu sehen', - artist: 'Künstler*in', - songInfo: 'Songinfos', - onTour: 'Auf Tour', - noTourEvents: 'Keine bevorstehenden Konzerte', - tourLoading: 'Wird geladen…', - poweredByBandsintown: 'Tourdaten via Bandsintown', - bioReadMore: 'Mehr anzeigen', - bioReadLess: 'Weniger anzeigen', - showMoreTours_one: '{{count}} weiteres anzeigen', - showMoreTours_other: '{{count}} weitere anzeigen', - showLessTours: 'Weniger anzeigen', - enableBandsintownPrompt: 'Anstehende Konzerte anzeigen?', - enableBandsintownPromptDesc: 'Optional. Lädt Tourdaten der aktuellen Künstler*in über die öffentliche Bandsintown-API.', - enableBandsintownPrivacy: 'Beim Aktivieren wird der Name der aktuell gespielten Künstler*in an die Bandsintown-API übertragen, um Tourdaten abzurufen. Es werden keine Konto- oder persönlichen Daten gesendet.', - enableBandsintownAction: 'Aktivieren', - role: { - artist: 'Hauptkünstler*in', - albumArtist: 'Album-Künstler*in', - composer: 'Komponist*in', - }, - }, - songInfo: { - title: 'Song-Infos', - songTitle: 'Titel', - artist: 'Künstler', - album: 'Album', - albumArtist: 'Album-Künstler', - year: 'Jahr', - genre: 'Genre', - duration: 'Länge', - track: 'Track', - format: 'Format', - bitrate: 'Bitrate', - sampleRate: 'Abtastrate', - bitDepth: 'Bittiefe', - channels: 'Kanäle', - fileSize: 'Dateigröße', - path: 'Speicherort', - replayGainTrack: 'RG Track Gain', - replayGainAlbum: 'RG Album Gain', - replayGainPeak: 'RG Track Peak', - mono: 'Mono', - stereo: 'Stereo', - }, - playlists: { - title: 'Playlists', - newPlaylist: 'Neue Playlist', - unnamed: 'Unbenannte Playlist', - createName: 'Playlist-Name…', - create: 'Erstellen', - cancel: 'Abbrechen', - empty: 'Noch keine Playlists.', - emptyPlaylist: 'Diese Playlist ist leer.', - addFirstSong: 'Ersten Song hinzufügen', - notFound: 'Playlist nicht gefunden.', - songs: '{{n}} Songs', - playAll: 'Alle abspielen', - shuffle: 'Zufallswiedergabe', - addToQueue: 'Zur Warteschlange', - back: 'Zurück zu Playlists', - deletePlaylist: 'Löschen', - confirmDelete: 'Nochmals klicken zum Bestätigen', - removeSong: 'Aus Playlist entfernen', - addSongs: 'Songs hinzufügen', - searchPlaceholder: 'Bibliothek durchsuchen…', - noResults: 'Keine Ergebnisse.', - suggestions: 'Vorgeschlagene Songs', - noSuggestions: 'Keine Vorschläge verfügbar.', - titleBadge: 'Playlist', - refreshSuggestions: 'Neue Vorschläge', - addSong: 'Zur Playlist hinzufügen', - preview: 'Vorschau (30 s)', - previewStop: 'Vorschau stoppen', - playNextSuggestion: 'Als Nächstes spielen', - suggestionsHint: 'Doppelklick auf eine Zeile fügt sie zur Playlist hinzu', - addSelected: 'Ausgewählte hinzufügen', - cacheOffline: 'Playlist offline speichern', - offlineCached: 'Playlist gecacht', - removeOffline: 'Aus Offline-Cache entfernen', - offlineDownloading: 'Wird gecacht… ({{done}}/{{total}} Alben)', - publicLabel: 'Öffentlich', - privateLabel: 'Privat', - editMeta: 'Playlist bearbeiten', - editNamePlaceholder: 'Playlist-Name…', - editCommentPlaceholder: 'Beschreibung hinzufügen…', - editPublic: 'Öffentliche Playlist', - editSave: 'Speichern', - editCancel: 'Abbrechen', - changeCover: 'Coverbild ändern', - changeCoverLabel: 'Foto ändern', - removeCover: 'Foto entfernen', - coverUpdated: 'Cover aktualisiert', - metaSaved: 'Playlist aktualisiert', - downloadZip: 'Herunterladen (ZIP)', - // Toast notifications for multi-select - addSuccess: '{{count}} Songs zu {{playlist}} hinzugefügt', - addPartial: '{{added}} hinzugefügt, {{skipped}} übersprungen (Duplikate)', - addAllSkipped: 'Alle übersprungen ({{count}} Duplikate)', - addedAsDuplicates: '{{count}} Songs zu {{playlist}} hinzugefügt (als Duplikate)', - duplicateConfirmTitle: 'Bereits in Playlist', - duplicateConfirmMessage: 'Alle {{count}} Songs sind bereits in "{{playlist}}". Trotzdem als Duplikate hinzufügen?', - duplicateConfirmAction: 'Trotzdem hinzufügen', - addError: 'Fehler beim Hinzufügen von Songs', - createAndAddSuccess: 'Playlist "{{playlist}}" mit {{count}} Songs erstellt', - createError: 'Fehler beim Erstellen der Playlist', - deleteSuccess: '{{count}} Playlists gelöscht', - deleteFailed: 'Fehler beim Löschen von {{name}}', - deleteSelected: 'Ausgewählte löschen', - deleteSelectedPartial: 'Nur {{n}} von {{total}} ausgewählten Playlists können gelöscht werden (die anderen gehören jemand anderem).', - mergeSuccess: '{{count}} Songs in {{playlist}} zusammengeführt', - mergeNoNewSongs: 'Keine neuen Songs zum Hinzufügen', - mergeError: 'Fehler beim Zusammenführen von Playlists', - mergeInto: 'Zusammenführen in', - selectionCount: '{{count}} ausgewählt', - select: 'Auswählen', - startSelect: 'Auswahl aktivieren', - cancelSelect: 'Abbrechen', - loadingAlbums: '{{count}} Alben werden aufgelöst…', - loadingArtists: '{{count}} Künstler werden aufgelöst…', - myPlaylists: 'Meine Playlists', - noOtherPlaylists: 'Keine anderen Playlists verfügbar', - addToPlaylistSuccess: '{{count}} Songs zu {{playlist}} hinzugefügt', - addToPlaylistNoNew: 'Keine neuen Songs für {{playlist}}', - addToPlaylistError: 'Fehler beim Hinzufügen zur Playlist', - removeSuccess: 'Song aus Playlist entfernt', - removeError: 'Fehler beim Entfernen aus der Playlist', - importCSV: 'CSV importieren', - importCSVTooltip: 'Aus Spotify-CSV importieren', - csvImportReport: 'CSV-Importbericht', - csvImportTotal: 'Gesamt', - csvImportAdded: 'Hinzugefügt', - csvImportDuplicates: 'Duplikate', - csvImportNotFound: 'Nicht gefunden', - csvImportNetworkErrors: 'Netzwerkfehler', - csvImportDuplicatesTitle: 'Doppelte Titel (bereits in Playlist):', - csvImportNotFoundTitle: 'Nicht gefundene Titel:', - csvImportNetworkErrorsTitle: 'Netzwerkfehler (Import kann wiederholt werden):', - csvImportDownloadReport: 'Bericht herunterladen', - csvImportClose: 'Schließen', - csvImportNoValidTracks: 'Keine gültigen Titel in CSV-Datei gefunden', - csvImportFailed: 'CSV-Import fehlgeschlagen', - csvImportToast: '{{added}} hinzugefügt, {{notFound}} nicht gefunden, {{duplicates}} Duplikate', - csvImportDownloadSuccess: 'Bericht erfolgreich heruntergeladen', - csvImportDownloadError: 'Bericht konnte nicht heruntergeladen werden', - }, - smartPlaylists: { - sectionBasic: '1. Basis', - sectionGenres: '2. Genres', - sectionYearsAndFilters: '3. Jahre und Filter', - genreMode: 'Genre-Modus', - genreModeInclude: 'Genres einschließen', - genreModeExclude: 'Genres ausschließen', - genreSearchPlaceholder: 'Genres filtern...', - availableGenres: 'Verfügbar', - selectedGenres: 'Ausgewählt', - yearMode: 'Jahresmodus', - yearModeInclude: 'Bereich einschließen', - yearModeExclude: 'Bereich ausschließen', - name: 'Name (ohne Präfix)', - limit: 'Limit', - limitHint: 'Wie viele Songs in die Playlist aufgenommen werden (1-{{max}}, üblicherweise 50).', - artistContains: 'Künstler enthält…', - albumContains: 'Album enthält…', - titleContains: 'Titel enthält…', - minRating: 'Mindestbewertung', - minRatingAria: 'Mindestbewertung für Smart Playlist', - minRatingHint: '0 deaktiviert die Mindestgrenze; 1-5 behält Songs mit Bewertung über dem gewählten Wert.', - fromYear: 'Von Jahr', - toYear: 'Bis Jahr', - excludeUnrated: 'Unbewertete Songs ausschließen', - compilationOnly: 'Nur Sammlungen', - create: 'Neue Smart Playlist', - save: 'Smart Playlist speichern', - created: '{{name}} erstellt', - updated: '{{name}} aktualisiert', - createFailed: 'Smart Playlist konnte nicht erstellt werden.', - updateFailed: 'Smart Playlist konnte nicht aktualisiert werden.', - navidromeOnly: 'Smart Playlists können nur auf Navidrome-Servern erstellt werden.', - loadFailed: 'Smart Playlists konnten nicht von Navidrome geladen werden.', - sortRandom: 'Sortierung: zufällig', - sortTitleAsc: 'Sortierung: Titel A-Z', - sortTitleDesc: 'Sortierung: Titel Z-A', - sortYearDesc: 'Sortierung: Jahr absteigend', - sortYearAsc: 'Sortierung: Jahr aufsteigend', - sortPlayCountDesc: 'Sortierung: Wiedergaben absteigend', - }, - mostPlayed: { - title: 'Meistgehört', - topArtists: 'Top-Künstler', - topAlbums: 'Top-Alben', - plays: '{{n}}× gespielt', - sortMost: 'Meiste Plays zuerst', - sortLeast: 'Wenigste Plays zuerst', - loadMore: 'Mehr Alben laden', - noData: 'Noch keine Wiedergabedaten. Fang an zu hören!', - noArtists: 'Alle Künstler herausgefiltert.', - filterCompilations: 'Sampler-Künstler ausblenden (Various Artists, Soundtracks usw.)', - filterCompilationsShort: 'Sampler ausblenden', - }, - losslessAlbums: { - empty: 'Noch keine Lossless-Alben in dieser Bibliothek.', - unsupported: 'Dieser Server liefert keine Metadaten, mit denen sich Lossless-Alben erkennen lassen.', - slowFetchHint: 'Lädt langsamer als andere Album-Seiten — Psysonic geht den gesamten Songkatalog nach Qualität durch.', - }, - radio: { - title: 'Internetradio', - empty: 'Keine Radiosender konfiguriert.', - addStation: 'Sender hinzufügen', - editStation: 'Bearbeiten', - deleteStation: 'Sender löschen', - confirmDelete: 'Zum Bestätigen erneut klicken', - stationName: 'Sendername…', - streamUrl: 'Stream-URL…', - homepageUrl: 'Homepage-URL (optional)', - save: 'Speichern', - cancel: 'Abbrechen', - live: 'LIVE', - liveStream: 'Internetradio', - openHomepage: 'Homepage öffnen', - changeCoverLabel: 'Cover ändern', - removeCover: 'Cover entfernen', - browseDirectory: 'Verzeichnis durchsuchen', - directoryPlaceholder: 'Sender suchen…', - noResults: 'Keine Sender gefunden.', - stationAdded: 'Sender hinzugefügt', - filterAll: 'Alle', - filterFavorites: 'Favoriten', - sortManual: 'Manuell', - sortAZ: 'A → Z', - sortZA: 'Z → A', - sortNewest: 'Neueste', - favorite: 'Zu Favoriten hinzufügen', - unfavorite: 'Aus Favoriten entfernen', - noFavorites: 'Keine Lieblingssender.', - listenerCount_one: '{{count}} Hörer', - listenerCount_other: '{{count}} Hörer', - recentlyPlayed: 'Zuletzt gespielt', - upNext: 'Als Nächstes', - }, - folderBrowser: { - empty: 'Leerer Ordner', - error: 'Laden fehlgeschlagen', - }, - deviceSync: { - title: 'Gerätesync', - targetFolder: 'Zielordner', - noFolderChosen: 'Kein Ordner gewählt', - selectDrive: 'Laufwerk auswählen…', - refreshDrives: 'Laufwerke aktualisieren', - noDrivesDetected: 'Keine Wechseldatenträger erkannt', - browseManual: 'Manuell durchsuchen…', - free: 'frei', - notMountedVolume: 'Ziel befindet sich nicht auf einem eingehängten Laufwerk. Das Gerät wurde möglicherweise getrennt.', - chooseFolder: 'Auswählen…', - targetDevice: 'Zielgerät', - schemaLabel: 'Benennungsschema', - schemaHint: 'Festes Schema für zuverlässige Synchronisation über verschiedene Betriebssysteme hinweg. Playlists werden als .m3u8-Dateien geschrieben und referenzieren die Album-Tracks — keine Duplikate auf dem Gerät.', - migrateButton: 'Bestehende Dateien re-organisieren…', - migrateTooltip: 'Vorhandene Dateien auf dem Gerät nach dem neuen Schema umbenennen (basierend auf der alten Namensvorlage).', - migrateTitle: 'Bestehende Dateien re-organisieren', - migrateLoading: 'Analysiere vorhandene Dateien…', - migrateNothingToDo: 'Alle vorhandenen Dateien entsprechen bereits dem neuen Schema — nichts zu tun.', - migrateNoTemplate: 'Keine alte Namensvorlage auf dem Gerät gefunden. Migration ist nur möglich, wenn der Stick mit einer Psysonic-Version synchronisiert wurde, die konfigurierbare Vorlagen unterstützte.', - migrateFilesToRename: 'Dateien werden umbenannt', - migrateUnchanged: '{{n}} Dateien liegen bereits am korrekten Pfad', - migrateCollisions: '{{n}} Dateien können nicht automatisch umbenannt werden (mehrere Tracks zeigen auf dasselbe Ziel). Sie bleiben unverändert — beim nächsten Sync werden sie neu heruntergeladen.', - migratePreviewNote: 'Alte Vorlage: {{tpl}}', - migrateExecuting: 'Dateien werden umbenannt…', - migrateSuccess: '{{n}} Dateien erfolgreich umbenannt', - migrateFailed: '{{n}} Umbenennungen fehlgeschlagen', - migrateShowErrors: 'Fehler anzeigen', - migrateStart: 'Umbenennen starten', - onDevice: 'Auf dem Gerät', - addSources: 'Hinzufügen…', - colName: 'Name', - colType: 'Typ', - syncResult: '{{done}} übertragen, {{skipped}} bereits aktuell ({{total}} gesamt)', - deleteFromDevice: 'Vom Gerät löschen ({{count}})', - confirmDelete: '{{count}} Eintrag/Einträge vom Gerät löschen: {{names}}?', - deleteComplete: '{{count}} Eintrag/Einträge vom Gerät entfernt.', - manifestImported: '{{count}} Quelle(n) aus Geräte-Manifest importiert.', - selectedSources: 'Ausgewählte Quellen', - noSourcesSelected: 'Keine Quellen ausgewählt. Klicke auf Einträge im Browser um sie hinzuzufügen.', - clearAll: 'Alle entfernen', - tabPlaylists: 'Wiedergabelisten', - tabAlbums: 'Alben', - tabArtists: 'Künstler', - searchPlaceholder: 'Suche…', - syncButton: 'Auf Gerät übertragen', - actionTransfer: 'Auf Gerät übertragen', - actionDelete: 'Vom Gerät löschen', - actionApplyAll: 'Änderungen synchronisieren', - cancel: 'Abbrechen', - noTargetDir: 'Bitte zuerst einen Zielordner auswählen.', - noSources: 'Bitte mindestens eine Quelle auswählen.', - noTracks: 'Keine Tracks in den ausgewählten Quellen gefunden.', - fetchError: 'Fehler beim Laden der Tracks vom Server.', - syncComplete: 'Übertragung abgeschlossen.', - dismiss: 'Schließen', - cancelSync: 'Abbrechen', - syncCancelled: 'Sync abgebrochen ({{done}} / {{total}} übertragen).', - colStatus: 'Status', - statusSynced: 'Synchronisiert', - statusPending: 'Ausstehend', - statusDeletion: 'Löschung', - markForDeletion: 'Zur Löschung markieren', - removeSource: 'Entfernen', - undoDeletion: 'Löschung rückgängig', - syncInBackground: 'Sync gestartet — du kannst die Seite verlassen.', - syncInProgress: '{{done}} / {{total}} Tracks…', - syncSummary: 'Sync-Zusammenfassung', - calculating: 'Payload wird berechnet…', - filesToAdd: 'Hinzuzufügende Dateien:', - filesToDelete: 'Zu löschende Dateien:', - netChange: 'Nettoänderung:', - availableSpace: 'Verfügbarer Speicher:', - spaceWarning: 'Warnung: Das Zielgerät hat nicht genug gemeldeten Speicherplatz.', - proceed: 'Sync durchführen', - notEnoughSpace: 'Nicht genug physischer Speicherplatz erkannt!', - liveSearch: 'Live', - randomAlbumsLabel: 'Zufallsalben', - }, - orbit: { - triggerLabel: 'Orbit', - triggerTooltip: 'Gemeinsame Hör-Session starten oder beitreten', - launchCreate: 'Session erstellen', - launchJoin: 'Session beitreten', - launchHelp: 'Wie funktioniert das?', - launchHelpSoon: 'Kommt bald', - joinModalTitle: 'Einer Orbit-Session beitreten', - joinModalSub: 'Füge den Einladungslink ein, den dir der Host geschickt hat.', - joinModalLinkLabel: 'Einladungslink', - joinModalLinkPlaceholder: 'psysonic2-…', - joinModalLinkHelper: 'Akzeptiert jeden gültigen Orbit-Link. Der Link muss zu dem Server gehören, auf dem du gerade angemeldet bist.', - joinModalPasteTooltip: 'Aus Zwischenablage einfügen', - joinModalSubmit: 'Beitreten', - joinModalBusy: 'Beitreten…', - joinErrEmpty: 'Bitte Einladungslink einfügen.', - joinErrInvalid: 'Das sieht nicht nach einem Orbit-Einladungslink aus.', - closeAria: 'Schließen', - heroTitlePrefix: 'Gemeinsam hören mit', - heroTitleBrand: 'Orbit', - heroSub: 'Starte eine Session — andere Nutzer auf {{server}} hören im Takt mit dir und können Songs vorschlagen.', - fallbackServer: 'diesem Server', - tipLan: 'Du bist aktuell mit einer Heimnetz-Adresse verbunden. Gäste außerhalb deines Heimnetzes können so nicht beitreten — wechsle vor dem Start in den Servereinstellungen zu einer öffentlichen Adresse.', - tipRemote: 'Damit Gäste außerhalb deines Heimnetzes beitreten können, muss deine Serveradresse öffentlich erreichbar sein. Ist dein Server nur intern verfügbar, wechsle vor dem Start zu einer öffentlichen Adresse.', - labelName: 'Sessionname', - namePlaceholder: 'Velvet Orbit', - reshuffleTooltip: 'Neuer Vorschlag', - reshuffleAria: 'Neuen Namen vorschlagen', - helperName: 'So taucht die Session für deine Gäste auf — Vorschlag übernehmen oder eigenen eintippen.', - labelMax: 'Maximale Gäste', - helperMax: 'Du zählst nicht mit — das ist nur die Obergrenze für beitretende Gäste.', - labelLink: 'Einladungslink', - tooltipCopied: 'Kopiert', - tooltipCopy: 'Kopieren', - ariaCopyLink: 'Link kopieren', - helperLink: 'Schicke diesen Link deinen Gästen. Sie fügen ihn mit Strg+V irgendwo in Psysonic ein.', - labelClearQueue: 'Eigene Warteschlange vorher leeren', - helperClearQueue: 'Mit leerer Warteschlange in die Session starten. Aus: bereits aufgereihte Titel bleiben und werden mit den Gästen geteilt.', - btnCancel: 'Abbrechen', - btnStarting: 'Starte…', - btnStart: 'Orbit starten', - btnCopyAndStart: 'Link kopieren & starten', - errNameRequired: 'Bitte gib deiner Session einen Namen.', - errStartFailed: 'Konnte nicht starten.', - hostLabel: 'Gastgeber: {{name}}', - participantsTooltip: 'Teilnehmer', - settingsTooltip: 'Session-Einstellungen', - shareTooltip: 'Einladungslink teilen', - shuffleLabel: 'Warteschlange wird neu gemischt in', - catchUpLabel: 'aufholen', - catchUpTooltip: 'Zur aktuellen Host-Position springen', - hostAway: 'Host offline', - hostOnline: 'Host online', - endTooltip: 'Session beenden', - leaveTooltip: 'Session verlassen', - helpTooltip: 'Wie Orbit funktioniert', - diag: { - openTooltip: 'Diagnose — kopierbares Ereignis-Log', - title: 'Orbit-Diagnose', - role: 'Rolle', - hostTrack: 'Host-Track-ID', - hostPos: 'Host-Position', - guestTrack: 'Meine Track-ID', - guestPos: 'Meine Position', - drift: 'Versatz', - stateAge: 'Zustand-Alter', - eventLog: 'Ereignis-Log ({{count}})', - copyLabel: 'Kopieren', - copyTooltip: 'Log in Zwischenablage kopieren', - clearLabel: 'Leeren', - clearTooltip: 'Puffer leeren', - empty: 'Noch keine Ereignisse — sie erscheinen sobald Orbit synchronisiert.', - hint: 'Vor dem Reproduzieren des Problems öffnen, dann Kopieren klicken und in den Bug-Report einfügen.', - copied: '{{count}} Zeilen kopiert', - copyFailed: 'Konnte nicht in Zwischenablage kopieren', - cleared: 'Puffer geleert', - }, - helpTitle: 'Wie Orbit funktioniert', - helpIntro: 'Orbit macht aus Psysonic einen gemeinsamen Hörraum. Der Host bestimmt die Musik; Gäste hören synchron mit und können Songs vorschlagen.', - helpHostOnly: '(Host)', - helpSec1Title: 'Was ist Orbit?', - helpSec1Body: 'Ein „Listen together"-Modus — der Host steuert die Wiedergabe, die Gäste hören mit. Alles läuft über Playlists auf deinem eigenen Navidrome-Server; keine externe Infrastruktur.', - helpSec2Title: 'Host und Gäste', - helpSec2Body: 'Der Host steuert die Wiedergabe (Play / Pause / Skip / Seek) und entscheidet, wann die Session endet. Gäste folgen der Wiedergabe des Hosts, können Songs vorschlagen und jederzeit verlassen oder wieder beitreten. Nur der Host kann Teilnehmer kicken oder dauerhaft bannen.', - helpSec2WarnHead: 'Wichtig: getrennte Accounts.', - helpSec2WarnBody: 'Jeder Teilnehmer braucht einen eigenen Navidrome-Account. Benutzen Host und Gast denselben User, kollidieren ihre Einreichungen und der Host sieht keine Vorschläge vom Gast.', - helpSec3Title: 'Session starten und einladen', - helpSec3Body: 'Klick auf den „Orbit"-Button → Session erstellen → im Start-Modal siehst du einen fertigen Einladungslink und kannst optional die aktuelle Warteschlange leeren. Link teilen wie du magst. Während die Session läuft, kopiert der Share-Button in der Session-Leiste oben jederzeit den Link erneut.', - helpSec4Title: 'Beitreten', - helpSec4Body: 'Einladungslink irgendwo in Psysonic mit Ctrl+V / Cmd+V einfügen — der Beitritt-Dialog erscheint automatisch. Alternativ: „Orbit" → Session beitreten → Link ins Feld pasten. Wenn der Link auf einen Server zeigt, für den du einen Account hast, wechselt Psysonic automatisch. Bei mehreren Accounts auf demselben Server fragt ein kleiner Picker, welcher genutzt werden soll.', - helpSec5Title: 'Songs vorschlagen', - helpSec5Body: 'In jeder Song-Liste: Doppelklick auf eine Zeile, oder Rechtsklick → „Zur Orbit-Session hinzufügen". Ein einfacher Klick zeigt nur einen Hinweis, statt das ganze Album in die geteilte Queue zu werfen — das ist bewusst so. Explizite Bulk-Aktionen wie „Play All" oder „Play Album" fragen zuerst nach und hängen dann an (ersetzen nie).', - helpSec6Title: 'Die geteilte Warteschlange', - helpSec6Body: 'Die Queue zeigt die kommenden Titel des Hosts — für alle sichtbar. Neu hinzugefügte Bulk-Inhalte werden immer angehängt, damit Gast-Vorschläge nicht verloren gehen. Auto-Shuffle mischt die Queue periodisch neu (konfigurierbar: 1 / 5 / 10 / 15 / 30 Min.). Wenn deine Wiedergabe vom Host abweicht, bringt dich der „Aufholen"-Button in der Session-Leiste zurück zur Live-Position des Hosts.', - helpSec7Title: 'Freigaben', - helpSec7Body: 'Standardmäßig müssen Vorschläge von Gästen manuell freigegeben werden — sie erscheinen in einer „Freigabe"-Leiste oben im Queue-Panel mit Annehmen/Ablehnen-Buttons. In den Session-Einstellungen lässt sich Auto-Übernehmen aktivieren, dann landen alle Vorschläge direkt in der Queue.', - helpSec8Title: 'Teilnehmer und Einstellungen', - helpSec8Body: 'Das Einstellungs-Icon in der Session-Leiste öffnet Shuffle-Takt, Auto-Übernehmen und die „Jetzt mischen"-Abkürzung. Klick auf die Teilnehmerzahl zeigt wer gerade dabei ist — Kick (kann über den Link wieder beitreten) oder Bann (für die Session gesperrt). Gäste sehen die Teilnehmerliste ebenfalls, aber nur lesend.', - helpSec9Title: 'Session beenden', - helpSec9Body: 'Host-X → Bestätigungsdialog → Session endet für alle und die Server-Playlists werden automatisch aufgeräumt. Gast-X → der Gast verlässt, die Session läuft weiter. Wenn der Host 5 Minuten lang nichts mehr sendet, verlässt der Gast die Session automatisch mit einer Meldung; kürzere Reconnects innerhalb dieser Zeit bleiben unsichtbar.', - participantsInviteLabel: 'Einladungslink', - participantsCountLabel: '{{count}} in Session', - participantsHost: 'Gastgeber', - participantsEmpty: 'Noch keine Gäste', - participantsKickTooltip: 'Aus Session entfernen', - participantsKickAria: '{{user}} entfernen', - participantsRemoveTooltip: 'Aus Session entfernen', - participantsRemoveAria: '{{user}} aus dieser Session entfernen', - participantsBanTooltip: 'Permanent bannen', - participantsBanAria: '{{user}} permanent bannen', - participantsMuteTooltip: 'Vorschläge sperren', - participantsUnmuteTooltip: 'Vorschläge erlauben', - participantsMuteAria: 'Vorschläge von {{user}} sperren', - participantsUnmuteAria: 'Vorschläge von {{user}} wieder erlauben', - confirmRemoveTitle: 'Aus Session entfernen?', - confirmRemoveBody: '{{user}} wird aus der Session geworfen, kann aber jederzeit über deinen Einladungslink wieder beitreten.', - confirmRemoveConfirm: 'Entfernen', - confirmBanTitle: 'Permanent bannen?', - confirmBanBody: '{{user}} wird entfernt und kann dieser Session nicht wieder beitreten. Für die Lebensdauer der Session nicht rückgängig zu machen.', - confirmBanConfirm: 'Bannen', - confirmCancel: 'Abbrechen', - confirmJoinTitle: 'Orbit-Session beitreten?', - confirmJoinBody: '{{host}} lädt dich zu „{{name}}" ein. Möchtest du der Session beitreten?', - confirmJoinConfirm: 'Beitreten', - confirmLeaveTitle: 'Session verlassen?', - confirmLeaveBody: '„{{name}}" wirklich verlassen? Du kannst jederzeit über {{host}}s Einladungslink wieder beitreten.', - confirmLeaveConfirm: 'Verlassen', - confirmEndTitle: 'Session für alle beenden?', - confirmEndBody: '„{{name}}" wird für alle Teilnehmer geschlossen. Die Session-Playlists werden automatisch aufgeräumt.', - confirmEndConfirm: 'Session beenden', - invalidLinkTitle: 'Einladungslink ist nicht mehr gültig', - invalidLinkBody: 'Diese Orbit-Session existiert nicht mehr oder wurde bereits beendet. Bitte den Gastgeber um einen neuen Einladungslink.', - settingsTitle: 'Session-Einstellungen', - settingAutoApprove: 'Vorschläge automatisch übernehmen', - settingAutoApproveHint: 'Neue Gäste-Vorschläge landen sofort in deiner Warteschlange. Aus: sie bleiben in der Session-Liste, du musst sie später manuell übernehmen.', - settingAutoShuffle: 'Automatisch mischen', - settingAutoShuffleHint: 'Periodischer Fisher-Yates-Shuffle der kommenden Warteschlange. Aus: Reihenfolge wird nur verändert, wenn du selbst sortierst.', - settingShuffleInterval: 'Alle', - settingShuffleIntervalHint: 'Wie oft die kommende Warteschlange während der Session neu gemischt wird.', - suggestBlockedMuted: 'Der Host hat dich für diese Session gesperrt — keine Vorschläge möglich.', - settingShuffleIntervalValue_one: '{{count}} Min.', - settingShuffleIntervalValue_other: '{{count}} Min.', - settingShuffleNow: 'Jetzt mischen', - toastSuggested: '{{user}} hat „{{title}}" vorgeschlagen', - toastSuggestedMany: '{{count}} neue Vorschläge in der Warteschlange', - toastShuffled: 'Warteschlange gemischt', - toastJoined: 'Session beigetreten', - toastLoginFirst: 'Erst anmelden, um einer Session beizutreten', - toastSwitchServer: 'Wechsle erst zu {{url}} und füge den Link dann erneut ein', - toastNoAccountForServer: 'Du hast keinen Zugang zu {{url}}. Bitte den Host um einen Einladungslink.', - toastSwitchFailed: 'Wechsel zu {{url}} fehlgeschlagen', - accountPickerTitle: 'Welcher Account?', - accountPickerSub: 'Du hast mehrere Accounts für {{url}}. Wähle aus, mit welchem du der Session beitreten willst.', - toastJoinFail: 'Session konnte nicht beigetreten werden', - joinErrNotFound: 'Session nicht gefunden', - joinErrEnded: 'Session wurde beendet', - joinErrFull: 'Session ist voll', - joinErrKicked: 'Du kannst dieser Session nicht mehr beitreten', - joinErrNoUser: 'Kein aktiver Server', - joinErrServerError: 'Beitritt fehlgeschlagen', - ctxAddToSession: 'Zur Orbit-Session hinzufügen', - ctxSuggestedToast: 'An Session vorgeschlagen', - ctxSuggestFailed: 'Vorschlag fehlgeschlagen — nicht beigetreten', - ctxAddToSessionHost: 'Zur Orbit-Session hinzufügen', - ctxAddedHostToast: 'Zur Session hinzugefügt', - ctxAddHostFailed: 'Hinzufügen fehlgeschlagen', - bulkConfirmTitle: 'Wirklich alles in die Orbit-Queue?', - bulkConfirmBody: 'Das würde {{count}} Titel auf einmal in die geteilte Queue werfen. Für deine Gäste ist das eine Menge. Trotzdem hinzufügen?', - bulkConfirmYes: 'Alle hinzufügen', - bulkConfirmNo: 'Abbrechen', - guestLive: 'Live', - guestPlaying: 'Läuft gerade', - guestPaused: 'Pausiert', - guestLoading: 'Lade…', - guestSuggestions: 'Vorschläge', - guestUpNext: 'Als Nächstes', - guestUpNextEmpty: 'Nichts in der Warteschlange. Öffne bei einem Song das Kontextmenü und wähle „Zur Orbit-Session hinzufügen", um etwas vorzuschlagen.', - guestPendingTitle: 'Wartet auf Host', - guestPendingHint: 'Vorgeschlagen — taucht in der Warteschlange auf, sobald der Host sie übernimmt.', - approvalTitle: 'Zur Freigabe', - approvalFrom: 'Vorgeschlagen von {{user}}', - approvalAccept: 'Übernehmen', - approvalDecline: 'Ablehnen', - guestUpNextMore: '+ {{count}} weitere in der Host-Warteschlange', - guestSubmitter: 'von {{user}}', - queueAddedByHost: 'Vom Host hinzugefügt', - queueAddedByYou: 'Von dir hinzugefügt', - queueAddedByUser: 'Hinzugefügt von {{user}}', - guestEmpty: 'Noch keine Vorschläge. Öffne bei einem Song das Kontextmenü und wähle „Zur Orbit-Session hinzufügen".', - guestFooter: 'Die Wiedergabe wird vom Gastgeber gesteuert — du kannst die Liste nicht ändern.', - exitKickedTitle: 'Du wurdest aus der Session gebannt', - exitRemovedTitle: 'Du wurdest aus der Session entfernt', - exitEndedTitle: 'Der Gastgeber hat die Session beendet', - exitHostTimeoutTitle: 'Host nicht mehr erreichbar', - exitHostTimeoutBody: '{{host}} hat sich länger nicht mehr gemeldet — „{{name}}" wurde auf deiner Seite beendet. Über den Einladungslink kannst du jederzeit wieder beitreten.', - exitKickedBody: '{{host}} hat dich aus „{{name}}" gebannt. Beitritt nicht mehr möglich.', - exitRemovedBody: '{{host}} hat dich aus „{{name}}" entfernt. Du kannst jederzeit über den Einladungslink wieder beitreten.', - exitEndedBody: '„{{name}}" ist zu Ende. Hoffentlich war\'s schön.', - exitOk: 'OK', - }, - tray: { - playPause: 'Wiedergabe / Pause', - nextTrack: 'Nächster Titel', - previousTrack: 'Vorheriger Titel', - showHide: 'Anzeigen / Verbergen', - exitPsysonic: 'Psysonic beenden', - nothingPlaying: 'Nichts wird abgespielt', - }, - licenses: { - title: 'Open-Source-Lizenzen', - intro: 'Psysonic basiert auf Open-Source-Software. Die untenstehende Liste zeigt jede Abhängigkeit, die mit der App ausgeliefert wird, inklusive Version, Lizenz und vollständigem Lizenztext.', - highlights: 'Wichtige Abhängigkeiten', - searchPlaceholder: 'Suche nach Name, Version oder Lizenz…', - noResults: 'Keine Treffer.', - loading: 'Lizenzen werden geladen…', - loadError: 'Lizenzdaten konnten nicht geladen werden.', - noLicenseText: 'Für diese Abhängigkeit ist kein Lizenztext gebündelt.', - viewSource: 'Quelle anzeigen', - totalLine: '{{total}} Abhängigkeiten — {{cargo}} Cargo, {{npm}} npm', - generatedAt: 'Zuletzt generiert {{date}}', - }, -}; diff --git a/src/locales/de/albumDetail.ts b/src/locales/de/albumDetail.ts new file mode 100644 index 00000000..6b89ff2d --- /dev/null +++ b/src/locales/de/albumDetail.ts @@ -0,0 +1,47 @@ +export const albumDetail = { + back: 'Zurück', + orbitDoubleClickHint: 'Doppelklick fügt diesen Titel zur Orbit-Queue hinzu', + playAll: 'Alle abspielen', + shareAlbum: 'Album teilen', + enqueue: 'Einreihen', + enqueueTooltip: 'Ganzes Album zur Warteschlange hinzufügen', + artistBio: 'Künstler-Bio', + download: 'Download (ZIP)', + downloading: 'Lade…', + cacheOffline: 'Offline verfügbar machen', + offlineCached: 'Offline verfügbar', + offlineDownloading: 'Wird gecacht… ({{n}}/{{total}})', + removeOffline: 'Offline-Cache löschen', + offlineStorageFull: 'Offline-Speicher voll (Limit: {{mb}} MB). Lösche ein Album aus der Offline-Bibliothek oder erhöhe das Limit in den Einstellungen.', + offlineStorageGoToSettings: 'Einstellungen', + offlineStorageGoToLibrary: 'Offline-Bibliothek', + favoriteAdd: 'Zu Favoriten hinzufügen', + favoriteRemove: 'Aus Favoriten entfernen', + favorite: 'Als Favorit', + noBio: 'Keine Biografie verfügbar.', + moreByArtist: 'Mehr von {{artist}}', + tracksCount: '{{n}} Tracks', + goToArtist: 'Zu {{artist}} wechseln', + moreLabelAlbums: 'Weitere Alben von {{label}} anzeigen', + trackTitle: 'Titel', + trackAlbum: 'Album', + trackArtist: 'Interpret', + trackGenre: 'Genre', + trackFormat: 'Format', + trackFavorite: 'Favorit', + trackRating: 'Bewertung', + trackDuration: 'Dauer', + trackTotal: 'Gesamt', + columns: 'Spalten', + resetColumns: 'Zurücksetzen', + notFound: 'Album nicht gefunden.', + bioModal: 'Künstler-Biografie', + bioClose: 'Schließen', + ratingLabel: 'Bewertung', + enlargeCover: 'Vergrößern', + filterSongs: 'Titel filtern…', + sortNatural: 'Reihenfolge', + sortByTitle: 'A–Z (Titel)', + sortByArtist: 'A–Z (Künstler)', + sortByAlbum: 'A–Z (Album)', +}; diff --git a/src/locales/de/albums.ts b/src/locales/de/albums.ts new file mode 100644 index 00000000..da4b29f5 --- /dev/null +++ b/src/locales/de/albums.ts @@ -0,0 +1,32 @@ +export const albums = { + title: 'Alle Alben', + sortByName: 'A–Z (Album)', + sortByArtist: 'A–Z (Künstler)', + sortNewest: 'Neueste zuerst', + sortRandom: 'Zufällig', + yearFrom: 'Von', + yearTo: 'Bis', + yearFilterClear: 'Jahresfilter zurücksetzen', + yearFilterLabel: 'Jahr', + compilationLabel: 'Sampler', + compilationOnly: 'Nur Sampler', + compilationHide: 'Ohne Sampler', + compilationTooltipAll: 'Alle Alben · klicken: nur Sampler', + compilationTooltipOnly: 'Nur Sampler · klicken: Sampler ausblenden', + compilationTooltipHide: 'Sampler ausgeblendet · klicken: alle zeigen', + select: 'Mehrfachauswahl', + startSelect: 'Mehrfachauswahl aktivieren', + cancelSelect: 'Abbrechen', + selectionCount: '{{count}} ausgewählt', + downloadZips: 'ZIPs herunterladen', + addOffline: 'Offline hinzufügen', + enqueueSelected_one: 'Einreihen ({{count}})', + enqueueSelected_other: 'Einreihen ({{count}})', + enqueueQueued_one: '{{count}} Album zur Warteschlange hinzugefügt', + enqueueQueued_other: '{{count}} Alben zur Warteschlange hinzugefügt', + downloadingZip: 'Lade {{current}}/{{total}} herunter: {{name}}', + downloadZipDone: '{{count}} ZIP(s) heruntergeladen', + downloadZipFailed: 'Download fehlgeschlagen: {{name}}', + offlineQueuing: '{{count}} Album(s) für Offline einreihen…', + offlineFailed: '{{name}} konnte nicht offline hinzugefügt werden', +}; diff --git a/src/locales/de/artistDetail.ts b/src/locales/de/artistDetail.ts new file mode 100644 index 00000000..8df7081f --- /dev/null +++ b/src/locales/de/artistDetail.ts @@ -0,0 +1,41 @@ +export const artistDetail = { + back: 'Zurück', + albums: 'Alben', + album: 'Album', + playAll: 'Alle abspielen', + shareArtist: 'Künstler teilen', + shuffle: 'Zufallswiedergabe', + radio: 'Radio', + loading: 'Lädt…', + noRadio: 'Keine ähnlichen Titel für diesen Künstler gefunden.', + notFound: 'Künstler nicht gefunden.', + albumsBy: 'Alben von {{name}}', + topTracks: 'Beliebteste Titel', + noAlbums: 'Keine Alben gefunden.', + trackTitle: 'Titel', + trackAlbum: 'Album', + trackDuration: 'Dauer', + favoriteAdd: 'Zu Favoriten hinzufügen', + favoriteRemove: 'Aus Favoriten entfernen', + favorite: 'Als Favorit', + albumCount_one: '{{count}} Album', + albumCount_other: '{{count}} Alben', + openedInBrowser: 'Im Browser geöffnet', + featuredOn: 'Auch enthalten auf', + similarArtists: 'Ähnliche Künstler', + cacheOffline: 'Diskografie offline speichern', + offlineCached: 'Diskografie gecacht', + offlineDownloading: 'Wird gecacht… ({{done}}/{{total}} Alben)', + uploadImage: 'Künstlerbild hochladen', + uploadImageError: 'Bild konnte nicht hochgeladen werden', + releaseTypes: { + album: 'Album', + ep: 'EP', + single: 'Single', + compilation: 'Kompilation', + live: 'Live', + soundtrack: 'Soundtrack', + remix: 'Remix', + other: 'Sonstige', + }, +}; diff --git a/src/locales/de/artists.ts b/src/locales/de/artists.ts new file mode 100644 index 00000000..d364f406 --- /dev/null +++ b/src/locales/de/artists.ts @@ -0,0 +1,18 @@ +export const artists = { + title: 'Künstler', + search: 'Suchen…', + all: 'Alle', + gridView: 'Gitteransicht', + listView: 'Listenansicht', + imagesOn: 'Künstlerbilder aktiv — kann Netzwerk- und Systemlast erhöhen', + imagesOff: 'Künstlerbilder deaktiviert — zeigt nur Initialen', + loadMore: 'Mehr laden', + notFound: 'Keine Künstler gefunden.', + albumCount_one: '{{count}} Album', + albumCount_other: '{{count}} Alben', + selectionCount: '{{count}} ausgewählt', + select: 'Mehrfachauswahl', + startSelect: 'Mehrfachauswahl aktivieren', + cancelSelect: 'Abbrechen', + addToPlaylist: 'Zur Playlist hinzufügen', +}; diff --git a/src/locales/de/changelog.ts b/src/locales/de/changelog.ts new file mode 100644 index 00000000..52f3005c --- /dev/null +++ b/src/locales/de/changelog.ts @@ -0,0 +1,5 @@ +export const changelog = { + modalTitle: 'Was ist neu', + dontShowAgain: 'Nicht mehr anzeigen', + close: 'Verstanden', +}; diff --git a/src/locales/de/common.ts b/src/locales/de/common.ts new file mode 100644 index 00000000..3fb487aa --- /dev/null +++ b/src/locales/de/common.ts @@ -0,0 +1,66 @@ +export const common = { + albums: 'Alben', + album: 'Album', + loading: 'Lade…', + loadingMore: 'Lade…', + loadingPlaylists: 'Lade Playlists…', + noAlbums: 'Keine Alben gefunden.', + downloading: 'Lade…', + downloadZip: 'Download (ZIP)', + back: 'Zurück', + cancel: 'Abbrechen', + close: 'Schließen', + save: 'Speichern', + delete: 'Löschen', + use: 'Verwenden', + add: 'Hinzufügen', + new: 'Neu', + active: 'Aktiv', + download: 'Herunterladen', + chooseDownloadFolder: 'Download-Ordner wählen', + noFolderSelected: 'Kein Ordner ausgewählt', + rememberDownloadFolder: 'Ordner merken', + filterGenre: 'Genre-Filter', + filterSearchGenres: 'Genres suchen…', + filterNoGenres: 'Keine Genres gefunden', + filterClear: 'Zurücksetzen', + favorites: 'Favoriten', + favoritesTooltipOff: 'Nur Favoriten anzeigen', + favoritesTooltipOn: 'Alle anzeigen', + play: 'Abspielen', + bulkSelected: '{{count}} ausgewählt', + clearSelection: 'Auswahl aufheben', + bulkAddToPlaylist: 'Zur Playlist hinzufügen', + bulkRemoveFromPlaylist: 'Aus Playlist entfernen', + bulkClear: 'Auswahl aufheben', + updaterAvailable: 'Update verfügbar', + updaterVersion: 'v{{version}} verfügbar', + updaterWebsite: 'Website', + updaterModalTitle: 'Neue Version verfügbar', + updaterChangelog: 'Was ist neu', + updaterDownloadBtn: 'Jetzt herunterladen', + updaterSkipBtn: 'Version überspringen', + updaterRemindBtn: 'Später erinnern', + updaterDone: 'Download abgeschlossen', + updaterShowFolder: 'Im Ordner anzeigen', + updaterInstallHint: 'Psysonic schließen und das Installationsprogramm manuell ausführen.', + updaterAurHint: 'Update über AUR installieren:', + updaterErrorMsg: 'Download fehlgeschlagen', + updaterInstallNow: 'Jetzt installieren', + updaterMacReadyTitle: 'Bereit zur Installation', + updaterMacReady: 'Das Update wird heruntergeladen, verifiziert und direkt übernommen — keine DMG nötig. Die App startet anschließend automatisch neu.', + updaterTrustNotarized: 'Von Apple beglaubigt', + updaterTrustSignature: 'Signatur verifiziert', + updaterMacDoneTitle: 'Update installiert', + updaterRestartingIn: 'Neustart in {{n}}s …', + updaterRestarting: 'Neustart läuft …', + updaterRestartNow: 'Jetzt neu starten', + updaterRetryBtn: 'Erneut versuchen', + durationHoursMinutes: '{{hours}} Std. {{minutes}} Min.', + durationMinutesOnly: '{{minutes}} Min.', + updaterOpenGitHub: 'Auf GitHub öffnen', + filters: 'Filter', + more: 'mehr', + yearRange: 'Jahresbereich', + clearAll: 'Alles zurücksetzen', +}; diff --git a/src/locales/de/composerDetail.ts b/src/locales/de/composerDetail.ts new file mode 100644 index 00000000..12b8b7e7 --- /dev/null +++ b/src/locales/de/composerDetail.ts @@ -0,0 +1,11 @@ +export const composerDetail = { + back: 'Zurück', + notFound: 'Komponist*in nicht gefunden.', + about: 'Über diese*n Komponist*in', + works: 'Werke', + noWorks: 'Keine Werke gefunden.', + workCount_one: '{{count}} Werk', + workCount_other: '{{count}} Werke', + shareComposer: 'Komponist*in teilen', + unknownComposer: 'Komponist*in', +}; diff --git a/src/locales/de/composers.ts b/src/locales/de/composers.ts new file mode 100644 index 00000000..6e383bee --- /dev/null +++ b/src/locales/de/composers.ts @@ -0,0 +1,10 @@ +export const composers = { + title: 'Komponist*innen', + search: 'Suchen…', + notFound: 'Keine Komponist*innen gefunden.', + unsupported: 'Komponist-Ansicht benötigt Navidrome 0.55 oder neuer.', + loadFailed: 'Komponist*innen konnten nicht geladen werden.', + retry: 'Erneut versuchen', + involvedIn_one: 'Beteiligt an {{count}} Album', + involvedIn_other: 'Beteiligt an {{count}} Alben', +}; diff --git a/src/locales/de/connection.ts b/src/locales/de/connection.ts new file mode 100644 index 00000000..eb6e32a8 --- /dev/null +++ b/src/locales/de/connection.ts @@ -0,0 +1,28 @@ +export const connection = { + connected: 'Verbunden', + connectedTo: 'Verbunden mit {{server}}', + disconnected: 'Getrennt', + disconnectedFrom: '{{server}} nicht erreichbar — klicken für Einstellungen', + checking: 'Verbinde…', + extern: 'Extern', + offlineTitle: 'Keine Serververbindung', + offlineSubtitle: '{{server}} ist nicht erreichbar. Prüfe Netzwerk oder Server.', + offlineModeBanner: 'Offline-Modus — Wiedergabe aus lokalem Cache', + offlineNoCacheBanner: 'Keine Serververbindung — {{server}} nicht erreichbar', + offlineLibraryTitle: 'Offline-Bibliothek', + offlineLibraryEmpty: 'Noch keine Alben gecacht. Online gehen, Album öffnen und "Offline verfügbar machen" klicken.', + offlineAlbumCount: '{{n}} Album', + offlineAlbumCount_plural: '{{n}} Alben', + offlineFilterAll: 'Alle', + offlineFilterAlbums: 'Alben', + offlineFilterPlaylists: 'Playlists', + offlineFilterArtists: 'Diskografien', + retry: 'Erneut versuchen', + serverSettings: 'Server-Einstellungen', + switchServerTitle: 'Server wechseln', + switchServerHint: 'Klicken, um einen anderen gespeicherten Server zu wählen.', + manageServers: 'Server verwalten…', + switchFailed: 'Wechsel fehlgeschlagen — Server nicht erreichbar.', + lastfmConnected: 'Last.fm verbunden als @{{user}}', + lastfmSessionInvalid: 'Session ungültig — klicken zum Neu-Verbinden', +}; diff --git a/src/locales/de/contextMenu.ts b/src/locales/de/contextMenu.ts new file mode 100644 index 00000000..2666bc60 --- /dev/null +++ b/src/locales/de/contextMenu.ts @@ -0,0 +1,33 @@ +export const contextMenu = { + playNow: 'Direkt abspielen', + playNext: 'Als Nächstes abspielen', + addToQueue: 'Zur Warteschlange hinzufügen', + enqueueAlbum: 'Ganzes Album einreihen', + enqueueAlbums_one: '{{count}} Album einreihen', + enqueueAlbums_other: '{{count}} Alben einreihen', + startRadio: 'Radio starten', + instantMix: 'Instant Mix', + instantMixFailed: 'Instant Mix konnte nicht erstellt werden — Server- oder Pluginfehler.', + cliMixNeedsTrack: 'Es läuft nichts — starte zuerst die Wiedergabe und führe den Mix-Befehl erneut aus.', + lfmLove: 'Auf Last.fm liken', + lfmUnlove: 'Last.fm-Like entfernen', + favorite: 'Favorisieren', + favoriteArtist: 'Künstler favorisieren', + favoriteAlbum: 'Album favorisieren', + unfavorite: 'Aus Favoriten entfernen', + unfavoriteArtist: 'Künstler aus Favoriten entfernen', + unfavoriteAlbum: 'Album aus Favoriten entfernen', + removeFromQueue: 'Diesen Song entfernen', + removeFromPlaylist: 'Aus Playlist entfernen', + openAlbum: 'Album öffnen', + goToArtist: 'Zum Künstler', + download: 'Herunterladen (ZIP)', + addToPlaylist: 'Zur Playlist hinzufügen', + selectedPlaylists: '{{count}} Playlists ausgewählt', + selectedAlbums: '{{count}} Alben ausgewählt', + selectedArtists: '{{count}} Künstler ausgewählt', + songInfo: 'Song-Infos', + shareLink: 'Freigabe-Link kopieren', + shareCopied: 'Freigabe-Link wurde in die Zwischenablage kopiert.', + shareCopyFailed: 'Kopieren in die Zwischenablage fehlgeschlagen.', +}; diff --git a/src/locales/de/deviceSync.ts b/src/locales/de/deviceSync.ts new file mode 100644 index 00000000..8a17bdae --- /dev/null +++ b/src/locales/de/deviceSync.ts @@ -0,0 +1,79 @@ +export const deviceSync = { + title: 'Gerätesync', + targetFolder: 'Zielordner', + noFolderChosen: 'Kein Ordner gewählt', + selectDrive: 'Laufwerk auswählen…', + refreshDrives: 'Laufwerke aktualisieren', + noDrivesDetected: 'Keine Wechseldatenträger erkannt', + browseManual: 'Manuell durchsuchen…', + free: 'frei', + notMountedVolume: 'Ziel befindet sich nicht auf einem eingehängten Laufwerk. Das Gerät wurde möglicherweise getrennt.', + chooseFolder: 'Auswählen…', + targetDevice: 'Zielgerät', + schemaLabel: 'Benennungsschema', + schemaHint: 'Festes Schema für zuverlässige Synchronisation über verschiedene Betriebssysteme hinweg. Playlists werden als .m3u8-Dateien geschrieben und referenzieren die Album-Tracks — keine Duplikate auf dem Gerät.', + migrateButton: 'Bestehende Dateien re-organisieren…', + migrateTooltip: 'Vorhandene Dateien auf dem Gerät nach dem neuen Schema umbenennen (basierend auf der alten Namensvorlage).', + migrateTitle: 'Bestehende Dateien re-organisieren', + migrateLoading: 'Analysiere vorhandene Dateien…', + migrateNothingToDo: 'Alle vorhandenen Dateien entsprechen bereits dem neuen Schema — nichts zu tun.', + migrateNoTemplate: 'Keine alte Namensvorlage auf dem Gerät gefunden. Migration ist nur möglich, wenn der Stick mit einer Psysonic-Version synchronisiert wurde, die konfigurierbare Vorlagen unterstützte.', + migrateFilesToRename: 'Dateien werden umbenannt', + migrateUnchanged: '{{n}} Dateien liegen bereits am korrekten Pfad', + migrateCollisions: '{{n}} Dateien können nicht automatisch umbenannt werden (mehrere Tracks zeigen auf dasselbe Ziel). Sie bleiben unverändert — beim nächsten Sync werden sie neu heruntergeladen.', + migratePreviewNote: 'Alte Vorlage: {{tpl}}', + migrateExecuting: 'Dateien werden umbenannt…', + migrateSuccess: '{{n}} Dateien erfolgreich umbenannt', + migrateFailed: '{{n}} Umbenennungen fehlgeschlagen', + migrateShowErrors: 'Fehler anzeigen', + migrateStart: 'Umbenennen starten', + onDevice: 'Auf dem Gerät', + addSources: 'Hinzufügen…', + colName: 'Name', + colType: 'Typ', + syncResult: '{{done}} übertragen, {{skipped}} bereits aktuell ({{total}} gesamt)', + deleteFromDevice: 'Vom Gerät löschen ({{count}})', + confirmDelete: '{{count}} Eintrag/Einträge vom Gerät löschen: {{names}}?', + deleteComplete: '{{count}} Eintrag/Einträge vom Gerät entfernt.', + manifestImported: '{{count}} Quelle(n) aus Geräte-Manifest importiert.', + selectedSources: 'Ausgewählte Quellen', + noSourcesSelected: 'Keine Quellen ausgewählt. Klicke auf Einträge im Browser um sie hinzuzufügen.', + clearAll: 'Alle entfernen', + tabPlaylists: 'Wiedergabelisten', + tabAlbums: 'Alben', + tabArtists: 'Künstler', + searchPlaceholder: 'Suche…', + syncButton: 'Auf Gerät übertragen', + actionTransfer: 'Auf Gerät übertragen', + actionDelete: 'Vom Gerät löschen', + actionApplyAll: 'Änderungen synchronisieren', + cancel: 'Abbrechen', + noTargetDir: 'Bitte zuerst einen Zielordner auswählen.', + noSources: 'Bitte mindestens eine Quelle auswählen.', + noTracks: 'Keine Tracks in den ausgewählten Quellen gefunden.', + fetchError: 'Fehler beim Laden der Tracks vom Server.', + syncComplete: 'Übertragung abgeschlossen.', + dismiss: 'Schließen', + cancelSync: 'Abbrechen', + syncCancelled: 'Sync abgebrochen ({{done}} / {{total}} übertragen).', + colStatus: 'Status', + statusSynced: 'Synchronisiert', + statusPending: 'Ausstehend', + statusDeletion: 'Löschung', + markForDeletion: 'Zur Löschung markieren', + removeSource: 'Entfernen', + undoDeletion: 'Löschung rückgängig', + syncInBackground: 'Sync gestartet — du kannst die Seite verlassen.', + syncInProgress: '{{done}} / {{total}} Tracks…', + syncSummary: 'Sync-Zusammenfassung', + calculating: 'Payload wird berechnet…', + filesToAdd: 'Hinzuzufügende Dateien:', + filesToDelete: 'Zu löschende Dateien:', + netChange: 'Nettoänderung:', + availableSpace: 'Verfügbarer Speicher:', + spaceWarning: 'Warnung: Das Zielgerät hat nicht genug gemeldeten Speicherplatz.', + proceed: 'Sync durchführen', + notEnoughSpace: 'Nicht genug physischer Speicherplatz erkannt!', + liveSearch: 'Live', + randomAlbumsLabel: 'Zufallsalben', +}; diff --git a/src/locales/de/entityRating.ts b/src/locales/de/entityRating.ts new file mode 100644 index 00000000..7b79fb80 --- /dev/null +++ b/src/locales/de/entityRating.ts @@ -0,0 +1,9 @@ +export const entityRating = { + albumShort: 'Albumbewertung', + artistShort: 'Künstlerbewertung', + albumAriaLabel: 'Albumbewertung', + artistAriaLabel: 'Künstlerbewertung', + selectedArtistsRatingAriaLabel: 'Sternebewertung für {{count}} ausgewählte Künstler', + selectedAlbumsRatingAriaLabel: 'Sternebewertung für {{count}} ausgewählte Alben', + saveFailed: 'Bewertung konnte nicht gespeichert werden.', +}; diff --git a/src/locales/de/favorites.ts b/src/locales/de/favorites.ts new file mode 100644 index 00000000..4dd74af8 --- /dev/null +++ b/src/locales/de/favorites.ts @@ -0,0 +1,19 @@ +export const favorites = { + title: 'Favoriten', + empty: 'Du hast noch keine Favoriten gespeichert.', + artists: 'Künstler', + albums: 'Alben', + songs: 'Songs', + enqueueAll: 'Alle in die Warteschlange', + playAll: 'Alle abspielen', + removeSong: 'Aus Favoriten entfernen', + stations: 'Radiosender', + showingFiltered: 'Zeige {{filtered}} von {{total}} ({{artist}})', + showingCount: 'Zeige {{filtered}} von {{total}}', + clearArtistFilter: 'Künstlerfilter zurücksetzen', + noFilterResults: 'Keine Ergebnisse mit den ausgewählten Filtern.', + allArtists: 'Alle Künstler', + topArtists: 'Top-Künstler nach Favoriten', + topArtistsSongCount_one: '{{count}} Song', + topArtistsSongCount_other: '{{count}} Songs', +}; diff --git a/src/locales/de/folderBrowser.ts b/src/locales/de/folderBrowser.ts new file mode 100644 index 00000000..1b434ea6 --- /dev/null +++ b/src/locales/de/folderBrowser.ts @@ -0,0 +1,4 @@ +export const folderBrowser = { + empty: 'Leerer Ordner', + error: 'Laden fehlgeschlagen', +}; diff --git a/src/locales/de/genres.ts b/src/locales/de/genres.ts new file mode 100644 index 00000000..41197333 --- /dev/null +++ b/src/locales/de/genres.ts @@ -0,0 +1,12 @@ +export const genres = { + title: 'Genres', + genreCount: 'Genres', + albumCount_one: '{{count}} Album', + albumCount_other: '{{count}} Alben', + loading: 'Genres werden geladen…', + empty: 'Keine Genres gefunden.', + albumsLoading: 'Alben werden geladen…', + albumsEmpty: 'Keine Alben in diesem Genre gefunden.', + loadMore: 'Mehr laden', + back: 'Zurück', +}; diff --git a/src/locales/de/help.ts b/src/locales/de/help.ts new file mode 100644 index 00000000..ca175e1b --- /dev/null +++ b/src/locales/de/help.ts @@ -0,0 +1,115 @@ +export const help = { + title: 'Hilfe', + searchPlaceholder: 'Hilfe durchsuchen…', + noResults: 'Keine passenden Themen. Versuche einen anderen Suchbegriff.', + // ── Section 1: Erste Schritte ────────────────────────────────────────── + s1: 'Erste Schritte', + q1: 'Welche Server sind kompatibel?', + a1: 'Psysonic ist primär für Navidrome gebaut und voll Subsonic-kompatibel — Gonic, Airsonic, LMS und andere Subsonic-API-Server funktionieren ebenfalls. Einige fortgeschrittene Features (Bewertungen, Smart Playlists, Magic-String-Sharing, User-Verwaltung) erfordern Navidrome.', + q2: 'Wie füge ich einen Server hinzu?', + a2: 'Einstellungen → Server → Server hinzufügen. URL eingeben (z. B. http://192.168.1.100:4533), Benutzername und Passwort. Psysonic testet die Verbindung vor dem Speichern — bei Fehler wird nichts gespeichert. Du kannst beliebig viele Server hinzufügen und im Header zwischen ihnen wechseln; immer ist nur einer aktiv.', + q3: 'Schnelle UI-Tour?', + a3: 'Sidebar (links) für Navigation, Mainstage / Seiten in der Mitte, Playerleiste unten, Warteschlangen-Panel rechts (über das Icon oben rechts neben dem Now-Playing-Indikator). Die Suche oben durchsucht die gesamte Bibliothek; "Now Playing" zeigt, was andere Nutzer auf dem gleichen Navidrome-Server gerade hören.', + // ── Section 2: Wiedergabe & Warteschlange ────────────────────────────── + s2: 'Wiedergabe & Warteschlange', + q4: 'Wie nutze ich die Warteschlange?', + a4: 'Warteschlangen-Panel oben rechts öffnen. Zeilen per Drag & Drop umsortieren, nach außen ziehen zum Entfernen, oder über die Toolbar mischen, als Playlist speichern oder zu einem Track springen. Zeilen lassen sich auch aus dem Panel heraus an andere Stellen ziehen.', + q5: 'Gapless vs. Crossfade — was ist der Unterschied?', + a5: 'Gapless puffert den nächsten Track vor, sodass keine Stille zwischen Songs entsteht (ideal für Live-Alben und DJ-Mixe). Crossfade blendet den aktuellen Track aus, während der nächste eingeblendet wird (1–10 s, gut für gemischte Mixe). Die zwei sind gegenseitig exklusiv — eines aktivieren deaktiviert das andere. Konfiguration in Einstellungen → Audio.', + q6: 'Was ist die Infinite Queue?', + a6: 'Wenn die Warteschlange leerläuft und Wiederholen aus ist, hängt Psysonic ähnliche / zufällige Tracks aus deiner Bibliothek hinten dran, sodass die Wiedergabe nie stoppt. Auto-hinzugefügte Tracks erscheinen unter dem Trenner „— Automatisch hinzugefügt —". Umschalten über das Unendlichkeits-Icon im Warteschlangen-Header; in Einstellungen → Warteschlange auf ein Genre einschränken.', + q7: 'Mehrfachauswahl und Shift-Klick-Bereich?', + a7: 'Im Mehrfach-Modus auf Alben / New Releases / Random Albums / Playlists: Klick toggelt einen Eintrag, dann Shift halten und einen anderen Eintrag klicken — alles dazwischen in der sichtbaren Reihenfolge wird ausgewählt. Shift-Klicks erweitern vom zuletzt geklickten Anker. Die Toolbar oben bietet Bulk-Aktionen (Queue, Download, Löschen usw.).', + q8: 'Tastenkürzel und globale Hotkeys?', + a8: 'Standard-In-App-Tasten: Leertaste = Play / Pause, Esc = Vollbild / Modal schließen, F1 = Shortcut-Spickzettel. Einstellungen → Eingabe lässt jede In-App-Aktion neu zuweisen (auch als Akkorde wie Strg+Shift+P) und systemweite globale Shortcuts setzen, die auch im Hintergrund oder minimiert funktionieren. Medientasten (Play/Pause, Weiter, Zurück) funktionieren auf allen Plattformen.', + // ── Section 3: Audio-Werkzeuge ───────────────────────────────────────── + s3: 'Audio-Werkzeuge', + q9: 'Replay-Gain-Modi?', + a9: 'Einstellungen → Audio → Replay Gain. Track-Modus normalisiert jeden Song auf einen Zielpegel. Album-Modus erhält die Lautstärke-Kurve innerhalb eines Albums. Auto-Modus wählt Track oder Album je nachdem, ob die Warteschlange aus einem einzelnen Album stammt. Tracks ohne Replay-Gain-Tags fallen auf einen konfigurierbaren Preamp zurück.', + q10: 'Was ist Smart Loudness Normalization (LUFS)?', + a10: 'Eine moderne Alternative zu Replay Gain in Einstellungen → Audio. Psysonic analysiert jeden Track nach LUFS / EBU R128 und speichert das Ergebnis, sodass die Lautstärke über die gesamte Bibliothek konsistent ist — auch bei Tracks ohne Replay-Gain-Tags. Die Cold-Cache-Analyse läuft im Hintergrund und nutzt 35–40 % CPU für ~1 Minute, danach 0. Ziel-Lautstärke (Standard −10 LUFS) einmal festlegen.', + q11: 'EQ und AutoEQ?', + a11: 'Ein 10-Band-Parametrik-EQ in Einstellungen → Audio → Equalizer mit manuellen Bändern und Presets. AutoEQ daneben holt ein gemessenes Korrekturprofil für dein Kopfhörermodell aus der AutoEQ-Datenbank und überträgt es automatisch auf die Bänder — Kopfhörer wählen, der EQ rastet auf der korrekten Kurve ein.', + q12: 'Wie wechsle ich das Audio-Ausgabegerät?', + a12: 'Einstellungen → Audio → Ausgabegerät. Psysonic listet alle verfügbaren Ausgaben und wechselt sofort beim Auswählen. Der Aktualisierungs-Button scannt nach Geräten, die nach dem Start angeschlossen wurden. Linux-ALSA-Namen wie „sysdefault" werden für die Lesbarkeit automatisch bereinigt.', + q13: 'Was ist der Hot Cache?', + a13: 'Der Hot Cache lädt den aktuellen Track plus die nächsten in den RAM und auf die Festplatte vor, sodass die Wiedergabe ohne Pufferverzögerung startet — besonders nützlich bei langsamen / entfernten Servern. Eviction greift, wenn das Größenlimit erreicht ist. Größe und Debounce-Verzögerung (damit schnelle Skips nicht überfetchen) in Einstellungen → Audio.', + // ── Section 4: Bibliothek & Discovery ────────────────────────────────── + s4: 'Bibliothek & Discovery', + q14: 'Wie funktionieren Bewertungen und Skip-to-1★?', + a14: 'Psysonic unterstützt 1–5-Sterne-Bewertungen über OpenSubsonic (Navidrome ≥ 0.53). Songs in Tracklisten, im Rechtsklick-Menü oder in der Playerleiste unter dem Künstlernamen bewerten; Alben auf der Albumseite; Künstler auf der Künstlerseite. Skip-to-1★ (Einstellungen → Bibliothek → Bewertungen) vergibt automatisch 1 Stern nach einer konfigurierbaren Anzahl aufeinanderfolgender Skips. Im selben Panel lässt sich eine Mindestbewertung als Filter für Random Mix und andere Mixes setzen.', + q15: 'Wie browse ich — Ordner, Genres, Tracks?', + a15: 'Der Ordner-Browser (Sidebar) navigiert durch das Musikverzeichnis des Servers im Miller-Column-Layout — Klick auf Ordner zum Öffnen, Klick auf Track oder Play-Icon eines Ordners zum Abspielen / Hinzufügen. Genres nutzt eine nach Track-Anzahl skalierte Tag-Cloud; Klick auf ein Genre öffnet es. Tracks ist ein flacher Library-Hub mit spaltensortierbarer virtueller Liste und Live-Suche.', + q16: 'Suche und erweiterte Suche?', + a16: 'Die Header-Suche läuft live während der Eingabe und durchsucht Künstler, Alben und Tracks. Die erweiterte Suche (Sidebar) bietet eine reichere Sicht: Filter nach Jahr, Genre, Bewertung, Format, Kanälen, Sample-Rate, BPM, Stimmung, kombinierbar. Rechtsklick auf jeden Treffer öffnet das gleiche Kontextmenü wie überall sonst in der App.', + q17: 'Was sind die Mixes (Random / Genre / Super Genre / Lucky)?', + a17: 'Random Mix erstellt eine Playlist aus zufälligen Tracks deiner Bibliothek; der Schlüsselwort-Filter schließt Hörbücher, Comedy etc. nach Genre / Titel / Album-Substrings aus. Super-Genre-Mix gruppiert deine Bibliothek in breite Stile (Rock, Metal, Electronic, Jazz, Klassik …) und erstellt einen fokussierten Mix. Lucky Mix nutzt Hörhistorie, Bewertungen und AudioMuse-AI-ähnliche Tracks, um per Klick eine sofortige Playlist zu bauen.', + q18: 'Statistik-Seite?', + a18: 'Statistik (Sidebar) zeigt Top-Künstler, Top-Alben, Top-Tracks, Genre-Verteilung, Hörzeit über die Zeit und pro Bibliothek, wenn mehrere Music Folder konfiguriert sind. Mehrere Ansichten lassen sich als teilbares Card-Bild exportieren.', + q19: 'Wie lade ich ein Album als ZIP herunter?', + a19: 'Albumseite → „Download (ZIP)". Der Server packt das Album zuerst — bei großen oder verlustfreien Alben (FLAC / WAV) erscheint der Fortschrittsbalken erst, wenn das Zippen fertig ist und der Transfer beginnt. Das ist normal.', + // ── Section 5: Lyrics ────────────────────────────────────────────────── + s5: 'Lyrics', + q20: 'Woher kommen die Lyrics?', + a20: 'Drei Quellen, konfigurierbar in Einstellungen → Lyrics: Navidrome-Server (eingebettete / OpenSubsonic-Lyrics), LRCLIB (community-gepflegte synchronisierte Texte) und NetEase Cloud Music (umfangreicher asiatischer + internationaler Katalog). Jede Quelle aktivieren / deaktivieren und per Drag & Drop priorisieren.', + q21: 'Wie zeige ich Lyrics während der Wiedergabe?', + a21: 'Klick auf das Mikrofon-Icon in der Playerleiste öffnet den Lyrics-Tab im Warteschlangen-Panel. Synchronisierte Lyrics scrollen automatisch und unterstützen Klick-zum-Springen; reine Texte scrollen als statischer Block. Den Vollbild-Player über das Cover in der Playerleiste öffnen für eine immersive Lyrics-Ansicht mit Mesh-Blob-Hintergrund.', + // ── Section 6: Sharing & Social ──────────────────────────────────────── + s6: 'Sharing & Social', + q22: 'Was sind Magic Strings?', + a22: 'Magic Strings sind kurze Copy-Paste-Tokens, die Dinge zwischen Psysonic-Nutzern ohne Drittanbieter-Server teilen. Server-Einladungs-Strings ermöglichen einem Freund das Onboarding auf deinem Navidrome mit einem Paste; Album- / Künstler- / Queue-Magic-Strings öffnen dasselbe Album / denselben Künstler / dieselbe Queue beim Empfänger. Aus dem Teilen-Menü generieren, in die Suche einfügen zum Konsumieren.', + q23: 'Was ist Orbit?', + a23: 'Orbit ist synchrones Zusammenhören: ein Host spielt einen Track, alle Gäste hören ihn synchron, und Gäste können Songs vorschlagen, die der Host in die Queue annehmen kann. Session über den Orbit-Button im Header starten, Einladungslink teilen, andere können von jeder Psysonic-Installation beitreten. Der Host kontrolliert die Wiedergabe (Skip, Seek, Queue) — Gäste sehen den Stand in Echtzeit und können Vorschläge machen. Sessions sind ephemer und enden, wenn der Host sie schließt.', + q24: 'Was ist das Now-Playing-Dropdown?', + a24: 'Das Broadcast-Symbol oben rechts im Header zeigt, was andere Nutzer auf deinem Navidrome-Server gerade hören, aktualisiert alle 10 Sekunden. Der eigene Eintrag verschwindet sofort beim Pausieren. Per-Server — Nutzer auf einem anderen aktiven Server werden nicht angezeigt.', + // ── Section 7: Personalisierung ──────────────────────────────────────── + s7: 'Personalisierung', + q25: 'Themes und der Theme-Scheduler?', + a25: 'Einstellungen → Darstellung → Theme bietet 60+ Themes in 8 Gruppen (Psysonic, Mediaplayer, Betriebssysteme, Spiele, Filme, Serien, Social Media, Open Source Classics — Catppuccin / Nord / Gruvbox / Nightfox / Dracula). Auto-Switch-Theme erlaubt das Setzen von Tag- und Nacht-Theme mit Startzeiten, sodass Psysonic automatisch wechselt.', + q26: 'Kann ich Sidebar, Home und Künstlerseite anpassen?', + a26: 'Ja — Einstellungen → Personalisierung. Der Sidebar-Customizer erlaubt das Umsortieren der Nav-Items per Drag und das Ausblenden ungenutzter. Der Home-Customizer schaltet jede Mainstage-Reihe (Hero, Recent, Discover, Recently Played, Starred …) ein/aus. Der Artist-Page-Customizer ordnet die Sektionen (Top Songs, Alben, Singles, Compilations, ähnliche Künstler usw.) um und blendet ungenutzte aus.', + q27: 'Was ist der Mini-Player?', + a27: 'Ein kleines schwebendes Fenster mit Cover, Transport-Controls und kompakter Queue. Über das Mini-Player-Icon in der Playerleiste oder das zugehörige Tastenkürzel öffnen. Das Fenster merkt sich Position und Größe zwischen Sessions. Auf Windows wird die Mini-Webview beim Start vorerstellt, sodass das Öffnen sofort geschieht; Linux / macOS aktivieren das optional über Einstellungen → Darstellung → Mini-Player vorladen.', + q28: 'Was ist die Floating Player Bar?', + a28: 'Eine optionale Playerleisten-Variante (Einstellungen → Darstellung), die sich mit themed Hintergrund, Akzent-Border, abgerundetem Cover und zentriertem Lautstärke-Bereich vom unteren Rand löst. Nützlich auf hohen Monitoren oder kompakten Themes.', + q29: 'Track-Vorschau beim Hovern?', + a29: 'Über eine Track-Zeile hovern, den kleinen Vorschau-Button auf dem Cover klicken oder die Vorschau über das Rechtsklick-Menü auslösen — Psysonic streamt die ersten ~15 s durch dieselbe Rust-Audio-Engine, sodass Loudness-Normalisierung greift. Praktisch beim Durchblättern eines neuen Albums.', + q30: 'Sleep-Timer?', + a30: 'Klick auf das Mond-Icon in der Playerleiste öffnet den Sleep-Timer. Eine Dauer wählen (oder „Ende des aktuellen Tracks") und Psysonic blendet aus und pausiert am Ende. Der Button zeigt einen Kreis-Ring und einen Countdown im Button, während der Timer läuft.', + q31: 'UI-Skalierung, Schrift, Seekbar-Stil?', + a31: 'Einstellungen → Darstellung — Anzeigeskalierung (80–125 %, ohne System-Schriftgröße zu beeinflussen), Schrift (10 UI-Schriften, u. a. IBM Plex Mono, Fira Code, Geist, Golos Text …), Seekbar-Stil (Wellenform analysiert / Pseudowave deterministisch / Linie & Punkt / Balken / Dicker Balken / Segmentiert / Neon-Glow / Pulswelle / Partikelspur / Flüssigfüllung / Retro-Tape).', + // ── Section 8: Power User ────────────────────────────────────────────── + s8: 'Power User', + q32: 'CLI-Player-Steuerung?', + a32: 'Das Psysonic-Binary kann als Fernsteuerung dienen. Beispiele: psysonic --player play / pause / next / prev, --player volume 75, --player seek 15, --player shuffle, --player repeat off|all|one, --player rating 1-5. Server, Audiogeräte, Bibliotheken wechseln; Instant Mix triggern; Künstler / Alben / Tracks suchen. Vollständige Liste mit psysonic --player --help. Shell-Completions für bash und zsh über psysonic completions.', + q33: 'Smart Playlists (Navidrome)?', + a33: 'Smart Playlists sind serverseitige dynamische Playlists, die durch Regeln definiert werden (Genre = Rock UND Jahr > 2020 etc.). Die Playlists-Seite in Psysonic erlaubt das Erstellen, Bearbeiten und Löschen mit visuellem Regel-Editor — Psysonic spricht dafür mit der Navidrome Native API. Sie verhalten sich wie normale Playlists im Rest der App und aktualisieren sich automatisch, wenn sich die Bibliothek ändert.', + q34: 'Einstellungen sichern und wiederherstellen?', + a34: 'Einstellungen → Storage → Backup & Restore exportiert Server-Profile, Themes, Tastenkürzel und andere Einstellungen in eine einzige JSON-Datei. Auf einem anderen Gerät oder nach einer Neuinstallation importieren, um alles auf einmal wiederherzustellen. Server-Passwörter sind enthalten — Datei sicher aufbewahren.', + q35: 'Wo sehe ich alle Open-Source-Lizenzen?', + a35: 'Einstellungen → System → Open Source Licenses. Die volle Abhängigkeitsliste (Cargo-Crates und npm-Pakete) wird mit gebündelten Lizenztexten ausgeliefert. Klick auf einen Eintrag öffnet den vollen Text; der kuratierte Highlight-Block oben hebt die User-bekannten Bibliotheken hervor (Tauri, React, rodio, symphonia usw.).', + // ── Section 9: Offline & Sync ────────────────────────────────────────── + s9: 'Offline & Sync', + q36: 'Offline-Modus — Alben und Playlists cachen?', + a36: 'Album oder Playlist öffnen und das Download-Icon im Header klicken — Psysonic cacht jeden Track lokal, sodass er ohne Netzwerkzugriff abspielt. Die Offline-Bibliothek (Sidebar) listet alles Gecachte, zeigt laufende Downloads und erlaubt das Entfernen über das Papierkorb-Icon (das nach Abschluss erscheint).', + q37: 'Offline-Speicherlimit?', + a37: 'Einstellungen → Bibliothek → Offline lässt eine maximale Cache-Größe setzen. Wird das Limit erreicht, zeigt die Albumseite einen Warnhinweis. Speicher freigeben durch Entfernen von Alben oder Playlists in der Offline-Bibliothek.', + q38: 'Device Sync — Musik auf USB / SD?', + a38: 'Device Sync (Sidebar) kopiert Alben, Playlists oder ganze Künstler auf ein externes Laufwerk für Offline-Hören auf anderen Geräten. Zielordner wählen, Quellen aus den Browser-Tabs auswählen, „Auf Gerät übertragen" klicken. Psysonic schreibt ein Manifest (psysonic-sync.json), sodass es weiß, welche Dateien bereits dort sind, auch beim Wieder-Öffnen unter einem anderen OS mit anderer Vorlage. Vorlagen unterstützen {artist} / {album} / {title} / {track_number} / {disc_number} / {year}-Tokens mit / als Ordner-Trennzeichen.', + // ── Section 10: Integrationen & Fehlerbehebung ───────────────────────── + s10: 'Integrationen & Fehlerbehebung', + q39: 'Last.fm-Scrobbling?', + a39: 'Einstellungen → Integrationen → Last.fm. Konto einmal verbinden, Psysonic scrobbelt direkt zu Last.fm — keine Navidrome-Konfiguration nötig. Ein Scrobble wird gesendet, wenn 50 % eines Tracks gehört wurden. Now-Playing-Pings gehen zu Beginn raus.', + q40: 'Discord Rich Presence?', + a40: 'Einstellungen → Integrationen → Discord zeigt deinen aktuellen Track auf deinem Discord-Profil. Wahl zwischen App-Icon, Cover-Art deines Servers (über getAlbumInfo2 — benötigt einen öffentlich erreichbaren Server) oder Apple-Music-Covern. Anzeige-Strings (Details, Status, Tooltip) per Token-Templates anpassen.', + q41: 'Bandsintown-Tour-Daten?', + a41: 'Opt-in unter Einstellungen → Integrationen → Now-Playing-Info. Der Now-Playing-Tab auf der Now-Playing-Seite zeigt dann kommende Tour-Daten für den laufenden Künstler über die Bandsintown-Widget-API. Standardmäßig aus — keine Anfragen, bevor aktiviert.', + q42: 'Internet Radio — Live-Streams abspielen?', + a42: 'Internet Radio (Sidebar) spielt jeden auf deinem Navidrome-Server gespeicherten Live-Stream (Sender über die Navidrome-Admin-UI hinzufügen). Wiedergabe läuft über die HTML5-Audio-Engine des Browsers — die meisten EQ- / Replay-Gain- / Loudness-Einstellungen gelten nicht für Radio, aber ICY-Metadaten (aktueller Songname) werden angezeigt. Unterstützt MP3, AAC, OGG Vorbis und die meisten HLS-Streams; Codec-Support hängt von der Plattform ab.', + q43: 'Der Verbindungstest schlägt fehl — was tun?', + a43: 'URL inklusive Port doppelt prüfen (z. B. http://192.168.1.100:4533). Im lokalen Netzwerk klappt http:// oft, wo https:// nicht funktioniert (kein Zertifikat). Sicherstellen, dass keine Firewall den Port blockiert und dass Benutzername und Passwort stimmen. Bei Servern hinter einem Reverse-Proxy zuerst die direkte URL probieren, um die Ursache einzugrenzen.', + q44: 'Cover und Künstlerbilder laden langsam.', + a44: 'Bilder werden beim ersten Aufruf vom Server geholt und dann 30 Tage lokal gecacht. Bei langsamen Server-Festplatten kann der erste Seitenaufruf einen Moment dauern; danach sind sie sofort da. Der Hot Cache hilft auch bei Tracks, der Bild-Cache ist davon unabhängig.', + q45: 'Linux-Probleme — schwarzer Bildschirm oder kein Ton?', + a45: 'Schwarzer Bildschirm ist meist ein GPU- / EGL-Treiberproblem in WebKitGTK — mit GDK_BACKEND=x11 WEBKIT_DISABLE_COMPOSITING_MODE=1 WEBKIT_DISABLE_DMABUF_RENDERER=1 starten (die AUR- / .deb- / .rpm-Installer setzen das automatisch). Für Audio sicherstellen, dass PipeWire oder PulseAudio läuft. Tonaussetzer nach Sleep / Wake werden mittlerweile vom Post-Sleep-Recovery-Hook automatisch behandelt.', +}; diff --git a/src/locales/de/hero.ts b/src/locales/de/hero.ts new file mode 100644 index 00000000..eafca0c0 --- /dev/null +++ b/src/locales/de/hero.ts @@ -0,0 +1,6 @@ +export const hero = { + eyebrow: 'Album des Augenblicks', + playAlbum: 'Album abspielen', + enqueue: 'Einreihen', + enqueueTooltip: 'Ganzes Album zur Warteschlange hinzufügen', +}; diff --git a/src/locales/de/home.ts b/src/locales/de/home.ts new file mode 100644 index 00000000..c502a366 --- /dev/null +++ b/src/locales/de/home.ts @@ -0,0 +1,19 @@ +export const home = { + hero: 'Featured', + starred: 'Persönliche Favoriten', + recent: 'Zuletzt hinzugefügt', + mostPlayed: 'Meistgehört', + recentlyPlayed: 'Kürzlich gespielt', + losslessAlbums: 'Lossless-Alben', + discover: 'Entdecken', + discoverSongs: 'Titel entdecken', + loadMore: 'Mehr laden', + discoverMore: 'Mehr entdecken', + discoverArtists: 'Künstler entdecken', + discoverArtistsMore: 'Alle Künstler', + becauseYouLike: 'Weil du gehört hast…', + becauseYouLikeFor: 'Weil du {{artist}} gehört hast', + similarTo: 'Ähnlich wie {{artist}}', + becauseYouLikeTracks_one: '{{count}} Titel', + becauseYouLikeTracks_other: '{{count}} Titel' +}; diff --git a/src/locales/de/index.ts b/src/locales/de/index.ts new file mode 100644 index 00000000..ea6622d4 --- /dev/null +++ b/src/locales/de/index.ts @@ -0,0 +1,91 @@ +import { sidebar } from './sidebar'; +import { home } from './home'; +import { hero } from './hero'; +import { search } from './search'; +import { nowPlaying } from './nowPlaying'; +import { contextMenu } from './contextMenu'; +import { sharePaste } from './sharePaste'; +import { albumDetail } from './albumDetail'; +import { entityRating } from './entityRating'; +import { artistDetail } from './artistDetail'; +import { favorites } from './favorites'; +import { randomLanding } from './randomLanding'; +import { randomAlbums } from './randomAlbums'; +import { genres } from './genres'; +import { randomMix } from './randomMix'; +import { luckyMix } from './luckyMix'; +import { albums } from './albums'; +import { tracks } from './tracks'; +import { artists } from './artists'; +import { composers } from './composers'; +import { composerDetail } from './composerDetail'; +import { login } from './login'; +import { connection } from './connection'; +import { common } from './common'; +import { settings } from './settings'; +import { changelog } from './changelog'; +import { whatsNew } from './whatsNew'; +import { help } from './help'; +import { queue } from './queue'; +import { miniPlayer } from './miniPlayer'; +import { statistics } from './statistics'; +import { player } from './player'; +import { nowPlayingInfo } from './nowPlayingInfo'; +import { songInfo } from './songInfo'; +import { playlists } from './playlists'; +import { smartPlaylists } from './smartPlaylists'; +import { mostPlayed } from './mostPlayed'; +import { losslessAlbums } from './losslessAlbums'; +import { radio } from './radio'; +import { folderBrowser } from './folderBrowser'; +import { deviceSync } from './deviceSync'; +import { orbit } from './orbit'; +import { tray } from './tray'; +import { licenses } from './licenses'; + +export const deTranslation = { + sidebar, + home, + hero, + search, + nowPlaying, + contextMenu, + sharePaste, + albumDetail, + entityRating, + artistDetail, + favorites, + randomLanding, + randomAlbums, + genres, + randomMix, + luckyMix, + albums, + tracks, + artists, + composers, + composerDetail, + login, + connection, + common, + settings, + changelog, + whatsNew, + help, + queue, + miniPlayer, + statistics, + player, + nowPlayingInfo, + songInfo, + playlists, + smartPlaylists, + mostPlayed, + losslessAlbums, + radio, + folderBrowser, + deviceSync, + orbit, + tray, + licenses, +}; diff --git a/src/locales/de/licenses.ts b/src/locales/de/licenses.ts new file mode 100644 index 00000000..2c00bed9 --- /dev/null +++ b/src/locales/de/licenses.ts @@ -0,0 +1,13 @@ +export const licenses = { + title: 'Open-Source-Lizenzen', + intro: 'Psysonic basiert auf Open-Source-Software. Die untenstehende Liste zeigt jede Abhängigkeit, die mit der App ausgeliefert wird, inklusive Version, Lizenz und vollständigem Lizenztext.', + highlights: 'Wichtige Abhängigkeiten', + searchPlaceholder: 'Suche nach Name, Version oder Lizenz…', + noResults: 'Keine Treffer.', + loading: 'Lizenzen werden geladen…', + loadError: 'Lizenzdaten konnten nicht geladen werden.', + noLicenseText: 'Für diese Abhängigkeit ist kein Lizenztext gebündelt.', + viewSource: 'Quelle anzeigen', + totalLine: '{{total}} Abhängigkeiten — {{cargo}} Cargo, {{npm}} npm', + generatedAt: 'Zuletzt generiert {{date}}', +}; diff --git a/src/locales/de/login.ts b/src/locales/de/login.ts new file mode 100644 index 00000000..662f77d7 --- /dev/null +++ b/src/locales/de/login.ts @@ -0,0 +1,22 @@ +export const login = { + subtitle: 'Dein Navidrome Desktop Player', + serverName: 'Server-Name (optional)', + serverNamePlaceholder: 'Mein Navidrome', + serverUrl: 'Server-URL', + serverUrlPlaceholder: '192.168.1.100:4533 oder https://music.example.com', + username: 'Benutzername', + usernamePlaceholder: 'admin', + password: 'Passwort', + showPassword: 'Passwort anzeigen', + hidePassword: 'Passwort verstecken', + connect: 'Verbinden', + connecting: 'Verbinde…', + connected: 'Verbunden!', + error: 'Verbindung fehlgeschlagen – bitte Daten prüfen.', + urlRequired: 'Bitte Server-URL eingeben.', + savedServers: 'Gespeicherte Server', + addNew: 'Oder neuen Server hinzufügen', + orMagicString: 'Oder Magic-String', + magicStringPlaceholder: 'Freigabe-String einfügen (psysonic1-…)', + magicStringInvalid: 'Ungültiger oder nicht lesbarer Magic-String.', +}; diff --git a/src/locales/de/losslessAlbums.ts b/src/locales/de/losslessAlbums.ts new file mode 100644 index 00000000..1a88e53d --- /dev/null +++ b/src/locales/de/losslessAlbums.ts @@ -0,0 +1,5 @@ +export const losslessAlbums = { + empty: 'Noch keine Lossless-Alben in dieser Bibliothek.', + unsupported: 'Dieser Server liefert keine Metadaten, mit denen sich Lossless-Alben erkennen lassen.', + slowFetchHint: 'Lädt langsamer als andere Album-Seiten — Psysonic geht den gesamten Songkatalog nach Qualität durch.', +}; diff --git a/src/locales/de/luckyMix.ts b/src/locales/de/luckyMix.ts new file mode 100644 index 00000000..4d350ac8 --- /dev/null +++ b/src/locales/de/luckyMix.ts @@ -0,0 +1,6 @@ +export const luckyMix = { + done: 'Glücks-Mix bereit: {{count}} Titel', + failed: 'Glücks-Mix konnte nicht erstellt werden. Bitte erneut versuchen.', + unavailable: 'Glücks-Mix ist für diesen Server nicht verfügbar.', + cancelTooltip: 'Glücks-Mix-Erstellung abbrechen', +}; diff --git a/src/locales/de/miniPlayer.ts b/src/locales/de/miniPlayer.ts new file mode 100644 index 00000000..914ad485 --- /dev/null +++ b/src/locales/de/miniPlayer.ts @@ -0,0 +1,9 @@ +export const miniPlayer = { + showQueue: 'Warteschlange einblenden', + hideQueue: 'Warteschlange ausblenden', + pinOnTop: 'Im Vordergrund halten', + pinOff: 'Vordergrund deaktivieren', + openMainWindow: 'Hauptfenster öffnen', + close: 'Schließen', + emptyQueue: 'Die Warteschlange ist leer', +}; diff --git a/src/locales/de/mostPlayed.ts b/src/locales/de/mostPlayed.ts new file mode 100644 index 00000000..79be9eeb --- /dev/null +++ b/src/locales/de/mostPlayed.ts @@ -0,0 +1,13 @@ +export const mostPlayed = { + title: 'Meistgehört', + topArtists: 'Top-Künstler', + topAlbums: 'Top-Alben', + plays: '{{n}}× gespielt', + sortMost: 'Meiste Plays zuerst', + sortLeast: 'Wenigste Plays zuerst', + loadMore: 'Mehr Alben laden', + noData: 'Noch keine Wiedergabedaten. Fang an zu hören!', + noArtists: 'Alle Künstler herausgefiltert.', + filterCompilations: 'Sampler-Künstler ausblenden (Various Artists, Soundtracks usw.)', + filterCompilationsShort: 'Sampler ausblenden', +}; diff --git a/src/locales/de/nowPlaying.ts b/src/locales/de/nowPlaying.ts new file mode 100644 index 00000000..32f1a977 --- /dev/null +++ b/src/locales/de/nowPlaying.ts @@ -0,0 +1,47 @@ +export const nowPlaying = { + tooltip: 'Wer hört was?', + title: 'Wer hört was?', + loading: 'Lädt…', + nobody: 'Gerade hört niemand Musik.', + minutesAgo: 'vor {{n}}m', + nothingPlaying: 'Noch nichts am Laufen. Leg einen Track auf!', + aboutArtist: 'Über den Künstler', + fromAlbum: 'Aus diesem Album', + viewAlbum: 'Album öffnen', + goToArtist: 'Zum Künstler', + readMore: 'Mehr lesen', + showLess: 'Weniger anzeigen', + genreInfo: 'Genre', + trackInfo: 'Track-Info', + topSongs: 'Meistgespielt von diesem Künstler', + topSongsCredit: 'Top-Tracks von {{name}}', + trackPosition: 'Track {{pos}}', + playsCount_one: '{{count}} Wiedergabe', + playsCount_other: '{{count}} Wiedergaben', + releasedYearsAgo_one: 'vor {{count}} Jahr', + releasedYearsAgo_other: 'vor {{count}} Jahren', + discography: 'Diskografie', + lastfmStats: 'Last.fm-Statistik', + thisTrack: 'Dieser Titel', + thisArtist: 'Dieser Künstler', + listeners: 'Hörer', + scrobbles: 'Scrobbles', + yourScrobbles: 'von dir', + listenersN: '{{n}} Hörer', + scrobblesN: '{{n}} Scrobbles', + playsByYouN: '{{n}}× von dir gespielt', + openTrackOnLastfm: 'Track auf Last.fm', + openArtistOnLastfm: 'Künstler auf Last.fm', + rgTrackTooltip: 'ReplayGain (Track)', + rgAlbumTooltip: 'ReplayGain (Album)', + rgAutoTooltip: 'ReplayGain (Auto)', + showMoreTracks: '{{count}} weitere anzeigen', + showLessTracks: 'Weniger anzeigen', + hideCard: 'Karte ausblenden', + layoutMenu: 'Layout', + visibleCards: 'Sichtbare Karten', + hiddenCards: 'Ausgeblendete Karten', + noHiddenCards: 'Keine ausgeblendeten Karten', + resetLayout: 'Layout zurücksetzen', + emptyColumn: 'Karten hier ablegen', +}; diff --git a/src/locales/de/nowPlayingInfo.ts b/src/locales/de/nowPlayingInfo.ts new file mode 100644 index 00000000..2c312298 --- /dev/null +++ b/src/locales/de/nowPlayingInfo.ts @@ -0,0 +1,24 @@ +export const nowPlayingInfo = { + tab: 'Info', + empty: 'Spiele etwas, um Infos zu sehen', + artist: 'Künstler*in', + songInfo: 'Songinfos', + onTour: 'Auf Tour', + noTourEvents: 'Keine bevorstehenden Konzerte', + tourLoading: 'Wird geladen…', + poweredByBandsintown: 'Tourdaten via Bandsintown', + bioReadMore: 'Mehr anzeigen', + bioReadLess: 'Weniger anzeigen', + showMoreTours_one: '{{count}} weiteres anzeigen', + showMoreTours_other: '{{count}} weitere anzeigen', + showLessTours: 'Weniger anzeigen', + enableBandsintownPrompt: 'Anstehende Konzerte anzeigen?', + enableBandsintownPromptDesc: 'Optional. Lädt Tourdaten der aktuellen Künstler*in über die öffentliche Bandsintown-API.', + enableBandsintownPrivacy: 'Beim Aktivieren wird der Name der aktuell gespielten Künstler*in an die Bandsintown-API übertragen, um Tourdaten abzurufen. Es werden keine Konto- oder persönlichen Daten gesendet.', + enableBandsintownAction: 'Aktivieren', + role: { + artist: 'Hauptkünstler*in', + albumArtist: 'Album-Künstler*in', + composer: 'Komponist*in', + }, +}; diff --git a/src/locales/de/orbit.ts b/src/locales/de/orbit.ts new file mode 100644 index 00000000..19e3ae4a --- /dev/null +++ b/src/locales/de/orbit.ts @@ -0,0 +1,200 @@ +export const orbit = { + triggerLabel: 'Orbit', + triggerTooltip: 'Gemeinsame Hör-Session starten oder beitreten', + launchCreate: 'Session erstellen', + launchJoin: 'Session beitreten', + launchHelp: 'Wie funktioniert das?', + launchHelpSoon: 'Kommt bald', + joinModalTitle: 'Einer Orbit-Session beitreten', + joinModalSub: 'Füge den Einladungslink ein, den dir der Host geschickt hat.', + joinModalLinkLabel: 'Einladungslink', + joinModalLinkPlaceholder: 'psysonic2-…', + joinModalLinkHelper: 'Akzeptiert jeden gültigen Orbit-Link. Der Link muss zu dem Server gehören, auf dem du gerade angemeldet bist.', + joinModalPasteTooltip: 'Aus Zwischenablage einfügen', + joinModalSubmit: 'Beitreten', + joinModalBusy: 'Beitreten…', + joinErrEmpty: 'Bitte Einladungslink einfügen.', + joinErrInvalid: 'Das sieht nicht nach einem Orbit-Einladungslink aus.', + closeAria: 'Schließen', + heroTitlePrefix: 'Gemeinsam hören mit', + heroTitleBrand: 'Orbit', + heroSub: 'Starte eine Session — andere Nutzer auf {{server}} hören im Takt mit dir und können Songs vorschlagen.', + fallbackServer: 'diesem Server', + tipLan: 'Du bist aktuell mit einer Heimnetz-Adresse verbunden. Gäste außerhalb deines Heimnetzes können so nicht beitreten — wechsle vor dem Start in den Servereinstellungen zu einer öffentlichen Adresse.', + tipRemote: 'Damit Gäste außerhalb deines Heimnetzes beitreten können, muss deine Serveradresse öffentlich erreichbar sein. Ist dein Server nur intern verfügbar, wechsle vor dem Start zu einer öffentlichen Adresse.', + labelName: 'Sessionname', + namePlaceholder: 'Velvet Orbit', + reshuffleTooltip: 'Neuer Vorschlag', + reshuffleAria: 'Neuen Namen vorschlagen', + helperName: 'So taucht die Session für deine Gäste auf — Vorschlag übernehmen oder eigenen eintippen.', + labelMax: 'Maximale Gäste', + helperMax: 'Du zählst nicht mit — das ist nur die Obergrenze für beitretende Gäste.', + labelLink: 'Einladungslink', + tooltipCopied: 'Kopiert', + tooltipCopy: 'Kopieren', + ariaCopyLink: 'Link kopieren', + helperLink: 'Schicke diesen Link deinen Gästen. Sie fügen ihn mit Strg+V irgendwo in Psysonic ein.', + labelClearQueue: 'Eigene Warteschlange vorher leeren', + helperClearQueue: 'Mit leerer Warteschlange in die Session starten. Aus: bereits aufgereihte Titel bleiben und werden mit den Gästen geteilt.', + btnCancel: 'Abbrechen', + btnStarting: 'Starte…', + btnStart: 'Orbit starten', + btnCopyAndStart: 'Link kopieren & starten', + errNameRequired: 'Bitte gib deiner Session einen Namen.', + errStartFailed: 'Konnte nicht starten.', + hostLabel: 'Gastgeber: {{name}}', + participantsTooltip: 'Teilnehmer', + settingsTooltip: 'Session-Einstellungen', + shareTooltip: 'Einladungslink teilen', + shuffleLabel: 'Warteschlange wird neu gemischt in', + catchUpLabel: 'aufholen', + catchUpTooltip: 'Zur aktuellen Host-Position springen', + hostAway: 'Host offline', + hostOnline: 'Host online', + endTooltip: 'Session beenden', + leaveTooltip: 'Session verlassen', + helpTooltip: 'Wie Orbit funktioniert', + diag: { + openTooltip: 'Diagnose — kopierbares Ereignis-Log', + title: 'Orbit-Diagnose', + role: 'Rolle', + hostTrack: 'Host-Track-ID', + hostPos: 'Host-Position', + guestTrack: 'Meine Track-ID', + guestPos: 'Meine Position', + drift: 'Versatz', + stateAge: 'Zustand-Alter', + eventLog: 'Ereignis-Log ({{count}})', + copyLabel: 'Kopieren', + copyTooltip: 'Log in Zwischenablage kopieren', + clearLabel: 'Leeren', + clearTooltip: 'Puffer leeren', + empty: 'Noch keine Ereignisse — sie erscheinen sobald Orbit synchronisiert.', + hint: 'Vor dem Reproduzieren des Problems öffnen, dann Kopieren klicken und in den Bug-Report einfügen.', + copied: '{{count}} Zeilen kopiert', + copyFailed: 'Konnte nicht in Zwischenablage kopieren', + cleared: 'Puffer geleert', + }, + helpTitle: 'Wie Orbit funktioniert', + helpIntro: 'Orbit macht aus Psysonic einen gemeinsamen Hörraum. Der Host bestimmt die Musik; Gäste hören synchron mit und können Songs vorschlagen.', + helpHostOnly: '(Host)', + helpSec1Title: 'Was ist Orbit?', + helpSec1Body: 'Ein „Listen together"-Modus — der Host steuert die Wiedergabe, die Gäste hören mit. Alles läuft über Playlists auf deinem eigenen Navidrome-Server; keine externe Infrastruktur.', + helpSec2Title: 'Host und Gäste', + helpSec2Body: 'Der Host steuert die Wiedergabe (Play / Pause / Skip / Seek) und entscheidet, wann die Session endet. Gäste folgen der Wiedergabe des Hosts, können Songs vorschlagen und jederzeit verlassen oder wieder beitreten. Nur der Host kann Teilnehmer kicken oder dauerhaft bannen.', + helpSec2WarnHead: 'Wichtig: getrennte Accounts.', + helpSec2WarnBody: 'Jeder Teilnehmer braucht einen eigenen Navidrome-Account. Benutzen Host und Gast denselben User, kollidieren ihre Einreichungen und der Host sieht keine Vorschläge vom Gast.', + helpSec3Title: 'Session starten und einladen', + helpSec3Body: 'Klick auf den „Orbit"-Button → Session erstellen → im Start-Modal siehst du einen fertigen Einladungslink und kannst optional die aktuelle Warteschlange leeren. Link teilen wie du magst. Während die Session läuft, kopiert der Share-Button in der Session-Leiste oben jederzeit den Link erneut.', + helpSec4Title: 'Beitreten', + helpSec4Body: 'Einladungslink irgendwo in Psysonic mit Ctrl+V / Cmd+V einfügen — der Beitritt-Dialog erscheint automatisch. Alternativ: „Orbit" → Session beitreten → Link ins Feld pasten. Wenn der Link auf einen Server zeigt, für den du einen Account hast, wechselt Psysonic automatisch. Bei mehreren Accounts auf demselben Server fragt ein kleiner Picker, welcher genutzt werden soll.', + helpSec5Title: 'Songs vorschlagen', + helpSec5Body: 'In jeder Song-Liste: Doppelklick auf eine Zeile, oder Rechtsklick → „Zur Orbit-Session hinzufügen". Ein einfacher Klick zeigt nur einen Hinweis, statt das ganze Album in die geteilte Queue zu werfen — das ist bewusst so. Explizite Bulk-Aktionen wie „Play All" oder „Play Album" fragen zuerst nach und hängen dann an (ersetzen nie).', + helpSec6Title: 'Die geteilte Warteschlange', + helpSec6Body: 'Die Queue zeigt die kommenden Titel des Hosts — für alle sichtbar. Neu hinzugefügte Bulk-Inhalte werden immer angehängt, damit Gast-Vorschläge nicht verloren gehen. Auto-Shuffle mischt die Queue periodisch neu (konfigurierbar: 1 / 5 / 10 / 15 / 30 Min.). Wenn deine Wiedergabe vom Host abweicht, bringt dich der „Aufholen"-Button in der Session-Leiste zurück zur Live-Position des Hosts.', + helpSec7Title: 'Freigaben', + helpSec7Body: 'Standardmäßig müssen Vorschläge von Gästen manuell freigegeben werden — sie erscheinen in einer „Freigabe"-Leiste oben im Queue-Panel mit Annehmen/Ablehnen-Buttons. In den Session-Einstellungen lässt sich Auto-Übernehmen aktivieren, dann landen alle Vorschläge direkt in der Queue.', + helpSec8Title: 'Teilnehmer und Einstellungen', + helpSec8Body: 'Das Einstellungs-Icon in der Session-Leiste öffnet Shuffle-Takt, Auto-Übernehmen und die „Jetzt mischen"-Abkürzung. Klick auf die Teilnehmerzahl zeigt wer gerade dabei ist — Kick (kann über den Link wieder beitreten) oder Bann (für die Session gesperrt). Gäste sehen die Teilnehmerliste ebenfalls, aber nur lesend.', + helpSec9Title: 'Session beenden', + helpSec9Body: 'Host-X → Bestätigungsdialog → Session endet für alle und die Server-Playlists werden automatisch aufgeräumt. Gast-X → der Gast verlässt, die Session läuft weiter. Wenn der Host 5 Minuten lang nichts mehr sendet, verlässt der Gast die Session automatisch mit einer Meldung; kürzere Reconnects innerhalb dieser Zeit bleiben unsichtbar.', + participantsInviteLabel: 'Einladungslink', + participantsCountLabel: '{{count}} in Session', + participantsHost: 'Gastgeber', + participantsEmpty: 'Noch keine Gäste', + participantsKickTooltip: 'Aus Session entfernen', + participantsKickAria: '{{user}} entfernen', + participantsRemoveTooltip: 'Aus Session entfernen', + participantsRemoveAria: '{{user}} aus dieser Session entfernen', + participantsBanTooltip: 'Permanent bannen', + participantsBanAria: '{{user}} permanent bannen', + participantsMuteTooltip: 'Vorschläge sperren', + participantsUnmuteTooltip: 'Vorschläge erlauben', + participantsMuteAria: 'Vorschläge von {{user}} sperren', + participantsUnmuteAria: 'Vorschläge von {{user}} wieder erlauben', + confirmRemoveTitle: 'Aus Session entfernen?', + confirmRemoveBody: '{{user}} wird aus der Session geworfen, kann aber jederzeit über deinen Einladungslink wieder beitreten.', + confirmRemoveConfirm: 'Entfernen', + confirmBanTitle: 'Permanent bannen?', + confirmBanBody: '{{user}} wird entfernt und kann dieser Session nicht wieder beitreten. Für die Lebensdauer der Session nicht rückgängig zu machen.', + confirmBanConfirm: 'Bannen', + confirmCancel: 'Abbrechen', + confirmJoinTitle: 'Orbit-Session beitreten?', + confirmJoinBody: '{{host}} lädt dich zu „{{name}}" ein. Möchtest du der Session beitreten?', + confirmJoinConfirm: 'Beitreten', + confirmLeaveTitle: 'Session verlassen?', + confirmLeaveBody: '„{{name}}" wirklich verlassen? Du kannst jederzeit über {{host}}s Einladungslink wieder beitreten.', + confirmLeaveConfirm: 'Verlassen', + confirmEndTitle: 'Session für alle beenden?', + confirmEndBody: '„{{name}}" wird für alle Teilnehmer geschlossen. Die Session-Playlists werden automatisch aufgeräumt.', + confirmEndConfirm: 'Session beenden', + invalidLinkTitle: 'Einladungslink ist nicht mehr gültig', + invalidLinkBody: 'Diese Orbit-Session existiert nicht mehr oder wurde bereits beendet. Bitte den Gastgeber um einen neuen Einladungslink.', + settingsTitle: 'Session-Einstellungen', + settingAutoApprove: 'Vorschläge automatisch übernehmen', + settingAutoApproveHint: 'Neue Gäste-Vorschläge landen sofort in deiner Warteschlange. Aus: sie bleiben in der Session-Liste, du musst sie später manuell übernehmen.', + settingAutoShuffle: 'Automatisch mischen', + settingAutoShuffleHint: 'Periodischer Fisher-Yates-Shuffle der kommenden Warteschlange. Aus: Reihenfolge wird nur verändert, wenn du selbst sortierst.', + settingShuffleInterval: 'Alle', + settingShuffleIntervalHint: 'Wie oft die kommende Warteschlange während der Session neu gemischt wird.', + suggestBlockedMuted: 'Der Host hat dich für diese Session gesperrt — keine Vorschläge möglich.', + settingShuffleIntervalValue_one: '{{count}} Min.', + settingShuffleIntervalValue_other: '{{count}} Min.', + settingShuffleNow: 'Jetzt mischen', + toastSuggested: '{{user}} hat „{{title}}" vorgeschlagen', + toastSuggestedMany: '{{count}} neue Vorschläge in der Warteschlange', + toastShuffled: 'Warteschlange gemischt', + toastJoined: 'Session beigetreten', + toastLoginFirst: 'Erst anmelden, um einer Session beizutreten', + toastSwitchServer: 'Wechsle erst zu {{url}} und füge den Link dann erneut ein', + toastNoAccountForServer: 'Du hast keinen Zugang zu {{url}}. Bitte den Host um einen Einladungslink.', + toastSwitchFailed: 'Wechsel zu {{url}} fehlgeschlagen', + accountPickerTitle: 'Welcher Account?', + accountPickerSub: 'Du hast mehrere Accounts für {{url}}. Wähle aus, mit welchem du der Session beitreten willst.', + toastJoinFail: 'Session konnte nicht beigetreten werden', + joinErrNotFound: 'Session nicht gefunden', + joinErrEnded: 'Session wurde beendet', + joinErrFull: 'Session ist voll', + joinErrKicked: 'Du kannst dieser Session nicht mehr beitreten', + joinErrNoUser: 'Kein aktiver Server', + joinErrServerError: 'Beitritt fehlgeschlagen', + ctxAddToSession: 'Zur Orbit-Session hinzufügen', + ctxSuggestedToast: 'An Session vorgeschlagen', + ctxSuggestFailed: 'Vorschlag fehlgeschlagen — nicht beigetreten', + ctxAddToSessionHost: 'Zur Orbit-Session hinzufügen', + ctxAddedHostToast: 'Zur Session hinzugefügt', + ctxAddHostFailed: 'Hinzufügen fehlgeschlagen', + bulkConfirmTitle: 'Wirklich alles in die Orbit-Queue?', + bulkConfirmBody: 'Das würde {{count}} Titel auf einmal in die geteilte Queue werfen. Für deine Gäste ist das eine Menge. Trotzdem hinzufügen?', + bulkConfirmYes: 'Alle hinzufügen', + bulkConfirmNo: 'Abbrechen', + guestLive: 'Live', + guestPlaying: 'Läuft gerade', + guestPaused: 'Pausiert', + guestLoading: 'Lade…', + guestSuggestions: 'Vorschläge', + guestUpNext: 'Als Nächstes', + guestUpNextEmpty: 'Nichts in der Warteschlange. Öffne bei einem Song das Kontextmenü und wähle „Zur Orbit-Session hinzufügen", um etwas vorzuschlagen.', + guestPendingTitle: 'Wartet auf Host', + guestPendingHint: 'Vorgeschlagen — taucht in der Warteschlange auf, sobald der Host sie übernimmt.', + approvalTitle: 'Zur Freigabe', + approvalFrom: 'Vorgeschlagen von {{user}}', + approvalAccept: 'Übernehmen', + approvalDecline: 'Ablehnen', + guestUpNextMore: '+ {{count}} weitere in der Host-Warteschlange', + guestSubmitter: 'von {{user}}', + queueAddedByHost: 'Vom Host hinzugefügt', + queueAddedByYou: 'Von dir hinzugefügt', + queueAddedByUser: 'Hinzugefügt von {{user}}', + guestEmpty: 'Noch keine Vorschläge. Öffne bei einem Song das Kontextmenü und wähle „Zur Orbit-Session hinzufügen".', + guestFooter: 'Die Wiedergabe wird vom Gastgeber gesteuert — du kannst die Liste nicht ändern.', + exitKickedTitle: 'Du wurdest aus der Session gebannt', + exitRemovedTitle: 'Du wurdest aus der Session entfernt', + exitEndedTitle: 'Der Gastgeber hat die Session beendet', + exitHostTimeoutTitle: 'Host nicht mehr erreichbar', + exitHostTimeoutBody: '{{host}} hat sich länger nicht mehr gemeldet — „{{name}}" wurde auf deiner Seite beendet. Über den Einladungslink kannst du jederzeit wieder beitreten.', + exitKickedBody: '{{host}} hat dich aus „{{name}}" gebannt. Beitritt nicht mehr möglich.', + exitRemovedBody: '{{host}} hat dich aus „{{name}}" entfernt. Du kannst jederzeit über den Einladungslink wieder beitreten.', + exitEndedBody: '„{{name}}" ist zu Ende. Hoffentlich war\'s schön.', + exitOk: 'OK', +}; diff --git a/src/locales/de/player.ts b/src/locales/de/player.ts new file mode 100644 index 00000000..b50875f0 --- /dev/null +++ b/src/locales/de/player.ts @@ -0,0 +1,56 @@ +export const player = { + regionLabel: 'Musikplayer', + openFullscreen: 'Vollbild-Player öffnen', + fullscreen: 'Vollbild-Player', + closeFullscreen: 'Vollbild schließen', + closeTooltip: 'Schließen (Esc)', + noTitle: 'Kein Titel', + stop: 'Stop', + prev: 'Vorheriger Titel', + play: 'Play', + pause: 'Pause', + previewActive: 'Vorschau läuft', + previewLabel: 'Vorschau', + delayModalTitle: 'Timer', + delayPauseSection: 'Pause nach', + delayStartSection: 'Start nach', + delayPreviewPause: 'Pause um', + delayPreviewStart: 'Start um', + delaySchedulePause: 'Pause planen', + delayScheduleStart: 'Start planen', + delayCancelPause: 'Pause-Timer abbrechen', + delayCancelStart: 'Start-Timer abbrechen', + delayInactivePause: 'Nur während der Wiedergabe verfügbar.', + delayInactiveStart: 'Nur in Pause mit geladenem Titel oder Radio.', + delayCustomMinutes: 'Eigene Dauer (Minuten)', + delayCustomPlaceholder: 'z. B. 2,5', + closeDelayModal: 'Schließen', + delayIn: 'in', + delayFmtSec: '{{n}} s', + delayFmtMin: '{{n}} Min', + delayFmtHr: '{{n}} Std', + delayCancel: 'Abbrechen', + delayApply: 'Übernehmen', + next: 'Nächster Titel', + repeat: 'Wiederholen', + repeatOff: 'Aus', + repeatAll: 'Alle', + repeatOne: 'Einen', + progress: 'Songfortschritt', + volume: 'Lautstärke', + toggleQueue: 'Warteschlange umschalten', + collapseQueueResize: 'Warteschlange einklappen, Breite ändern', + moreOptions: 'Weitere Optionen', + equalizer: 'Equalizer', + miniPlayer: 'Mini-Player', + lyrics: 'Lyrics', + fsLyricsToggle: 'Lyrics im Vollbild', + lyricsLoading: 'Lyrics werden geladen…', + lyricsNotFound: 'Keine Lyrics für diesen Titel gefunden', + lyricsSourceServer: 'Quelle: Server', + lyricsSourceLrclib: 'Quelle: LRCLIB', + lyricsSourceNetease: 'Quelle: Netease', + lyricsSourceLyricsplus: 'Quelle: YouLyPlus', + showDuration: 'Dauer anzeigen', + showRemainingTime: 'Verbleibende Zeit anzeigen', +}; diff --git a/src/locales/de/playlists.ts b/src/locales/de/playlists.ts new file mode 100644 index 00000000..4bb36c81 --- /dev/null +++ b/src/locales/de/playlists.ts @@ -0,0 +1,101 @@ +export const playlists = { + title: 'Playlists', + newPlaylist: 'Neue Playlist', + unnamed: 'Unbenannte Playlist', + createName: 'Playlist-Name…', + create: 'Erstellen', + cancel: 'Abbrechen', + empty: 'Noch keine Playlists.', + emptyPlaylist: 'Diese Playlist ist leer.', + addFirstSong: 'Ersten Song hinzufügen', + notFound: 'Playlist nicht gefunden.', + songs: '{{n}} Songs', + playAll: 'Alle abspielen', + shuffle: 'Zufallswiedergabe', + addToQueue: 'Zur Warteschlange', + back: 'Zurück zu Playlists', + deletePlaylist: 'Löschen', + confirmDelete: 'Nochmals klicken zum Bestätigen', + removeSong: 'Aus Playlist entfernen', + addSongs: 'Songs hinzufügen', + searchPlaceholder: 'Bibliothek durchsuchen…', + noResults: 'Keine Ergebnisse.', + suggestions: 'Vorgeschlagene Songs', + noSuggestions: 'Keine Vorschläge verfügbar.', + titleBadge: 'Playlist', + refreshSuggestions: 'Neue Vorschläge', + addSong: 'Zur Playlist hinzufügen', + preview: 'Vorschau (30 s)', + previewStop: 'Vorschau stoppen', + playNextSuggestion: 'Als Nächstes spielen', + suggestionsHint: 'Doppelklick auf eine Zeile fügt sie zur Playlist hinzu', + addSelected: 'Ausgewählte hinzufügen', + cacheOffline: 'Playlist offline speichern', + offlineCached: 'Playlist gecacht', + removeOffline: 'Aus Offline-Cache entfernen', + offlineDownloading: 'Wird gecacht… ({{done}}/{{total}} Alben)', + publicLabel: 'Öffentlich', + privateLabel: 'Privat', + editMeta: 'Playlist bearbeiten', + editNamePlaceholder: 'Playlist-Name…', + editCommentPlaceholder: 'Beschreibung hinzufügen…', + editPublic: 'Öffentliche Playlist', + editSave: 'Speichern', + editCancel: 'Abbrechen', + changeCover: 'Coverbild ändern', + changeCoverLabel: 'Foto ändern', + removeCover: 'Foto entfernen', + coverUpdated: 'Cover aktualisiert', + metaSaved: 'Playlist aktualisiert', + downloadZip: 'Herunterladen (ZIP)', + // Toast notifications for multi-select + addSuccess: '{{count}} Songs zu {{playlist}} hinzugefügt', + addPartial: '{{added}} hinzugefügt, {{skipped}} übersprungen (Duplikate)', + addAllSkipped: 'Alle übersprungen ({{count}} Duplikate)', + addedAsDuplicates: '{{count}} Songs zu {{playlist}} hinzugefügt (als Duplikate)', + duplicateConfirmTitle: 'Bereits in Playlist', + duplicateConfirmMessage: 'Alle {{count}} Songs sind bereits in "{{playlist}}". Trotzdem als Duplikate hinzufügen?', + duplicateConfirmAction: 'Trotzdem hinzufügen', + addError: 'Fehler beim Hinzufügen von Songs', + createAndAddSuccess: 'Playlist "{{playlist}}" mit {{count}} Songs erstellt', + createError: 'Fehler beim Erstellen der Playlist', + deleteSuccess: '{{count}} Playlists gelöscht', + deleteFailed: 'Fehler beim Löschen von {{name}}', + deleteSelected: 'Ausgewählte löschen', + deleteSelectedPartial: 'Nur {{n}} von {{total}} ausgewählten Playlists können gelöscht werden (die anderen gehören jemand anderem).', + mergeSuccess: '{{count}} Songs in {{playlist}} zusammengeführt', + mergeNoNewSongs: 'Keine neuen Songs zum Hinzufügen', + mergeError: 'Fehler beim Zusammenführen von Playlists', + mergeInto: 'Zusammenführen in', + selectionCount: '{{count}} ausgewählt', + select: 'Auswählen', + startSelect: 'Auswahl aktivieren', + cancelSelect: 'Abbrechen', + loadingAlbums: '{{count}} Alben werden aufgelöst…', + loadingArtists: '{{count}} Künstler werden aufgelöst…', + myPlaylists: 'Meine Playlists', + noOtherPlaylists: 'Keine anderen Playlists verfügbar', + addToPlaylistSuccess: '{{count}} Songs zu {{playlist}} hinzugefügt', + addToPlaylistNoNew: 'Keine neuen Songs für {{playlist}}', + addToPlaylistError: 'Fehler beim Hinzufügen zur Playlist', + removeSuccess: 'Song aus Playlist entfernt', + removeError: 'Fehler beim Entfernen aus der Playlist', + importCSV: 'CSV importieren', + importCSVTooltip: 'Aus Spotify-CSV importieren', + csvImportReport: 'CSV-Importbericht', + csvImportTotal: 'Gesamt', + csvImportAdded: 'Hinzugefügt', + csvImportDuplicates: 'Duplikate', + csvImportNotFound: 'Nicht gefunden', + csvImportNetworkErrors: 'Netzwerkfehler', + csvImportDuplicatesTitle: 'Doppelte Titel (bereits in Playlist):', + csvImportNotFoundTitle: 'Nicht gefundene Titel:', + csvImportNetworkErrorsTitle: 'Netzwerkfehler (Import kann wiederholt werden):', + csvImportDownloadReport: 'Bericht herunterladen', + csvImportClose: 'Schließen', + csvImportNoValidTracks: 'Keine gültigen Titel in CSV-Datei gefunden', + csvImportFailed: 'CSV-Import fehlgeschlagen', + csvImportToast: '{{added}} hinzugefügt, {{notFound}} nicht gefunden, {{duplicates}} Duplikate', + csvImportDownloadSuccess: 'Bericht erfolgreich heruntergeladen', + csvImportDownloadError: 'Bericht konnte nicht heruntergeladen werden', +}; diff --git a/src/locales/de/queue.ts b/src/locales/de/queue.ts new file mode 100644 index 00000000..7a121b56 --- /dev/null +++ b/src/locales/de/queue.ts @@ -0,0 +1,45 @@ +export const queue = { + title: 'Warteschlange', + savePlaylist: 'Playlist speichern', + updatePlaylist: 'Playlist aktualisieren', + filterPlaylists: 'Playlists filtern…', + playlistName: 'Name der Playlist', + cancel: 'Abbrechen', + save: 'Speichern', + loadPlaylist: 'Playlist laden', + loading: 'Lade…', + noPlaylists: 'Keine Playlists gefunden.', + load: 'Warteschlange ersetzen & abspielen', + appendToQueue: 'An Warteschlange anhängen', + delete: 'Löschen', + deleteConfirm: 'Playlist "{{name}}" löschen?', + clear: 'Leeren', + shuffle: 'Warteschlange mischen', + gapless: 'Nahtlos', + crossfade: 'Crossfade', + infiniteQueue: 'Endlose Warteschlange', + autoAdded: '— Automatisch hinzugefügt —', + radioAdded: '— Radio —', + hide: 'Verbergen', + hideNowPlaying: 'Wiedergabeinformationen ausblenden', + showNowPlaying: 'Wiedergabeinformationen anzeigen', + close: 'Schließen', + nextTracks: 'Nächste Titel', + shareQueue: 'Warteschlangen-Link kopieren', + shareQueueEmpty: 'Die Warteschlange ist leer — nichts zu teilen.', + emptyQueue: 'Die Warteschlange ist leer.', + trackSingular: 'Titel', + trackPlural: 'Titel', + showRemaining: 'Restzeit anzeigen', + showTotal: 'Gesamtzeit anzeigen', + showEta: 'Endzeit anzeigen', + replayGain: 'ReplayGain', + rgTrack: 'T {{db}} dB', + rgAlbum: 'A {{db}} dB', + rgPeak: 'Peak {{pk}}', + sourceOffline: 'Wiedergabe aus der Offline-Bibliothek', + sourceHot: 'Wiedergabe aus dem Cache', + sourceStream: 'Wiedergabe aus dem Netzwerkstream', + clearCachedLoudnessWaveform: 'Clear cached loudness and waveform, then re-analyze this track', + recalculatingLoudnessWaveform: 'Recalculating loudness and waveform for this track…', +}; diff --git a/src/locales/de/radio.ts b/src/locales/de/radio.ts new file mode 100644 index 00000000..57bb39df --- /dev/null +++ b/src/locales/de/radio.ts @@ -0,0 +1,35 @@ +export const radio = { + title: 'Internetradio', + empty: 'Keine Radiosender konfiguriert.', + addStation: 'Sender hinzufügen', + editStation: 'Bearbeiten', + deleteStation: 'Sender löschen', + confirmDelete: 'Zum Bestätigen erneut klicken', + stationName: 'Sendername…', + streamUrl: 'Stream-URL…', + homepageUrl: 'Homepage-URL (optional)', + save: 'Speichern', + cancel: 'Abbrechen', + live: 'LIVE', + liveStream: 'Internetradio', + openHomepage: 'Homepage öffnen', + changeCoverLabel: 'Cover ändern', + removeCover: 'Cover entfernen', + browseDirectory: 'Verzeichnis durchsuchen', + directoryPlaceholder: 'Sender suchen…', + noResults: 'Keine Sender gefunden.', + stationAdded: 'Sender hinzugefügt', + filterAll: 'Alle', + filterFavorites: 'Favoriten', + sortManual: 'Manuell', + sortAZ: 'A → Z', + sortZA: 'Z → A', + sortNewest: 'Neueste', + favorite: 'Zu Favoriten hinzufügen', + unfavorite: 'Aus Favoriten entfernen', + noFavorites: 'Keine Lieblingssender.', + listenerCount_one: '{{count}} Hörer', + listenerCount_other: '{{count}} Hörer', + recentlyPlayed: 'Zuletzt gespielt', + upNext: 'Als Nächstes', +}; diff --git a/src/locales/de/randomAlbums.ts b/src/locales/de/randomAlbums.ts new file mode 100644 index 00000000..999d4e95 --- /dev/null +++ b/src/locales/de/randomAlbums.ts @@ -0,0 +1,4 @@ +export const randomAlbums = { + title: 'Zufallsalben', + refresh: 'Neu laden', +}; diff --git a/src/locales/de/randomLanding.ts b/src/locales/de/randomLanding.ts new file mode 100644 index 00000000..892dfa68 --- /dev/null +++ b/src/locales/de/randomLanding.ts @@ -0,0 +1,9 @@ +export const randomLanding = { + title: 'Mix erstellen', + mixByTracks: 'Mix nach Titeln', + mixByTracksDesc: 'Zufällige Auswahl aus deiner gesamten Mediathek', + mixByAlbums: 'Mix nach Alben', + mixByAlbumsDesc: 'Zufällige Alben für neue Entdeckungen', + mixByLucky: 'Glücks-Mix', + mixByLuckyDesc: 'Smarter Instant Mix aus Top-Künstlern, Alben und Bewertungen', +}; diff --git a/src/locales/de/randomMix.ts b/src/locales/de/randomMix.ts new file mode 100644 index 00000000..94eca17e --- /dev/null +++ b/src/locales/de/randomMix.ts @@ -0,0 +1,39 @@ +export const randomMix = { + title: 'Zufallsmix', + remix: 'Neu mixen', + remixTooltip: 'Neue Songs laden', + remixGenre: '{{genre}} neu mixen', + remixTooltipGenre: 'Neue {{genre}}-Songs laden', + playAll: 'Alle abspielen', + trackTitle: 'Titel', + trackArtist: 'Künstler', + trackAlbum: 'Album', + trackFavorite: 'Favorit', + trackDuration: 'Dauer', + favoriteAdd: 'Zu Favoriten hinzufügen', + favoriteRemove: 'Aus Favoriten entfernen', + play: 'Abspielen', + trackGenre: 'Genre', + mixSettingsHeader: 'Mix-Einstellungen', + exclusionsHeader: 'Ausschlüsse', + filterPanelInexactSizeNote: 'Die Mix-Größe ist ein Ziel — bei großen Anfragen kann der Server weniger eindeutige Tracks liefern, wenn sein Zufallspool erschöpft ist.', + mixSize: 'Playlistgröße', + excludeAudiobooks: 'Hörbücher & Hörspiele ausschließen', + excludeAudiobooksDesc: 'Prüft Keywords gegen Genre, Titel, Album und Künstler — z. B. Hörbuch, Audiobook, Spoken Word, …', + genreBlocked: 'Keyword gesperrt', + genreAddedToBlacklist: 'Zur Filterliste hinzugefügt', + genreAlreadyBlocked: 'Bereits gesperrt', + artistBlocked: 'Künstler gesperrt', + artistAddedToBlacklist: 'Künstler zur Filterliste hinzugefügt', + artistClickHint: 'Klicken um diesen Künstler zu sperren', + blacklistToggle: 'Keyword-Filter', + genreMixTitle: 'Genre-Mix', + genreMixDesc: 'Top 20 Genres nach Songanzahl — klicken für einen Zufallsmix', + genreMixAll: 'Alle Songs', + genreMixLoadMore: '10 weitere laden', + genreMixNoGenres: 'Keine Genres auf dem Server gefunden.', + shuffleGenres: 'Andere Genres anzeigen', + filterPanelTitle: 'Filter', + filterPanelDesc: 'Genre-Tag oder Künstlername in der Liste anklicken, um ihn aus zukünftigen Mixes auszuschließen.', + genreClickHint: 'Genre-Tag anklicken,\num es als Filter-Keyword hinzuzufügen.\nPrüft Genre, Titel, Album & Künstler.', +}; diff --git a/src/locales/de/search.ts b/src/locales/de/search.ts new file mode 100644 index 00000000..7a358bab --- /dev/null +++ b/src/locales/de/search.ts @@ -0,0 +1,29 @@ +export const search = { + placeholder: 'Suchen nach Künstler, Album oder Song…', + noResults: 'Keine Ergebnisse für „{{query}}"', + artists: 'Künstler', + albums: 'Alben', + songs: 'Songs', + clearLabel: 'Suche leeren', + addedToQueueToast: '„{{title}}" zur Warteschlange hinzugefügt', + title: 'Suche', + resultsFor: 'Ergebnisse für „{{query}}"', + album: 'Album', + advanced: 'Erweiterte Suche', + advancedSearchTerm: 'Suchbegriff', + advancedSearchPlaceholder: 'Titel, Album, Künstler…', + advancedGenre: 'Genre', + advancedAllGenres: 'Alle Genres', + advancedYear: 'Jahr', + advancedYearFrom: 'von', + advancedYearTo: 'bis', + advancedAll: 'Alle', + advancedSearch: 'Suchen', + advancedEmpty: 'Suchbegriff eingeben oder Filter wählen, um zu beginnen.', + advancedNoResults: 'Keine Ergebnisse gefunden.', + advancedGenreNote: 'Songs werden zufällig aus dem Genre gewählt.', + recentSearches: 'Zuletzt gesucht', + browse: 'Stöbern', + emptyHint: 'Was möchtest du hören?', + genres: 'Genres', +}; diff --git a/src/locales/de/settings.ts b/src/locales/de/settings.ts new file mode 100644 index 00000000..5173f45b --- /dev/null +++ b/src/locales/de/settings.ts @@ -0,0 +1,442 @@ +export const settings = { + title: 'Einstellungen', + language: 'Sprache', + languageEn: 'English', + languageDe: 'Deutsch', + languageEs: 'Español', + languageFr: 'Français', + languageNl: 'Nederlands', + languageNb: 'Norsk', + languageRu: 'Русский', + languageZh: '中文', + languageRo: 'Română', + font: 'Schriftart', + fontHintOpenDyslexic: 'Legasthenie-freundlich · keine Chinesisch-Unterstützung', + theme: 'Design', + appearance: 'Darstellung', + servers: 'Server', + serverName: 'Server-Name', + serverUrl: 'Server-URL', + serverUrlPlaceholder: '192.168.1.100:4533 oder https://music.example.com', + serverUsername: 'Benutzername', + serverPassword: 'Passwort', + addServer: 'Server hinzufügen', + addServerTitle: 'Neuen Server hinzufügen', + useServer: 'Verwenden', + deleteServer: 'Löschen', + noServers: 'Keine Server gespeichert.', + serverActive: 'Aktiv', + confirmDeleteServer: 'Server „{{name}}" löschen?', + serverConnecting: 'Verbinde…', + serverConnected: 'Verbunden!', + serverFailed: 'Verbindung fehlgeschlagen.', + testBtn: 'Verbindung testen', + testingBtn: 'Teste…', + serverCompatible: 'Für Navidrome entwickelt. Andere Subsonic-kompatible Server (Gonic, Airsonic, …) funktionieren ggf. eingeschränkt, weil Psysonic viele Navidrome-spezifische API-Endpunkte nutzt.', + userMgmtTitle: 'Benutzerverwaltung', + userMgmtDesc: 'Benutzer auf diesem Server verwalten. Erfordert Admin-Rechte.', + userMgmtNoAdmin: 'Du brauchst Admin-Rechte, um Benutzer auf diesem Server zu verwalten.', + userMgmtLoadError: 'Benutzer konnten nicht geladen werden.', + userMgmtLoadFriendly: 'Server hat nicht geantwortet — meistens ein Einzelfall.', + userMgmtRetry: 'Erneut versuchen', + userMgmtEmpty: 'Keine Benutzer gefunden.', + userMgmtYouBadge: 'Du', + userMgmtAdminBadge: 'Admin', + userMgmtAddUser: 'Benutzer hinzufügen', + userMgmtAddUserTitle: 'Neuen Benutzer anlegen', + userMgmtEditUserTitle: 'Benutzer bearbeiten', + userMgmtUsername: 'Benutzername', + userMgmtName: 'Anzeigename', + userMgmtEmail: 'E-Mail', + userMgmtPassword: 'Passwort', + userMgmtPasswordEditHint: 'Neues Passwort eingeben, um es zu ändern.', + userMgmtRoleAdmin: 'Admin', + userMgmtLibraries: 'Bibliotheken', + userMgmtLibrariesAdminHint: 'Admin-Benutzer haben automatisch Zugriff auf alle Bibliotheken.', + userMgmtLibrariesEmpty: 'Keine Bibliotheken auf diesem Server vorhanden.', + userMgmtLibrariesValidation: 'Mindestens eine Bibliothek auswählen.', + userMgmtLibrariesUpdateError: 'Benutzer gespeichert, aber Bibliothekszuweisung fehlgeschlagen', + userMgmtNoLibraries: 'Keine Bibliotheken zugewiesen', + userMgmtNeverSeen: 'Nie', + userMgmtSave: 'Speichern', + userMgmtCancel: 'Abbrechen', + userMgmtDelete: 'Löschen', + userMgmtEdit: 'Bearbeiten', + userMgmtConfirmDelete: 'Benutzer „{{username}}" löschen? Das kann nicht rückgängig gemacht werden.', + userMgmtCreateError: 'Benutzer konnte nicht angelegt werden.', + userMgmtUpdateError: 'Benutzer konnte nicht aktualisiert werden.', + userMgmtDeleteError: 'Benutzer konnte nicht gelöscht werden.', + userMgmtCreated: 'Benutzer angelegt.', + userMgmtUpdated: 'Benutzer aktualisiert.', + userMgmtDeleted: 'Benutzer gelöscht.', + userMgmtValidationMissing: 'Benutzername, Anzeigename und Passwort sind erforderlich.', + userMgmtValidationMissingIdentity: 'Benutzername und Anzeigename sind erforderlich.', + userMgmtMagicStringGenerate: 'Magic-String erzeugen', + userMgmtSaveAndMagicString: 'Speichern und Magic-String kopieren', + userMgmtMagicStringPasswordNavHint: + 'Navidrome speichert dieses Passwort für den Benutzer. Weicht es vom aktuellen ab, wird das Anmeldepasswort auf dem Server aktualisiert.', + userMgmtMagicStringPlaintextWarning: + 'Teilen Sie den Magic-String vorsichtig: Er enthält das Passwort im Klartext (Kodierung ist keine Verschlüsselung). Wer die vollständige Zeichenkette hat, kann sich als dieser Benutzer anmelden.', + userMgmtMagicStringCopied: 'Magic-String in die Zwischenablage kopiert.', + userMgmtMagicStringCopyFailed: 'Kopieren in die Zwischenablage fehlgeschlagen.', + userMgmtMagicStringLoginFailed: 'Passwortprüfung fehlgeschlagen — Anmeldedaten konnten nicht verifiziert werden.', + userMgmtMagicStringModalTitle: 'Magic-String erzeugen', + userMgmtMagicStringModalDesc: 'Subsonic-Passwort für „{{username}}" eingeben — es wird in den kopierten Magic-String übernommen.', + userMgmtMagicStringModalConfirm: 'String kopieren', + audiomuseTitle: 'AudioMuse-AI (Navidrome)', + audiomuseDesc: + 'Aktivieren, wenn dieser Server das AudioMuse-AI-Navidrome-Plugin nutzt. Schaltet Instant Mix pro Titel frei und nutzt ähnliche Künstler vom Server statt Last.fm auf Künstlerseiten.', + audiomuseIssueHint: + 'Instant Mix ist kürzlich fehlgeschlagen — Navidrome-Plugin und AudioMuse-API prüfen. Ohne Server-Treffer werden ähnliche Künstler über Last.fm geladen.', + connected: 'Verbunden', + failed: 'Fehlgeschlagen', + eqTitle: 'Equalizer', + eqEnabled: 'Equalizer aktivieren', + eqPreset: 'Preset', + eqPresetCustom: 'Benutzerdefiniert', + eqPresetBuiltin: 'Eingebaute Presets', + eqPresetCustomGroup: 'Meine Presets', + eqSavePreset: 'Als Preset speichern', + eqPresetName: 'Preset-Name…', + eqDeletePreset: 'Preset löschen', + eqResetBands: 'Auf Flat zurücksetzen', + eqPreGain: 'Vorverstärkung', + eqResetPreGain: 'Vorverstärkung zurücksetzen', + eqAutoEqTitle: 'AutoEQ Kopfhörer-Suche', + eqAutoEqPlaceholder: 'Kopfhörer / IEM Modell suchen…', + eqAutoEqSearching: 'Suche…', + eqAutoEqNoResults: 'Keine Ergebnisse gefunden', + eqAutoEqError: 'Suche fehlgeschlagen', + eqAutoEqRateLimit: 'GitHub Rate-Limit erreicht — in einer Minute erneut versuchen', + eqAutoEqFetchError: 'EQ-Profil konnte nicht geladen werden', + lfmTitle: 'Last.fm', + lfmConnect: 'Mit Last.fm verbinden', + lfmConnecting: 'Warte auf Bestätigung…', + lfmConfirm: 'Ich habe die App autorisiert', + lfmConnected: 'Verbunden als', + lfmDisconnect: 'Trennen', + lfmConnectDesc: 'Verbinde deinen Last.fm Account, um Scrobbling und Now-Playing-Updates direkt aus Psysonic heraus zu aktivieren — keine Navidrome-Konfiguration erforderlich.', + lfmOpenBrowser: 'Es öffnet sich ein Browserfenster. Autorisiere Psysonic auf Last.fm und klicke dann unten auf den Button.', + lfmScrobbles: '{{n}} Scrobbles', + lfmMemberSince: 'Dabei seit {{year}}', + scrobbleEnabled: 'Scrobbling aktiviert', + scrobbleDesc: 'Songs nach 50% Laufzeit an Last.fm senden', + behavior: 'App-Verhalten', + cacheTitle: 'Max. Speichergröße', + cacheDesc: 'Cover und Künstlerbilder. Wenn voll, werden die ältesten Einträge automatisch entfernt. Offline-Alben werden nicht automatisch gelöscht, aber beim manuellen Cache leeren entfernt.', + cacheUsedImages: 'Bilder:', + cacheUsedOffline: 'Offline-Tracks:', + cacheUsedHot: 'Belegter Speicher:', + hotCacheTrackCount: 'Titel im Cache:', + cacheMaxLabel: 'Max. Größe', + cacheClearBtn: 'Cache leeren', + cacheClearWarning: 'Alle Offline-Alben werden damit aus der Bibliothek entfernt.', + cacheClearConfirm: 'Alles löschen', + cacheClearCancel: 'Abbrechen', + offlineDirTitle: 'Offline-Bibliothek (In-App)', + offlineDirDesc: 'Speicherort für Titel, die du innerhalb von Psysonic offline verfügbar machst.', + offlineDirDefault: 'Standard (App-Daten)', + offlineDirChange: 'Verzeichnis ändern', + offlineDirClear: 'Auf Standard zurücksetzen', + offlineDirHint: 'Neue Downloads werden an diesem Ort gespeichert. Bestehende Downloads verbleiben am ursprünglichen Pfad.', + hotCacheTitle: 'Hot-Playback-Cache', + hotCacheDisclaimer: 'Lädt kommende Warteschlangen-Titel vor und behält zuletzt gespielte. Bei aktivierter Option: Speicherplatz und Netzwerk.', + hotCacheDirDefault: 'Standard (App-Daten)', + hotCacheDirChange: 'Ordner ändern', + hotCacheDirClear: 'Auf Standard zurücksetzen', + hotCacheDirHint: 'Beim Ordnerwechsel wird der App-Index zurückgesetzt; alte Dateien bleiben am alten Ort, bis Sie sie löschen.', + hotCacheEnabled: 'Hot-Playback-Cache aktivieren', + hotCacheMaxMb: 'Maximale Cache-Größe', + hotCacheDebounce: 'Debounce bei Warteschlangen-Änderungen', + hotCacheDebounceImmediate: 'Sofort', + hotCacheDebounceSeconds: '{{n}} s', + hotCacheClearBtn: 'Hot-Cache leeren', + audioOutputDevice: 'Audio-Ausgabegerät', + audioOutputDeviceDesc: 'Wähle das Audiogerät, über das Psysonic spielt. Änderungen werden sofort übernommen und starten den aktuellen Track neu.', + audioOutputDeviceDefault: 'Systemstandard', + audioOutputDeviceRefresh: 'Geräteliste aktualisieren', + audioOutputDeviceOsDefaultNow: 'aktuelle Systemausgabe', + audioOutputDeviceListError: 'Audiogeräteliste konnte nicht geladen werden.', + audioOutputDeviceNotInCurrentList: 'nicht in der aktuellen Liste', + audioOutputDeviceMacNotice: 'Auf macOS folgt die Wiedergabe aus technischen Gründen zurzeit immer dem System-Ausgabegerät. Du kannst das Ziel über Systemeinstellungen → Ton oder das Lautsprecher-Symbol in der Menüleiste wechseln. Hintergrund: CoreAudio löst beim Öffnen eines nicht-Default-Streams eine Mikrofonberechtigungsabfrage aus — wir vermeiden sie, indem wir stets den System-Default verwenden.', + hiResTitle: 'Native Hi-Res-Wiedergabe', + hiResEnabled: 'Native Hi-Res-Wiedergabe aktivieren', + hiResDesc: "Standardmäßig wird auf 44,1 kHz begrenzt (maximale Stabilität). Nur aktivieren, wenn Hardware und Netzwerk zuverlässig hohe Abtastraten (88,2 kHz+) unterstützen.", + showArtistImages: 'Künstlerbilder anzeigen', + showArtistImagesDesc: 'Lädt und zeigt Künstlerbilder in der Künstlerübersicht. Standardmäßig deaktiviert, um Server-I/O und Netzwerklast bei großen Bibliotheken zu reduzieren.', + showOrbitTrigger: '„Orbit" im Header zeigen', + showOrbitTriggerDesc: 'Der Kopfzeilen-Button zum Starten oder Beitreten einer gemeinsamen Hör-Session. Ausblenden, wenn du Orbit nicht nutzt — hier lässt er sich jederzeit wieder einschalten.', + showTrayIcon: 'Tray-Icon anzeigen', + showTrayIconDesc: 'Psysonic-Icon im System-Tray / in der Menüleiste anzeigen.', + minimizeToTray: 'Im Tray minimieren', + minimizeToTrayDesc: 'Beim Schließen des Fensters läuft Psysonic weiter im System-Tray statt zu beenden.', + preloadMiniPlayer: 'Mini-Player vorladen', + preloadMiniPlayerDesc: 'Baut das Mini-Player-Fenster beim App-Start im Hintergrund auf, damit es beim ersten Öffnen sofort Inhalt zeigt. Kostet etwas mehr RAM.', + discordRichPresence: 'Discord Rich Presence', + discordRichPresenceDesc: 'Zeigt den aktuell gespielten Titel im Discord-Profil an. Discord muss dafür geöffnet sein.', + useCustomTitlebar: 'Eigene Titelleiste', + useCustomTitlebarDesc: 'Ersetzt die System-Titelleiste durch eine eingebaute, die zum App-Theme passt. Deaktivieren, um die native GNOME/GTK-Titelleiste zu verwenden.', + linuxWebkitSmoothScroll: 'Sanftes Mausrad (Linux)', + linuxWebkitSmoothScrollDesc: 'An: mit Nachlauf. Aus: zeilenweise wie in GTK-Apps.', + discordCoverSource: 'Cover-Quelle', + discordCoverSourceDesc: 'Woher das Album-Cover für dein Discord-Profil geladen wird.', + discordCoverNone: 'Keine (nur App-Symbol)', + discordCoverServer: 'Server (über Album-Info)', + discordCoverApple: 'Apple Music', + discordOptions: 'Erweiterte Discord-Optionen', + discordTemplates: 'Benutzerdefinierte Textvorlagen', + discordTemplatesDesc: 'Passen Sie an, welche Informationen in Ihrem Discord-Profil angezeigt werden. Variablen: {title}, {artist}, {album}', + discordTemplateDetails: 'Primäre Zeile (details)', + discordTemplateState: 'Sekundäre Zeile (state)', + discordTemplateLargeText: 'Album-Tooltip (largeText)', + nowPlayingEnabled: 'Im Livefenster anzeigen', + nowPlayingEnabledDesc: 'Überträgt den aktuell gespielten Titel an die Livehörer-Ansicht des Servers. Deaktivieren, um keine Wiedergabedaten zu senden.', + enableBandsintown: 'Bandsintown-Tourdaten', + enableBandsintownDesc: 'Zeigt anstehende Konzerte des aktuellen Künstlers im Info-Tab. Daten werden über die öffentliche Bandsintown-API abgerufen.', + lyricsServerFirst: 'Server-Lyrics bevorzugen', + lyricsServerFirstDesc: 'Server-seitige Lyrics (eingebettete Tags, Sidecar-Dateien) vor LRCLIB abfragen. Deaktivieren, um LRCLIB zuerst zu verwenden.', + enableNeteaselyrics: 'Netease Cloud Music Lyrics', + enableNeteaselyricsDesc: 'Netease Cloud Music als letzte Lyrics-Quelle verwenden, wenn Server und LRCLIB nichts liefern. Besonders gut für asiatische und internationale Musik.', + lyricsSourcesTitle: 'Lyrics-Quellen', + lyricsSourcesDesc: 'Wähle, welche Quellen für Lyrics abgefragt werden und in welcher Reihenfolge. Ziehen zum Sortieren. Deaktivierte Quellen werden übersprungen.', + lyricsSourceServer: 'Server', + lyricsSourceLrclib: 'LRCLIB', + lyricsSourceNetease: 'Netease Cloud Music', + lyricsModeStandard: 'Standard', + lyricsModeStandardDesc: 'Drei Quellen mit frei wählbarer Reihenfolge: Server-Tags, LRCLIB, Netease.', + lyricsModeLyricsplus: 'YouLyPlus (Karaoke)', + lyricsModeLyricsplusDesc: 'Wort-für-Wort-Sync aus Apple Music, Spotify, Musixmatch & QQ (Community-Backend). Fällt still zurück auf die Standard-Quellen, wenn nichts gefunden wird.', + lyricsStaticOnly: 'Nur statische Lyrics anzeigen', + lyricsStaticOnlyDesc: 'Synchronisierte Lyrics werden ohne Auto-Scroll und ohne Wort-Hervorhebung als statischer Text dargestellt.', + downloadsTitle: 'ZIP-Export & Archivierung', + downloadsFolderDesc: 'Zielverzeichnis für Alben, die du als ZIP-Datei auf deinen Computer herunterlädst.', + downloadsDefault: 'Standard-Downloads-Ordner', + pickFolder: 'Auswählen', + pickFolderTitle: 'Download-Ordner auswählen', + clearFolder: 'Download-Ordner löschen', + logout: 'Abmelden', + aboutTitle: 'Über Psysonic', + aboutDesc: 'Ein moderner Desktop-Musikplayer für Navidrome. Nutzt die Subsonic-API plus Navidrome-spezifische Erweiterungen. Basiert auf Tauri v2 mit einer nativen Rust-Audio-Engine — schlank und schnell, aber vollgepackt mit Features: Wellenform-Seekbar, synchronisierte Lyrics, Last.fm-Integration, 10-Band-EQ, Crossfade, nahtlose Wiedergabe, Replay Gain, Genre-Browser und eine große Theme-Bibliothek.', + aboutLicense: 'Lizenz', + aboutLicenseText: 'GNU GPL v3 — kostenlos nutzbar, veränderbar und unter gleicher Lizenz weiterzugeben.', + aboutRepo: 'Quellcode auf GitHub', + aboutVersion: 'Version', + aboutBuiltWith: 'Gebaut mit Tauri · React · TypeScript · Rust/rodio', + aboutMaintainersLabel: 'Projektleitung', + aboutReleaseNotesLabel: 'Release Notes', + aboutReleaseNotesLink: 'Neuigkeiten dieser Version öffnen', + aboutContributorsLabel: 'Mitwirkende', + showChangelogOnUpdate: "'Was ist neu' bei Update anzeigen", + showChangelogOnUpdateDesc: 'Blendet nach einem Update einen dezenten Changelog-Banner über Now Playing ein. Klick öffnet die Release Notes, X blendet ihn aus.', + randomMixTitle: 'Zufallsmix-Blacklist', + luckyMixMenuTitle: 'Glücks-Mix im Menü anzeigen', + luckyMixMenuDesc: 'Aktiviert Glücks-Mix im "Mix erstellen"-Hub und als separaten Menüeintrag bei getrennter Navigation. Sichtbar nur bei aktiviertem AudioMuse auf dem aktiven Server.', + randomMixBlacklistTitle: 'Eigene Filter-Keywords', + randomMixBlacklistDesc: 'Songs werden ausgeschlossen, wenn ein Keyword auf Genre, Titel, Album oder Künstler zutrifft (aktiv wenn die Checkbox oben an ist).', + randomMixBlacklistPlaceholder: 'Keyword hinzufügen…', + randomMixBlacklistAdd: 'Hinzufügen', + randomMixBlacklistEmpty: 'Noch keine eigenen Keywords hinzugefügt.', + randomMixHardcodedTitle: 'Eingebaute Keywords (aktiv wenn Checkbox an)', + tabAudio: 'Audio', + tabStorage: 'Offline & Cache', + tabAppearance: 'Darstellung', + tabLibrary: 'Bibliothek', + tabServers: 'Server', + tabLyrics: 'Songtexte', + tabPersonalisation: 'Personalisierung', + tabIntegrations: 'Integrationen', + inputKeybindingsTitle: 'Tastenkombinationen', + aboutContributorsCount_one: '{{count}} Beitrag', + aboutContributorsCount_other: '{{count}} Beiträge', + searchPlaceholder: 'Einstellungen durchsuchen…', + searchNoResults: 'Keine Treffer für deine Suche.', + integrationsPrivacyTitle: 'Hinweis zum Datenschutz', + integrationsPrivacyBody: 'Alle Integrationen auf diesem Tab sind Opt-in und senden, sobald aktiviert, Daten an externe Dienste oder an deinen Navidrome-Server. Last.fm erhält deinen Wiedergabeverlauf, Discord zeigt den aktuell laufenden Track in deinem Profil an, Bandsintown wird pro Künstler für Tour-Daten abgefragt, und der „Jetzt läuft"-Hinweis veröffentlicht deinen aktuellen Titel für andere Benutzer deines Navidrome-Servers. Wer das nicht möchte, lässt den jeweiligen Abschnitt einfach deaktiviert.', + homeCustomizerTitle: 'Startseite', + queueToolbarTitle: 'Warteschlangen-Toolbar', + queueToolbarReset: 'Zurücksetzen', + queueToolbarSeparator: 'Trennlinie', + sidebarTitle: 'Seitenleiste', + sidebarReset: 'Zurücksetzen', + artistLayoutTitle: 'Künstlerseiten-Abschnitte', + artistLayoutDesc: 'Per Drag & Drop neu anordnen, einzelne Abschnitte der Künstlerseite ein- oder ausblenden. Abschnitte ohne Daten werden automatisch übersprungen.', + artistLayoutReset: 'Zurücksetzen', + artistLayoutBio: 'Künstler-Biografie', + artistLayoutTopTracks: 'Top-Tracks', + artistLayoutSimilar: 'Ähnliche Künstler*innen', + artistLayoutAlbums: 'Alben', + artistLayoutFeatured: 'Auch enthalten auf', + sidebarDrag: 'Ziehen zum Umsortieren', + sidebarFixed: 'Immer sichtbar', + randomNavSplitTitle: 'Mix-Navigation aufteilen', + randomNavSplitDesc: '"Zufallsmix", "Zufallsalben" und "Glücks-Mix" als separate Sidebar-Einträge statt als "Mix erstellen"-Hub anzeigen.', + tabInput: 'Eingabe', + tabUsers: 'Benutzer', + shortcutsReset: 'Auf Standard zurücksetzen', + shortcutListening: 'Taste drücken…', + shortcutUnbound: '—', + shortcutClear: 'Löschen', + globalShortcutsTitle: 'Globale Shortcuts', + globalShortcutsNote: 'Funktionieren systemweit, auch wenn Psysonic im Hintergrund läuft. Mindestens Ctrl, Alt oder Super als Modifier erforderlich.', + shortcutPlayPause: 'Wiedergabe / Pause', + shortcutNext: 'Nächster Titel', + shortcutPrev: 'Vorheriger Titel', + shortcutVolumeUp: 'Lautstärke erhöhen', + shortcutVolumeDown: 'Lautstärke verringern', + shortcutSeekForward: '10s vorspulen', + shortcutSeekBackward: '10s zurückspulen', + shortcutToggleQueue: 'Warteschlange ein-/ausblenden', + shortcutOpenFolderBrowser: '{{folderBrowser}} öffnen', + shortcutFullscreenPlayer: 'Vollbild-Player', + shortcutNativeFullscreen: 'Nativer Vollbildmodus', + shortcutOpenMiniPlayer: 'Mini-Player öffnen', + shortcutStartSearch: 'Suche starten', + shortcutStartAdvancedSearch: 'Erweiterte Suche starten', + shortcutToggleSidebar: 'Seitenleiste umschalten', + shortcutMuteSound: 'Stumm schalten', + shortcutToggleEqualizer: 'Equalizer öffnen / umschalten', + shortcutToggleRepeat: 'Wiederholen umschalten', + shortcutOpenNowPlaying: '„Now Playing" öffnen', + shortcutShowLyrics: 'Songtexte anzeigen', + shortcutFavoriteCurrentTrack: 'Aktuellen Titel zu Favoriten hinzufügen', + shortcutOpenHelp: 'Hilfe', + tabSystem: 'System', + loggingTitle: 'Protokollierung', + loggingModeDesc: 'Steuert die Ausführlichkeit der Backend-Protokolle im Terminal.', + loggingModeOff: 'Aus', + loggingModeNormal: 'Normal', + loggingModeDebug: 'Debug', + loggingExport: 'Protokolle exportieren', + loggingExportSuccess: 'Protokolle exportiert ({{count}} Zeilen).', + loggingExportError: 'Protokolle konnten nicht exportiert werden.', + ratingsSectionTitle: 'Bewertungen', + ratingsSkipStarTitle: 'Skip → 1 Stern', + ratingsSkipStarDesc: + 'Wird ein Titel mehrmals hintereinander übersprungen, bekommt er automatisch 1★. Nur für noch nicht bewertete Titel.', + ratingsSkipStarThresholdLabel: 'Skips', + ratingsMixFilterTitle: 'Nach Bewertung filtern', + ratingsMixFilterDesc: + 'Gering bewertete Titel in {{mix}} und {{albums}} ausblenden. Nochmals auf den gewählten Stern klicken, um den Filter zu deaktivieren.', + ratingsMixMinSong: 'Titel', + ratingsMixMinAlbum: 'Alben', + ratingsMixMinArtist: 'Interpreten', + ratingsMixMinThresholdAria: 'Mindest-Sterne: {{label}}', + backupTitle: 'Backup & Wiederherstellung', + backupExport: 'Einstellungen exportieren', + backupExportDesc: 'Speichert alle Einstellungen, Serverprofile, Last.fm-Konfiguration, Theme, EQ und Tastenkürzel in eine .psybkp-Datei. Passwörter werden im Klartext gespeichert — Datei sicher aufbewahren.', + backupImport: 'Einstellungen importieren', + backupImportDesc: 'Stellt Einstellungen aus einer .psybkp-Datei wieder her. Die App wird nach dem Import neu geladen.', + backupImportConfirm: 'Alle aktuellen Einstellungen werden überschrieben. Fortfahren?', + backupSuccess: 'Backup gespeichert', + backupImportSuccess: 'Einstellungen wiederhergestellt — wird neu geladen…', + backupImportError: 'Ungültige oder beschädigte Backup-Datei.', + playbackTitle: 'Wiedergabe', + replayGain: 'Replay Gain', + replayGainDesc: 'Lautstärke mit ReplayGain-Metadaten normalisieren', + replayGainMode: 'Modus', + replayGainAuto: 'Auto', + replayGainAutoDesc: 'Wählt Album-Gain, wenn benachbarte Tracks in der Warteschlange vom selben Album sind, sonst Track-Gain.', + replayGainTrack: 'Track', + replayGainAlbum: 'Album', + replayGainPreGain: 'Pre-Gain (getaggte Dateien)', + replayGainPreGainDesc: 'Pauschaler Boost, der auf jede ReplayGain-Berechnung aufaddiert wird. Hilft, wenn deine Bibliothek insgesamt zu leise wirkt.', + replayGainFallback: 'Fallback (ohne Tags / Radio)', + replayGainFallbackDesc: 'Wird auf Titel (und Radio-Streams) ohne ReplayGain-Tags angewendet, damit Untagged-Inhalt nicht lauter aus dem Mix springt.', + normalization: 'Normalisierung', + normalizationDesc: 'Empfundene Lautstärke über Titel, Alben und Radio angleichen.', + normalizationOff: 'Aus', + normalizationReplayGain: 'ReplayGain', + normalizationLufs: 'LUFS', + loudnessTargetLufs: 'Ziel-LUFS', + loudnessTargetLufsDesc: 'Referenz-Lautstärke, an die alle Titel angepasst werden. Niedrigere Werte = lautere Ausgabe. Streaming-Dienste liegen meist bei etwa -14 LUFS.', + loudnessPreAnalysisAttenuation: 'Dämpfung vor Messung', + loudnessPreAnalysisAttenuationDesc: + 'Zusätzliche Dämpfung, bis die Loudness des Titels gespeichert ist. Beim Streamen folgen nur grobe Schätzungen, keine volle Messung. 0 dB = aus; negativer = leiser. Rechts steht der wirksame dB-Wert für die gewählte Ziel-LUFS.', + loudnessPreAnalysisAttenuationRef: 'Wirksam {{eff}} dB bei Ziel {{tgt}} LUFS.', + loudnessPreAnalysisAttenuationReset: 'Standard', + loudnessFirstPlayNote: + 'Beim ersten Abspielen eines neuen Titels kann die Lautstärke kurz schwanken, während gemessen wird. Beim nächsten Mal greift die gespeicherte Messung und alles bleibt stabil. Kommende Queue-Titel werden meist schon während des vorherigen Songs analysiert — in der Praxis tritt das daher selten auf.', + crossfade: 'Crossfade', + crossfadeDesc: 'Überblendung zwischen Tracks', + crossfadeSecs: '{{n}} s', + notWithGapless: 'Nicht verfügbar wenn Nahtlose Wiedergabe aktiv ist', + notWithCrossfade: 'Nicht verfügbar wenn Crossfade aktiv ist', + gapless: 'Nahtlose Wiedergabe', + gaplessDesc: 'Nächsten Track vorpuffern um Lücken zwischen Songs zu vermeiden', + preservePlayNextOrder: '„Als Nächstes"-Reihenfolge bewahren', + preservePlayNextOrderDesc: 'Neu hinzugefügte „Als Nächstes"-Titel reihen sich hinten an statt sich vorn einzuschieben.', + trackPreviewsTitle: 'Track-Vorschau', + trackPreviewsToggle: 'Track-Vorschau aktivieren', + trackPreviewsDesc: 'Inline Play- und Vorschau-Buttons in den Tracklisten anzeigen für eine kurze Hörprobe mitten im Song.', + trackPreviewStart: 'Startposition', + trackPreviewStartDesc: 'Wie weit der Track schon gespielt sein soll wenn die Vorschau startet (% der Länge).', + trackPreviewDuration: 'Dauer', + trackPreviewDurationDesc: 'Wie lange jede Vorschau spielt bevor sie automatisch stoppt.', + trackPreviewDurationSecs: '{{n}} s', + trackPreviewLocationsTitle: 'Wo Vorschauen erscheinen', + trackPreviewLocationsDesc: 'Wähle aus, in welchen Listen die Vorschau-Buttons angezeigt werden.', + trackPreviewLocation_suggestions: 'In Playlist-Vorschlägen', + trackPreviewLocation_albums: 'In Album-Tracklisten', + trackPreviewLocation_playlists: 'In Playlists', + trackPreviewLocation_favorites: 'In Favoriten', + trackPreviewLocation_artist: 'In Künstler-Top-Tracks', + trackPreviewLocation_randomMix: 'In Random Mix', + preloadMode: 'Nächsten Track vorpuffern', + preloadModeDesc: 'Wann mit dem Puffern des nächsten Tracks begonnen werden soll', + nextTrackBufferingTitle: 'Pufferung', + preloadHotCacheMutualExclusive: 'Preload und Hot Cache erfüllen denselben Zweck – nur eine Methode kann gleichzeitig aktiv sein. Das Aktivieren einer deaktiviert die andere automatisch.', + preloadOff: 'Aus', + preloadBalanced: 'Ausgewogen (30 s vor Ende)', + preloadEarly: 'Früh (nach 5 s Wiedergabe)', + preloadCustom: 'Benutzerdefiniert', + preloadCustomSeconds: 'Sekunden vor Ende: {{n}}', + infiniteQueue: 'Endlose Warteschlange', + infiniteQueueDesc: 'Automatisch Zufallstitel anhängen wenn die Warteschlange leer wird', + experimental: 'Experimentell', + fsPlayerSection: 'Vollbild-Player', + fsShowArtistPortrait: 'Künstlerfoto anzeigen', + fsShowArtistPortraitDesc: 'Künstlerfoto (oder Albumcover) auf der rechten Seite des Vollbild-Players anzeigen.', + fsPortraitDim: 'Abdunkelung des Fotos', + fsLyricsStyle: 'Liedtext-Stil', + fsLyricsStyleRail: 'Schiene', + fsLyricsStyleRailDesc: 'Klassische 5-Zeilen-Schiene.', + fsLyricsStyleApple: 'Scrollen', + fsLyricsStyleAppleDesc: 'Vollbild-Scrollliste.', + sidebarLyricsStyle: 'Text-Scroll-Stil', + sidebarLyricsStyleClassic: 'Klassisch', + sidebarLyricsStyleClassicDesc: 'Aktive Zeile wird zentriert.', + sidebarLyricsStyleApple: 'Apple Music-like', + sidebarLyricsStyleAppleDesc: 'Aktive Zeile oben mit sanfter Animation.', + seekbarStyle: 'Seekbar-Stil', + seekbarStyleDesc: 'Aussehen der Wiedergabe-Seekbar auswählen', + seekbarTruewave: 'Echte Wellenform', + seekbarPseudowave: 'Pseudo-Wellenform', + seekbarLinedot: 'Linie & Punkt', + seekbarBar: 'Balken', + seekbarThick: 'Dicker Balken', + seekbarSegmented: 'Segmentiert', + seekbarNeon: 'Neonröhre', + seekbarPulsewave: 'Pulswelle', + seekbarParticletrail: 'Partikel-Spur', + seekbarLiquidfill: 'Flüssigkeit', + seekbarRetrotape: 'Retro-Band', + themeSchedulerTitle: 'Theme-Zeitplan', + themeSchedulerEnable: 'Theme-Zeitplan aktivieren', + themeSchedulerEnableSub: 'Wechselt automatisch zwischen zwei Themes basierend auf der Uhrzeit', + themeSchedulerDayTheme: 'Tages-Theme', + themeSchedulerDayStart: 'Tag beginnt um', + themeSchedulerNightTheme: 'Nacht-Theme', + themeSchedulerNightStart: 'Nacht beginnt um', + themeSchedulerActiveHint: 'Theme-Zeitplan ist aktiv - Themes werden automatisch gewechselt.', + visualOptionsTitle: 'Visuelle Optionen', + coverArtBackground: 'Cover-Hintergrund', + coverArtBackgroundSub: 'Zeigt verschwommenes Cover als Hintergrund in Album/Playlist-Kopfzeilen', + playlistCoverPhoto: 'Playlist-Coverfoto', + playlistCoverPhotoSub: 'Zeigt Coverfoto-Raster in der Playlist-Detailansicht', + showBitrate: 'Bitrate anzeigen', + showBitrateSub: 'Audio-Bitrate in Track-Listen anzeigen', + floatingPlayerBar: 'Schwebende Player-Leiste', + floatingPlayerBarSub: 'Player-Leiste über dem Inhalt schweben lassen', + uiScaleTitle: 'Interface-Skalierung', + uiScaleLabel: 'Zoom', +}; diff --git a/src/locales/de/sharePaste.ts b/src/locales/de/sharePaste.ts new file mode 100644 index 00000000..1596cd99 --- /dev/null +++ b/src/locales/de/sharePaste.ts @@ -0,0 +1,18 @@ +export const sharePaste = { + notLoggedIn: 'Melde dich an und füge den Server hinzu, bevor du einen Freigabe-Link einfügst.', + noMatchingServer: 'Kein gespeicherter Server passt zu diesem Link. Füge einen Server mit dieser Adresse hinzu: {{url}}', + trackUnavailable: 'Dieser Titel wurde auf dem Server nicht gefunden.', + albumUnavailable: 'Dieses Album wurde auf dem Server nicht gefunden.', + artistUnavailable: 'Dieser Künstler wurde auf dem Server nicht gefunden.', + composerUnavailable: 'Diese*r Komponist*in wurde auf dem Server nicht gefunden.', + openedTrack: 'Geteilter Titel wird abgespielt.', + openedAlbum: 'Geteiltes Album wird geöffnet.', + openedArtist: 'Geteilter Künstler wird geöffnet.', + openedComposer: 'Geteilte*r Komponist*in wird geöffnet.', + openedQueue_one: '{{count}} Titel aus Freigabe-Link wird abgespielt.', + openedQueue_other: '{{count}} Titel aus Freigabe-Link werden abgespielt.', + openedQueuePartial: + '{{played}} von {{total}} Titeln aus dem Link werden abgespielt ({{skipped}} auf diesem Server nicht gefunden).', + queueAllUnavailable: 'Keiner der Titel aus diesem Link wurde auf dem Server gefunden.', + genericError: 'Freigabe-Link konnte nicht geöffnet werden.', +}; diff --git a/src/locales/de/sidebar.ts b/src/locales/de/sidebar.ts new file mode 100644 index 00000000..b7d668ea --- /dev/null +++ b/src/locales/de/sidebar.ts @@ -0,0 +1,37 @@ +export const sidebar = { + library: 'Bibliothek', + mainstage: 'Mainstage', + newReleases: 'Neueste', + allAlbums: 'Alle Alben', + randomAlbums: 'Zufallsalben', + randomPicker: 'Mix erstellen', + artists: 'Künstler', + composers: 'Komponist*innen', + randomMix: 'Zufallsmix', + favorites: 'Favoriten', + nowPlaying: 'Now Playing', + system: 'System', + statistics: 'Statistiken', + settings: 'Einstellungen', + help: 'Hilfe', + expand: 'Sidebar einblenden', + collapse: 'Sidebar ausblenden', + downloadingTracks: '{{n}} Tracks werden gecacht…', + syncingTracks: 'Synchronisiere {{done}}/{{total}}…', + cancelDownload: 'Download abbrechen', + offlineLibrary: 'Offline-Bibliothek', + genres: 'Genres', + tracks: 'Titel', + playlists: 'Playlists', + mostPlayed: 'Meistgehört', + losslessAlbums: 'Lossless', + radio: 'Internetradio', + folderBrowser: 'Ordner-Browser', + deviceSync: 'Gerätesync', + libraryScope: 'Bibliotheksumfang', + allLibraries: 'Alle Bibliotheken', + expandPlaylists: 'Playlists ausklappen', + collapsePlaylists: 'Playlists einklappen', + more: 'Mehr', + feelingLucky: 'Glücks-Mix', +}; diff --git a/src/locales/de/smartPlaylists.ts b/src/locales/de/smartPlaylists.ts new file mode 100644 index 00000000..5ad6b0a6 --- /dev/null +++ b/src/locales/de/smartPlaylists.ts @@ -0,0 +1,41 @@ +export const smartPlaylists = { + sectionBasic: '1. Basis', + sectionGenres: '2. Genres', + sectionYearsAndFilters: '3. Jahre und Filter', + genreMode: 'Genre-Modus', + genreModeInclude: 'Genres einschließen', + genreModeExclude: 'Genres ausschließen', + genreSearchPlaceholder: 'Genres filtern...', + availableGenres: 'Verfügbar', + selectedGenres: 'Ausgewählt', + yearMode: 'Jahresmodus', + yearModeInclude: 'Bereich einschließen', + yearModeExclude: 'Bereich ausschließen', + name: 'Name (ohne Präfix)', + limit: 'Limit', + limitHint: 'Wie viele Songs in die Playlist aufgenommen werden (1-{{max}}, üblicherweise 50).', + artistContains: 'Künstler enthält…', + albumContains: 'Album enthält…', + titleContains: 'Titel enthält…', + minRating: 'Mindestbewertung', + minRatingAria: 'Mindestbewertung für Smart Playlist', + minRatingHint: '0 deaktiviert die Mindestgrenze; 1-5 behält Songs mit Bewertung über dem gewählten Wert.', + fromYear: 'Von Jahr', + toYear: 'Bis Jahr', + excludeUnrated: 'Unbewertete Songs ausschließen', + compilationOnly: 'Nur Sammlungen', + create: 'Neue Smart Playlist', + save: 'Smart Playlist speichern', + created: '{{name}} erstellt', + updated: '{{name}} aktualisiert', + createFailed: 'Smart Playlist konnte nicht erstellt werden.', + updateFailed: 'Smart Playlist konnte nicht aktualisiert werden.', + navidromeOnly: 'Smart Playlists können nur auf Navidrome-Servern erstellt werden.', + loadFailed: 'Smart Playlists konnten nicht von Navidrome geladen werden.', + sortRandom: 'Sortierung: zufällig', + sortTitleAsc: 'Sortierung: Titel A-Z', + sortTitleDesc: 'Sortierung: Titel Z-A', + sortYearDesc: 'Sortierung: Jahr absteigend', + sortYearAsc: 'Sortierung: Jahr aufsteigend', + sortPlayCountDesc: 'Sortierung: Wiedergaben absteigend', +}; diff --git a/src/locales/de/songInfo.ts b/src/locales/de/songInfo.ts new file mode 100644 index 00000000..30d7e82f --- /dev/null +++ b/src/locales/de/songInfo.ts @@ -0,0 +1,23 @@ +export const songInfo = { + title: 'Song-Infos', + songTitle: 'Titel', + artist: 'Künstler', + album: 'Album', + albumArtist: 'Album-Künstler', + year: 'Jahr', + genre: 'Genre', + duration: 'Länge', + track: 'Track', + format: 'Format', + bitrate: 'Bitrate', + sampleRate: 'Abtastrate', + bitDepth: 'Bittiefe', + channels: 'Kanäle', + fileSize: 'Dateigröße', + path: 'Speicherort', + replayGainTrack: 'RG Track Gain', + replayGainAlbum: 'RG Album Gain', + replayGainPeak: 'RG Track Peak', + mono: 'Mono', + stereo: 'Stereo', +}; diff --git a/src/locales/de/statistics.ts b/src/locales/de/statistics.ts new file mode 100644 index 00000000..8aa3c064 --- /dev/null +++ b/src/locales/de/statistics.ts @@ -0,0 +1,65 @@ +export const statistics = { + title: 'Statistiken', + recentlyPlayed: 'Zuletzt gehört', + mostPlayed: 'Meistgespielte Alben', + highestRated: 'Höchstbewertete Alben', + genreDistribution: 'Genre-Verteilung (Top 20)', + loadMore: 'Mehr laden', + statArtists: 'Künstler', + statArtistsTooltip: 'Nur Album-Künstler — Künstler, die ausschließlich als Track-Künstler vorkommen (Featured, Gast usw.) und kein eigenes Album haben, werden nicht gezählt.', + statAlbums: 'Alben', + statSongs: 'Songs', + statGenres: 'Genres', + statPlaytime: 'Gesamtspielzeit', + genreInsights: 'Genre-Einblicke', + formatDistribution: 'Format-Verteilung', + formatSample: 'Stichprobe von {{n}} Titeln', + computing: 'Wird berechnet…', + genreSongs: '{{count}} Songs', + genreAlbums: '{{count}} Alben', + recentlyAdded: 'Neu hinzugefügt', + decadeDistribution: 'Alben nach Jahrzehnt', + decadeAlbums_one: '{{count}} Album', + decadeAlbums_other: '{{count}} Alben', + decadeUnknown: 'Unbekannt', + lfmTitle: 'Last.fm Statistiken', + lfmTopArtists: 'Top-Künstler', + lfmTopAlbums: 'Top-Alben', + lfmTopTracks: 'Top-Titel', + lfmPlays: '{{count}} Plays', + lfmPeriodOverall: 'Gesamt', + lfmPeriod7day: '7 Tage', + lfmPeriod1month: '1 Monat', + lfmPeriod3month: '3 Monate', + lfmPeriod6month: '6 Monate', + lfmPeriod12month: '12 Monate', + lfmNotConnected: 'Verbinde Last.fm in den Einstellungen, um deine Statistiken zu sehen.', + lfmRecentTracks: 'Zuletzt gescrobbelt', + lfmNowPlaying: 'Läuft gerade', + lfmJustNow: 'gerade eben', + lfmMinutesAgo: 'vor {{n}} Min.', + lfmHoursAgo: 'vor {{n}} Std.', + lfmDaysAgo: 'vor {{n}} Tagen', + topRatedSongs: 'Bestbewertete Songs', + topRatedArtists: 'Bestbewertete Künstler', + noRatedSongs: 'Noch keine bewerteten Songs. Songs in Album- oder Playlist-Ansicht bewerten.', + noRatedArtists: 'Noch keine bewerteten Künstler.', + exportShare: 'Teilen', + exportTitle: 'Top-Alben teilen', + exportSubtitle: 'Ein teilbares Bild deiner meistgespielten Alben erstellen.', + exportFormat: 'Format', + exportFormatStory: 'Story', + exportFormatSquare: 'Quadrat', + exportFormatTwitter: 'Twitter-Card', + exportGrid: 'Raster', + exportGridLabel: '{{n}}×{{n}}', + exportPreview: 'Vorschau', + exportGenerate: 'Erstellen', + exportSave: 'Bild speichern…', + exportCancel: 'Abbrechen', + exportFooterLabel: 'Top-Alben', + exportNotEnough: 'Für ein {{n}}×{{n}}-Raster braucht es mindestens {{count}} Alben in der Library.', + exportSaving: 'Speichere…', + exportSaved: 'Gespeichert.', + exportSaveFailed: 'Bild konnte nicht gespeichert werden.', +}; diff --git a/src/locales/de/tracks.ts b/src/locales/de/tracks.ts new file mode 100644 index 00000000..54d5fd7b --- /dev/null +++ b/src/locales/de/tracks.ts @@ -0,0 +1,15 @@ +export const tracks = { + title: 'Titel', + subtitle: 'Stöbern. Suchen. Entdecken.', + heroEyebrow: 'Titel des Moments', + heroReroll: 'Anderen wählen', + playSong: 'Abspielen', + enqueueSong: 'Zur Warteschlange', + railRandom: 'Zufallsauswahl', + railHighlyRated: 'Hoch bewertet', + browseTitle: 'Alle Titel durchstöbern', + browseUnsupported: 'Dieser Server listet nicht die ganze Bibliothek auf einmal. Nutze die Suche oben, um bestimmte Titel zu finden.', + searchPlaceholder: 'Titel, Künstler oder Album suchen…', + count_one: '{{count}} Titel', + count_other: '{{count}} Titel', +}; diff --git a/src/locales/de/tray.ts b/src/locales/de/tray.ts new file mode 100644 index 00000000..b088315e --- /dev/null +++ b/src/locales/de/tray.ts @@ -0,0 +1,8 @@ +export const tray = { + playPause: 'Wiedergabe / Pause', + nextTrack: 'Nächster Titel', + previousTrack: 'Vorheriger Titel', + showHide: 'Anzeigen / Verbergen', + exitPsysonic: 'Psysonic beenden', + nothingPlaying: 'Nichts wird abgespielt', +}; diff --git a/src/locales/de/whatsNew.ts b/src/locales/de/whatsNew.ts new file mode 100644 index 00000000..1d2a6b36 --- /dev/null +++ b/src/locales/de/whatsNew.ts @@ -0,0 +1,8 @@ +export const whatsNew = { + title: 'Was ist neu', + empty: 'Für diese Version liegt noch kein Changelog-Eintrag vor.', + bannerTitle: 'Changelog', + bannerCollapsed: 'Neu in v{{version}}', + dismiss: 'Ausblenden', + close: 'Schließen', +}; diff --git a/src/locales/en.ts b/src/locales/en.ts deleted file mode 100644 index 403eb19d..00000000 --- a/src/locales/en.ts +++ /dev/null @@ -1,1876 +0,0 @@ -export const enTranslation = { - sidebar: { - library: 'Library', - mainstage: 'Mainstage', - newReleases: 'New Releases', - allAlbums: 'All Albums', - randomAlbums: 'Random Albums', - randomPicker: 'Build a Mix', - artists: 'Artists', - composers: 'Composers', - randomMix: 'Random Mix', - favorites: 'Favorites', - nowPlaying: 'Now Playing', - system: 'System', - statistics: 'Statistics', - settings: 'Settings', - help: 'Help', - expand: 'Expand Sidebar', - collapse: 'Collapse Sidebar', - - downloadingTracks: 'Caching {{n}} tracks…', - syncingTracks: 'Syncing {{done}}/{{total}}…', - cancelDownload: 'Cancel download', - offlineLibrary: 'Offline Library', - genres: 'Genres', - tracks: 'Tracks', - playlists: 'Playlists', - smartPlaylists: 'Smart Playlists', - mostPlayed: 'Most Played', - losslessAlbums: 'Lossless', - radio: 'Internet Radio', - folderBrowser: 'Folder Browser', - deviceSync: 'Device Sync', - libraryScope: 'Library scope', - allLibraries: 'All libraries', - expandPlaylists: 'Expand playlists', - collapsePlaylists: 'Collapse playlists', - more: 'More', - feelingLucky: 'Lucky Mix', - }, - home: { - hero: 'Featured', - starred: 'Personal Favorites', - recent: 'Recently Added', - mostPlayed: 'Most Played', - recentlyPlayed: 'Recently Played', - losslessAlbums: 'Lossless Albums', - discover: 'Discover', - discoverSongs: 'Discover Songs', - loadMore: 'Load More', - discoverMore: 'Discover More', - discoverArtists: 'Discover Artists', - discoverArtistsMore: 'All Artists', - becauseYouLike: 'Because you listened…', - becauseYouLikeFor: 'Because you listened to {{artist}}', - similarTo: 'Similar to {{artist}}', - becauseYouLikeTracks_one: '{{count}} track', - becauseYouLikeTracks_other: '{{count}} tracks' - }, - hero: { - eyebrow: 'Featured Album', - playAlbum: 'Play Album', - enqueue: 'Enqueue', - enqueueTooltip: 'Add entire album to queue', - }, - search: { - placeholder: 'Search for artist, album or song…', - noResults: 'No results for "{{query}}"', - artists: 'Artists', - albums: 'Albums', - songs: 'Songs', - clearLabel: 'Clear search', - addedToQueueToast: 'Added "{{title}}" to queue', - title: 'Search', - resultsFor: 'Results for "{{query}}"', - album: 'Album', - advanced: 'Advanced Search', - advancedSearchTerm: 'Search term', - advancedSearchPlaceholder: 'Title, album, artist…', - advancedGenre: 'Genre', - advancedAllGenres: 'All genres', - advancedYear: 'Year', - advancedYearFrom: 'from', - advancedYearTo: 'to', - advancedAll: 'All', - advancedSearch: 'Search', - advancedEmpty: 'Enter a search term or select a filter to begin.', - advancedNoResults: 'No results found.', - advancedGenreNote: 'Songs are randomly selected from this genre.', - recentSearches: 'Recent Searches', - browse: 'Browse', - emptyHint: 'What do you want to hear?', - genres: 'Genres', - }, - nowPlaying: { - tooltip: 'Who is listening?', - title: 'Who is listening?', - loading: 'Loading…', - nobody: 'Nobody is currently listening.', - minutesAgo: '{{n}}m ago', - nothingPlaying: 'Nothing playing yet. Start a track!', - aboutArtist: 'About the Artist', - fromAlbum: 'From this Album', - viewAlbum: 'View Album', - goToArtist: 'Go to Artist', - readMore: 'Read more', - showLess: 'Show less', - genreInfo: 'Genre', - trackInfo: 'Track Info', - topSongs: 'Most played by this artist', - topSongsCredit: 'Top tracks from {{name}}', - trackPosition: 'Track {{pos}}', - playsCount_one: '{{count}} play', - playsCount_other: '{{count}} plays', - releasedYearsAgo_one: '{{count}} year ago', - releasedYearsAgo_other: '{{count}} years ago', - discography: 'Discography', - lastfmStats: 'Last.fm stats', - thisTrack: 'This track', - thisArtist: 'This artist', - listeners: 'listeners', - scrobbles: 'scrobbles', - yourScrobbles: 'by you', - listenersN: '{{n}} listeners', - scrobblesN: '{{n}} scrobbles', - playsByYouN: 'played {{n}}× by you', - openTrackOnLastfm: 'Track on Last.fm', - openArtistOnLastfm: 'Artist on Last.fm', - rgTrackTooltip: 'ReplayGain (track)', - rgAlbumTooltip: 'ReplayGain (album)', - rgAutoTooltip: 'ReplayGain (auto)', - showMoreTracks: 'Show {{count}} more', - showLessTracks: 'Show less', - hideCard: 'Hide card', - layoutMenu: 'Layout', - visibleCards: 'Visible cards', - hiddenCards: 'Hidden cards', - noHiddenCards: 'No hidden cards', - resetLayout: 'Reset layout', - emptyColumn: 'Drop cards here', - }, - contextMenu: { - playNow: 'Play Now', - playNext: 'Play Next', - addToQueue: 'Add to Queue', - enqueueAlbum: 'Enqueue Album', - enqueueAlbums_one: 'Enqueue {{count}} Album', - enqueueAlbums_other: 'Enqueue {{count}} Albums', - startRadio: 'Start Radio', - instantMix: 'Instant Mix', - instantMixFailed: 'Could not build Instant Mix — server or plugin error.', - cliMixNeedsTrack: 'Nothing is playing — start playback first, then run the mix command again.', - lfmLove: 'Love on Last.fm', - lfmUnlove: 'Unlove on Last.fm', - favorite: 'Favorite', - favoriteArtist: 'Favorite Artist', - favoriteAlbum: 'Favorite Album', - unfavorite: 'Remove from Favorites', - unfavoriteArtist: 'Remove Artist from Favorites', - unfavoriteAlbum: 'Remove Album from Favorites', - removeFromQueue: 'Remove from Queue', - removeFromPlaylist: 'Remove from Playlist', - openAlbum: 'Open Album', - goToArtist: 'Go to Artist', - download: 'Download (ZIP)', - addToPlaylist: 'Add to Playlist', - selectedPlaylists: '{{count}} playlists selected', - selectedAlbums: '{{count}} albums selected', - selectedArtists: '{{count}} artists selected', - songInfo: 'Song Info', - shareLink: 'Copy share link', - shareCopied: 'Share link copied to the clipboard.', - shareCopyFailed: 'Could not copy to the clipboard.', - }, - sharePaste: { - notLoggedIn: 'Sign in and add the server before pasting a share link.', - noMatchingServer: 'No saved server matches this link. Add a server with this address: {{url}}', - trackUnavailable: 'This track was not found on the server.', - albumUnavailable: 'This album was not found on the server.', - artistUnavailable: 'This artist was not found on the server.', - composerUnavailable: 'This composer was not found on the server.', - openedTrack: 'Playing shared track.', - openedAlbum: 'Opening shared album.', - openedArtist: 'Opening shared artist.', - openedComposer: 'Opening shared composer.', - openedQueue_one: 'Playing {{count}} track from the share link.', - openedQueue_other: 'Playing {{count}} tracks from the share link.', - openedQueuePartial: - 'Playing {{played}} of {{total}} tracks from the link ({{skipped}} not found on this server).', - queueAllUnavailable: 'None of the tracks from this link were found on the server.', - genericError: 'Could not open the share link.', - }, - albumDetail: { - back: 'Back', - orbitDoubleClickHint: 'Double-click to add this track to the Orbit queue', - playAll: 'Play All', - shareAlbum: 'Share album', - enqueue: 'Enqueue', - enqueueTooltip: 'Add entire album to queue', - artistBio: 'Artist Bio', - download: 'Download (ZIP)', - downloading: 'Loading…', - cacheOffline: 'Make available offline', - offlineCached: 'Available offline', - offlineDownloading: 'Caching… ({{n}}/{{total}})', - removeOffline: 'Remove offline cache', - offlineStorageFull: 'Offline storage full (limit: {{mb}} MB). Free up space by deleting an album from your Offline Library, or increase the limit in Settings.', - offlineStorageGoToLibrary: 'Offline Library', - offlineStorageGoToSettings: 'Settings', - favoriteAdd: 'Add to Favorites', - favoriteRemove: 'Remove from Favorites', - favorite: 'Favorite', - noBio: 'No biography available.', - moreByArtist: 'More by {{artist}}', - tracksCount: '{{n}} Tracks', - goToArtist: 'Go to {{artist}}', - moreLabelAlbums: 'More albums on {{label}}', - trackTitle: 'Title', - trackAlbum: 'Album', - trackArtist: 'Artist', - trackGenre: 'Genre', - trackFormat: 'Format', - trackFavorite: 'Favorite', - trackRating: 'Rating', - trackDuration: 'Duration', - trackTotal: 'Total', - columns: 'Columns', - resetColumns: 'Reset to defaults', - notFound: 'Album not found.', - bioModal: 'Artist Biography', - bioClose: 'Close', - ratingLabel: 'Rating', - enlargeCover: 'Enlarge', - filterSongs: 'Filter songs…', - sortNatural: 'Natural', - sortByTitle: 'A–Z (Title)', - sortByArtist: 'A–Z (Artist)', - sortByAlbum: 'A–Z (Album)', - }, - entityRating: { - albumShort: 'Album rating', - artistShort: 'Artist rating', - albumAriaLabel: 'Album rating', - artistAriaLabel: 'Artist rating', - selectedArtistsRatingAriaLabel: 'Star rating for {{count}} selected artists', - selectedAlbumsRatingAriaLabel: 'Star rating for {{count}} selected albums', - saveFailed: 'Could not save rating.', - }, - artistDetail: { - back: 'Back', - albums: 'Albums', - album: 'Album', - playAll: 'Play All', - shareArtist: 'Share artist', - shuffle: 'Shuffle', - radio: 'Radio', - loading: 'Loading…', - noRadio: 'No similar tracks found for this artist.', - notFound: 'Artist not found.', - albumsBy: 'Albums by {{name}}', - topTracks: 'Top Tracks', - noAlbums: 'No albums found.', - trackTitle: 'Title', - trackAlbum: 'Album', - trackDuration: 'Duration', - favoriteAdd: 'Add to Favorites', - favoriteRemove: 'Remove from Favorites', - favorite: 'Favorite', - albumCount_one: '{{count}} Album', - albumCount_other: '{{count}} Albums', - openedInBrowser: 'Opened in browser', - featuredOn: 'Also Featured On', - similarArtists: 'Similar Artists', - cacheOffline: 'Save discography offline', - offlineCached: 'Discography cached', - offlineDownloading: 'Caching… ({{done}}/{{total}} albums)', - uploadImage: 'Upload artist image', - uploadImageError: 'Failed to upload image', - releaseTypes: { - album: 'Album', - ep: 'EP', - single: 'Single', - compilation: 'Compilation', - live: 'Live', - soundtrack: 'Soundtrack', - remix: 'Remix', - other: 'Other', - }, - }, - favorites: { - title: 'Favorites', - empty: "You haven't saved any favorites yet.", - artists: 'Artists', - albums: 'Albums', - songs: 'Songs', - enqueueAll: 'Add all to queue', - playAll: 'Play all', - removeSong: 'Remove from favorites', - stations: 'Radio Stations', - showingFiltered: 'Showing {{filtered}} of {{total}} ({{artist}})', - showingCount: 'Showing {{filtered}} of {{total}}', - clearArtistFilter: 'Clear artist filter', - noFilterResults: 'No results with selected filters.', - allArtists: 'All Artists', - topArtists: 'Top Artists by Favorites', - topArtistsSongCount_one: '{{count}} song', - topArtistsSongCount_other: '{{count}} songs', - }, - randomLanding: { - title: 'Build a Mix', - mixByTracks: 'Mix by Tracks', - mixByTracksDesc: 'Random selection of tracks from your entire library', - mixByAlbums: 'Mix by Albums', - mixByAlbumsDesc: 'Random album picks for your next discovery', - mixByLucky: 'Lucky Mix', - mixByLuckyDesc: 'Smart instant mix from your top artists, albums, and ratings', - }, - randomAlbums: { - title: 'Random Albums', - refresh: 'Refresh', - }, - genres: { - title: 'Genres', - genreCount: 'Genres', - albumCount_one: '{{count}} album', - albumCount_other: '{{count}} albums', - loading: 'Loading genres…', - empty: 'No genres found.', - albumsLoading: 'Loading albums…', - albumsEmpty: 'No albums found for this genre.', - loadMore: 'Load more', - back: 'Back', - }, - randomMix: { - title: 'Random Mix', - remix: 'Remix', - remixTooltip: 'Load new random songs', - remixGenre: 'Remix {{genre}}', - remixTooltipGenre: 'Load new {{genre}} songs', - playAll: 'Play All', - trackTitle: 'Title', - trackArtist: 'Artist', - trackAlbum: 'Album', - trackFavorite: 'Favorite', - trackDuration: 'Duration', - favoriteAdd: 'Add to Favorites', - favoriteRemove: 'Remove from Favorites', - play: 'Play', - trackGenre: 'Genre', - mixSettingsHeader: 'Mix Settings', - exclusionsHeader: 'Exclusions', - filterPanelInexactSizeNote: 'Mix size is a target — large requests may return fewer unique tracks if the server\'s random pool runs short.', - mixSize: 'Playlist size', - excludeAudiobooks: 'Exclude audiobooks & radio plays', - excludeAudiobooksDesc: 'Matches keywords against genre, title, album, and artist — e.g. Hörbuch, Audiobook, Spoken Word, …', - genreBlocked: 'Keyword blocked', - genreAddedToBlacklist: 'Added to filter list', - genreAlreadyBlocked: 'Already blocked', - artistBlocked: 'Artist blocked', - artistAddedToBlacklist: 'Artist added to filter list', - artistClickHint: 'Click to block this artist', - blacklistToggle: 'Keyword Filter', - genreMixTitle: 'Genre Mix', - genreMixDesc: 'Top 20 genres by song count — click to load a random mix', - genreMixAll: 'All Songs', - genreMixLoadMore: 'Load 10 more', - genreMixNoGenres: 'No genres found on server.', - shuffleGenres: 'Show different genres', - filterPanelTitle: 'Filters', - filterPanelDesc: 'Click a genre tag or artist name in the tracklist below to block it from future mixes.', - genreClickHint: 'Click a genre tag to add it\nas a filter keyword.\nMatches genre, title, album & artist.', - }, - luckyMix: { - done: 'Lucky Mix ready: {{count}} tracks', - failed: 'Could not build Lucky Mix. Try again.', - unavailable: 'Lucky Mix is unavailable for this server.', - cancelTooltip: 'Cancel Lucky Mix build', - }, - albums: { - title: 'All Albums', - sortByName: 'A–Z (Album)', - sortByArtist: 'A–Z (Artist)', - sortNewest: 'Newest first', - sortRandom: 'Random', - yearFrom: 'From', - yearTo: 'To', - yearFilterClear: 'Clear year filter', - yearFilterLabel: 'Year', - compilationLabel: 'Compilations', - compilationOnly: 'Only compilations', - compilationHide: 'Hide compilations', - compilationTooltipAll: 'All albums · click: only compilations', - compilationTooltipOnly: 'Only compilations · click: hide compilations', - compilationTooltipHide: 'Compilations hidden · click: show all', - select: 'Multi-select', - startSelect: 'Enable multi-select', - cancelSelect: 'Cancel', - selectionCount: '{{count}} selected', - downloadZips: 'Download ZIPs', - addOffline: 'Add Offline', - enqueueSelected_one: 'Enqueue ({{count}})', - enqueueSelected_other: 'Enqueue ({{count}})', - enqueueQueued_one: 'Added {{count}} album to queue', - enqueueQueued_other: 'Added {{count}} albums to queue', - downloadingZip: 'Downloading {{current}}/{{total}}: {{name}}', - downloadZipDone: '{{count}} ZIP(s) downloaded', - downloadZipFailed: 'Failed to download {{name}}', - offlineQueuing: 'Queuing {{count}} album(s) for offline…', - offlineFailed: 'Failed to add {{name}} offline', - }, - tracks: { - title: 'Tracks', - subtitle: 'Browse. Search. Discover.', - heroEyebrow: 'Track of the moment', - heroReroll: 'Pick another', - playSong: 'Play', - enqueueSong: 'Add to queue', - railRandom: 'Random Pick', - railHighlyRated: 'Highly Rated', - browseTitle: 'Browse all tracks', - browseUnsupported: "This server doesn't list the whole library at once. Use the search above to find specific tracks.", - searchPlaceholder: 'Find a track by title, artist or album…', - count_one: '{{count}} track', - count_other: '{{count}} tracks', - }, - artists: { - title: 'Artists', - search: 'Search…', - all: 'All', - gridView: 'Grid view', - listView: 'List view', - imagesOn: 'Artist images on — may increase network and system load', - imagesOff: 'Artist images off — showing initials only', - loadMore: 'Load more', - notFound: 'No artists found.', - albumCount_one: '{{count}} Album', - albumCount_other: '{{count}} Albums', - selectionCount: '{{count}} selected', - select: 'Multi-select', - startSelect: 'Enable multi-select', - cancelSelect: 'Cancel', - addToPlaylist: 'Add to Playlist', - }, - composers: { - title: 'Composers', - search: 'Search…', - notFound: 'No composers found.', - unsupported: 'Browse by Composer requires Navidrome 0.55 or newer.', - loadFailed: 'Could not load composers.', - retry: 'Retry', - involvedIn_one: 'Involved in {{count}} album', - involvedIn_other: 'Involved in {{count}} albums', - }, - composerDetail: { - back: 'Back', - notFound: 'Composer not found.', - about: 'About this composer', - works: 'Works', - noWorks: 'No works found.', - workCount_one: '{{count}} work', - workCount_other: '{{count}} works', - shareComposer: 'Share composer', - unknownComposer: 'Composer', - }, - login: { - subtitle: 'Your Navidrome Desktop Player', - serverName: 'Server Name (optional)', - serverNamePlaceholder: 'My Navidrome', - serverUrl: 'Server URL', - serverUrlPlaceholder: '192.168.1.100:4533 or https://music.example.com', - username: 'Username', - usernamePlaceholder: 'admin', - password: 'Password', - showPassword: 'Show password', - hidePassword: 'Hide password', - connect: 'Connect', - connecting: 'Connecting…', - connected: 'Connected!', - error: 'Connection failed – please check your details.', - urlRequired: 'Please enter a server URL.', - savedServers: 'Saved Servers', - addNew: 'Or add a new server', - orMagicString: 'Or magic string', - magicStringPlaceholder: 'Paste a share string (psysonic1-…)', - magicStringInvalid: 'Invalid or unreadable magic string.', - }, - connection: { - connected: 'Connected', - connectedTo: 'Connected to {{server}}', - disconnected: 'Disconnected', - disconnectedFrom: 'Cannot reach {{server}} — click to check settings', - checking: 'Connecting…', - extern: 'Extern', - offlineTitle: 'No server connection', - offlineSubtitle: 'Cannot reach {{server}}. Check your network or server.', - offlineModeBanner: 'Offline Mode — playing from local cache', - offlineNoCacheBanner: 'No server connection — cannot reach {{server}}', - offlineLibraryTitle: 'Offline Library', - offlineLibraryEmpty: 'No albums cached yet. Go online, open an album and click "Make available offline".', - offlineAlbumCount: '{{n}} album', - offlineAlbumCount_plural: '{{n}} albums', - offlineFilterAll: 'All', - offlineFilterAlbums: 'Albums', - offlineFilterPlaylists: 'Playlists', - offlineFilterArtists: 'Discographies', - retry: 'Retry', - serverSettings: 'Server Settings', - switchServerTitle: 'Switch server', - switchServerHint: 'Click to choose another saved server.', - manageServers: 'Manage servers…', - switchFailed: 'Could not switch — server unreachable.', - lastfmConnected: 'Last.fm connected as @{{user}}', - lastfmSessionInvalid: 'Session invalid — click to re-connect', - }, - common: { - albums: 'Albums', - album: 'Album', - loading: 'Loading…', - loadingMore: 'Loading…', - loadingPlaylists: 'Loading Playlists…', - noAlbums: 'No albums found.', - downloading: 'Downloading…', - downloadZip: 'Download (ZIP)', - back: 'Back', - cancel: 'Cancel', - close: 'Close', - save: 'Save', - delete: 'Delete', - use: 'Use', - add: 'Add', - new: 'New', - active: 'Active', - download: 'Download', - chooseDownloadFolder: 'Choose download folder', - noFolderSelected: 'No folder selected', - rememberDownloadFolder: 'Remember this folder', - filterGenre: 'Genre Filter', - filterSearchGenres: 'Search genres…', - filterNoGenres: 'No genres match', - filterClear: 'Clear', - favorites: 'Favorites', - favoritesTooltipOff: 'Show only favorites', - favoritesTooltipOn: 'Show all', - play: 'Play', - bulkSelected: '{{count}} selected', - clearSelection: 'Clear selection', - bulkAddToPlaylist: 'Add to Playlist', - bulkRemoveFromPlaylist: 'Remove from Playlist', - bulkClear: 'Clear selection', - updaterAvailable: 'Update available', - updaterVersion: 'v{{version}} is available', - updaterWebsite: 'Website', - updaterModalTitle: 'New Version Available', - updaterChangelog: "What's New", - updaterDownloadBtn: 'Download Now', - updaterSkipBtn: 'Skip this Version', - updaterRemindBtn: 'Remind me Later', - updaterDone: 'Download complete', - updaterShowFolder: 'Show in Folder', - updaterInstallHint: 'Close Psysonic and run the installer manually.', - updaterAurHint: 'Install the update via AUR:', - updaterErrorMsg: 'Download failed', - updaterRetryBtn: 'Retry', - updaterInstallNow: 'Install now', - updaterMacReadyTitle: 'Ready to install', - updaterMacReady: 'The update downloads, verifies and applies in place — no DMG needed. The app restarts automatically when done.', - updaterTrustNotarized: 'Notarized by Apple', - updaterTrustSignature: 'Signature verified', - updaterMacDoneTitle: 'Update installed', - updaterRestartingIn: 'Restarting in {{n}}s…', - updaterRestarting: 'Restarting…', - updaterRestartNow: 'Restart now', - durationHoursMinutes: '{{hours}}h {{minutes}}m', - durationMinutesOnly: '{{minutes}}m', - updaterOpenGitHub: 'Open on GitHub', - filters: 'Filters', - more: 'more', - yearRange: 'Year Range', - clearAll: 'Clear all', - }, - settings: { - title: 'Settings', - language: 'Language', - languageEn: 'English', - languageDe: 'Deutsch', - languageEs: 'Español', - languageFr: 'Français', - languageNl: 'Nederlands', - languageNb: 'Norsk', - languageRu: 'Русский', - languageZh: '中文', - languageRo: 'Română', - font: 'Font', - fontHintOpenDyslexic: 'Dyslexia-friendly · no Chinese support', - theme: 'Theme', - appearance: 'Appearance', - servers: 'Servers', - serverName: 'Server Name', - serverUrl: 'Server URL', - serverUrlPlaceholder: '192.168.1.100:4533 or https://music.example.com', - serverUsername: 'Username', - serverPassword: 'Password', - addServer: 'Add Server', - addServerTitle: 'Add New Server', - useServer: 'Use', - deleteServer: 'Delete', - noServers: 'No servers saved.', - serverActive: 'Active', - confirmDeleteServer: 'Delete server "{{name}}"?', - serverConnecting: 'Connecting…', - serverConnected: 'Connected!', - serverFailed: 'Connection failed.', - testBtn: 'Test Connection', - testingBtn: 'Testing…', - serverCompatible: 'Built for Navidrome. Other Subsonic-compatible servers (Gonic, Airsonic, …) may work with reduced functionality, since Psysonic uses many Navidrome-specific API endpoints.', - userMgmtTitle: 'User Management', - userMgmtDesc: 'Manage users on this server. Requires admin privileges.', - userMgmtNoAdmin: 'You need admin privileges to manage users on this server.', - userMgmtLoadError: 'Failed to load users.', - userMgmtLoadFriendly: 'Server didn\'t answer — this is usually a one-off.', - userMgmtRetry: 'Retry', - userMgmtEmpty: 'No users found.', - userMgmtYouBadge: 'You', - userMgmtAdminBadge: 'Admin', - userMgmtAddUser: 'Add User', - userMgmtAddUserTitle: 'Add New User', - userMgmtEditUserTitle: 'Edit User', - userMgmtUsername: 'Username', - userMgmtName: 'Display Name', - userMgmtEmail: 'Email', - userMgmtPassword: 'Password', - userMgmtPasswordEditHint: 'Enter a new password to update it.', - userMgmtRoleAdmin: 'Admin', - userMgmtLibraries: 'Libraries', - userMgmtLibrariesAdminHint: 'Admin users automatically have access to all libraries.', - userMgmtLibrariesEmpty: 'No libraries available on this server.', - userMgmtLibrariesValidation: 'Select at least one library.', - userMgmtLibrariesUpdateError: 'User saved, but library assignment failed', - userMgmtNoLibraries: 'No libraries assigned', - userMgmtNeverSeen: 'Never', - userMgmtSave: 'Save', - userMgmtCancel: 'Cancel', - userMgmtDelete: 'Delete', - userMgmtEdit: 'Edit', - userMgmtConfirmDelete: 'Delete user "{{username}}"? This cannot be undone.', - userMgmtCreateError: 'Failed to create user.', - userMgmtUpdateError: 'Failed to update user.', - userMgmtDeleteError: 'Failed to delete user.', - userMgmtCreated: 'User created.', - userMgmtUpdated: 'User updated.', - userMgmtDeleted: 'User deleted.', - userMgmtValidationMissing: 'Username, display name and password are required.', - userMgmtValidationMissingIdentity: 'Username and display name are required.', - userMgmtMagicStringGenerate: 'Generate magic string', - userMgmtSaveAndMagicString: 'Save and get magic string', - userMgmtMagicStringPasswordNavHint: - 'Navidrome will save this password for the user. If it differs from the current one, the server will update the login password.', - userMgmtMagicStringPlaintextWarning: - 'Share the magic string carefully: it contains an unencrypted password (encoding is not encryption). Anyone with the full string can sign in as this user.', - userMgmtMagicStringCopied: 'Magic string copied to clipboard.', - userMgmtMagicStringCopyFailed: 'Could not copy to clipboard.', - userMgmtMagicStringLoginFailed: 'Password check failed — credentials could not be verified.', - userMgmtMagicStringModalTitle: 'Generate magic string', - userMgmtMagicStringModalDesc: 'Enter the Subsonic password for "{{username}}". It is included in the copied magic string.', - userMgmtMagicStringModalConfirm: 'Copy string', - audiomuseTitle: 'AudioMuse-AI (Navidrome)', - audiomuseDesc: - 'Turn on if this server has the AudioMuse-AI Navidrome plugin configured. Enables Instant Mix from tracks and uses server-side similar artists instead of Last.fm on artist pages.', - audiomuseIssueHint: - 'Instant Mix failed recently — check the Navidrome plugin and AudioMuse API. Similar artists fall back to Last.fm when the server returns none.', - connected: 'Connected', - failed: 'Failed', - eqTitle: 'Equalizer', - eqEnabled: 'Enable Equalizer', - eqPreset: 'Preset', - eqPresetCustom: 'Custom', - eqPresetBuiltin: 'Built-in Presets', - eqPresetCustomGroup: 'My Presets', - eqSavePreset: 'Save as Preset', - eqPresetName: 'Preset name…', - eqDeletePreset: 'Delete preset', - eqResetBands: 'Reset to Flat', - eqPreGain: 'Pre-gain', - eqResetPreGain: 'Reset pre-gain', - eqAutoEqTitle: 'AutoEQ Headphone Lookup', - eqAutoEqPlaceholder: 'Search headphone / IEM model…', - eqAutoEqSearching: 'Searching…', - eqAutoEqNoResults: 'No results found', - eqAutoEqError: 'Search failed', - eqAutoEqRateLimit: 'GitHub rate limit reached — try again in a minute', - eqAutoEqFetchError: 'Failed to fetch EQ profile', - lfmTitle: 'Last.fm', - lfmConnect: 'Connect with Last.fm', - lfmConnecting: 'Waiting for authorisation…', - lfmConfirm: 'I have authorised the app', - lfmConnected: 'Connected as', - lfmDisconnect: 'Disconnect', - lfmConnectDesc: 'Connect your Last.fm account to enable scrobbling and Now Playing updates directly from Psysonic — no Navidrome configuration required.', - lfmOpenBrowser: 'A browser window will open. Authorise Psysonic on Last.fm, then click the button below.', - lfmScrobbles: '{{n}} scrobbles', - lfmMemberSince: 'Member since {{year}}', - scrobbleEnabled: 'Scrobbling enabled', - scrobbleDesc: 'Send songs to Last.fm after 50% playtime', - behavior: 'App Behavior', - cacheTitle: 'Max. Storage Size', - cacheDesc: 'Cover art and artist images. When full, the oldest entries are removed automatically. Offline albums are not auto-removed, but will be deleted when clearing the cache manually.', - cacheUsedImages: 'Images:', - cacheUsedOffline: 'Offline tracks:', - cacheUsedHot: 'Size on disk:', - hotCacheTrackCount: 'Tracks in cache:', - cacheMaxLabel: 'Max. size', - cacheClearBtn: 'Clear Cache', - waveformCacheClearBtn: 'Clear waveform cache', - cacheClearWarning: 'This will also remove all offline albums from the library.', - cacheClearConfirm: 'Clear Everything', - cacheClearCancel: 'Cancel', - waveformCacheCleared: 'Waveform cache cleared ({{count}} rows).', - waveformCacheClearFailed: 'Failed to clear waveform cache.', - offlineDirTitle: 'Offline Library (In-App)', - offlineDirDesc: 'Storage location for tracks you make available offline within Psysonic.', - offlineDirDefault: 'Default (App Data)', - offlineDirChange: 'Change Directory', - offlineDirClear: 'Reset to Default', - offlineDirHint: 'New downloads will use this location. Existing downloads remain at their original path.', - hotCacheTitle: 'Hot playback cache', - hotCacheDisclaimer: 'Preloads upcoming queue tracks and keeps previous ones. When enabled, uses disk space and network.', - hotCacheDirDefault: 'Default (App Data)', - hotCacheDirChange: 'Change folder', - hotCacheDirClear: 'Reset to default', - hotCacheDirHint: 'Changing the folder resets the in-app index; files already on disk stay where they are until you remove them.', - hotCacheEnabled: 'Enable hot playback cache', - hotCacheMaxMb: 'Maximum cache size', - hotCacheDebounce: 'Queue change debounce', - hotCacheDebounceImmediate: 'Immediate', - hotCacheDebounceSeconds: '{{n}} s', - hotCacheClearBtn: 'Clear hot cache', - audioOutputDevice: 'Audio Output Device', - audioOutputDeviceDesc: 'Select which audio device Psysonic plays through. Changes take effect immediately and restart the current track.', - audioOutputDeviceDefault: 'System Default', - audioOutputDeviceRefresh: 'Refresh device list', - audioOutputDeviceOsDefaultNow: 'current system output', - audioOutputDeviceListError: 'Could not load the audio device list.', - audioOutputDeviceNotInCurrentList: 'not in current list', - audioOutputDeviceMacNotice: 'On macOS, playback currently always follows the system output device for technical reasons. Change the target via System Settings → Sound or the speaker icon in the menu bar. Background: CoreAudio triggers a microphone-permission prompt when opening a non-default stream — we avoid it by always using the system default.', - hiResTitle: 'Native Hi-Res Playback', - hiResEnabled: 'Enable native hi-res playback', - hiResDesc: "Forces 44.1 kHz output by default for maximum stability. Enable only if your hardware and network reliably support high sample rates (88.2 kHz+).", - showArtistImages: 'Show Artist Images', - showArtistImagesDesc: 'Load and display artist images in the Artists overview. Disabled by default to reduce server disk I/O and network load on large libraries.', - showOrbitTrigger: 'Show "Orbit" in the header', - showOrbitTriggerDesc: 'The top-bar trigger for starting or joining a shared listening session. Hide it if you don\'t use Orbit — you can turn it back on here.', - showTrayIcon: 'Show Tray Icon', - showTrayIconDesc: 'Display the Psysonic icon in the system notification area / menu bar.', - minimizeToTray: 'Minimize to Tray', - minimizeToTrayDesc: 'When closing the window, keep Psysonic running in the system tray instead of quitting.', - preloadMiniPlayer: 'Preload mini player', - preloadMiniPlayerDesc: 'Build the mini player window in the background at app start so it shows content instantly on first open. Uses a little extra memory.', - discordRichPresence: 'Discord Rich Presence', - discordRichPresenceDesc: 'Show the currently playing track on your Discord profile. Requires Discord to be running.', - useCustomTitlebar: 'Custom title bar', - useCustomTitlebarDesc: 'Replace the system title bar with a built-in one that matches the app theme. Disable to use the native GNOME/GTK title bar.', - linuxWebkitSmoothScroll: 'Smooth wheel (Linux)', - linuxWebkitSmoothScrollDesc: 'On: inertial scroll. Off: line-by-line, GTK-style.', - discordCoverSource: 'Cover art source', - discordCoverSourceDesc: 'Where to fetch album artwork shown on your Discord profile.', - discordCoverNone: 'None (app icon only)', - discordCoverServer: 'Server (via album info)', - discordCoverApple: 'Apple Music', - discordOptions: 'Advanced Discord options', - discordTemplates: 'Custom text templates', - discordTemplatesDesc: 'Customize what information is shown on your Discord profile. Variables: {title}, {artist}, {album}', - discordTemplateDetails: 'Primary line (details)', - discordTemplateState: 'Secondary line (state)', - discordTemplateLargeText: 'Album tooltip (largeText)', - nowPlayingEnabled: 'Show in Now Playing', - nowPlayingEnabledDesc: 'Broadcast your currently playing track to the server\'s live listener view. Disable to stop sending playback data.', - enableBandsintown: 'Bandsintown tour dates', - enableBandsintownDesc: 'Show upcoming concerts for the current artist in the Info tab. Data is fetched from the public Bandsintown API.', - lyricsServerFirst: 'Prefer server lyrics', - lyricsServerFirstDesc: 'Check server-provided lyrics (embedded tags, sidecar files) before querying LRCLIB. Disable to use LRCLIB first.', - enableNeteaselyrics: 'Netease Cloud Music lyrics', - enableNeteaselyricsDesc: 'Use Netease Cloud Music as a last-resort lyrics source when server and LRCLIB both return nothing. Best coverage for Asian and international music.', - lyricsSourcesTitle: 'Lyrics Sources', - lyricsSourcesDesc: 'Choose which sources to query for lyrics and in what order. Drag to reorder. Disabled sources are skipped entirely.', - lyricsSourceServer: 'Server', - lyricsSourceLrclib: 'LRCLIB', - lyricsSourceNetease: 'Netease Cloud Music', - lyricsModeStandard: 'Standard', - lyricsModeStandardDesc: 'Three sources in a freely orderable list: server tags, LRCLIB, Netease.', - lyricsModeLyricsplus: 'YouLyPlus (Karaoke)', - lyricsModeLyricsplusDesc: 'Word-by-word sync sourced from Apple Music, Spotify, Musixmatch & QQ (community backend). Silently falls back to the standard sources when nothing is found.', - lyricsStaticOnly: 'Show lyrics as static text only', - lyricsStaticOnlyDesc: 'Render synced lyrics without auto-scroll and without word highlighting.', - downloadsTitle: 'ZIP Export & Archiving', - downloadsFolderDesc: 'Destination folder for albums you download as a ZIP file to your computer.', - downloadsDefault: 'Default Downloads Folder', - pickFolder: 'Select', - pickFolderTitle: 'Select Download Folder', - clearFolder: 'Clear download folder', - logout: 'Logout', - aboutTitle: 'About Psysonic', - aboutDesc: 'A modern desktop music player built for Navidrome. Uses the Subsonic API plus Navidrome-specific extensions. Built on Tauri v2 with a native Rust audio engine — lightweight and fast, yet packed with features: waveform seekbar, synchronized lyrics, Last.fm integration, 10-band EQ, crossfade, gapless playback, Replay Gain, genre browsing, and a large library of themes.', - aboutLicense: 'License', - aboutLicenseText: 'GNU GPL v3 — free to use, modify, and distribute under the same license.', - aboutRepo: 'Source Code on GitHub', - aboutVersion: 'Version', - aboutBuiltWith: 'Built with Tauri · React · TypeScript · Rust/rodio', - aboutMaintainersLabel: 'Maintainers', - aboutReleaseNotesLabel: 'Release notes', - aboutReleaseNotesLink: "Open this version's what's-new", - aboutContributorsLabel: 'Contributors', - showChangelogOnUpdate: "Show 'What's New' on update", - showChangelogOnUpdateDesc: "Show a discreet changelog banner above Now Playing after an update. Click opens the release notes; X dismisses it.", - randomMixTitle: 'Random Mix Blacklist', - luckyMixMenuTitle: 'Show Lucky Mix in menu', - luckyMixMenuDesc: 'Enables Lucky Mix in Build a Mix and as a separate menu item when split navigation is on. Visible only when AudioMuse is enabled on the active server.', - randomMixBlacklistTitle: 'Custom Filter Keywords', - randomMixBlacklistDesc: 'Songs are excluded when any keyword matches their genre, title, album, or artist (active when the checkbox above is on).', - randomMixBlacklistPlaceholder: 'Add keyword…', - randomMixBlacklistAdd: 'Add', - randomMixBlacklistEmpty: 'No custom keywords added yet.', - randomMixHardcodedTitle: 'Built-in keywords (active when checkbox is on)', - tabAudio: 'Audio', - tabStorage: 'Offline & Cache', - tabAppearance: 'Appearance', - tabLibrary: 'Library', - tabServers: 'Servers', - tabLyrics: 'Lyrics', - tabPersonalisation: 'Personalisation', - tabIntegrations: 'Integrations', - inputKeybindingsTitle: 'Keyboard shortcuts', - aboutContributorsCount_one: '{{count}} contribution', - aboutContributorsCount_other: '{{count}} contributions', - searchPlaceholder: 'Search settings…', - searchNoResults: 'No settings match your search.', - integrationsPrivacyTitle: 'Privacy notice', - integrationsPrivacyBody: 'All integrations on this tab are opt-in and send data to external services or to your Navidrome server when enabled. Last.fm receives your listening history, Discord shows the currently playing track in your profile, Bandsintown is queried per artist to fetch tour dates, and the Now-Playing share publishes your current track to other users of your Navidrome server. If you don\'t want any of this, simply leave the corresponding section disabled.', - homeCustomizerTitle: 'Home Page', - queueToolbarTitle: 'Queue Toolbar', - queueToolbarReset: 'Reset to default', - queueToolbarSeparator: 'Separator', - sidebarTitle: 'Sidebar', - sidebarReset: 'Reset to default', - artistLayoutTitle: 'Artist page sections', - artistLayoutDesc: 'Drag to reorder, toggle to hide individual sections of the artist page. Sections without data are skipped automatically.', - artistLayoutReset: 'Reset to default', - artistLayoutBio: 'Artist biography', - artistLayoutTopTracks: 'Top tracks', - artistLayoutSimilar: 'Similar artists', - artistLayoutAlbums: 'Albums', - artistLayoutFeatured: 'Also featured on', - sidebarDrag: 'Drag to reorder', - sidebarFixed: 'Always visible', - randomNavSplitTitle: 'Split Mix navigation', - randomNavSplitDesc: 'Show "Random Mix", "Random Albums", and "Lucky Mix" as separate sidebar entries instead of the "Build a Mix" hub.', - tabInput: 'Input', - tabUsers: 'Users', - tabSystem: 'System', - loggingTitle: 'Logging', - loggingModeDesc: 'Controls backend log verbosity in the terminal.', - loggingModeOff: 'Off', - loggingModeNormal: 'Normal', - loggingModeDebug: 'Debug', - loggingExport: 'Export logs', - loggingExportSuccess: 'Logs exported ({{count}} lines).', - loggingExportError: 'Could not export logs.', - ratingsSectionTitle: 'Ratings', - ratingsSkipStarTitle: 'Skip for 1 star', - ratingsSkipStarDesc: - 'After several skips in a row, set the track to 1★. Only for tracks not yet rated.', - ratingsSkipStarThresholdLabel: 'Skips', - ratingsMixFilterTitle: 'Filter by rating', - ratingsMixFilterDesc: - 'Filter low-rated items in {{mix}} and {{albums}}. Click the selected star again to turn off the threshold.', - ratingsMixMinSong: 'Songs', - ratingsMixMinAlbum: 'Albums', - ratingsMixMinArtist: 'Artists', - ratingsMixMinThresholdAria: 'Minimum stars: {{label}}', - backupTitle: 'Backup & Restore', - backupExport: 'Export settings', - backupExportDesc: 'Saves all settings, server profiles, Last.fm config, theme, EQ and keybindings to a .psybkp file. Passwords are stored in plaintext — keep the file secure.', - backupImport: 'Import settings', - backupImportDesc: 'Restores settings from a .psybkp file. The app will reload after import.', - backupImportConfirm: 'This will overwrite all current settings. Continue?', - backupSuccess: 'Backup saved', - backupImportSuccess: 'Settings restored — reloading…', - backupImportError: 'Invalid or corrupted backup file.', - shortcutsReset: 'Reset to defaults', - shortcutListening: 'Press a key…', - shortcutUnbound: '—', - globalShortcutsTitle: 'Global Shortcuts', - globalShortcutsNote: 'Work system-wide even when Psysonic is in the background. Requires Ctrl, Alt, or Super as a modifier.', - shortcutClear: 'Clear', - shortcutPlayPause: 'Play / Pause', - shortcutNext: 'Next track', - shortcutPrev: 'Previous track', - shortcutVolumeUp: 'Volume up', - shortcutVolumeDown: 'Volume down', - shortcutSeekForward: 'Seek forward 10s', - shortcutSeekBackward: 'Seek backward 10s', - shortcutToggleQueue: 'Toggle queue', - shortcutOpenFolderBrowser: 'Open {{folderBrowser}}', - shortcutFullscreenPlayer: 'Fullscreen player', - shortcutNativeFullscreen: 'Native fullscreen', - shortcutOpenMiniPlayer: 'Open mini player', - shortcutStartSearch: 'Start a search', - shortcutStartAdvancedSearch: 'Start an advanced search', - shortcutToggleSidebar: 'Toggle Sidebar', - shortcutMuteSound: 'Mute sound', - shortcutToggleEqualizer: 'Open / Toggle Equalizer', - shortcutToggleRepeat: 'Toggle Repeat', - shortcutOpenNowPlaying: 'Open "Now Playing"', - shortcutShowLyrics: 'Show Lyrics', - shortcutFavoriteCurrentTrack: 'Add current track to favorites', - shortcutOpenHelp: 'Help', - playbackTitle: 'Playback', - replayGain: 'Replay Gain', - replayGainDesc: 'Normalize track volume using ReplayGain metadata', - replayGainMode: 'Mode', - replayGainAuto: 'Auto', - replayGainAutoDesc: 'Picks album gain when neighbouring queue tracks are from the same album, otherwise track gain.', - replayGainTrack: 'Track', - replayGainAlbum: 'Album', - replayGainPreGain: 'Pre-Gain (tagged files)', - replayGainPreGainDesc: 'Universal boost added on top of every ReplayGain calculation. Use to compensate if your library feels too quiet overall.', - replayGainFallback: 'Fallback (untagged / radio)', - replayGainFallbackDesc: 'Applied to tracks (and radio streams) that have no ReplayGain tags at all, so untagged content does not pop louder than the rest.', - normalization: 'Normalization', - normalizationDesc: 'Even out perceived loudness across tracks, albums and radio.', - normalizationOff: 'Off', - normalizationReplayGain: 'ReplayGain', - normalizationLufs: 'LUFS', - loudnessTargetLufs: 'Target LUFS', - loudnessTargetLufsDesc: 'Reference loudness all tracks are matched to. Lower numbers = louder output. Streaming services typically sit around -14 LUFS.', - loudnessPreAnalysisAttenuation: 'Pre-analysis attenuation', - loudnessPreAnalysisAttenuationDesc: - 'Extra quieting until loudness for this track is saved. Streaming then uses rough guesses, not a full measurement. 0 dB = off; lower = quieter. The number on the right is the effective dB for your current target.', - loudnessPreAnalysisAttenuationRef: 'Effective {{eff}} dB with target {{tgt}} LUFS.', - loudnessPreAnalysisAttenuationReset: 'Reset to default', - loudnessFirstPlayNote: - 'First play of a brand-new track may briefly drift in volume while it is being measured. The next play uses the cached measurement and is rock-solid. Upcoming queue tracks are usually pre-analysed during the previous song, so this rarely happens in practice.', - crossfade: 'Crossfade', - crossfadeDesc: 'Fade between tracks', - crossfadeSecs: '{{n}} s', - notWithGapless: 'Not available while Gapless is active', - notWithCrossfade: 'Not available while Crossfade is active', - gapless: 'Gapless Playback', - gaplessDesc: 'Pre-buffer next track to eliminate gaps between songs', - preservePlayNextOrder: 'Preserve "Play Next" order', - preservePlayNextOrderDesc: 'Newly added Play Next items queue up behind earlier ones instead of jumping in front.', - trackPreviewsTitle: 'Track Previews', - trackPreviewsToggle: 'Enable track previews', - trackPreviewsDesc: 'Show inline Play and Preview buttons in tracklists for a quick mid-song sample.', - trackPreviewStart: 'Start position', - trackPreviewStartDesc: 'How far into the track the preview starts (% of track length).', - trackPreviewDuration: 'Duration', - trackPreviewDurationDesc: 'How long each preview plays before it stops.', - trackPreviewDurationSecs: '{{n}} s', - trackPreviewLocationsTitle: 'Where previews appear', - trackPreviewLocationsDesc: 'Pick which lists show inline preview buttons.', - trackPreviewLocation_suggestions: 'In playlist suggestions', - trackPreviewLocation_albums: 'In album tracklists', - trackPreviewLocation_playlists: 'In playlists', - trackPreviewLocation_favorites: 'In favorites', - trackPreviewLocation_artist: 'In artist top tracks', - trackPreviewLocation_randomMix: 'In Random Mix', - preloadMode: 'Preload Next Track', - preloadModeDesc: 'When to start buffering the next track in the queue', - nextTrackBufferingTitle: 'Buffering', - preloadHotCacheMutualExclusive: 'Preload and Hot Cache serve the same purpose — only one can be active at a time. Enabling one will automatically disable the other.', - preloadOff: 'Off', - preloadBalanced: 'Balanced (30 s before end)', - preloadEarly: 'Early (after 5 s of playback)', - preloadCustom: 'Custom', - preloadCustomSeconds: 'Seconds before end: {{n}}', - infiniteQueue: 'Infinite Queue', - infiniteQueueDesc: 'Automatically append random tracks when the queue runs out', - experimental: 'Experimental', - fsPlayerSection: 'Fullscreen Player', - fsLyricsStyle: 'Lyrics style', - fsLyricsStyleRail: 'Rail', - fsLyricsStyleRailDesc: 'Classic 5-line sliding rail.', - fsLyricsStyleApple: 'Scrolling', - fsLyricsStyleAppleDesc: 'Full-screen scrollable list.', - sidebarLyricsStyle: 'Lyrics scroll style', - sidebarLyricsStyleClassic: 'Classic', - sidebarLyricsStyleClassicDesc: 'Scroll active line to center.', - sidebarLyricsStyleApple: 'Apple Music-like', - sidebarLyricsStyleAppleDesc: 'Active line anchors near the top with smooth spring transitions.', - fsShowArtistPortrait: 'Show artist photo', - fsShowArtistPortraitDesc: 'Display the artist photo (or album art) on the right side of the fullscreen player.', - fsPortraitDim: 'Photo dimming', - seekbarStyle: 'Seekbar Style', - seekbarStyleDesc: 'Choose the look of the player seek bar', - seekbarTruewave: 'Truewave', - seekbarPseudowave: 'Pseudowave', - seekbarLinedot: 'Line & Dot', - seekbarBar: 'Bar', - seekbarThick: 'Thick Bar', - seekbarSegmented: 'Segmented', - seekbarNeon: 'Neon Glow', - seekbarPulsewave: 'Pulse Wave', - seekbarParticletrail: 'Particle Trail', - seekbarLiquidfill: 'Liquid Fill', - seekbarRetrotape: 'Retro Tape', - themeSchedulerTitle: 'Auto-Switch Theme', - themeSchedulerEnable: 'Enable Theme Scheduler', - themeSchedulerEnableSub: 'Automatically switch between two themes based on the time of day', - themeSchedulerDayTheme: 'Day Theme', - themeSchedulerDayStart: 'Day Starts At', - themeSchedulerNightTheme: 'Night Theme', - themeSchedulerNightStart: 'Night Starts At', - themeSchedulerActiveHint: 'Theme Scheduler is active - theme changes are managed automatically.', - visualOptionsTitle: 'Visual Options', - coverArtBackground: 'Cover Art Background', - coverArtBackgroundSub: 'Show blurred cover art as background in album/playlist headers', - playlistCoverPhoto: 'Playlist Cover Photo', - playlistCoverPhotoSub: 'Show cover photo grid in playlist detail view', - showBitrate: 'Show Bitrate', - showBitrateSub: 'Display audio bitrate in track listings', - floatingPlayerBar: 'Floating Player Bar', - floatingPlayerBarSub: 'Keep the player bar floating above content', - uiScaleTitle: 'Interface Scale', - uiScaleLabel: 'Zoom', - }, - changelog: { - modalTitle: "What's New", - dontShowAgain: "Don't show again", - close: 'Got it', - }, - whatsNew: { - title: "What's New", - empty: 'No changelog entry for this version yet.', - bannerTitle: 'Changelog', - bannerCollapsed: "What's new in v{{version}}", - dismiss: 'Dismiss', - close: 'Close', - }, - help: { - title: 'Help', - searchPlaceholder: 'Search Help…', - noResults: 'No matching topics. Try a different search term.', - // ── Section 1: Getting Started ───────────────────────────────────────── - s1: 'Getting Started', - q1: 'Which servers are compatible?', - a1: 'Psysonic is built first and foremost for Navidrome and is fully Subsonic-compatible — Gonic, Airsonic, LMS and other Subsonic-API servers also work. Some advanced features (ratings, smart playlists, magic-string sharing, user management) require Navidrome.', - q2: 'How do I add a server?', - a2: 'Settings → Servers → Add Server. Enter the URL (e.g. http://192.168.1.100:4533), username, and password. Psysonic tests the connection before saving — nothing is stored if it fails. You can add as many servers as you like and switch between them in the header at any time; only one is active at a time.', - q3: 'Quick tour of the UI?', - a3: 'Sidebar (left) for navigation, Mainstage / pages in the middle, Player Bar at the bottom, and the Queue Panel on the right (toggle from the top-right header next to the Now-Playing indicator). The search bar at the top searches your whole library; "Now Playing" shows what other users on the same Navidrome server are listening to right now.', - // ── Section 2: Playback & Queue ──────────────────────────────────────── - s2: 'Playback & Queue', - q4: 'How do I use the queue?', - a4: 'Open the Queue Panel from the top-right header. Drag rows to reorder them, drop them outside to remove, or use the queue toolbar to shuffle, save the queue as a playlist, or jump to a track. Drag rows out of the panel to drop them somewhere else as a transfer.', - q5: 'Gapless vs Crossfade — what is the difference?', - a5: 'Gapless pre-buffers the next track so there is zero silence between songs (best for live albums and DJ mixes). Crossfade fades the current track out while the next fades in over 1–10 s (best for shuffled mixes). They are mutually exclusive — enabling one disables the other. Configure both in Settings → Audio.', - q6: 'What is Infinite Queue?', - a6: 'When the queue runs out and Repeat is off, Psysonic silently appends similar / random tracks from your library so playback never stops. Auto-added tracks appear below a "— Added automatically —" divider. Toggle it with the infinity icon in the queue header; restrict auto-additions to a genre in Settings → Queue.', - q7: 'Multi-select and Shift-click range selection?', - a7: 'Activate "Select" on Albums / New Releases / Random Albums / Playlists. Click an item to toggle it, then hold Shift and click another item to select everything between them in the visible order. Shift-clicks extend from the most recently clicked anchor. The toolbar above the grid offers bulk actions (queue, download, delete, etc.).', - q8: 'Keyboard shortcuts and global hotkeys?', - a8: 'Default in-app keys: Space = Play / Pause, Esc = close fullscreen / modals, F1 = shortcuts cheat-sheet. Settings → Input lets you rebind every in-app action (also as chords like Ctrl+Shift+P) and set system-wide global shortcuts that work even when Psysonic is in the background or minimized. Media keys (Play/Pause, Next, Previous) work on all platforms.', - // ── Section 3: Audio Tools ───────────────────────────────────────────── - s3: 'Audio Tools', - q9: 'Replay Gain modes?', - a9: 'Settings → Audio → Replay Gain. Track mode normalises every song to a target level. Album mode preserves the loudness curve within an album. Auto mode picks Track or Album based on whether the queue is from a single album. Tracks without Replay Gain tags fall back to a configurable preamp.', - q10: 'What is Smart Loudness Normalization (LUFS)?', - a10: 'A modern alternative to Replay Gain in Settings → Audio. Psysonic analyses each track to LUFS / EBU R128 and stores the result, so volume is consistent across your whole library — including tracks without Replay Gain tags. Cold-cache analysis runs in the background and uses 35–40 % CPU for ~1 minute, then drops to 0. Set your target loudness (default −10 LUFS) once.', - q11: 'EQ and AutoEQ?', - a11: 'A 10-band parametric EQ lives in Settings → Audio → Equalizer with manual bands and presets. AutoEQ next to it pulls a measured correction profile for your headphone model from the AutoEQ database and applies it to the bands automatically — pick your headphones and the EQ snaps to the correct curve.', - q12: 'How do I switch the audio output device?', - a12: 'Settings → Audio → Output Device. Psysonic lists every available output and switches instantly when you pick one. The refresh button rescans devices that were plugged in after launch. Linux ALSA names like "sysdefault" are auto-cleaned for readability.', - q13: 'What is Hot Cache?', - a13: 'Hot Cache preloads the current track plus the next several into RAM and onto disk so playback starts with no buffering — especially useful on slow / remote servers. Eviction kicks in when the size limit is reached. Configure size and the debounce delay (so quick skips do not over-fetch) in Settings → Audio.', - // ── Section 4: Library & Discovery ───────────────────────────────────── - s4: 'Library & Discovery', - q14: 'How do ratings and Skip-to-1★ work?', - a14: 'Psysonic supports 1–5 star ratings via OpenSubsonic (Navidrome ≥ 0.53). Rate songs in track lists, in the right-click menu, or in the player bar below the artist name; albums on the album page; artists on the artist page. Skip-to-1★ (Settings → Library → Ratings) auto-assigns 1 star after a configurable number of consecutive skips. The same panel lets you set a minimum rating filter for Random Mix and other generated mixes.', - q15: 'How do I browse — Folders, Genres, Tracks?', - a15: 'Folder Browser (sidebar) walks your server\'s music directory in a Miller-column layout — click a folder to drill in, click a track or a folder\'s play icon to play / enqueue. Genres uses a tag-cloud view scaled by track count; click a genre to open it. Tracks is a flat library hub with column-sortable virtual list and live search.', - q16: 'Search and Advanced Search?', - a16: 'The header search bar runs a fast live search across artists, albums and tracks as you type. Open Advanced Search (sidebar) for a richer view: filter by year, genre, rating, format, channels, sample rate, BPM, mood, and combine criteria. Right-click any result for the same context menu used elsewhere in the app.', - q17: 'What are the Mixes (Random / Genre / Super Genre / Lucky)?', - a17: 'Random Mix builds a playlist of random tracks from your library; the Keyword Filter excludes audiobooks, comedy, etc. by genre / title / album substrings. Super Genre Mix groups your library into broad styles (Rock, Metal, Electronic, Jazz, Classical…) and builds a focused mix from one. Lucky Mix uses your listening history, ratings and AudioMuse-AI similar tracks to assemble an instant playlist with one click.', - q18: 'Statistics page?', - a18: 'Statistics (sidebar) shows top artists, top albums, top tracks, genre breakdown, listening time over time, and per-library scope when you have more than one music folder configured. Several views are exportable as a sharable card image.', - q19: 'How do I download an album as a ZIP?', - a19: 'Album page → "Download (ZIP)". The server compresses the album first — for large or lossless albums (FLAC / WAV) the progress bar appears only after zipping completes and the transfer starts. This is normal.', - // ── Section 5: Lyrics ────────────────────────────────────────────────── - s5: 'Lyrics', - q20: 'Where do lyrics come from?', - a20: 'Three sources, configurable in Settings → Lyrics: your Navidrome server (embedded / OpenSubsonic lyrics), LRCLIB (community-contributed synced lyrics), and NetEase Cloud Music (large Asian + international catalog). Each source can be enabled / disabled and re-ordered by drag.', - q21: 'How do I view lyrics during playback?', - a21: 'Click the microphone icon in the player bar to open the Lyrics tab inside the queue panel. Synced lyrics auto-scroll and support click-to-seek; plain-text lyrics scroll as a static block. Toggle the Fullscreen Player from the player-bar artwork for an immersive lyrics view with mesh-blob background.', - // ── Section 6: Sharing & Social ──────────────────────────────────────── - s6: 'Sharing & Social', - q22: 'What are Magic Strings?', - a22: 'Magic Strings are short copy-paste tokens that share things between Psysonic users without any third-party server. Server-Invite strings let a friend onboard onto your Navidrome with one paste; Album / Artist / Queue Magic Strings open the same album / artist / queue on the recipient\'s installed Psysonic. Generate them from the share menu, paste them into the search bar to consume.', - q23: 'What is Orbit?', - a23: 'Orbit is synchronized listen-together: a host plays a track, every guest hears it in sync, and guests can suggest songs the host can accept into the queue. Start a session from the header Orbit button, share the invite link, and others can join from any Psysonic install. The host owns playback (skip, seek, queue) — guests get a real-time view and a suggestion box. Sessions are ephemeral and end when the host closes them.', - q24: 'What is the Now Playing dropdown?', - a24: 'The broadcast icon in the top-right header shows what other users on your Navidrome server are currently listening to, refreshed every 10 seconds. Your own entry disappears the moment you pause. It is per-server, so users on a different active server are not shown.', - // ── Section 7: Personalization ───────────────────────────────────────── - s7: 'Personalization', - q25: 'Themes and the Theme Scheduler?', - a25: 'Settings → Appearance → Theme picks from 60+ themes across 8 groups (Psysonic, Mediaplayer, Operating Systems, Games, Movies, Series, Social Media, Open Source Classics — Catppuccin / Nord / Gruvbox / Nightfox / Dracula). Auto-Switch Theme lets you set a day theme + night theme with start times so Psysonic flips automatically.', - q26: 'Can I customize the Sidebar, Home and Artist pages?', - a26: 'Yes — Settings → Personalisation. The sidebar customizer lets you drag nav items into the order you want and hide ones you do not use. The Home customizer toggles each Mainstage rail (Hero, Recent, Discover, Recently Played, Starred…). The Artist page customizer reorders the sections (Top Songs, Albums, Singles, Compilations, Similar Artists, etc.) and lets you hide ones you never look at.', - q27: 'What is the Mini Player?', - a27: 'A small floating window with cover art, transport controls and a compact queue. Open it from the player-bar mini-player icon or with its keyboard shortcut. The window remembers its position and size between sessions. On Windows the mini-webview is pre-created at startup so opening is instant; Linux / macOS opt in via Settings → Appearance → Preload mini player.', - q28: 'What is the Floating Player Bar?', - a28: 'An optional player-bar style (Settings → Appearance) that detaches from the bottom edge with a themed background, accent border, rounded album art and a centered volume section. Useful on tall monitors or compact themes.', - q29: 'Track Preview on hover?', - a29: 'Hover over a track row, click the small preview button on the cover, or trigger preview from the right-click menu — Psysonic streams the first ~15 s through the same Rust audio engine so loudness normalisation applies. Useful for skimming an album you have not heard before.', - q30: 'Sleep timer?', - a30: 'Click the moon icon in the player bar to open the sleep timer. Pick a duration (or "end of current track") and Psysonic fades out and pauses at the end. The button shows a circular ring and an in-button countdown while the timer runs.', - q31: 'UI scale, font, seekbar style?', - a31: 'Settings → Appearance — Interface Scale (80–125 % without affecting system font size), Font (10 UI fonts including IBM Plex Mono, Fira Code, Geist, Golos Text…), Seekbar Style (Waveform analysed / pseudowave deterministic / Line & Dot / Bar / Thick Bar / Segmented / Neon Glow / Pulse Wave / Particle Trail / Liquid Fill / Retro Tape).', - // ── Section 8: Power User ────────────────────────────────────────────── - s8: 'Power User', - q32: 'CLI player controls?', - a32: 'The Psysonic binary doubles as a remote control. Examples: psysonic --player play / pause / next / prev, --player volume 75, --player seek 15, --player shuffle, --player repeat off|all|one, --player rating 1-5. Switch servers, audio devices, libraries; trigger Instant Mix; search artists / albums / tracks. Run psysonic --player --help for the full list. Shell completions for bash and zsh via psysonic completions.', - q33: 'Smart Playlists (Navidrome)?', - a33: 'Smart Playlists are Navidrome-side dynamic playlists defined by rules (genre = Rock AND year > 2020, etc.). The Playlists page in Psysonic lets you create, edit and delete them with a visual rule editor — Psysonic talks to the Navidrome native API for that. They behave like normal playlists in the rest of the app and update automatically as your library changes.', - q34: 'Backup and restore settings?', - a34: 'Settings → Storage → Backup & Restore exports server profiles, themes, keybindings and other settings to a single JSON file. Import the file on another machine or after a reinstall to restore everything at once. Server passwords are included — keep the file private.', - q35: 'Where do I see all open-source licenses?', - a35: 'Settings → System → Open Source Licenses. The full dependency list (cargo crates and npm packages) ships in the build with bundled license texts. Click an entry for the full text; the curated highlight block at the top calls out the user-recognisable libraries (Tauri, React, rodio, symphonia, etc.).', - // ── Section 9: Offline & Sync ────────────────────────────────────────── - s9: 'Offline & Sync', - q36: 'Offline Mode — caching albums and playlists?', - a36: 'Open any album or playlist and click the download icon in the header — Psysonic caches every track locally so it plays from disk with no network call. The Offline Library page (sidebar) lists everything cached, shows progress in flight, and lets you remove entries with the trash icon (which appears once a download completes).', - q37: 'Offline storage limit?', - a37: 'Settings → Library → Offline lets you set a maximum cache size. When the limit is reached, the album-page download button shows a warning banner. Free space by removing albums or playlists from the Offline Library page.', - q38: 'Device Sync — copy music to USB / SD?', - a38: 'Device Sync (sidebar) copies albums, playlists or whole artists to an external drive for offline listening on other devices. Pick a target folder, choose sources from the browser tabs, click "Transfer to Device". Psysonic writes a manifest (psysonic-sync.json) so it knows which files are already there even if you reopen Device Sync on a different OS with a different filename template. Templates support {artist} / {album} / {title} / {track_number} / {disc_number} / {year} tokens with / for folder separators.', - // ── Section 10: Integrations & Troubleshooting ───────────────────────── - s10: 'Integrations & Troubleshooting', - q39: 'Last.fm scrobbling?', - a39: 'Settings → Integrations → Last.fm. Connect your account once and Psysonic scrobbles directly to Last.fm — no Navidrome configuration needed. A scrobble is sent after you have heard 50 % of a track. Now-playing pings are sent at the start.', - q40: 'Discord Rich Presence?', - a40: 'Settings → Integrations → Discord shows your current track on your Discord profile. Choose between the app icon, your server\'s cover art (via getAlbumInfo2 — needs a publicly reachable server), or Apple Music covers. Customize the display strings (details, state, tooltip) with token templates.', - q41: 'Bandsintown tour dates?', - a41: 'Opt in under Settings → Integrations → Now-Playing Info. The Now Playing tab on the Now Playing page then shows upcoming tour dates for the playing artist via the Bandsintown widget API. Off by default — no requests are made until you enable it.', - q42: 'Internet Radio — playing live streams?', - a42: 'Internet Radio (sidebar) plays any live stream stored on your Navidrome server (add stations via the Navidrome admin UI). Playback runs through the browser HTML5 audio engine — most EQ / Replay Gain / Loudness settings do not apply to radio, but ICY metadata (current song name) does show up. Supports MP3, AAC, OGG Vorbis and most HLS streams; codec support depends on the platform.', - q43: 'The connection test fails — what now?', - a43: 'Double-check the URL including port (e.g. http://192.168.1.100:4533). On a local network http:// often works where https:// does not (no certificate). Make sure no firewall blocks the port and that the username and password are correct. If your server is behind a reverse proxy, try the direct URL first to isolate the cause.', - q44: 'Cover art and artist images load slowly.', - a44: 'Images are fetched from your server on first view and then cached locally for 30 days. If your server\'s storage is slow, the first visit to a page can take a moment; subsequent visits are instant. The Hot Cache also helps for tracks but image cache is independent.', - q45: 'Linux issues — black screen or no audio?', - a45: 'Black screen is usually a GPU / EGL driver issue in WebKitGTK — launch with GDK_BACKEND=x11 WEBKIT_DISABLE_COMPOSITING_MODE=1 WEBKIT_DISABLE_DMABUF_RENDERER=1 (the AUR / .deb / .rpm installers set these automatically). For audio, make sure PipeWire or PulseAudio is running. If audio drops out after sleep / wake, this is now handled automatically by the post-sleep recovery hook.', - }, - queue: { - title: 'Queue', - savePlaylist: 'Save Playlist', - updatePlaylist: 'Update Playlist', - filterPlaylists: 'Filter playlists…', - playlistName: 'Playlist Name', - cancel: 'Cancel', - save: 'Save', - loadPlaylist: 'Load Playlist', - loading: 'Loading…', - noPlaylists: 'No playlists found.', - load: 'Replace queue & play', - appendToQueue: 'Append to queue', - delete: 'Delete', - deleteConfirm: 'Delete playlist "{{name}}"?', - clear: 'Clear', - shuffle: 'Shuffle queue', - gapless: 'Gapless', - crossfade: 'Crossfade', - infiniteQueue: 'Infinite Queue', - autoAdded: '— Added automatically —', - radioAdded: '— Radio —', - hide: 'Hide', - hideNowPlaying: 'Hide now playing info', - showNowPlaying: 'Show now playing info', - close: 'Close', - nextTracks: 'Next Tracks', - shareQueue: 'Copy queue share link', - shareQueueEmpty: 'The queue is empty — nothing to share.', - emptyQueue: 'The queue is empty.', - trackSingular: 'track', - trackPlural: 'tracks', - showRemaining: 'Show remaining time', - showTotal: 'Show total time', - showEta: 'Show estimated end time', - replayGain: 'ReplayGain', - rgTrack: 'T {{db}} dB', - rgAlbum: 'A {{db}} dB', - rgPeak: 'Peak {{pk}}', - sourceOffline: 'Playing from offline library', - sourceHot: 'Playing from cache', - sourceStream: 'Playing from network stream', - clearCachedLoudnessWaveform: 'Clear cached loudness and waveform, then re-analyze this track', - recalculatingLoudnessWaveform: 'Recalculating loudness and waveform for this track…', - }, - miniPlayer: { - showQueue: 'Show queue', - hideQueue: 'Hide queue', - pinOnTop: 'Pin on top', - pinOff: 'Unpin', - openMainWindow: 'Open main window', - close: 'Close', - emptyQueue: 'Queue is empty', - }, - statistics: { - title: 'Statistics', - recentlyPlayed: 'Recently Played', - mostPlayed: 'Most Played Albums', - highestRated: 'Highest Rated Albums', - genreDistribution: 'Genre Distribution (Top 20)', - loadMore: 'Load more', - statArtists: 'Artists', - statArtistsTooltip: 'Album artists only — artists appearing only as a track-level artist (featured, guest, etc.) without their own album are not included.', - statAlbums: 'Albums', - statSongs: 'Songs', - statGenres: 'Genres', - statPlaytime: 'Total Playtime', - genreInsights: 'Genre Insights', - formatDistribution: 'Format Distribution', - formatSample: 'Sample of {{n}} tracks', - computing: 'Computing…', - genreSongs: '{{count}} Songs', - genreAlbums: '{{count}} Albums', - recentlyAdded: 'Recently Added', - decadeDistribution: 'Albums by Decade', - decadeAlbums_one: '{{count}} Album', - decadeAlbums_other: '{{count}} Albums', - decadeUnknown: 'Unknown', - lfmTitle: 'Last.fm Stats', - lfmTopArtists: 'Top Artists', - lfmTopAlbums: 'Top Albums', - lfmTopTracks: 'Top Tracks', - lfmPlays: '{{count}} plays', - lfmPeriodOverall: 'All Time', - lfmPeriod7day: '7 Days', - lfmPeriod1month: '1 Month', - lfmPeriod3month: '3 Months', - lfmPeriod6month: '6 Months', - lfmPeriod12month: '12 Months', - lfmNotConnected: 'Connect Last.fm in Settings to see your stats.', - lfmRecentTracks: 'Recent Scrobbles', - lfmNowPlaying: 'Now Playing', - lfmJustNow: 'just now', - lfmMinutesAgo: '{{n}}m ago', - lfmHoursAgo: '{{n}}h ago', - lfmDaysAgo: '{{n}}d ago', - topRatedSongs: 'Top Rated Songs', - topRatedArtists: 'Top Rated Artists', - noRatedSongs: 'No rated songs yet. Rate songs in album or playlist view.', - noRatedArtists: 'No rated artists yet.', - exportShare: 'Share', - exportTitle: 'Share Top Albums', - exportSubtitle: 'Generate a shareable image of your most-played albums.', - exportFormat: 'Format', - exportFormatStory: 'Story', - exportFormatSquare: 'Square', - exportFormatTwitter: 'Twitter Card', - exportGrid: 'Grid', - exportGridLabel: '{{n}}×{{n}}', - exportPreview: 'Preview', - exportGenerate: 'Generate', - exportSave: 'Save image…', - exportCancel: 'Cancel', - exportFooterLabel: 'Top Albums', - exportNotEnough: 'Need at least {{count}} albums in your library for a {{n}}×{{n}} grid.', - exportSaving: 'Saving…', - exportSaved: 'Saved.', - exportSaveFailed: 'Could not save the image.', - }, - player: { - regionLabel: 'Music Player', - openFullscreen: 'Open Fullscreen Player', - fullscreen: 'Fullscreen Player', - closeFullscreen: 'Close Fullscreen', - closeTooltip: 'Close (Esc)', - noTitle: 'No Title', - stop: 'Stop', - prev: 'Previous Track', - play: 'Play', - pause: 'Pause', - previewActive: 'Preview playing', - previewLabel: 'Preview', - delayModalTitle: 'Timer', - delayPauseSection: 'Pause after', - delayStartSection: 'Start after', - delayPreviewPause: 'Pauses at', - delayPreviewStart: 'Starts at', - delaySchedulePause: 'Schedule pause', - delayScheduleStart: 'Schedule start', - delayCancelPause: 'Cancel pause timer', - delayCancelStart: 'Cancel start timer', - delayInactivePause: 'Available only while something is playing.', - delayInactiveStart: 'Available when paused with a track or radio loaded.', - delayCustomMinutes: 'Custom delay (minutes)', - delayCustomPlaceholder: 'e.g. 2.5', - closeDelayModal: 'Close', - delayIn: 'in', - delayFmtSec: '{{n}}s', - delayFmtMin: '{{n}} min', - delayFmtHr: '{{n}} h', - delayCancel: 'Cancel', - delayApply: 'Apply', - next: 'Next Track', - repeat: 'Repeat', - repeatOff: 'Off', - repeatAll: 'All', - repeatOne: 'One', - progress: 'Song Progress', - volume: 'Volume', - toggleQueue: 'Toggle Queue', - collapseQueueResize: 'Collapse queue, resize', - moreOptions: 'More options', - equalizer: 'Equalizer', - miniPlayer: 'Mini Player', - lyrics: 'Lyrics', - fsLyricsToggle: 'Lyrics in fullscreen', - lyricsLoading: 'Loading lyrics…', - lyricsNotFound: 'No lyrics found for this track', - lyricsSourceServer: 'Source: Server', - lyricsSourceLrclib: 'Source: LRCLIB', - lyricsSourceNetease: 'Source: Netease', - lyricsSourceLyricsplus: 'Source: YouLyPlus', - showDuration: 'Show duration', - showRemainingTime: 'Show remaining time', - }, - nowPlayingInfo: { - tab: 'Info', - empty: 'Play something to see info', - artist: 'Artist', - songInfo: 'Song info', - onTour: 'On tour', - noTourEvents: 'No upcoming shows', - tourLoading: 'Loading…', - poweredByBandsintown: 'Tour data via Bandsintown', - bioReadMore: 'Read more', - bioReadLess: 'Show less', - showMoreTours_one: 'Show {{count}} more', - showMoreTours_other: 'Show {{count}} more', - showLessTours: 'Show less', - enableBandsintownPrompt: 'See upcoming tour dates?', - enableBandsintownPromptDesc: 'Optional. Loads concerts for the current artist via the public Bandsintown API.', - enableBandsintownPrivacy: 'When enabled, the name of the currently playing artist is sent to the Bandsintown API to fetch tour dates. No account or personal data leaves your device.', - enableBandsintownAction: 'Enable', - role: { - artist: 'Artist', - albumArtist: 'Album artist', - composer: 'Composer', - }, - }, - songInfo: { - title: 'Song Info', - songTitle: 'Title', - artist: 'Artist', - album: 'Album', - albumArtist: 'Album Artist', - year: 'Year', - genre: 'Genre', - duration: 'Duration', - track: 'Track', - format: 'Format', - bitrate: 'Bitrate', - sampleRate: 'Sample Rate', - bitDepth: 'Bit Depth', - channels: 'Channels', - fileSize: 'File Size', - path: 'Path', - replayGainTrack: 'RG Track Gain', - replayGainAlbum: 'RG Album Gain', - replayGainPeak: 'RG Track Peak', - mono: 'Mono', - stereo: 'Stereo', - }, - playlists: { - title: 'Playlists', - newPlaylist: 'New Playlist', - unnamed: 'Unnamed Playlist', - createName: 'Playlist name…', - create: 'Create', - cancel: 'Cancel', - empty: 'No playlists yet.', - emptyPlaylist: 'This playlist is empty.', - addFirstSong: 'Add your first song', - notFound: 'Playlist not found.', - songs: '{{n}} songs', - playAll: 'Play All', - shuffle: 'Shuffle', - addToQueue: 'Add to Queue', - back: 'Back to Playlists', - deletePlaylist: 'Delete', - confirmDelete: 'Click again to confirm', - removeSong: 'Remove from playlist', - addSongs: 'Add Songs', - searchPlaceholder: 'Search your library…', - noResults: 'No results.', - suggestions: 'Suggested Songs', - noSuggestions: 'No suggestions available.', - titleBadge: 'Playlist', - refreshSuggestions: 'New suggestions', - addSong: 'Add to playlist', - preview: 'Preview (30s)', - previewStop: 'Stop preview', - playNextSuggestion: 'Play next', - suggestionsHint: 'Double-click a row to add it to the playlist', - addSelected: 'Add selected', - cacheOffline: 'Cache playlist offline', - offlineCached: 'Playlist cached', - removeOffline: 'Remove from offline cache', - offlineDownloading: 'Caching… ({{done}}/{{total}} albums)', - publicLabel: 'Public', - privateLabel: 'Private', - editMeta: 'Edit playlist', - editNamePlaceholder: 'Playlist name…', - editCommentPlaceholder: 'Add a description…', - editPublic: 'Public playlist', - editSave: 'Save', - editCancel: 'Cancel', - changeCover: 'Change cover image', - changeCoverLabel: 'Change photo', - removeCover: 'Remove photo', - coverUpdated: 'Cover updated', - metaSaved: 'Playlist updated', - downloadZip: 'Download (ZIP)', - // Toast notifications for multi-select - addSuccess: '{{count}} songs added to {{playlist}}', - addPartial: '{{added}} added, {{skipped}} skipped (duplicates)', - addAllSkipped: 'All skipped ({{count}} duplicates)', - addedAsDuplicates: '{{count}} songs added to {{playlist}} (as duplicates)', - duplicateConfirmTitle: 'Already in playlist', - duplicateConfirmMessage: 'All {{count}} songs are already in "{{playlist}}". Add them again as duplicates?', - duplicateConfirmAction: 'Add anyway', - addError: 'Error adding songs', - createAndAddSuccess: 'Playlist "{{playlist}}" created with {{count}} songs', - createError: 'Error creating playlist', - deleteSuccess: '{{count}} playlists deleted', - deleteFailed: 'Error deleting {{name}}', - deleteSelected: 'Delete selected', - deleteSelectedPartial: 'Only {{n}} of {{total}} selected playlists can be deleted (the others belong to someone else).', - mergeSuccess: '{{count}} songs merged into {{playlist}}', - mergeNoNewSongs: 'No new songs to add', - mergeError: 'Error merging playlists', - mergeInto: 'Merge into', - selectionCount: '{{count}} selected', - select: 'Select', - startSelect: 'Enable selection', - cancelSelect: 'Cancel', - loadingAlbums: 'Resolving {{count}} albums…', - loadingArtists: 'Resolving {{count}} artists…', - myPlaylists: 'My Playlists', - noOtherPlaylists: 'No other playlists available', - addToPlaylistSuccess: '{{count}} songs added to {{playlist}}', - addToPlaylistNoNew: 'No new songs to add to {{playlist}}', - addToPlaylistError: 'Error adding to playlist', - removeSuccess: 'Song removed from playlist', - removeError: 'Error removing song from playlist', - importCSV: 'Import CSV', - importCSVTooltip: 'Import from Spotify CSV', - csvImportReport: 'CSV Import Report', - csvImportTotal: 'Total', - csvImportAdded: 'Added', - csvImportDuplicates: 'Duplicates', - csvImportNotFound: 'Not Found', - csvImportNetworkErrors: 'Network Errors', - csvImportDuplicatesTitle: 'Duplicate Tracks (Already in Playlist):', - csvImportNotFoundTitle: 'Tracks Not Found:', - csvImportNetworkErrorsTitle: 'Network Errors (may retry import):', - csvImportDownloadReport: 'Download Report', - csvImportClose: 'Close', - csvImportNoValidTracks: 'No valid tracks found in CSV file', - csvImportFailed: 'Failed to import CSV file', - csvImportToast: '{{added}} added, {{notFound}} not found, {{duplicates}} duplicates', - csvImportDownloadSuccess: 'Report downloaded successfully', - csvImportDownloadError: 'Failed to download report', - }, - smartPlaylists: { - sectionBasic: '1. Basic', - sectionGenres: '2. Genres', - sectionYearsAndFilters: '3. Years and filters', - genreMode: 'Genre mode', - genreModeInclude: 'Include genres', - genreModeExclude: 'Exclude genres', - genreSearchPlaceholder: 'Filter genres...', - availableGenres: 'Available', - selectedGenres: 'Selected', - yearMode: 'Year mode', - yearModeInclude: 'Include range', - yearModeExclude: 'Exclude range', - name: 'Name (without prefix)', - limit: 'Limit', - limitHint: 'How many tracks to include in playlist (1-{{max}}, usually 50).', - artistContains: 'Artist contains…', - albumContains: 'Album contains…', - titleContains: 'Title contains…', - minRating: 'Minimum rating', - minRatingAria: 'Minimum rating for smart playlist', - minRatingHint: '0 disables minimum threshold; 1-5 keeps tracks with rating above selected value.', - fromYear: 'From year', - toYear: 'To year', - excludeUnrated: 'Exclude unrated tracks', - compilationOnly: 'Only compilations', - create: 'New Smart Playlist', - save: 'Save Smart Playlist', - created: 'Created {{name}}', - updated: 'Updated {{name}}', - createFailed: 'Could not create smart playlist.', - updateFailed: 'Could not update smart playlist.', - navidromeOnly: 'Smart playlists can only be created on Navidrome servers.', - loadFailed: 'Could not load smart playlists from Navidrome.', - sortRandom: 'Sort: random', - sortTitleAsc: 'Sort: title A-Z', - sortTitleDesc: 'Sort: title Z-A', - sortYearDesc: 'Sort: year desc', - sortYearAsc: 'Sort: year asc', - sortPlayCountDesc: 'Sort: play count desc', - }, - mostPlayed: { - title: 'Most Played', - topArtists: 'Top Artists', - topAlbums: 'Top Albums', - plays: '{{n}} plays', - sortMost: 'Most plays first', - sortLeast: 'Fewest plays first', - loadMore: 'Load more albums', - noData: 'No play data yet. Start listening!', - noArtists: 'All artists filtered out.', - filterCompilations: 'Hide compilation artists (Various Artists, Soundtracks, etc.)', - filterCompilationsShort: 'Hide compilations', - }, - losslessAlbums: { - empty: 'No lossless albums in this library yet.', - unsupported: 'This server does not expose the metadata needed to find lossless albums.', - slowFetchHint: 'Loads slower than other album pages — Psysonic walks the full song catalog by quality.', - }, - radio: { - title: 'Internet Radio', - empty: 'No radio stations configured.', - addStation: 'Add Station', - editStation: 'Edit', - deleteStation: 'Delete station', - confirmDelete: 'Click again to confirm', - stationName: 'Station name…', - streamUrl: 'Stream URL…', - homepageUrl: 'Homepage URL (optional)', - save: 'Save', - cancel: 'Cancel', - live: 'LIVE', - liveStream: 'Internet Radio', - openHomepage: 'Open homepage', - changeCoverLabel: 'Change cover', - removeCover: 'Remove cover', - browseDirectory: 'Search Directory', - directoryPlaceholder: 'Search stations…', - noResults: 'No stations found.', - stationAdded: 'Station added', - filterAll: 'All', - filterFavorites: 'Favorites', - sortManual: 'Manual', - sortAZ: 'A → Z', - sortZA: 'Z → A', - sortNewest: 'Newest', - favorite: 'Add to favorites', - unfavorite: 'Remove from favorites', - noFavorites: 'No favorite stations.', - listenerCount_one: '{{count}} listener', - listenerCount_other: '{{count}} listeners', - recentlyPlayed: 'Recently Played', - upNext: 'Up Next', - }, - folderBrowser: { - empty: 'Empty folder', - error: 'Failed to load', - }, - deviceSync: { - title: 'Device Sync', - targetFolder: 'Target Folder', - noFolderChosen: 'No folder chosen', - selectDrive: 'Select a drive…', - refreshDrives: 'Refresh drives', - noDrivesDetected: 'No removable drives detected', - browseManual: 'Browse manually…', - free: 'free', - notMountedVolume: 'Target is not on a mounted volume. The drive may have been disconnected.', - chooseFolder: 'Choose…', - targetDevice: 'Target Device', - schemaLabel: 'Naming scheme', - schemaHint: 'Fixed scheme for reliable cross-OS sync. Playlists are written as .m3u8 that reference the album tracks — no duplicates on the device.', - migrateButton: 'Reorganize existing files…', - migrateTooltip: 'Rename existing files on the device into the new scheme (from the old filename template).', - migrateTitle: 'Reorganize existing files', - migrateLoading: 'Analyzing existing files…', - migrateNothingToDo: 'All existing files already match the new scheme — nothing to do.', - migrateNoTemplate: 'No legacy filename template found on the device. Migration only applies when the stick was synced with a Psysonic version that supported custom templates.', - migrateFilesToRename: 'files will be renamed', - migrateUnchanged: '{{n}} files are already at the correct path', - migrateCollisions: '{{n}} files cannot be renamed automatically (multiple tracks map to the same target). They will be left untouched — the next sync re-downloads them into the correct location.', - migratePreviewNote: 'Old template: {{tpl}}', - migrateExecuting: 'Renaming files…', - migrateSuccess: '{{n}} files renamed successfully', - migrateFailed: '{{n}} renames failed', - migrateShowErrors: 'Show errors', - migrateStart: 'Start renaming', - onDevice: 'Device Manager', - addSources: 'Add…', - colName: 'Name', - colType: 'Type', - colStatus: 'Status', - syncResult: '{{done}} transferred, {{skipped}} already up to date ({{total}} total)', - deleteFromDevice: 'Mark for deletion ({{count}})', - confirmDelete: 'Delete {{count}} item(s) from the device: {{names}}?', - deleteComplete: '{{count}} item(s) removed from device.', - manifestImported: 'Imported {{count}} source(s) from device manifest.', - selectedSources: 'Selected Sources', - noSourcesSelected: 'No sources selected. Click items in the browser to add them.', - clearAll: 'Clear all', - tabPlaylists: 'Playlists', - tabAlbums: 'Albums', - tabArtists: 'Artists', - searchPlaceholder: 'Search…', - syncButton: 'Sync to Device', - actionTransfer: 'Transfer to Device', - actionDelete: 'Delete from Device', - actionApplyAll: 'Apply All Changes', - cancel: 'Cancel', - noTargetDir: 'Please choose a target folder first.', - noSources: 'Please select at least one source.', - noTracks: 'No tracks found in the selected sources.', - fetchError: 'Failed to fetch tracks from server.', - syncComplete: 'Sync complete.', - dismiss: 'Dismiss', - cancelSync: 'Cancel', - syncCancelled: 'Sync cancelled ({{done}} / {{total}} transferred).', - statusSynced: 'Synced', - statusPending: 'Pending', - statusDeletion: 'Deletion', - markForDeletion: 'Mark for deletion', - undoDeletion: 'Undo deletion', - removeSource: 'Remove', - syncInBackground: 'Sync started in background — you can navigate away.', - syncInProgress: '{{done}} / {{total}} tracks…', - scanningDevice: 'Scanning device…', - syncSummary: 'Sync Summary', - calculating: 'Calculating required payload…', - filesToAdd: 'Files to Add:', - filesToDelete: 'Files to Delete:', - netChange: 'Net Change:', - availableSpace: 'Available Disk Space:', - spaceWarning: 'Warning: Target device does not have enough reported space.', - proceed: 'Proceed with Sync', - notEnoughSpace: 'Not enough physical disk space detected!', - liveSearch: 'Live', - randomAlbumsLabel: 'Random Albums', - }, - orbit: { - triggerLabel: 'Orbit', - triggerTooltip: 'Start or join a shared listening session', - launchCreate: 'Create a session', - launchJoin: 'Join a session', - launchHelp: 'How does this work?', - launchHelpSoon: 'Coming soon', - joinModalTitle: 'Join an Orbit session', - joinModalSub: 'Paste the invite link your host sent you.', - joinModalLinkLabel: 'Invite link', - joinModalLinkPlaceholder: 'psysonic2-…', - joinModalLinkHelper: 'Works with any valid Orbit link. Must point to the server you\'re currently signed into.', - joinModalPasteTooltip: 'Paste from clipboard', - joinModalSubmit: 'Join', - joinModalBusy: 'Joining…', - joinErrEmpty: 'Please paste an invite link.', - joinErrInvalid: 'That doesn\'t look like an Orbit invite link.', - closeAria: 'Close', - heroTitlePrefix: 'Listen together with', - heroTitleBrand: 'Orbit', - heroSub: 'Start a session — other users on {{server}} will listen along and can suggest tracks.', - fallbackServer: 'this server', - tipLan: "You're currently connected via a home-network address. Guests outside your network can't join — switch to a public server address in settings before you start.", - tipRemote: 'For guests outside your home network to join, your server address has to be publicly reachable. If your server is internal only, switch before you start.', - labelName: 'Session name', - namePlaceholder: 'Velvet Orbit', - reshuffleTooltip: 'New suggestion', - reshuffleAria: 'Suggest a new name', - helperName: 'How the session shows up to your guests — keep it or type your own.', - labelMax: 'Max guests', - helperMax: "You don't count — this only caps incoming guests.", - labelLink: 'Invite link', - tooltipCopied: 'Copied', - tooltipCopy: 'Copy', - ariaCopyLink: 'Copy invite link', - helperLink: 'Send this link to your guests. They can paste it anywhere in Psysonic with Ctrl+V.', - labelClearQueue: 'Clear my queue first', - helperClearQueue: 'Start the session with a fresh, empty queue. Off: the tracks you already have queued stay and get shared with guests.', - btnCancel: 'Cancel', - btnStarting: 'Starting…', - btnStart: 'Start Orbit', - btnCopyAndStart: 'Copy link & start', - errNameRequired: 'Please give your session a name.', - errStartFailed: "Couldn't start.", - hostLabel: 'Host: {{name}}', - participantsTooltip: 'Participants', - settingsTooltip: 'Session settings', - shareTooltip: 'Share invite link', - shuffleLabel: 'Queue reshuffles in', - catchUpLabel: 'catch up', - catchUpTooltip: "Jump to the host's current position", - hostAway: 'Host offline', - hostOnline: 'Host online', - endTooltip: 'End session', - leaveTooltip: 'Leave session', - helpTooltip: 'How Orbit works', - diag: { - openTooltip: 'Diagnostics — copyable event log', - title: 'Orbit diagnostics', - role: 'Role', - hostTrack: 'Host track id', - hostPos: 'Host position', - guestTrack: 'My track id', - guestPos: 'My position', - drift: 'Drift', - stateAge: 'State age', - eventLog: 'Event log ({{count}})', - copyLabel: 'Copy', - copyTooltip: 'Copy log to clipboard', - clearLabel: 'Clear', - clearTooltip: 'Wipe the buffer', - empty: 'No events yet — events appear as Orbit syncs.', - hint: 'Open this before reproducing a problem, then click Copy and paste into the bug report.', - copied: 'Copied {{count}} event lines', - copyFailed: 'Could not copy to clipboard', - cleared: 'Buffer cleared', - }, - helpTitle: 'How Orbit works', - helpIntro: 'Orbit turns Psysonic into a shared listening room. A host picks the music; guests listen in sync and can suggest tracks.', - helpHostOnly: '(host)', - helpSec1Title: 'What is Orbit?', - helpSec1Body: "A \"listen together\" mode — the host drives playback, guests tune in. Everything runs through playlists on your own Navidrome server; no external infrastructure.", - helpSec2Title: 'Host and guests', - helpSec2Body: 'Host controls playback (play / pause / skip / seek) and decides when the session ends. Guests follow the host\'s playback, can suggest tracks, and leave or re-join any time. Only the host can kick or permanently ban a participant.', - helpSec2WarnHead: 'Important: separate accounts.', - helpSec2WarnBody: "Every participant needs their own Navidrome account. If host and guest sign in with the same user their submissions collide and the host never sees the guest's suggestions.", - helpSec3Title: 'Starting and inviting', - helpSec3Body: 'Click the "Orbit" button → Create a session → the start modal shows a ready-to-copy invite link and lets you optionally clear your current queue. Share that link however you like. While a session is running, the share button in the session bar at the top copies the link again at any time.', - helpSec4Title: 'Joining', - helpSec4Body: 'Paste the invite link anywhere in Psysonic with Ctrl+V / Cmd+V — the join prompt pops up automatically. Alternatively: "Orbit" → Join a session → paste into the field. If the link points to a server you have an account on, Psysonic switches for you. When you have more than one account on that server, a small picker asks which to use.', - helpSec5Title: 'Suggesting tracks', - helpSec5Body: 'In any song list: double-click a row, or right-click → "Add to Orbit session". A single click shows a hint instead of dumping the whole album into the shared queue — that\'s intentional. Explicit bulk actions like "Play All" or "Play Album" ask for confirmation first and then append (never replace).', - helpSec6Title: 'The shared queue', - helpSec6Body: "The queue shows the host's upcoming tracks — visible to everyone. Incoming bulk additions are always appended, so guest suggestions aren't lost. Auto-shuffle reorders the queue periodically (configurable: 1 / 5 / 10 / 15 / 30 min). If your playback drifts away from the host, the \"Catch up\" button in the session bar jumps you back to the host's live position.", - helpSec7Title: 'Approvals', - helpSec7Body: 'By default, guest suggestions need manual approval — they appear in an "Approvals" strip at the top of the queue panel with accept / decline buttons. Auto-approve can be turned on in the session settings so everything lands straight away.', - helpSec8Title: 'Participants and settings', - helpSec8Body: 'Open the settings icon in the session bar for shuffle cadence, auto-approve, and the "Shuffle now" shortcut. Click the participants count to see who\'s connected — kick (can re-join via the link) or ban (locked out for the session). Guests see the participant list too, but read-only.', - helpSec9Title: 'Ending the session', - helpSec9Body: "Host X → confirm dialog → session closes for everyone and the server playlists are cleaned up automatically. Guest X → the guest leaves, the session keeps running. If the host goes quiet for 5 minutes the guest auto-leaves with a notice; short reconnects within that window are invisible.", - participantsInviteLabel: 'Invite link', - participantsCountLabel: '{{count}} in session', - participantsHost: 'host', - participantsEmpty: 'No guests yet', - participantsKickTooltip: 'Remove from session', - participantsKickAria: 'Remove {{user}}', - participantsRemoveTooltip: 'Remove from session', - participantsRemoveAria: 'Remove {{user}} from this session', - participantsBanTooltip: 'Ban permanently', - participantsBanAria: 'Permanently ban {{user}}', - participantsMuteTooltip: 'Mute suggestions', - participantsUnmuteTooltip: 'Allow suggestions', - participantsMuteAria: 'Mute suggestions from {{user}}', - participantsUnmuteAria: 'Allow suggestions from {{user}}', - confirmRemoveTitle: 'Remove from session?', - confirmRemoveBody: '{{user}} will be dropped from the session, but can re-join via your invite link.', - confirmRemoveConfirm: 'Remove', - confirmBanTitle: 'Permanently ban?', - confirmBanBody: '{{user}} will be removed and blocked from re-joining this session. This can\'t be undone for the lifetime of the session.', - confirmBanConfirm: 'Ban', - confirmCancel: 'Cancel', - confirmJoinTitle: 'Join Orbit session?', - confirmJoinBody: '{{host}} invited you to "{{name}}". Join the session?', - confirmJoinConfirm: 'Join', - confirmLeaveTitle: 'Leave session?', - confirmLeaveBody: 'Leave "{{name}}"? You can re-join via {{host}}\'s invite link any time.', - confirmLeaveConfirm: 'Leave', - confirmEndTitle: 'End session for everyone?', - confirmEndBody: '"{{name}}" will close for all participants. The session\'s playlists are cleaned up automatically.', - confirmEndConfirm: 'End session', - invalidLinkTitle: 'Invite link is no longer valid', - invalidLinkBody: 'This Orbit session doesn\'t exist any more or has already ended. Ask the host for a fresh invite link.', - settingsTitle: 'Session settings', - settingAutoApprove: 'Auto-approve suggestions', - settingAutoApproveHint: "Guest suggestions land in your queue instantly. Off: they stay in the session list for you to review later.", - settingAutoShuffle: 'Automatic reshuffle', - settingAutoShuffleHint: "Periodic Fisher–Yates shuffle of the upcoming queue. Off: order only changes when you rearrange it.", - settingShuffleInterval: 'Reshuffle every', - settingShuffleIntervalHint: 'How often the upcoming queue gets reshuffled while the session runs.', - suggestBlockedMuted: 'The host muted you for this session — suggestions are off.', - settingShuffleIntervalValue_one: '{{count}} min', - settingShuffleIntervalValue_other: '{{count}} min', - settingShuffleNow: 'Shuffle now', - toastSuggested: '{{user}} suggested "{{title}}"', - toastSuggestedMany: '{{count}} new suggestions in the queue', - toastShuffled: 'Queue shuffled', - toastJoined: 'Joined session', - toastLoginFirst: 'Log in before joining a session', - toastSwitchServer: 'Switch to {{url}} first, then paste again', - toastNoAccountForServer: "You don't have access to {{url}}. Ask the host for an invite.", - toastSwitchFailed: "Couldn't switch to {{url}}", - accountPickerTitle: 'Which account?', - accountPickerSub: 'You have more than one account for {{url}}. Pick the one to join the session as.', - toastJoinFail: "Couldn't join session", - joinErrNotFound: 'Session not found', - joinErrEnded: 'Session has ended', - joinErrFull: 'Session is full', - joinErrKicked: "You can't rejoin this session", - joinErrNoUser: 'No active server', - joinErrServerError: "Couldn't join", - ctxAddToSession: 'Add to Orbit session', - ctxSuggestedToast: 'Suggested to the session', - ctxSuggestFailed: "Couldn't suggest — not joined", - ctxAddToSessionHost: 'Add to Orbit session', - ctxAddedHostToast: 'Added to the session', - ctxAddHostFailed: "Couldn't add to session", - bulkConfirmTitle: 'Add all of this to the Orbit queue?', - bulkConfirmBody: "This would drop {{count}} tracks into the shared queue in one go. That's a lot for your guests to notice. Go ahead?", - bulkConfirmYes: 'Add them all', - bulkConfirmNo: 'Cancel', - guestLive: 'Live', - guestPlaying: 'Playing now', - guestPaused: 'Paused', - guestLoading: 'Loading…', - guestSuggestions: 'Suggestions', - guestUpNext: 'Up next', - guestUpNextEmpty: 'Nothing queued. Open a track\'s context menu and pick "Add to Orbit session" to suggest one.', - guestPendingTitle: 'Waiting for host', - guestPendingHint: 'Suggested — will appear in the queue when the host picks it up.', - approvalTitle: 'Pending approvals', - approvalFrom: 'Suggested by {{user}}', - approvalAccept: 'Accept', - approvalDecline: 'Decline', - guestUpNextMore: '+ {{count}} more in the host\'s queue', - guestSubmitter: 'by {{user}}', - queueAddedByHost: 'Added by host', - queueAddedByYou: 'Added by you', - queueAddedByUser: 'Added by {{user}}', - guestEmpty: 'No suggestions yet. Open a track\'s context menu and pick "Add to Orbit session".', - guestFooter: "The host controls playback — you can't change the list.", - exitKickedTitle: 'You were banned from the session', - exitRemovedTitle: 'You were removed from the session', - exitEndedTitle: 'The host ended the session', - exitHostTimeoutTitle: 'Host went silent', - exitHostTimeoutBody: "{{host}} hasn't sent an update for a while, so \"{{name}}\" was closed on your end. You can re-join any time with the invite link.", - exitKickedBody: '{{host}} banned you from "{{name}}". You can\'t re-join.', - exitRemovedBody: '{{host}} removed you from "{{name}}". You can re-join any time via the invite link.', - exitEndedBody: '"{{name}}" has ended. Hope you had fun.', - exitOk: 'OK', - }, - tray: { - playPause: 'Play / Pause', - nextTrack: 'Next Track', - previousTrack: 'Previous Track', - showHide: 'Show / Hide', - exitPsysonic: 'Exit Psysonic', - nothingPlaying: 'Nothing playing', - }, - licenses: { - title: 'Open Source Licenses', - intro: 'Psysonic is built on open-source software. The list below shows every dependency that ships in the app, with its version, license, and full license text.', - highlights: 'Key dependencies', - searchPlaceholder: 'Search by name, version or license…', - noResults: 'No matches.', - loading: 'Loading licenses…', - loadError: 'Could not load license data.', - noLicenseText: 'No license text bundled for this dependency.', - viewSource: 'View source', - totalLine: '{{total}} dependencies — {{cargo}} cargo, {{npm}} npm', - generatedAt: 'Last generated {{date}}', - }, -}; diff --git a/src/locales/en/albumDetail.ts b/src/locales/en/albumDetail.ts new file mode 100644 index 00000000..bd8e8d23 --- /dev/null +++ b/src/locales/en/albumDetail.ts @@ -0,0 +1,47 @@ +export const albumDetail = { + back: 'Back', + orbitDoubleClickHint: 'Double-click to add this track to the Orbit queue', + playAll: 'Play All', + shareAlbum: 'Share album', + enqueue: 'Enqueue', + enqueueTooltip: 'Add entire album to queue', + artistBio: 'Artist Bio', + download: 'Download (ZIP)', + downloading: 'Loading…', + cacheOffline: 'Make available offline', + offlineCached: 'Available offline', + offlineDownloading: 'Caching… ({{n}}/{{total}})', + removeOffline: 'Remove offline cache', + offlineStorageFull: 'Offline storage full (limit: {{mb}} MB). Free up space by deleting an album from your Offline Library, or increase the limit in Settings.', + offlineStorageGoToLibrary: 'Offline Library', + offlineStorageGoToSettings: 'Settings', + favoriteAdd: 'Add to Favorites', + favoriteRemove: 'Remove from Favorites', + favorite: 'Favorite', + noBio: 'No biography available.', + moreByArtist: 'More by {{artist}}', + tracksCount: '{{n}} Tracks', + goToArtist: 'Go to {{artist}}', + moreLabelAlbums: 'More albums on {{label}}', + trackTitle: 'Title', + trackAlbum: 'Album', + trackArtist: 'Artist', + trackGenre: 'Genre', + trackFormat: 'Format', + trackFavorite: 'Favorite', + trackRating: 'Rating', + trackDuration: 'Duration', + trackTotal: 'Total', + columns: 'Columns', + resetColumns: 'Reset to defaults', + notFound: 'Album not found.', + bioModal: 'Artist Biography', + bioClose: 'Close', + ratingLabel: 'Rating', + enlargeCover: 'Enlarge', + filterSongs: 'Filter songs…', + sortNatural: 'Natural', + sortByTitle: 'A–Z (Title)', + sortByArtist: 'A–Z (Artist)', + sortByAlbum: 'A–Z (Album)', +}; diff --git a/src/locales/en/albums.ts b/src/locales/en/albums.ts new file mode 100644 index 00000000..bcb9e003 --- /dev/null +++ b/src/locales/en/albums.ts @@ -0,0 +1,32 @@ +export const albums = { + title: 'All Albums', + sortByName: 'A–Z (Album)', + sortByArtist: 'A–Z (Artist)', + sortNewest: 'Newest first', + sortRandom: 'Random', + yearFrom: 'From', + yearTo: 'To', + yearFilterClear: 'Clear year filter', + yearFilterLabel: 'Year', + compilationLabel: 'Compilations', + compilationOnly: 'Only compilations', + compilationHide: 'Hide compilations', + compilationTooltipAll: 'All albums · click: only compilations', + compilationTooltipOnly: 'Only compilations · click: hide compilations', + compilationTooltipHide: 'Compilations hidden · click: show all', + select: 'Multi-select', + startSelect: 'Enable multi-select', + cancelSelect: 'Cancel', + selectionCount: '{{count}} selected', + downloadZips: 'Download ZIPs', + addOffline: 'Add Offline', + enqueueSelected_one: 'Enqueue ({{count}})', + enqueueSelected_other: 'Enqueue ({{count}})', + enqueueQueued_one: 'Added {{count}} album to queue', + enqueueQueued_other: 'Added {{count}} albums to queue', + downloadingZip: 'Downloading {{current}}/{{total}}: {{name}}', + downloadZipDone: '{{count}} ZIP(s) downloaded', + downloadZipFailed: 'Failed to download {{name}}', + offlineQueuing: 'Queuing {{count}} album(s) for offline…', + offlineFailed: 'Failed to add {{name}} offline', +}; diff --git a/src/locales/en/artistDetail.ts b/src/locales/en/artistDetail.ts new file mode 100644 index 00000000..893cc8c5 --- /dev/null +++ b/src/locales/en/artistDetail.ts @@ -0,0 +1,41 @@ +export const artistDetail = { + back: 'Back', + albums: 'Albums', + album: 'Album', + playAll: 'Play All', + shareArtist: 'Share artist', + shuffle: 'Shuffle', + radio: 'Radio', + loading: 'Loading…', + noRadio: 'No similar tracks found for this artist.', + notFound: 'Artist not found.', + albumsBy: 'Albums by {{name}}', + topTracks: 'Top Tracks', + noAlbums: 'No albums found.', + trackTitle: 'Title', + trackAlbum: 'Album', + trackDuration: 'Duration', + favoriteAdd: 'Add to Favorites', + favoriteRemove: 'Remove from Favorites', + favorite: 'Favorite', + albumCount_one: '{{count}} Album', + albumCount_other: '{{count}} Albums', + openedInBrowser: 'Opened in browser', + featuredOn: 'Also Featured On', + similarArtists: 'Similar Artists', + cacheOffline: 'Save discography offline', + offlineCached: 'Discography cached', + offlineDownloading: 'Caching… ({{done}}/{{total}} albums)', + uploadImage: 'Upload artist image', + uploadImageError: 'Failed to upload image', + releaseTypes: { + album: 'Album', + ep: 'EP', + single: 'Single', + compilation: 'Compilation', + live: 'Live', + soundtrack: 'Soundtrack', + remix: 'Remix', + other: 'Other', + }, +}; diff --git a/src/locales/en/artists.ts b/src/locales/en/artists.ts new file mode 100644 index 00000000..e5af1574 --- /dev/null +++ b/src/locales/en/artists.ts @@ -0,0 +1,18 @@ +export const artists = { + title: 'Artists', + search: 'Search…', + all: 'All', + gridView: 'Grid view', + listView: 'List view', + imagesOn: 'Artist images on — may increase network and system load', + imagesOff: 'Artist images off — showing initials only', + loadMore: 'Load more', + notFound: 'No artists found.', + albumCount_one: '{{count}} Album', + albumCount_other: '{{count}} Albums', + selectionCount: '{{count}} selected', + select: 'Multi-select', + startSelect: 'Enable multi-select', + cancelSelect: 'Cancel', + addToPlaylist: 'Add to Playlist', +}; diff --git a/src/locales/en/changelog.ts b/src/locales/en/changelog.ts new file mode 100644 index 00000000..64ff8f03 --- /dev/null +++ b/src/locales/en/changelog.ts @@ -0,0 +1,5 @@ +export const changelog = { + modalTitle: "What's New", + dontShowAgain: "Don't show again", + close: 'Got it', +}; diff --git a/src/locales/en/common.ts b/src/locales/en/common.ts new file mode 100644 index 00000000..36c5a208 --- /dev/null +++ b/src/locales/en/common.ts @@ -0,0 +1,66 @@ +export const common = { + albums: 'Albums', + album: 'Album', + loading: 'Loading…', + loadingMore: 'Loading…', + loadingPlaylists: 'Loading Playlists…', + noAlbums: 'No albums found.', + downloading: 'Downloading…', + downloadZip: 'Download (ZIP)', + back: 'Back', + cancel: 'Cancel', + close: 'Close', + save: 'Save', + delete: 'Delete', + use: 'Use', + add: 'Add', + new: 'New', + active: 'Active', + download: 'Download', + chooseDownloadFolder: 'Choose download folder', + noFolderSelected: 'No folder selected', + rememberDownloadFolder: 'Remember this folder', + filterGenre: 'Genre Filter', + filterSearchGenres: 'Search genres…', + filterNoGenres: 'No genres match', + filterClear: 'Clear', + favorites: 'Favorites', + favoritesTooltipOff: 'Show only favorites', + favoritesTooltipOn: 'Show all', + play: 'Play', + bulkSelected: '{{count}} selected', + clearSelection: 'Clear selection', + bulkAddToPlaylist: 'Add to Playlist', + bulkRemoveFromPlaylist: 'Remove from Playlist', + bulkClear: 'Clear selection', + updaterAvailable: 'Update available', + updaterVersion: 'v{{version}} is available', + updaterWebsite: 'Website', + updaterModalTitle: 'New Version Available', + updaterChangelog: "What's New", + updaterDownloadBtn: 'Download Now', + updaterSkipBtn: 'Skip this Version', + updaterRemindBtn: 'Remind me Later', + updaterDone: 'Download complete', + updaterShowFolder: 'Show in Folder', + updaterInstallHint: 'Close Psysonic and run the installer manually.', + updaterAurHint: 'Install the update via AUR:', + updaterErrorMsg: 'Download failed', + updaterRetryBtn: 'Retry', + updaterInstallNow: 'Install now', + updaterMacReadyTitle: 'Ready to install', + updaterMacReady: 'The update downloads, verifies and applies in place — no DMG needed. The app restarts automatically when done.', + updaterTrustNotarized: 'Notarized by Apple', + updaterTrustSignature: 'Signature verified', + updaterMacDoneTitle: 'Update installed', + updaterRestartingIn: 'Restarting in {{n}}s…', + updaterRestarting: 'Restarting…', + updaterRestartNow: 'Restart now', + durationHoursMinutes: '{{hours}}h {{minutes}}m', + durationMinutesOnly: '{{minutes}}m', + updaterOpenGitHub: 'Open on GitHub', + filters: 'Filters', + more: 'more', + yearRange: 'Year Range', + clearAll: 'Clear all', +}; diff --git a/src/locales/en/composerDetail.ts b/src/locales/en/composerDetail.ts new file mode 100644 index 00000000..ea055721 --- /dev/null +++ b/src/locales/en/composerDetail.ts @@ -0,0 +1,11 @@ +export const composerDetail = { + back: 'Back', + notFound: 'Composer not found.', + about: 'About this composer', + works: 'Works', + noWorks: 'No works found.', + workCount_one: '{{count}} work', + workCount_other: '{{count}} works', + shareComposer: 'Share composer', + unknownComposer: 'Composer', +}; diff --git a/src/locales/en/composers.ts b/src/locales/en/composers.ts new file mode 100644 index 00000000..9fedc71b --- /dev/null +++ b/src/locales/en/composers.ts @@ -0,0 +1,10 @@ +export const composers = { + title: 'Composers', + search: 'Search…', + notFound: 'No composers found.', + unsupported: 'Browse by Composer requires Navidrome 0.55 or newer.', + loadFailed: 'Could not load composers.', + retry: 'Retry', + involvedIn_one: 'Involved in {{count}} album', + involvedIn_other: 'Involved in {{count}} albums', +}; diff --git a/src/locales/en/connection.ts b/src/locales/en/connection.ts new file mode 100644 index 00000000..6f4856e9 --- /dev/null +++ b/src/locales/en/connection.ts @@ -0,0 +1,28 @@ +export const connection = { + connected: 'Connected', + connectedTo: 'Connected to {{server}}', + disconnected: 'Disconnected', + disconnectedFrom: 'Cannot reach {{server}} — click to check settings', + checking: 'Connecting…', + extern: 'Extern', + offlineTitle: 'No server connection', + offlineSubtitle: 'Cannot reach {{server}}. Check your network or server.', + offlineModeBanner: 'Offline Mode — playing from local cache', + offlineNoCacheBanner: 'No server connection — cannot reach {{server}}', + offlineLibraryTitle: 'Offline Library', + offlineLibraryEmpty: 'No albums cached yet. Go online, open an album and click "Make available offline".', + offlineAlbumCount: '{{n}} album', + offlineAlbumCount_plural: '{{n}} albums', + offlineFilterAll: 'All', + offlineFilterAlbums: 'Albums', + offlineFilterPlaylists: 'Playlists', + offlineFilterArtists: 'Discographies', + retry: 'Retry', + serverSettings: 'Server Settings', + switchServerTitle: 'Switch server', + switchServerHint: 'Click to choose another saved server.', + manageServers: 'Manage servers…', + switchFailed: 'Could not switch — server unreachable.', + lastfmConnected: 'Last.fm connected as @{{user}}', + lastfmSessionInvalid: 'Session invalid — click to re-connect', +}; diff --git a/src/locales/en/contextMenu.ts b/src/locales/en/contextMenu.ts new file mode 100644 index 00000000..e1c7762a --- /dev/null +++ b/src/locales/en/contextMenu.ts @@ -0,0 +1,33 @@ +export const contextMenu = { + playNow: 'Play Now', + playNext: 'Play Next', + addToQueue: 'Add to Queue', + enqueueAlbum: 'Enqueue Album', + enqueueAlbums_one: 'Enqueue {{count}} Album', + enqueueAlbums_other: 'Enqueue {{count}} Albums', + startRadio: 'Start Radio', + instantMix: 'Instant Mix', + instantMixFailed: 'Could not build Instant Mix — server or plugin error.', + cliMixNeedsTrack: 'Nothing is playing — start playback first, then run the mix command again.', + lfmLove: 'Love on Last.fm', + lfmUnlove: 'Unlove on Last.fm', + favorite: 'Favorite', + favoriteArtist: 'Favorite Artist', + favoriteAlbum: 'Favorite Album', + unfavorite: 'Remove from Favorites', + unfavoriteArtist: 'Remove Artist from Favorites', + unfavoriteAlbum: 'Remove Album from Favorites', + removeFromQueue: 'Remove from Queue', + removeFromPlaylist: 'Remove from Playlist', + openAlbum: 'Open Album', + goToArtist: 'Go to Artist', + download: 'Download (ZIP)', + addToPlaylist: 'Add to Playlist', + selectedPlaylists: '{{count}} playlists selected', + selectedAlbums: '{{count}} albums selected', + selectedArtists: '{{count}} artists selected', + songInfo: 'Song Info', + shareLink: 'Copy share link', + shareCopied: 'Share link copied to the clipboard.', + shareCopyFailed: 'Could not copy to the clipboard.', +}; diff --git a/src/locales/en/deviceSync.ts b/src/locales/en/deviceSync.ts new file mode 100644 index 00000000..0a857e16 --- /dev/null +++ b/src/locales/en/deviceSync.ts @@ -0,0 +1,80 @@ +export const deviceSync = { + title: 'Device Sync', + targetFolder: 'Target Folder', + noFolderChosen: 'No folder chosen', + selectDrive: 'Select a drive…', + refreshDrives: 'Refresh drives', + noDrivesDetected: 'No removable drives detected', + browseManual: 'Browse manually…', + free: 'free', + notMountedVolume: 'Target is not on a mounted volume. The drive may have been disconnected.', + chooseFolder: 'Choose…', + targetDevice: 'Target Device', + schemaLabel: 'Naming scheme', + schemaHint: 'Fixed scheme for reliable cross-OS sync. Playlists are written as .m3u8 that reference the album tracks — no duplicates on the device.', + migrateButton: 'Reorganize existing files…', + migrateTooltip: 'Rename existing files on the device into the new scheme (from the old filename template).', + migrateTitle: 'Reorganize existing files', + migrateLoading: 'Analyzing existing files…', + migrateNothingToDo: 'All existing files already match the new scheme — nothing to do.', + migrateNoTemplate: 'No legacy filename template found on the device. Migration only applies when the stick was synced with a Psysonic version that supported custom templates.', + migrateFilesToRename: 'files will be renamed', + migrateUnchanged: '{{n}} files are already at the correct path', + migrateCollisions: '{{n}} files cannot be renamed automatically (multiple tracks map to the same target). They will be left untouched — the next sync re-downloads them into the correct location.', + migratePreviewNote: 'Old template: {{tpl}}', + migrateExecuting: 'Renaming files…', + migrateSuccess: '{{n}} files renamed successfully', + migrateFailed: '{{n}} renames failed', + migrateShowErrors: 'Show errors', + migrateStart: 'Start renaming', + onDevice: 'Device Manager', + addSources: 'Add…', + colName: 'Name', + colType: 'Type', + colStatus: 'Status', + syncResult: '{{done}} transferred, {{skipped}} already up to date ({{total}} total)', + deleteFromDevice: 'Mark for deletion ({{count}})', + confirmDelete: 'Delete {{count}} item(s) from the device: {{names}}?', + deleteComplete: '{{count}} item(s) removed from device.', + manifestImported: 'Imported {{count}} source(s) from device manifest.', + selectedSources: 'Selected Sources', + noSourcesSelected: 'No sources selected. Click items in the browser to add them.', + clearAll: 'Clear all', + tabPlaylists: 'Playlists', + tabAlbums: 'Albums', + tabArtists: 'Artists', + searchPlaceholder: 'Search…', + syncButton: 'Sync to Device', + actionTransfer: 'Transfer to Device', + actionDelete: 'Delete from Device', + actionApplyAll: 'Apply All Changes', + cancel: 'Cancel', + noTargetDir: 'Please choose a target folder first.', + noSources: 'Please select at least one source.', + noTracks: 'No tracks found in the selected sources.', + fetchError: 'Failed to fetch tracks from server.', + syncComplete: 'Sync complete.', + dismiss: 'Dismiss', + cancelSync: 'Cancel', + syncCancelled: 'Sync cancelled ({{done}} / {{total}} transferred).', + statusSynced: 'Synced', + statusPending: 'Pending', + statusDeletion: 'Deletion', + markForDeletion: 'Mark for deletion', + undoDeletion: 'Undo deletion', + removeSource: 'Remove', + syncInBackground: 'Sync started in background — you can navigate away.', + syncInProgress: '{{done}} / {{total}} tracks…', + scanningDevice: 'Scanning device…', + syncSummary: 'Sync Summary', + calculating: 'Calculating required payload…', + filesToAdd: 'Files to Add:', + filesToDelete: 'Files to Delete:', + netChange: 'Net Change:', + availableSpace: 'Available Disk Space:', + spaceWarning: 'Warning: Target device does not have enough reported space.', + proceed: 'Proceed with Sync', + notEnoughSpace: 'Not enough physical disk space detected!', + liveSearch: 'Live', + randomAlbumsLabel: 'Random Albums', +}; diff --git a/src/locales/en/entityRating.ts b/src/locales/en/entityRating.ts new file mode 100644 index 00000000..7297fd5c --- /dev/null +++ b/src/locales/en/entityRating.ts @@ -0,0 +1,9 @@ +export const entityRating = { + albumShort: 'Album rating', + artistShort: 'Artist rating', + albumAriaLabel: 'Album rating', + artistAriaLabel: 'Artist rating', + selectedArtistsRatingAriaLabel: 'Star rating for {{count}} selected artists', + selectedAlbumsRatingAriaLabel: 'Star rating for {{count}} selected albums', + saveFailed: 'Could not save rating.', +}; diff --git a/src/locales/en/favorites.ts b/src/locales/en/favorites.ts new file mode 100644 index 00000000..b41d22c0 --- /dev/null +++ b/src/locales/en/favorites.ts @@ -0,0 +1,19 @@ +export const favorites = { + title: 'Favorites', + empty: "You haven't saved any favorites yet.", + artists: 'Artists', + albums: 'Albums', + songs: 'Songs', + enqueueAll: 'Add all to queue', + playAll: 'Play all', + removeSong: 'Remove from favorites', + stations: 'Radio Stations', + showingFiltered: 'Showing {{filtered}} of {{total}} ({{artist}})', + showingCount: 'Showing {{filtered}} of {{total}}', + clearArtistFilter: 'Clear artist filter', + noFilterResults: 'No results with selected filters.', + allArtists: 'All Artists', + topArtists: 'Top Artists by Favorites', + topArtistsSongCount_one: '{{count}} song', + topArtistsSongCount_other: '{{count}} songs', +}; diff --git a/src/locales/en/folderBrowser.ts b/src/locales/en/folderBrowser.ts new file mode 100644 index 00000000..3ec92273 --- /dev/null +++ b/src/locales/en/folderBrowser.ts @@ -0,0 +1,4 @@ +export const folderBrowser = { + empty: 'Empty folder', + error: 'Failed to load', +}; diff --git a/src/locales/en/genres.ts b/src/locales/en/genres.ts new file mode 100644 index 00000000..192a0f96 --- /dev/null +++ b/src/locales/en/genres.ts @@ -0,0 +1,12 @@ +export const genres = { + title: 'Genres', + genreCount: 'Genres', + albumCount_one: '{{count}} album', + albumCount_other: '{{count}} albums', + loading: 'Loading genres…', + empty: 'No genres found.', + albumsLoading: 'Loading albums…', + albumsEmpty: 'No albums found for this genre.', + loadMore: 'Load more', + back: 'Back', +}; diff --git a/src/locales/en/help.ts b/src/locales/en/help.ts new file mode 100644 index 00000000..d64bf21c --- /dev/null +++ b/src/locales/en/help.ts @@ -0,0 +1,115 @@ +export const help = { + title: 'Help', + searchPlaceholder: 'Search Help…', + noResults: 'No matching topics. Try a different search term.', + // ── Section 1: Getting Started ───────────────────────────────────────── + s1: 'Getting Started', + q1: 'Which servers are compatible?', + a1: 'Psysonic is built first and foremost for Navidrome and is fully Subsonic-compatible — Gonic, Airsonic, LMS and other Subsonic-API servers also work. Some advanced features (ratings, smart playlists, magic-string sharing, user management) require Navidrome.', + q2: 'How do I add a server?', + a2: 'Settings → Servers → Add Server. Enter the URL (e.g. http://192.168.1.100:4533), username, and password. Psysonic tests the connection before saving — nothing is stored if it fails. You can add as many servers as you like and switch between them in the header at any time; only one is active at a time.', + q3: 'Quick tour of the UI?', + a3: 'Sidebar (left) for navigation, Mainstage / pages in the middle, Player Bar at the bottom, and the Queue Panel on the right (toggle from the top-right header next to the Now-Playing indicator). The search bar at the top searches your whole library; "Now Playing" shows what other users on the same Navidrome server are listening to right now.', + // ── Section 2: Playback & Queue ──────────────────────────────────────── + s2: 'Playback & Queue', + q4: 'How do I use the queue?', + a4: 'Open the Queue Panel from the top-right header. Drag rows to reorder them, drop them outside to remove, or use the queue toolbar to shuffle, save the queue as a playlist, or jump to a track. Drag rows out of the panel to drop them somewhere else as a transfer.', + q5: 'Gapless vs Crossfade — what is the difference?', + a5: 'Gapless pre-buffers the next track so there is zero silence between songs (best for live albums and DJ mixes). Crossfade fades the current track out while the next fades in over 1–10 s (best for shuffled mixes). They are mutually exclusive — enabling one disables the other. Configure both in Settings → Audio.', + q6: 'What is Infinite Queue?', + a6: 'When the queue runs out and Repeat is off, Psysonic silently appends similar / random tracks from your library so playback never stops. Auto-added tracks appear below a "— Added automatically —" divider. Toggle it with the infinity icon in the queue header; restrict auto-additions to a genre in Settings → Queue.', + q7: 'Multi-select and Shift-click range selection?', + a7: 'Activate "Select" on Albums / New Releases / Random Albums / Playlists. Click an item to toggle it, then hold Shift and click another item to select everything between them in the visible order. Shift-clicks extend from the most recently clicked anchor. The toolbar above the grid offers bulk actions (queue, download, delete, etc.).', + q8: 'Keyboard shortcuts and global hotkeys?', + a8: 'Default in-app keys: Space = Play / Pause, Esc = close fullscreen / modals, F1 = shortcuts cheat-sheet. Settings → Input lets you rebind every in-app action (also as chords like Ctrl+Shift+P) and set system-wide global shortcuts that work even when Psysonic is in the background or minimized. Media keys (Play/Pause, Next, Previous) work on all platforms.', + // ── Section 3: Audio Tools ───────────────────────────────────────────── + s3: 'Audio Tools', + q9: 'Replay Gain modes?', + a9: 'Settings → Audio → Replay Gain. Track mode normalises every song to a target level. Album mode preserves the loudness curve within an album. Auto mode picks Track or Album based on whether the queue is from a single album. Tracks without Replay Gain tags fall back to a configurable preamp.', + q10: 'What is Smart Loudness Normalization (LUFS)?', + a10: 'A modern alternative to Replay Gain in Settings → Audio. Psysonic analyses each track to LUFS / EBU R128 and stores the result, so volume is consistent across your whole library — including tracks without Replay Gain tags. Cold-cache analysis runs in the background and uses 35–40 % CPU for ~1 minute, then drops to 0. Set your target loudness (default −10 LUFS) once.', + q11: 'EQ and AutoEQ?', + a11: 'A 10-band parametric EQ lives in Settings → Audio → Equalizer with manual bands and presets. AutoEQ next to it pulls a measured correction profile for your headphone model from the AutoEQ database and applies it to the bands automatically — pick your headphones and the EQ snaps to the correct curve.', + q12: 'How do I switch the audio output device?', + a12: 'Settings → Audio → Output Device. Psysonic lists every available output and switches instantly when you pick one. The refresh button rescans devices that were plugged in after launch. Linux ALSA names like "sysdefault" are auto-cleaned for readability.', + q13: 'What is Hot Cache?', + a13: 'Hot Cache preloads the current track plus the next several into RAM and onto disk so playback starts with no buffering — especially useful on slow / remote servers. Eviction kicks in when the size limit is reached. Configure size and the debounce delay (so quick skips do not over-fetch) in Settings → Audio.', + // ── Section 4: Library & Discovery ───────────────────────────────────── + s4: 'Library & Discovery', + q14: 'How do ratings and Skip-to-1★ work?', + a14: 'Psysonic supports 1–5 star ratings via OpenSubsonic (Navidrome ≥ 0.53). Rate songs in track lists, in the right-click menu, or in the player bar below the artist name; albums on the album page; artists on the artist page. Skip-to-1★ (Settings → Library → Ratings) auto-assigns 1 star after a configurable number of consecutive skips. The same panel lets you set a minimum rating filter for Random Mix and other generated mixes.', + q15: 'How do I browse — Folders, Genres, Tracks?', + a15: 'Folder Browser (sidebar) walks your server\'s music directory in a Miller-column layout — click a folder to drill in, click a track or a folder\'s play icon to play / enqueue. Genres uses a tag-cloud view scaled by track count; click a genre to open it. Tracks is a flat library hub with column-sortable virtual list and live search.', + q16: 'Search and Advanced Search?', + a16: 'The header search bar runs a fast live search across artists, albums and tracks as you type. Open Advanced Search (sidebar) for a richer view: filter by year, genre, rating, format, channels, sample rate, BPM, mood, and combine criteria. Right-click any result for the same context menu used elsewhere in the app.', + q17: 'What are the Mixes (Random / Genre / Super Genre / Lucky)?', + a17: 'Random Mix builds a playlist of random tracks from your library; the Keyword Filter excludes audiobooks, comedy, etc. by genre / title / album substrings. Super Genre Mix groups your library into broad styles (Rock, Metal, Electronic, Jazz, Classical…) and builds a focused mix from one. Lucky Mix uses your listening history, ratings and AudioMuse-AI similar tracks to assemble an instant playlist with one click.', + q18: 'Statistics page?', + a18: 'Statistics (sidebar) shows top artists, top albums, top tracks, genre breakdown, listening time over time, and per-library scope when you have more than one music folder configured. Several views are exportable as a sharable card image.', + q19: 'How do I download an album as a ZIP?', + a19: 'Album page → "Download (ZIP)". The server compresses the album first — for large or lossless albums (FLAC / WAV) the progress bar appears only after zipping completes and the transfer starts. This is normal.', + // ── Section 5: Lyrics ────────────────────────────────────────────────── + s5: 'Lyrics', + q20: 'Where do lyrics come from?', + a20: 'Three sources, configurable in Settings → Lyrics: your Navidrome server (embedded / OpenSubsonic lyrics), LRCLIB (community-contributed synced lyrics), and NetEase Cloud Music (large Asian + international catalog). Each source can be enabled / disabled and re-ordered by drag.', + q21: 'How do I view lyrics during playback?', + a21: 'Click the microphone icon in the player bar to open the Lyrics tab inside the queue panel. Synced lyrics auto-scroll and support click-to-seek; plain-text lyrics scroll as a static block. Toggle the Fullscreen Player from the player-bar artwork for an immersive lyrics view with mesh-blob background.', + // ── Section 6: Sharing & Social ──────────────────────────────────────── + s6: 'Sharing & Social', + q22: 'What are Magic Strings?', + a22: 'Magic Strings are short copy-paste tokens that share things between Psysonic users without any third-party server. Server-Invite strings let a friend onboard onto your Navidrome with one paste; Album / Artist / Queue Magic Strings open the same album / artist / queue on the recipient\'s installed Psysonic. Generate them from the share menu, paste them into the search bar to consume.', + q23: 'What is Orbit?', + a23: 'Orbit is synchronized listen-together: a host plays a track, every guest hears it in sync, and guests can suggest songs the host can accept into the queue. Start a session from the header Orbit button, share the invite link, and others can join from any Psysonic install. The host owns playback (skip, seek, queue) — guests get a real-time view and a suggestion box. Sessions are ephemeral and end when the host closes them.', + q24: 'What is the Now Playing dropdown?', + a24: 'The broadcast icon in the top-right header shows what other users on your Navidrome server are currently listening to, refreshed every 10 seconds. Your own entry disappears the moment you pause. It is per-server, so users on a different active server are not shown.', + // ── Section 7: Personalization ───────────────────────────────────────── + s7: 'Personalization', + q25: 'Themes and the Theme Scheduler?', + a25: 'Settings → Appearance → Theme picks from 60+ themes across 8 groups (Psysonic, Mediaplayer, Operating Systems, Games, Movies, Series, Social Media, Open Source Classics — Catppuccin / Nord / Gruvbox / Nightfox / Dracula). Auto-Switch Theme lets you set a day theme + night theme with start times so Psysonic flips automatically.', + q26: 'Can I customize the Sidebar, Home and Artist pages?', + a26: 'Yes — Settings → Personalisation. The sidebar customizer lets you drag nav items into the order you want and hide ones you do not use. The Home customizer toggles each Mainstage rail (Hero, Recent, Discover, Recently Played, Starred…). The Artist page customizer reorders the sections (Top Songs, Albums, Singles, Compilations, Similar Artists, etc.) and lets you hide ones you never look at.', + q27: 'What is the Mini Player?', + a27: 'A small floating window with cover art, transport controls and a compact queue. Open it from the player-bar mini-player icon or with its keyboard shortcut. The window remembers its position and size between sessions. On Windows the mini-webview is pre-created at startup so opening is instant; Linux / macOS opt in via Settings → Appearance → Preload mini player.', + q28: 'What is the Floating Player Bar?', + a28: 'An optional player-bar style (Settings → Appearance) that detaches from the bottom edge with a themed background, accent border, rounded album art and a centered volume section. Useful on tall monitors or compact themes.', + q29: 'Track Preview on hover?', + a29: 'Hover over a track row, click the small preview button on the cover, or trigger preview from the right-click menu — Psysonic streams the first ~15 s through the same Rust audio engine so loudness normalisation applies. Useful for skimming an album you have not heard before.', + q30: 'Sleep timer?', + a30: 'Click the moon icon in the player bar to open the sleep timer. Pick a duration (or "end of current track") and Psysonic fades out and pauses at the end. The button shows a circular ring and an in-button countdown while the timer runs.', + q31: 'UI scale, font, seekbar style?', + a31: 'Settings → Appearance — Interface Scale (80–125 % without affecting system font size), Font (10 UI fonts including IBM Plex Mono, Fira Code, Geist, Golos Text…), Seekbar Style (Waveform analysed / pseudowave deterministic / Line & Dot / Bar / Thick Bar / Segmented / Neon Glow / Pulse Wave / Particle Trail / Liquid Fill / Retro Tape).', + // ── Section 8: Power User ────────────────────────────────────────────── + s8: 'Power User', + q32: 'CLI player controls?', + a32: 'The Psysonic binary doubles as a remote control. Examples: psysonic --player play / pause / next / prev, --player volume 75, --player seek 15, --player shuffle, --player repeat off|all|one, --player rating 1-5. Switch servers, audio devices, libraries; trigger Instant Mix; search artists / albums / tracks. Run psysonic --player --help for the full list. Shell completions for bash and zsh via psysonic completions.', + q33: 'Smart Playlists (Navidrome)?', + a33: 'Smart Playlists are Navidrome-side dynamic playlists defined by rules (genre = Rock AND year > 2020, etc.). The Playlists page in Psysonic lets you create, edit and delete them with a visual rule editor — Psysonic talks to the Navidrome native API for that. They behave like normal playlists in the rest of the app and update automatically as your library changes.', + q34: 'Backup and restore settings?', + a34: 'Settings → Storage → Backup & Restore exports server profiles, themes, keybindings and other settings to a single JSON file. Import the file on another machine or after a reinstall to restore everything at once. Server passwords are included — keep the file private.', + q35: 'Where do I see all open-source licenses?', + a35: 'Settings → System → Open Source Licenses. The full dependency list (cargo crates and npm packages) ships in the build with bundled license texts. Click an entry for the full text; the curated highlight block at the top calls out the user-recognisable libraries (Tauri, React, rodio, symphonia, etc.).', + // ── Section 9: Offline & Sync ────────────────────────────────────────── + s9: 'Offline & Sync', + q36: 'Offline Mode — caching albums and playlists?', + a36: 'Open any album or playlist and click the download icon in the header — Psysonic caches every track locally so it plays from disk with no network call. The Offline Library page (sidebar) lists everything cached, shows progress in flight, and lets you remove entries with the trash icon (which appears once a download completes).', + q37: 'Offline storage limit?', + a37: 'Settings → Library → Offline lets you set a maximum cache size. When the limit is reached, the album-page download button shows a warning banner. Free space by removing albums or playlists from the Offline Library page.', + q38: 'Device Sync — copy music to USB / SD?', + a38: 'Device Sync (sidebar) copies albums, playlists or whole artists to an external drive for offline listening on other devices. Pick a target folder, choose sources from the browser tabs, click "Transfer to Device". Psysonic writes a manifest (psysonic-sync.json) so it knows which files are already there even if you reopen Device Sync on a different OS with a different filename template. Templates support {artist} / {album} / {title} / {track_number} / {disc_number} / {year} tokens with / for folder separators.', + // ── Section 10: Integrations & Troubleshooting ───────────────────────── + s10: 'Integrations & Troubleshooting', + q39: 'Last.fm scrobbling?', + a39: 'Settings → Integrations → Last.fm. Connect your account once and Psysonic scrobbles directly to Last.fm — no Navidrome configuration needed. A scrobble is sent after you have heard 50 % of a track. Now-playing pings are sent at the start.', + q40: 'Discord Rich Presence?', + a40: 'Settings → Integrations → Discord shows your current track on your Discord profile. Choose between the app icon, your server\'s cover art (via getAlbumInfo2 — needs a publicly reachable server), or Apple Music covers. Customize the display strings (details, state, tooltip) with token templates.', + q41: 'Bandsintown tour dates?', + a41: 'Opt in under Settings → Integrations → Now-Playing Info. The Now Playing tab on the Now Playing page then shows upcoming tour dates for the playing artist via the Bandsintown widget API. Off by default — no requests are made until you enable it.', + q42: 'Internet Radio — playing live streams?', + a42: 'Internet Radio (sidebar) plays any live stream stored on your Navidrome server (add stations via the Navidrome admin UI). Playback runs through the browser HTML5 audio engine — most EQ / Replay Gain / Loudness settings do not apply to radio, but ICY metadata (current song name) does show up. Supports MP3, AAC, OGG Vorbis and most HLS streams; codec support depends on the platform.', + q43: 'The connection test fails — what now?', + a43: 'Double-check the URL including port (e.g. http://192.168.1.100:4533). On a local network http:// often works where https:// does not (no certificate). Make sure no firewall blocks the port and that the username and password are correct. If your server is behind a reverse proxy, try the direct URL first to isolate the cause.', + q44: 'Cover art and artist images load slowly.', + a44: 'Images are fetched from your server on first view and then cached locally for 30 days. If your server\'s storage is slow, the first visit to a page can take a moment; subsequent visits are instant. The Hot Cache also helps for tracks but image cache is independent.', + q45: 'Linux issues — black screen or no audio?', + a45: 'Black screen is usually a GPU / EGL driver issue in WebKitGTK — launch with GDK_BACKEND=x11 WEBKIT_DISABLE_COMPOSITING_MODE=1 WEBKIT_DISABLE_DMABUF_RENDERER=1 (the AUR / .deb / .rpm installers set these automatically). For audio, make sure PipeWire or PulseAudio is running. If audio drops out after sleep / wake, this is now handled automatically by the post-sleep recovery hook.', +}; diff --git a/src/locales/en/hero.ts b/src/locales/en/hero.ts new file mode 100644 index 00000000..56833ade --- /dev/null +++ b/src/locales/en/hero.ts @@ -0,0 +1,6 @@ +export const hero = { + eyebrow: 'Featured Album', + playAlbum: 'Play Album', + enqueue: 'Enqueue', + enqueueTooltip: 'Add entire album to queue', +}; diff --git a/src/locales/en/home.ts b/src/locales/en/home.ts new file mode 100644 index 00000000..5273c27f --- /dev/null +++ b/src/locales/en/home.ts @@ -0,0 +1,19 @@ +export const home = { + hero: 'Featured', + starred: 'Personal Favorites', + recent: 'Recently Added', + mostPlayed: 'Most Played', + recentlyPlayed: 'Recently Played', + losslessAlbums: 'Lossless Albums', + discover: 'Discover', + discoverSongs: 'Discover Songs', + loadMore: 'Load More', + discoverMore: 'Discover More', + discoverArtists: 'Discover Artists', + discoverArtistsMore: 'All Artists', + becauseYouLike: 'Because you listened…', + becauseYouLikeFor: 'Because you listened to {{artist}}', + similarTo: 'Similar to {{artist}}', + becauseYouLikeTracks_one: '{{count}} track', + becauseYouLikeTracks_other: '{{count}} tracks' +}; diff --git a/src/locales/en/index.ts b/src/locales/en/index.ts new file mode 100644 index 00000000..08ddc704 --- /dev/null +++ b/src/locales/en/index.ts @@ -0,0 +1,91 @@ +import { sidebar } from './sidebar'; +import { home } from './home'; +import { hero } from './hero'; +import { search } from './search'; +import { nowPlaying } from './nowPlaying'; +import { contextMenu } from './contextMenu'; +import { sharePaste } from './sharePaste'; +import { albumDetail } from './albumDetail'; +import { entityRating } from './entityRating'; +import { artistDetail } from './artistDetail'; +import { favorites } from './favorites'; +import { randomLanding } from './randomLanding'; +import { randomAlbums } from './randomAlbums'; +import { genres } from './genres'; +import { randomMix } from './randomMix'; +import { luckyMix } from './luckyMix'; +import { albums } from './albums'; +import { tracks } from './tracks'; +import { artists } from './artists'; +import { composers } from './composers'; +import { composerDetail } from './composerDetail'; +import { login } from './login'; +import { connection } from './connection'; +import { common } from './common'; +import { settings } from './settings'; +import { changelog } from './changelog'; +import { whatsNew } from './whatsNew'; +import { help } from './help'; +import { queue } from './queue'; +import { miniPlayer } from './miniPlayer'; +import { statistics } from './statistics'; +import { player } from './player'; +import { nowPlayingInfo } from './nowPlayingInfo'; +import { songInfo } from './songInfo'; +import { playlists } from './playlists'; +import { smartPlaylists } from './smartPlaylists'; +import { mostPlayed } from './mostPlayed'; +import { losslessAlbums } from './losslessAlbums'; +import { radio } from './radio'; +import { folderBrowser } from './folderBrowser'; +import { deviceSync } from './deviceSync'; +import { orbit } from './orbit'; +import { tray } from './tray'; +import { licenses } from './licenses'; + +export const enTranslation = { + sidebar, + home, + hero, + search, + nowPlaying, + contextMenu, + sharePaste, + albumDetail, + entityRating, + artistDetail, + favorites, + randomLanding, + randomAlbums, + genres, + randomMix, + luckyMix, + albums, + tracks, + artists, + composers, + composerDetail, + login, + connection, + common, + settings, + changelog, + whatsNew, + help, + queue, + miniPlayer, + statistics, + player, + nowPlayingInfo, + songInfo, + playlists, + smartPlaylists, + mostPlayed, + losslessAlbums, + radio, + folderBrowser, + deviceSync, + orbit, + tray, + licenses, +}; diff --git a/src/locales/en/licenses.ts b/src/locales/en/licenses.ts new file mode 100644 index 00000000..7b0ed810 --- /dev/null +++ b/src/locales/en/licenses.ts @@ -0,0 +1,13 @@ +export const licenses = { + title: 'Open Source Licenses', + intro: 'Psysonic is built on open-source software. The list below shows every dependency that ships in the app, with its version, license, and full license text.', + highlights: 'Key dependencies', + searchPlaceholder: 'Search by name, version or license…', + noResults: 'No matches.', + loading: 'Loading licenses…', + loadError: 'Could not load license data.', + noLicenseText: 'No license text bundled for this dependency.', + viewSource: 'View source', + totalLine: '{{total}} dependencies — {{cargo}} cargo, {{npm}} npm', + generatedAt: 'Last generated {{date}}', +}; diff --git a/src/locales/en/login.ts b/src/locales/en/login.ts new file mode 100644 index 00000000..0433682a --- /dev/null +++ b/src/locales/en/login.ts @@ -0,0 +1,22 @@ +export const login = { + subtitle: 'Your Navidrome Desktop Player', + serverName: 'Server Name (optional)', + serverNamePlaceholder: 'My Navidrome', + serverUrl: 'Server URL', + serverUrlPlaceholder: '192.168.1.100:4533 or https://music.example.com', + username: 'Username', + usernamePlaceholder: 'admin', + password: 'Password', + showPassword: 'Show password', + hidePassword: 'Hide password', + connect: 'Connect', + connecting: 'Connecting…', + connected: 'Connected!', + error: 'Connection failed – please check your details.', + urlRequired: 'Please enter a server URL.', + savedServers: 'Saved Servers', + addNew: 'Or add a new server', + orMagicString: 'Or magic string', + magicStringPlaceholder: 'Paste a share string (psysonic1-…)', + magicStringInvalid: 'Invalid or unreadable magic string.', +}; diff --git a/src/locales/en/losslessAlbums.ts b/src/locales/en/losslessAlbums.ts new file mode 100644 index 00000000..ee9efff8 --- /dev/null +++ b/src/locales/en/losslessAlbums.ts @@ -0,0 +1,5 @@ +export const losslessAlbums = { + empty: 'No lossless albums in this library yet.', + unsupported: 'This server does not expose the metadata needed to find lossless albums.', + slowFetchHint: 'Loads slower than other album pages — Psysonic walks the full song catalog by quality.', +}; diff --git a/src/locales/en/luckyMix.ts b/src/locales/en/luckyMix.ts new file mode 100644 index 00000000..ac05b764 --- /dev/null +++ b/src/locales/en/luckyMix.ts @@ -0,0 +1,6 @@ +export const luckyMix = { + done: 'Lucky Mix ready: {{count}} tracks', + failed: 'Could not build Lucky Mix. Try again.', + unavailable: 'Lucky Mix is unavailable for this server.', + cancelTooltip: 'Cancel Lucky Mix build', +}; diff --git a/src/locales/en/miniPlayer.ts b/src/locales/en/miniPlayer.ts new file mode 100644 index 00000000..2153fbbc --- /dev/null +++ b/src/locales/en/miniPlayer.ts @@ -0,0 +1,9 @@ +export const miniPlayer = { + showQueue: 'Show queue', + hideQueue: 'Hide queue', + pinOnTop: 'Pin on top', + pinOff: 'Unpin', + openMainWindow: 'Open main window', + close: 'Close', + emptyQueue: 'Queue is empty', +}; diff --git a/src/locales/en/mostPlayed.ts b/src/locales/en/mostPlayed.ts new file mode 100644 index 00000000..a97b7228 --- /dev/null +++ b/src/locales/en/mostPlayed.ts @@ -0,0 +1,13 @@ +export const mostPlayed = { + title: 'Most Played', + topArtists: 'Top Artists', + topAlbums: 'Top Albums', + plays: '{{n}} plays', + sortMost: 'Most plays first', + sortLeast: 'Fewest plays first', + loadMore: 'Load more albums', + noData: 'No play data yet. Start listening!', + noArtists: 'All artists filtered out.', + filterCompilations: 'Hide compilation artists (Various Artists, Soundtracks, etc.)', + filterCompilationsShort: 'Hide compilations', +}; diff --git a/src/locales/en/nowPlaying.ts b/src/locales/en/nowPlaying.ts new file mode 100644 index 00000000..ca131044 --- /dev/null +++ b/src/locales/en/nowPlaying.ts @@ -0,0 +1,47 @@ +export const nowPlaying = { + tooltip: 'Who is listening?', + title: 'Who is listening?', + loading: 'Loading…', + nobody: 'Nobody is currently listening.', + minutesAgo: '{{n}}m ago', + nothingPlaying: 'Nothing playing yet. Start a track!', + aboutArtist: 'About the Artist', + fromAlbum: 'From this Album', + viewAlbum: 'View Album', + goToArtist: 'Go to Artist', + readMore: 'Read more', + showLess: 'Show less', + genreInfo: 'Genre', + trackInfo: 'Track Info', + topSongs: 'Most played by this artist', + topSongsCredit: 'Top tracks from {{name}}', + trackPosition: 'Track {{pos}}', + playsCount_one: '{{count}} play', + playsCount_other: '{{count}} plays', + releasedYearsAgo_one: '{{count}} year ago', + releasedYearsAgo_other: '{{count}} years ago', + discography: 'Discography', + lastfmStats: 'Last.fm stats', + thisTrack: 'This track', + thisArtist: 'This artist', + listeners: 'listeners', + scrobbles: 'scrobbles', + yourScrobbles: 'by you', + listenersN: '{{n}} listeners', + scrobblesN: '{{n}} scrobbles', + playsByYouN: 'played {{n}}× by you', + openTrackOnLastfm: 'Track on Last.fm', + openArtistOnLastfm: 'Artist on Last.fm', + rgTrackTooltip: 'ReplayGain (track)', + rgAlbumTooltip: 'ReplayGain (album)', + rgAutoTooltip: 'ReplayGain (auto)', + showMoreTracks: 'Show {{count}} more', + showLessTracks: 'Show less', + hideCard: 'Hide card', + layoutMenu: 'Layout', + visibleCards: 'Visible cards', + hiddenCards: 'Hidden cards', + noHiddenCards: 'No hidden cards', + resetLayout: 'Reset layout', + emptyColumn: 'Drop cards here', +}; diff --git a/src/locales/en/nowPlayingInfo.ts b/src/locales/en/nowPlayingInfo.ts new file mode 100644 index 00000000..e57559e6 --- /dev/null +++ b/src/locales/en/nowPlayingInfo.ts @@ -0,0 +1,24 @@ +export const nowPlayingInfo = { + tab: 'Info', + empty: 'Play something to see info', + artist: 'Artist', + songInfo: 'Song info', + onTour: 'On tour', + noTourEvents: 'No upcoming shows', + tourLoading: 'Loading…', + poweredByBandsintown: 'Tour data via Bandsintown', + bioReadMore: 'Read more', + bioReadLess: 'Show less', + showMoreTours_one: 'Show {{count}} more', + showMoreTours_other: 'Show {{count}} more', + showLessTours: 'Show less', + enableBandsintownPrompt: 'See upcoming tour dates?', + enableBandsintownPromptDesc: 'Optional. Loads concerts for the current artist via the public Bandsintown API.', + enableBandsintownPrivacy: 'When enabled, the name of the currently playing artist is sent to the Bandsintown API to fetch tour dates. No account or personal data leaves your device.', + enableBandsintownAction: 'Enable', + role: { + artist: 'Artist', + albumArtist: 'Album artist', + composer: 'Composer', + }, +}; diff --git a/src/locales/en/orbit.ts b/src/locales/en/orbit.ts new file mode 100644 index 00000000..49a72332 --- /dev/null +++ b/src/locales/en/orbit.ts @@ -0,0 +1,200 @@ +export const orbit = { + triggerLabel: 'Orbit', + triggerTooltip: 'Start or join a shared listening session', + launchCreate: 'Create a session', + launchJoin: 'Join a session', + launchHelp: 'How does this work?', + launchHelpSoon: 'Coming soon', + joinModalTitle: 'Join an Orbit session', + joinModalSub: 'Paste the invite link your host sent you.', + joinModalLinkLabel: 'Invite link', + joinModalLinkPlaceholder: 'psysonic2-…', + joinModalLinkHelper: 'Works with any valid Orbit link. Must point to the server you\'re currently signed into.', + joinModalPasteTooltip: 'Paste from clipboard', + joinModalSubmit: 'Join', + joinModalBusy: 'Joining…', + joinErrEmpty: 'Please paste an invite link.', + joinErrInvalid: 'That doesn\'t look like an Orbit invite link.', + closeAria: 'Close', + heroTitlePrefix: 'Listen together with', + heroTitleBrand: 'Orbit', + heroSub: 'Start a session — other users on {{server}} will listen along and can suggest tracks.', + fallbackServer: 'this server', + tipLan: "You're currently connected via a home-network address. Guests outside your network can't join — switch to a public server address in settings before you start.", + tipRemote: 'For guests outside your home network to join, your server address has to be publicly reachable. If your server is internal only, switch before you start.', + labelName: 'Session name', + namePlaceholder: 'Velvet Orbit', + reshuffleTooltip: 'New suggestion', + reshuffleAria: 'Suggest a new name', + helperName: 'How the session shows up to your guests — keep it or type your own.', + labelMax: 'Max guests', + helperMax: "You don't count — this only caps incoming guests.", + labelLink: 'Invite link', + tooltipCopied: 'Copied', + tooltipCopy: 'Copy', + ariaCopyLink: 'Copy invite link', + helperLink: 'Send this link to your guests. They can paste it anywhere in Psysonic with Ctrl+V.', + labelClearQueue: 'Clear my queue first', + helperClearQueue: 'Start the session with a fresh, empty queue. Off: the tracks you already have queued stay and get shared with guests.', + btnCancel: 'Cancel', + btnStarting: 'Starting…', + btnStart: 'Start Orbit', + btnCopyAndStart: 'Copy link & start', + errNameRequired: 'Please give your session a name.', + errStartFailed: "Couldn't start.", + hostLabel: 'Host: {{name}}', + participantsTooltip: 'Participants', + settingsTooltip: 'Session settings', + shareTooltip: 'Share invite link', + shuffleLabel: 'Queue reshuffles in', + catchUpLabel: 'catch up', + catchUpTooltip: "Jump to the host's current position", + hostAway: 'Host offline', + hostOnline: 'Host online', + endTooltip: 'End session', + leaveTooltip: 'Leave session', + helpTooltip: 'How Orbit works', + diag: { + openTooltip: 'Diagnostics — copyable event log', + title: 'Orbit diagnostics', + role: 'Role', + hostTrack: 'Host track id', + hostPos: 'Host position', + guestTrack: 'My track id', + guestPos: 'My position', + drift: 'Drift', + stateAge: 'State age', + eventLog: 'Event log ({{count}})', + copyLabel: 'Copy', + copyTooltip: 'Copy log to clipboard', + clearLabel: 'Clear', + clearTooltip: 'Wipe the buffer', + empty: 'No events yet — events appear as Orbit syncs.', + hint: 'Open this before reproducing a problem, then click Copy and paste into the bug report.', + copied: 'Copied {{count}} event lines', + copyFailed: 'Could not copy to clipboard', + cleared: 'Buffer cleared', + }, + helpTitle: 'How Orbit works', + helpIntro: 'Orbit turns Psysonic into a shared listening room. A host picks the music; guests listen in sync and can suggest tracks.', + helpHostOnly: '(host)', + helpSec1Title: 'What is Orbit?', + helpSec1Body: "A \"listen together\" mode — the host drives playback, guests tune in. Everything runs through playlists on your own Navidrome server; no external infrastructure.", + helpSec2Title: 'Host and guests', + helpSec2Body: 'Host controls playback (play / pause / skip / seek) and decides when the session ends. Guests follow the host\'s playback, can suggest tracks, and leave or re-join any time. Only the host can kick or permanently ban a participant.', + helpSec2WarnHead: 'Important: separate accounts.', + helpSec2WarnBody: "Every participant needs their own Navidrome account. If host and guest sign in with the same user their submissions collide and the host never sees the guest's suggestions.", + helpSec3Title: 'Starting and inviting', + helpSec3Body: 'Click the "Orbit" button → Create a session → the start modal shows a ready-to-copy invite link and lets you optionally clear your current queue. Share that link however you like. While a session is running, the share button in the session bar at the top copies the link again at any time.', + helpSec4Title: 'Joining', + helpSec4Body: 'Paste the invite link anywhere in Psysonic with Ctrl+V / Cmd+V — the join prompt pops up automatically. Alternatively: "Orbit" → Join a session → paste into the field. If the link points to a server you have an account on, Psysonic switches for you. When you have more than one account on that server, a small picker asks which to use.', + helpSec5Title: 'Suggesting tracks', + helpSec5Body: 'In any song list: double-click a row, or right-click → "Add to Orbit session". A single click shows a hint instead of dumping the whole album into the shared queue — that\'s intentional. Explicit bulk actions like "Play All" or "Play Album" ask for confirmation first and then append (never replace).', + helpSec6Title: 'The shared queue', + helpSec6Body: "The queue shows the host's upcoming tracks — visible to everyone. Incoming bulk additions are always appended, so guest suggestions aren't lost. Auto-shuffle reorders the queue periodically (configurable: 1 / 5 / 10 / 15 / 30 min). If your playback drifts away from the host, the \"Catch up\" button in the session bar jumps you back to the host's live position.", + helpSec7Title: 'Approvals', + helpSec7Body: 'By default, guest suggestions need manual approval — they appear in an "Approvals" strip at the top of the queue panel with accept / decline buttons. Auto-approve can be turned on in the session settings so everything lands straight away.', + helpSec8Title: 'Participants and settings', + helpSec8Body: 'Open the settings icon in the session bar for shuffle cadence, auto-approve, and the "Shuffle now" shortcut. Click the participants count to see who\'s connected — kick (can re-join via the link) or ban (locked out for the session). Guests see the participant list too, but read-only.', + helpSec9Title: 'Ending the session', + helpSec9Body: "Host X → confirm dialog → session closes for everyone and the server playlists are cleaned up automatically. Guest X → the guest leaves, the session keeps running. If the host goes quiet for 5 minutes the guest auto-leaves with a notice; short reconnects within that window are invisible.", + participantsInviteLabel: 'Invite link', + participantsCountLabel: '{{count}} in session', + participantsHost: 'host', + participantsEmpty: 'No guests yet', + participantsKickTooltip: 'Remove from session', + participantsKickAria: 'Remove {{user}}', + participantsRemoveTooltip: 'Remove from session', + participantsRemoveAria: 'Remove {{user}} from this session', + participantsBanTooltip: 'Ban permanently', + participantsBanAria: 'Permanently ban {{user}}', + participantsMuteTooltip: 'Mute suggestions', + participantsUnmuteTooltip: 'Allow suggestions', + participantsMuteAria: 'Mute suggestions from {{user}}', + participantsUnmuteAria: 'Allow suggestions from {{user}}', + confirmRemoveTitle: 'Remove from session?', + confirmRemoveBody: '{{user}} will be dropped from the session, but can re-join via your invite link.', + confirmRemoveConfirm: 'Remove', + confirmBanTitle: 'Permanently ban?', + confirmBanBody: '{{user}} will be removed and blocked from re-joining this session. This can\'t be undone for the lifetime of the session.', + confirmBanConfirm: 'Ban', + confirmCancel: 'Cancel', + confirmJoinTitle: 'Join Orbit session?', + confirmJoinBody: '{{host}} invited you to "{{name}}". Join the session?', + confirmJoinConfirm: 'Join', + confirmLeaveTitle: 'Leave session?', + confirmLeaveBody: 'Leave "{{name}}"? You can re-join via {{host}}\'s invite link any time.', + confirmLeaveConfirm: 'Leave', + confirmEndTitle: 'End session for everyone?', + confirmEndBody: '"{{name}}" will close for all participants. The session\'s playlists are cleaned up automatically.', + confirmEndConfirm: 'End session', + invalidLinkTitle: 'Invite link is no longer valid', + invalidLinkBody: 'This Orbit session doesn\'t exist any more or has already ended. Ask the host for a fresh invite link.', + settingsTitle: 'Session settings', + settingAutoApprove: 'Auto-approve suggestions', + settingAutoApproveHint: "Guest suggestions land in your queue instantly. Off: they stay in the session list for you to review later.", + settingAutoShuffle: 'Automatic reshuffle', + settingAutoShuffleHint: "Periodic Fisher–Yates shuffle of the upcoming queue. Off: order only changes when you rearrange it.", + settingShuffleInterval: 'Reshuffle every', + settingShuffleIntervalHint: 'How often the upcoming queue gets reshuffled while the session runs.', + suggestBlockedMuted: 'The host muted you for this session — suggestions are off.', + settingShuffleIntervalValue_one: '{{count}} min', + settingShuffleIntervalValue_other: '{{count}} min', + settingShuffleNow: 'Shuffle now', + toastSuggested: '{{user}} suggested "{{title}}"', + toastSuggestedMany: '{{count}} new suggestions in the queue', + toastShuffled: 'Queue shuffled', + toastJoined: 'Joined session', + toastLoginFirst: 'Log in before joining a session', + toastSwitchServer: 'Switch to {{url}} first, then paste again', + toastNoAccountForServer: "You don't have access to {{url}}. Ask the host for an invite.", + toastSwitchFailed: "Couldn't switch to {{url}}", + accountPickerTitle: 'Which account?', + accountPickerSub: 'You have more than one account for {{url}}. Pick the one to join the session as.', + toastJoinFail: "Couldn't join session", + joinErrNotFound: 'Session not found', + joinErrEnded: 'Session has ended', + joinErrFull: 'Session is full', + joinErrKicked: "You can't rejoin this session", + joinErrNoUser: 'No active server', + joinErrServerError: "Couldn't join", + ctxAddToSession: 'Add to Orbit session', + ctxSuggestedToast: 'Suggested to the session', + ctxSuggestFailed: "Couldn't suggest — not joined", + ctxAddToSessionHost: 'Add to Orbit session', + ctxAddedHostToast: 'Added to the session', + ctxAddHostFailed: "Couldn't add to session", + bulkConfirmTitle: 'Add all of this to the Orbit queue?', + bulkConfirmBody: "This would drop {{count}} tracks into the shared queue in one go. That's a lot for your guests to notice. Go ahead?", + bulkConfirmYes: 'Add them all', + bulkConfirmNo: 'Cancel', + guestLive: 'Live', + guestPlaying: 'Playing now', + guestPaused: 'Paused', + guestLoading: 'Loading…', + guestSuggestions: 'Suggestions', + guestUpNext: 'Up next', + guestUpNextEmpty: 'Nothing queued. Open a track\'s context menu and pick "Add to Orbit session" to suggest one.', + guestPendingTitle: 'Waiting for host', + guestPendingHint: 'Suggested — will appear in the queue when the host picks it up.', + approvalTitle: 'Pending approvals', + approvalFrom: 'Suggested by {{user}}', + approvalAccept: 'Accept', + approvalDecline: 'Decline', + guestUpNextMore: '+ {{count}} more in the host\'s queue', + guestSubmitter: 'by {{user}}', + queueAddedByHost: 'Added by host', + queueAddedByYou: 'Added by you', + queueAddedByUser: 'Added by {{user}}', + guestEmpty: 'No suggestions yet. Open a track\'s context menu and pick "Add to Orbit session".', + guestFooter: "The host controls playback — you can't change the list.", + exitKickedTitle: 'You were banned from the session', + exitRemovedTitle: 'You were removed from the session', + exitEndedTitle: 'The host ended the session', + exitHostTimeoutTitle: 'Host went silent', + exitHostTimeoutBody: "{{host}} hasn't sent an update for a while, so \"{{name}}\" was closed on your end. You can re-join any time with the invite link.", + exitKickedBody: '{{host}} banned you from "{{name}}". You can\'t re-join.', + exitRemovedBody: '{{host}} removed you from "{{name}}". You can re-join any time via the invite link.', + exitEndedBody: '"{{name}}" has ended. Hope you had fun.', + exitOk: 'OK', +}; diff --git a/src/locales/en/player.ts b/src/locales/en/player.ts new file mode 100644 index 00000000..d92b5562 --- /dev/null +++ b/src/locales/en/player.ts @@ -0,0 +1,56 @@ +export const player = { + regionLabel: 'Music Player', + openFullscreen: 'Open Fullscreen Player', + fullscreen: 'Fullscreen Player', + closeFullscreen: 'Close Fullscreen', + closeTooltip: 'Close (Esc)', + noTitle: 'No Title', + stop: 'Stop', + prev: 'Previous Track', + play: 'Play', + pause: 'Pause', + previewActive: 'Preview playing', + previewLabel: 'Preview', + delayModalTitle: 'Timer', + delayPauseSection: 'Pause after', + delayStartSection: 'Start after', + delayPreviewPause: 'Pauses at', + delayPreviewStart: 'Starts at', + delaySchedulePause: 'Schedule pause', + delayScheduleStart: 'Schedule start', + delayCancelPause: 'Cancel pause timer', + delayCancelStart: 'Cancel start timer', + delayInactivePause: 'Available only while something is playing.', + delayInactiveStart: 'Available when paused with a track or radio loaded.', + delayCustomMinutes: 'Custom delay (minutes)', + delayCustomPlaceholder: 'e.g. 2.5', + closeDelayModal: 'Close', + delayIn: 'in', + delayFmtSec: '{{n}}s', + delayFmtMin: '{{n}} min', + delayFmtHr: '{{n}} h', + delayCancel: 'Cancel', + delayApply: 'Apply', + next: 'Next Track', + repeat: 'Repeat', + repeatOff: 'Off', + repeatAll: 'All', + repeatOne: 'One', + progress: 'Song Progress', + volume: 'Volume', + toggleQueue: 'Toggle Queue', + collapseQueueResize: 'Collapse queue, resize', + moreOptions: 'More options', + equalizer: 'Equalizer', + miniPlayer: 'Mini Player', + lyrics: 'Lyrics', + fsLyricsToggle: 'Lyrics in fullscreen', + lyricsLoading: 'Loading lyrics…', + lyricsNotFound: 'No lyrics found for this track', + lyricsSourceServer: 'Source: Server', + lyricsSourceLrclib: 'Source: LRCLIB', + lyricsSourceNetease: 'Source: Netease', + lyricsSourceLyricsplus: 'Source: YouLyPlus', + showDuration: 'Show duration', + showRemainingTime: 'Show remaining time', +}; diff --git a/src/locales/en/playlists.ts b/src/locales/en/playlists.ts new file mode 100644 index 00000000..272f0d14 --- /dev/null +++ b/src/locales/en/playlists.ts @@ -0,0 +1,101 @@ +export const playlists = { + title: 'Playlists', + newPlaylist: 'New Playlist', + unnamed: 'Unnamed Playlist', + createName: 'Playlist name…', + create: 'Create', + cancel: 'Cancel', + empty: 'No playlists yet.', + emptyPlaylist: 'This playlist is empty.', + addFirstSong: 'Add your first song', + notFound: 'Playlist not found.', + songs: '{{n}} songs', + playAll: 'Play All', + shuffle: 'Shuffle', + addToQueue: 'Add to Queue', + back: 'Back to Playlists', + deletePlaylist: 'Delete', + confirmDelete: 'Click again to confirm', + removeSong: 'Remove from playlist', + addSongs: 'Add Songs', + searchPlaceholder: 'Search your library…', + noResults: 'No results.', + suggestions: 'Suggested Songs', + noSuggestions: 'No suggestions available.', + titleBadge: 'Playlist', + refreshSuggestions: 'New suggestions', + addSong: 'Add to playlist', + preview: 'Preview (30s)', + previewStop: 'Stop preview', + playNextSuggestion: 'Play next', + suggestionsHint: 'Double-click a row to add it to the playlist', + addSelected: 'Add selected', + cacheOffline: 'Cache playlist offline', + offlineCached: 'Playlist cached', + removeOffline: 'Remove from offline cache', + offlineDownloading: 'Caching… ({{done}}/{{total}} albums)', + publicLabel: 'Public', + privateLabel: 'Private', + editMeta: 'Edit playlist', + editNamePlaceholder: 'Playlist name…', + editCommentPlaceholder: 'Add a description…', + editPublic: 'Public playlist', + editSave: 'Save', + editCancel: 'Cancel', + changeCover: 'Change cover image', + changeCoverLabel: 'Change photo', + removeCover: 'Remove photo', + coverUpdated: 'Cover updated', + metaSaved: 'Playlist updated', + downloadZip: 'Download (ZIP)', + // Toast notifications for multi-select + addSuccess: '{{count}} songs added to {{playlist}}', + addPartial: '{{added}} added, {{skipped}} skipped (duplicates)', + addAllSkipped: 'All skipped ({{count}} duplicates)', + addedAsDuplicates: '{{count}} songs added to {{playlist}} (as duplicates)', + duplicateConfirmTitle: 'Already in playlist', + duplicateConfirmMessage: 'All {{count}} songs are already in "{{playlist}}". Add them again as duplicates?', + duplicateConfirmAction: 'Add anyway', + addError: 'Error adding songs', + createAndAddSuccess: 'Playlist "{{playlist}}" created with {{count}} songs', + createError: 'Error creating playlist', + deleteSuccess: '{{count}} playlists deleted', + deleteFailed: 'Error deleting {{name}}', + deleteSelected: 'Delete selected', + deleteSelectedPartial: 'Only {{n}} of {{total}} selected playlists can be deleted (the others belong to someone else).', + mergeSuccess: '{{count}} songs merged into {{playlist}}', + mergeNoNewSongs: 'No new songs to add', + mergeError: 'Error merging playlists', + mergeInto: 'Merge into', + selectionCount: '{{count}} selected', + select: 'Select', + startSelect: 'Enable selection', + cancelSelect: 'Cancel', + loadingAlbums: 'Resolving {{count}} albums…', + loadingArtists: 'Resolving {{count}} artists…', + myPlaylists: 'My Playlists', + noOtherPlaylists: 'No other playlists available', + addToPlaylistSuccess: '{{count}} songs added to {{playlist}}', + addToPlaylistNoNew: 'No new songs to add to {{playlist}}', + addToPlaylistError: 'Error adding to playlist', + removeSuccess: 'Song removed from playlist', + removeError: 'Error removing song from playlist', + importCSV: 'Import CSV', + importCSVTooltip: 'Import from Spotify CSV', + csvImportReport: 'CSV Import Report', + csvImportTotal: 'Total', + csvImportAdded: 'Added', + csvImportDuplicates: 'Duplicates', + csvImportNotFound: 'Not Found', + csvImportNetworkErrors: 'Network Errors', + csvImportDuplicatesTitle: 'Duplicate Tracks (Already in Playlist):', + csvImportNotFoundTitle: 'Tracks Not Found:', + csvImportNetworkErrorsTitle: 'Network Errors (may retry import):', + csvImportDownloadReport: 'Download Report', + csvImportClose: 'Close', + csvImportNoValidTracks: 'No valid tracks found in CSV file', + csvImportFailed: 'Failed to import CSV file', + csvImportToast: '{{added}} added, {{notFound}} not found, {{duplicates}} duplicates', + csvImportDownloadSuccess: 'Report downloaded successfully', + csvImportDownloadError: 'Failed to download report', +}; diff --git a/src/locales/en/queue.ts b/src/locales/en/queue.ts new file mode 100644 index 00000000..7a4506a1 --- /dev/null +++ b/src/locales/en/queue.ts @@ -0,0 +1,45 @@ +export const queue = { + title: 'Queue', + savePlaylist: 'Save Playlist', + updatePlaylist: 'Update Playlist', + filterPlaylists: 'Filter playlists…', + playlistName: 'Playlist Name', + cancel: 'Cancel', + save: 'Save', + loadPlaylist: 'Load Playlist', + loading: 'Loading…', + noPlaylists: 'No playlists found.', + load: 'Replace queue & play', + appendToQueue: 'Append to queue', + delete: 'Delete', + deleteConfirm: 'Delete playlist "{{name}}"?', + clear: 'Clear', + shuffle: 'Shuffle queue', + gapless: 'Gapless', + crossfade: 'Crossfade', + infiniteQueue: 'Infinite Queue', + autoAdded: '— Added automatically —', + radioAdded: '— Radio —', + hide: 'Hide', + hideNowPlaying: 'Hide now playing info', + showNowPlaying: 'Show now playing info', + close: 'Close', + nextTracks: 'Next Tracks', + shareQueue: 'Copy queue share link', + shareQueueEmpty: 'The queue is empty — nothing to share.', + emptyQueue: 'The queue is empty.', + trackSingular: 'track', + trackPlural: 'tracks', + showRemaining: 'Show remaining time', + showTotal: 'Show total time', + showEta: 'Show estimated end time', + replayGain: 'ReplayGain', + rgTrack: 'T {{db}} dB', + rgAlbum: 'A {{db}} dB', + rgPeak: 'Peak {{pk}}', + sourceOffline: 'Playing from offline library', + sourceHot: 'Playing from cache', + sourceStream: 'Playing from network stream', + clearCachedLoudnessWaveform: 'Clear cached loudness and waveform, then re-analyze this track', + recalculatingLoudnessWaveform: 'Recalculating loudness and waveform for this track…', +}; diff --git a/src/locales/en/radio.ts b/src/locales/en/radio.ts new file mode 100644 index 00000000..20154aee --- /dev/null +++ b/src/locales/en/radio.ts @@ -0,0 +1,35 @@ +export const radio = { + title: 'Internet Radio', + empty: 'No radio stations configured.', + addStation: 'Add Station', + editStation: 'Edit', + deleteStation: 'Delete station', + confirmDelete: 'Click again to confirm', + stationName: 'Station name…', + streamUrl: 'Stream URL…', + homepageUrl: 'Homepage URL (optional)', + save: 'Save', + cancel: 'Cancel', + live: 'LIVE', + liveStream: 'Internet Radio', + openHomepage: 'Open homepage', + changeCoverLabel: 'Change cover', + removeCover: 'Remove cover', + browseDirectory: 'Search Directory', + directoryPlaceholder: 'Search stations…', + noResults: 'No stations found.', + stationAdded: 'Station added', + filterAll: 'All', + filterFavorites: 'Favorites', + sortManual: 'Manual', + sortAZ: 'A → Z', + sortZA: 'Z → A', + sortNewest: 'Newest', + favorite: 'Add to favorites', + unfavorite: 'Remove from favorites', + noFavorites: 'No favorite stations.', + listenerCount_one: '{{count}} listener', + listenerCount_other: '{{count}} listeners', + recentlyPlayed: 'Recently Played', + upNext: 'Up Next', +}; diff --git a/src/locales/en/randomAlbums.ts b/src/locales/en/randomAlbums.ts new file mode 100644 index 00000000..499f6771 --- /dev/null +++ b/src/locales/en/randomAlbums.ts @@ -0,0 +1,4 @@ +export const randomAlbums = { + title: 'Random Albums', + refresh: 'Refresh', +}; diff --git a/src/locales/en/randomLanding.ts b/src/locales/en/randomLanding.ts new file mode 100644 index 00000000..c5059e56 --- /dev/null +++ b/src/locales/en/randomLanding.ts @@ -0,0 +1,9 @@ +export const randomLanding = { + title: 'Build a Mix', + mixByTracks: 'Mix by Tracks', + mixByTracksDesc: 'Random selection of tracks from your entire library', + mixByAlbums: 'Mix by Albums', + mixByAlbumsDesc: 'Random album picks for your next discovery', + mixByLucky: 'Lucky Mix', + mixByLuckyDesc: 'Smart instant mix from your top artists, albums, and ratings', +}; diff --git a/src/locales/en/randomMix.ts b/src/locales/en/randomMix.ts new file mode 100644 index 00000000..8b0d7d9c --- /dev/null +++ b/src/locales/en/randomMix.ts @@ -0,0 +1,39 @@ +export const randomMix = { + title: 'Random Mix', + remix: 'Remix', + remixTooltip: 'Load new random songs', + remixGenre: 'Remix {{genre}}', + remixTooltipGenre: 'Load new {{genre}} songs', + playAll: 'Play All', + trackTitle: 'Title', + trackArtist: 'Artist', + trackAlbum: 'Album', + trackFavorite: 'Favorite', + trackDuration: 'Duration', + favoriteAdd: 'Add to Favorites', + favoriteRemove: 'Remove from Favorites', + play: 'Play', + trackGenre: 'Genre', + mixSettingsHeader: 'Mix Settings', + exclusionsHeader: 'Exclusions', + filterPanelInexactSizeNote: 'Mix size is a target — large requests may return fewer unique tracks if the server\'s random pool runs short.', + mixSize: 'Playlist size', + excludeAudiobooks: 'Exclude audiobooks & radio plays', + excludeAudiobooksDesc: 'Matches keywords against genre, title, album, and artist — e.g. Hörbuch, Audiobook, Spoken Word, …', + genreBlocked: 'Keyword blocked', + genreAddedToBlacklist: 'Added to filter list', + genreAlreadyBlocked: 'Already blocked', + artistBlocked: 'Artist blocked', + artistAddedToBlacklist: 'Artist added to filter list', + artistClickHint: 'Click to block this artist', + blacklistToggle: 'Keyword Filter', + genreMixTitle: 'Genre Mix', + genreMixDesc: 'Top 20 genres by song count — click to load a random mix', + genreMixAll: 'All Songs', + genreMixLoadMore: 'Load 10 more', + genreMixNoGenres: 'No genres found on server.', + shuffleGenres: 'Show different genres', + filterPanelTitle: 'Filters', + filterPanelDesc: 'Click a genre tag or artist name in the tracklist below to block it from future mixes.', + genreClickHint: 'Click a genre tag to add it\nas a filter keyword.\nMatches genre, title, album & artist.', +}; diff --git a/src/locales/en/search.ts b/src/locales/en/search.ts new file mode 100644 index 00000000..0825776c --- /dev/null +++ b/src/locales/en/search.ts @@ -0,0 +1,29 @@ +export const search = { + placeholder: 'Search for artist, album or song…', + noResults: 'No results for "{{query}}"', + artists: 'Artists', + albums: 'Albums', + songs: 'Songs', + clearLabel: 'Clear search', + addedToQueueToast: 'Added "{{title}}" to queue', + title: 'Search', + resultsFor: 'Results for "{{query}}"', + album: 'Album', + advanced: 'Advanced Search', + advancedSearchTerm: 'Search term', + advancedSearchPlaceholder: 'Title, album, artist…', + advancedGenre: 'Genre', + advancedAllGenres: 'All genres', + advancedYear: 'Year', + advancedYearFrom: 'from', + advancedYearTo: 'to', + advancedAll: 'All', + advancedSearch: 'Search', + advancedEmpty: 'Enter a search term or select a filter to begin.', + advancedNoResults: 'No results found.', + advancedGenreNote: 'Songs are randomly selected from this genre.', + recentSearches: 'Recent Searches', + browse: 'Browse', + emptyHint: 'What do you want to hear?', + genres: 'Genres', +}; diff --git a/src/locales/en/settings.ts b/src/locales/en/settings.ts new file mode 100644 index 00000000..2dd1fac4 --- /dev/null +++ b/src/locales/en/settings.ts @@ -0,0 +1,445 @@ +export const settings = { + title: 'Settings', + language: 'Language', + languageEn: 'English', + languageDe: 'Deutsch', + languageEs: 'Español', + languageFr: 'Français', + languageNl: 'Nederlands', + languageNb: 'Norsk', + languageRu: 'Русский', + languageZh: '中文', + languageRo: 'Română', + font: 'Font', + fontHintOpenDyslexic: 'Dyslexia-friendly · no Chinese support', + theme: 'Theme', + appearance: 'Appearance', + servers: 'Servers', + serverName: 'Server Name', + serverUrl: 'Server URL', + serverUrlPlaceholder: '192.168.1.100:4533 or https://music.example.com', + serverUsername: 'Username', + serverPassword: 'Password', + addServer: 'Add Server', + addServerTitle: 'Add New Server', + useServer: 'Use', + deleteServer: 'Delete', + noServers: 'No servers saved.', + serverActive: 'Active', + confirmDeleteServer: 'Delete server "{{name}}"?', + serverConnecting: 'Connecting…', + serverConnected: 'Connected!', + serverFailed: 'Connection failed.', + testBtn: 'Test Connection', + testingBtn: 'Testing…', + serverCompatible: 'Built for Navidrome. Other Subsonic-compatible servers (Gonic, Airsonic, …) may work with reduced functionality, since Psysonic uses many Navidrome-specific API endpoints.', + userMgmtTitle: 'User Management', + userMgmtDesc: 'Manage users on this server. Requires admin privileges.', + userMgmtNoAdmin: 'You need admin privileges to manage users on this server.', + userMgmtLoadError: 'Failed to load users.', + userMgmtLoadFriendly: 'Server didn\'t answer — this is usually a one-off.', + userMgmtRetry: 'Retry', + userMgmtEmpty: 'No users found.', + userMgmtYouBadge: 'You', + userMgmtAdminBadge: 'Admin', + userMgmtAddUser: 'Add User', + userMgmtAddUserTitle: 'Add New User', + userMgmtEditUserTitle: 'Edit User', + userMgmtUsername: 'Username', + userMgmtName: 'Display Name', + userMgmtEmail: 'Email', + userMgmtPassword: 'Password', + userMgmtPasswordEditHint: 'Enter a new password to update it.', + userMgmtRoleAdmin: 'Admin', + userMgmtLibraries: 'Libraries', + userMgmtLibrariesAdminHint: 'Admin users automatically have access to all libraries.', + userMgmtLibrariesEmpty: 'No libraries available on this server.', + userMgmtLibrariesValidation: 'Select at least one library.', + userMgmtLibrariesUpdateError: 'User saved, but library assignment failed', + userMgmtNoLibraries: 'No libraries assigned', + userMgmtNeverSeen: 'Never', + userMgmtSave: 'Save', + userMgmtCancel: 'Cancel', + userMgmtDelete: 'Delete', + userMgmtEdit: 'Edit', + userMgmtConfirmDelete: 'Delete user "{{username}}"? This cannot be undone.', + userMgmtCreateError: 'Failed to create user.', + userMgmtUpdateError: 'Failed to update user.', + userMgmtDeleteError: 'Failed to delete user.', + userMgmtCreated: 'User created.', + userMgmtUpdated: 'User updated.', + userMgmtDeleted: 'User deleted.', + userMgmtValidationMissing: 'Username, display name and password are required.', + userMgmtValidationMissingIdentity: 'Username and display name are required.', + userMgmtMagicStringGenerate: 'Generate magic string', + userMgmtSaveAndMagicString: 'Save and get magic string', + userMgmtMagicStringPasswordNavHint: + 'Navidrome will save this password for the user. If it differs from the current one, the server will update the login password.', + userMgmtMagicStringPlaintextWarning: + 'Share the magic string carefully: it contains an unencrypted password (encoding is not encryption). Anyone with the full string can sign in as this user.', + userMgmtMagicStringCopied: 'Magic string copied to clipboard.', + userMgmtMagicStringCopyFailed: 'Could not copy to clipboard.', + userMgmtMagicStringLoginFailed: 'Password check failed — credentials could not be verified.', + userMgmtMagicStringModalTitle: 'Generate magic string', + userMgmtMagicStringModalDesc: 'Enter the Subsonic password for "{{username}}". It is included in the copied magic string.', + userMgmtMagicStringModalConfirm: 'Copy string', + audiomuseTitle: 'AudioMuse-AI (Navidrome)', + audiomuseDesc: + 'Turn on if this server has the AudioMuse-AI Navidrome plugin configured. Enables Instant Mix from tracks and uses server-side similar artists instead of Last.fm on artist pages.', + audiomuseIssueHint: + 'Instant Mix failed recently — check the Navidrome plugin and AudioMuse API. Similar artists fall back to Last.fm when the server returns none.', + connected: 'Connected', + failed: 'Failed', + eqTitle: 'Equalizer', + eqEnabled: 'Enable Equalizer', + eqPreset: 'Preset', + eqPresetCustom: 'Custom', + eqPresetBuiltin: 'Built-in Presets', + eqPresetCustomGroup: 'My Presets', + eqSavePreset: 'Save as Preset', + eqPresetName: 'Preset name…', + eqDeletePreset: 'Delete preset', + eqResetBands: 'Reset to Flat', + eqPreGain: 'Pre-gain', + eqResetPreGain: 'Reset pre-gain', + eqAutoEqTitle: 'AutoEQ Headphone Lookup', + eqAutoEqPlaceholder: 'Search headphone / IEM model…', + eqAutoEqSearching: 'Searching…', + eqAutoEqNoResults: 'No results found', + eqAutoEqError: 'Search failed', + eqAutoEqRateLimit: 'GitHub rate limit reached — try again in a minute', + eqAutoEqFetchError: 'Failed to fetch EQ profile', + lfmTitle: 'Last.fm', + lfmConnect: 'Connect with Last.fm', + lfmConnecting: 'Waiting for authorisation…', + lfmConfirm: 'I have authorised the app', + lfmConnected: 'Connected as', + lfmDisconnect: 'Disconnect', + lfmConnectDesc: 'Connect your Last.fm account to enable scrobbling and Now Playing updates directly from Psysonic — no Navidrome configuration required.', + lfmOpenBrowser: 'A browser window will open. Authorise Psysonic on Last.fm, then click the button below.', + lfmScrobbles: '{{n}} scrobbles', + lfmMemberSince: 'Member since {{year}}', + scrobbleEnabled: 'Scrobbling enabled', + scrobbleDesc: 'Send songs to Last.fm after 50% playtime', + behavior: 'App Behavior', + cacheTitle: 'Max. Storage Size', + cacheDesc: 'Cover art and artist images. When full, the oldest entries are removed automatically. Offline albums are not auto-removed, but will be deleted when clearing the cache manually.', + cacheUsedImages: 'Images:', + cacheUsedOffline: 'Offline tracks:', + cacheUsedHot: 'Size on disk:', + hotCacheTrackCount: 'Tracks in cache:', + cacheMaxLabel: 'Max. size', + cacheClearBtn: 'Clear Cache', + waveformCacheClearBtn: 'Clear waveform cache', + cacheClearWarning: 'This will also remove all offline albums from the library.', + cacheClearConfirm: 'Clear Everything', + cacheClearCancel: 'Cancel', + waveformCacheCleared: 'Waveform cache cleared ({{count}} rows).', + waveformCacheClearFailed: 'Failed to clear waveform cache.', + offlineDirTitle: 'Offline Library (In-App)', + offlineDirDesc: 'Storage location for tracks you make available offline within Psysonic.', + offlineDirDefault: 'Default (App Data)', + offlineDirChange: 'Change Directory', + offlineDirClear: 'Reset to Default', + offlineDirHint: 'New downloads will use this location. Existing downloads remain at their original path.', + hotCacheTitle: 'Hot playback cache', + hotCacheDisclaimer: 'Preloads upcoming queue tracks and keeps previous ones. When enabled, uses disk space and network.', + hotCacheDirDefault: 'Default (App Data)', + hotCacheDirChange: 'Change folder', + hotCacheDirClear: 'Reset to default', + hotCacheDirHint: 'Changing the folder resets the in-app index; files already on disk stay where they are until you remove them.', + hotCacheEnabled: 'Enable hot playback cache', + hotCacheMaxMb: 'Maximum cache size', + hotCacheDebounce: 'Queue change debounce', + hotCacheDebounceImmediate: 'Immediate', + hotCacheDebounceSeconds: '{{n}} s', + hotCacheClearBtn: 'Clear hot cache', + audioOutputDevice: 'Audio Output Device', + audioOutputDeviceDesc: 'Select which audio device Psysonic plays through. Changes take effect immediately and restart the current track.', + audioOutputDeviceDefault: 'System Default', + audioOutputDeviceRefresh: 'Refresh device list', + audioOutputDeviceOsDefaultNow: 'current system output', + audioOutputDeviceListError: 'Could not load the audio device list.', + audioOutputDeviceNotInCurrentList: 'not in current list', + audioOutputDeviceMacNotice: 'On macOS, playback currently always follows the system output device for technical reasons. Change the target via System Settings → Sound or the speaker icon in the menu bar. Background: CoreAudio triggers a microphone-permission prompt when opening a non-default stream — we avoid it by always using the system default.', + hiResTitle: 'Native Hi-Res Playback', + hiResEnabled: 'Enable native hi-res playback', + hiResDesc: "Forces 44.1 kHz output by default for maximum stability. Enable only if your hardware and network reliably support high sample rates (88.2 kHz+).", + showArtistImages: 'Show Artist Images', + showArtistImagesDesc: 'Load and display artist images in the Artists overview. Disabled by default to reduce server disk I/O and network load on large libraries.', + showOrbitTrigger: 'Show "Orbit" in the header', + showOrbitTriggerDesc: 'The top-bar trigger for starting or joining a shared listening session. Hide it if you don\'t use Orbit — you can turn it back on here.', + showTrayIcon: 'Show Tray Icon', + showTrayIconDesc: 'Display the Psysonic icon in the system notification area / menu bar.', + minimizeToTray: 'Minimize to Tray', + minimizeToTrayDesc: 'When closing the window, keep Psysonic running in the system tray instead of quitting.', + preloadMiniPlayer: 'Preload mini player', + preloadMiniPlayerDesc: 'Build the mini player window in the background at app start so it shows content instantly on first open. Uses a little extra memory.', + discordRichPresence: 'Discord Rich Presence', + discordRichPresenceDesc: 'Show the currently playing track on your Discord profile. Requires Discord to be running.', + useCustomTitlebar: 'Custom title bar', + useCustomTitlebarDesc: 'Replace the system title bar with a built-in one that matches the app theme. Disable to use the native GNOME/GTK title bar.', + linuxWebkitSmoothScroll: 'Smooth wheel (Linux)', + linuxWebkitSmoothScrollDesc: 'On: inertial scroll. Off: line-by-line, GTK-style.', + discordCoverSource: 'Cover art source', + discordCoverSourceDesc: 'Where to fetch album artwork shown on your Discord profile.', + discordCoverNone: 'None (app icon only)', + discordCoverServer: 'Server (via album info)', + discordCoverApple: 'Apple Music', + discordOptions: 'Advanced Discord options', + discordTemplates: 'Custom text templates', + discordTemplatesDesc: 'Customize what information is shown on your Discord profile. Variables: {title}, {artist}, {album}', + discordTemplateDetails: 'Primary line (details)', + discordTemplateState: 'Secondary line (state)', + discordTemplateLargeText: 'Album tooltip (largeText)', + nowPlayingEnabled: 'Show in Now Playing', + nowPlayingEnabledDesc: 'Broadcast your currently playing track to the server\'s live listener view. Disable to stop sending playback data.', + enableBandsintown: 'Bandsintown tour dates', + enableBandsintownDesc: 'Show upcoming concerts for the current artist in the Info tab. Data is fetched from the public Bandsintown API.', + lyricsServerFirst: 'Prefer server lyrics', + lyricsServerFirstDesc: 'Check server-provided lyrics (embedded tags, sidecar files) before querying LRCLIB. Disable to use LRCLIB first.', + enableNeteaselyrics: 'Netease Cloud Music lyrics', + enableNeteaselyricsDesc: 'Use Netease Cloud Music as a last-resort lyrics source when server and LRCLIB both return nothing. Best coverage for Asian and international music.', + lyricsSourcesTitle: 'Lyrics Sources', + lyricsSourcesDesc: 'Choose which sources to query for lyrics and in what order. Drag to reorder. Disabled sources are skipped entirely.', + lyricsSourceServer: 'Server', + lyricsSourceLrclib: 'LRCLIB', + lyricsSourceNetease: 'Netease Cloud Music', + lyricsModeStandard: 'Standard', + lyricsModeStandardDesc: 'Three sources in a freely orderable list: server tags, LRCLIB, Netease.', + lyricsModeLyricsplus: 'YouLyPlus (Karaoke)', + lyricsModeLyricsplusDesc: 'Word-by-word sync sourced from Apple Music, Spotify, Musixmatch & QQ (community backend). Silently falls back to the standard sources when nothing is found.', + lyricsStaticOnly: 'Show lyrics as static text only', + lyricsStaticOnlyDesc: 'Render synced lyrics without auto-scroll and without word highlighting.', + downloadsTitle: 'ZIP Export & Archiving', + downloadsFolderDesc: 'Destination folder for albums you download as a ZIP file to your computer.', + downloadsDefault: 'Default Downloads Folder', + pickFolder: 'Select', + pickFolderTitle: 'Select Download Folder', + clearFolder: 'Clear download folder', + logout: 'Logout', + aboutTitle: 'About Psysonic', + aboutDesc: 'A modern desktop music player built for Navidrome. Uses the Subsonic API plus Navidrome-specific extensions. Built on Tauri v2 with a native Rust audio engine — lightweight and fast, yet packed with features: waveform seekbar, synchronized lyrics, Last.fm integration, 10-band EQ, crossfade, gapless playback, Replay Gain, genre browsing, and a large library of themes.', + aboutLicense: 'License', + aboutLicenseText: 'GNU GPL v3 — free to use, modify, and distribute under the same license.', + aboutRepo: 'Source Code on GitHub', + aboutVersion: 'Version', + aboutBuiltWith: 'Built with Tauri · React · TypeScript · Rust/rodio', + aboutMaintainersLabel: 'Maintainers', + aboutReleaseNotesLabel: 'Release notes', + aboutReleaseNotesLink: "Open this version's what's-new", + aboutContributorsLabel: 'Contributors', + showChangelogOnUpdate: "Show 'What's New' on update", + showChangelogOnUpdateDesc: "Show a discreet changelog banner above Now Playing after an update. Click opens the release notes; X dismisses it.", + randomMixTitle: 'Random Mix Blacklist', + luckyMixMenuTitle: 'Show Lucky Mix in menu', + luckyMixMenuDesc: 'Enables Lucky Mix in Build a Mix and as a separate menu item when split navigation is on. Visible only when AudioMuse is enabled on the active server.', + randomMixBlacklistTitle: 'Custom Filter Keywords', + randomMixBlacklistDesc: 'Songs are excluded when any keyword matches their genre, title, album, or artist (active when the checkbox above is on).', + randomMixBlacklistPlaceholder: 'Add keyword…', + randomMixBlacklistAdd: 'Add', + randomMixBlacklistEmpty: 'No custom keywords added yet.', + randomMixHardcodedTitle: 'Built-in keywords (active when checkbox is on)', + tabAudio: 'Audio', + tabStorage: 'Offline & Cache', + tabAppearance: 'Appearance', + tabLibrary: 'Library', + tabServers: 'Servers', + tabLyrics: 'Lyrics', + tabPersonalisation: 'Personalisation', + tabIntegrations: 'Integrations', + inputKeybindingsTitle: 'Keyboard shortcuts', + aboutContributorsCount_one: '{{count}} contribution', + aboutContributorsCount_other: '{{count}} contributions', + searchPlaceholder: 'Search settings…', + searchNoResults: 'No settings match your search.', + integrationsPrivacyTitle: 'Privacy notice', + integrationsPrivacyBody: 'All integrations on this tab are opt-in and send data to external services or to your Navidrome server when enabled. Last.fm receives your listening history, Discord shows the currently playing track in your profile, Bandsintown is queried per artist to fetch tour dates, and the Now-Playing share publishes your current track to other users of your Navidrome server. If you don\'t want any of this, simply leave the corresponding section disabled.', + homeCustomizerTitle: 'Home Page', + queueToolbarTitle: 'Queue Toolbar', + queueToolbarReset: 'Reset to default', + queueToolbarSeparator: 'Separator', + sidebarTitle: 'Sidebar', + sidebarReset: 'Reset to default', + artistLayoutTitle: 'Artist page sections', + artistLayoutDesc: 'Drag to reorder, toggle to hide individual sections of the artist page. Sections without data are skipped automatically.', + artistLayoutReset: 'Reset to default', + artistLayoutBio: 'Artist biography', + artistLayoutTopTracks: 'Top tracks', + artistLayoutSimilar: 'Similar artists', + artistLayoutAlbums: 'Albums', + artistLayoutFeatured: 'Also featured on', + sidebarDrag: 'Drag to reorder', + sidebarFixed: 'Always visible', + randomNavSplitTitle: 'Split Mix navigation', + randomNavSplitDesc: 'Show "Random Mix", "Random Albums", and "Lucky Mix" as separate sidebar entries instead of the "Build a Mix" hub.', + tabInput: 'Input', + tabUsers: 'Users', + tabSystem: 'System', + loggingTitle: 'Logging', + loggingModeDesc: 'Controls backend log verbosity in the terminal.', + loggingModeOff: 'Off', + loggingModeNormal: 'Normal', + loggingModeDebug: 'Debug', + loggingExport: 'Export logs', + loggingExportSuccess: 'Logs exported ({{count}} lines).', + loggingExportError: 'Could not export logs.', + ratingsSectionTitle: 'Ratings', + ratingsSkipStarTitle: 'Skip for 1 star', + ratingsSkipStarDesc: + 'After several skips in a row, set the track to 1★. Only for tracks not yet rated.', + ratingsSkipStarThresholdLabel: 'Skips', + ratingsMixFilterTitle: 'Filter by rating', + ratingsMixFilterDesc: + 'Filter low-rated items in {{mix}} and {{albums}}. Click the selected star again to turn off the threshold.', + ratingsMixMinSong: 'Songs', + ratingsMixMinAlbum: 'Albums', + ratingsMixMinArtist: 'Artists', + ratingsMixMinThresholdAria: 'Minimum stars: {{label}}', + backupTitle: 'Backup & Restore', + backupExport: 'Export settings', + backupExportDesc: 'Saves all settings, server profiles, Last.fm config, theme, EQ and keybindings to a .psybkp file. Passwords are stored in plaintext — keep the file secure.', + backupImport: 'Import settings', + backupImportDesc: 'Restores settings from a .psybkp file. The app will reload after import.', + backupImportConfirm: 'This will overwrite all current settings. Continue?', + backupSuccess: 'Backup saved', + backupImportSuccess: 'Settings restored — reloading…', + backupImportError: 'Invalid or corrupted backup file.', + shortcutsReset: 'Reset to defaults', + shortcutListening: 'Press a key…', + shortcutUnbound: '—', + globalShortcutsTitle: 'Global Shortcuts', + globalShortcutsNote: 'Work system-wide even when Psysonic is in the background. Requires Ctrl, Alt, or Super as a modifier.', + shortcutClear: 'Clear', + shortcutPlayPause: 'Play / Pause', + shortcutNext: 'Next track', + shortcutPrev: 'Previous track', + shortcutVolumeUp: 'Volume up', + shortcutVolumeDown: 'Volume down', + shortcutSeekForward: 'Seek forward 10s', + shortcutSeekBackward: 'Seek backward 10s', + shortcutToggleQueue: 'Toggle queue', + shortcutOpenFolderBrowser: 'Open {{folderBrowser}}', + shortcutFullscreenPlayer: 'Fullscreen player', + shortcutNativeFullscreen: 'Native fullscreen', + shortcutOpenMiniPlayer: 'Open mini player', + shortcutStartSearch: 'Start a search', + shortcutStartAdvancedSearch: 'Start an advanced search', + shortcutToggleSidebar: 'Toggle Sidebar', + shortcutMuteSound: 'Mute sound', + shortcutToggleEqualizer: 'Open / Toggle Equalizer', + shortcutToggleRepeat: 'Toggle Repeat', + shortcutOpenNowPlaying: 'Open "Now Playing"', + shortcutShowLyrics: 'Show Lyrics', + shortcutFavoriteCurrentTrack: 'Add current track to favorites', + shortcutOpenHelp: 'Help', + playbackTitle: 'Playback', + replayGain: 'Replay Gain', + replayGainDesc: 'Normalize track volume using ReplayGain metadata', + replayGainMode: 'Mode', + replayGainAuto: 'Auto', + replayGainAutoDesc: 'Picks album gain when neighbouring queue tracks are from the same album, otherwise track gain.', + replayGainTrack: 'Track', + replayGainAlbum: 'Album', + replayGainPreGain: 'Pre-Gain (tagged files)', + replayGainPreGainDesc: 'Universal boost added on top of every ReplayGain calculation. Use to compensate if your library feels too quiet overall.', + replayGainFallback: 'Fallback (untagged / radio)', + replayGainFallbackDesc: 'Applied to tracks (and radio streams) that have no ReplayGain tags at all, so untagged content does not pop louder than the rest.', + normalization: 'Normalization', + normalizationDesc: 'Even out perceived loudness across tracks, albums and radio.', + normalizationOff: 'Off', + normalizationReplayGain: 'ReplayGain', + normalizationLufs: 'LUFS', + loudnessTargetLufs: 'Target LUFS', + loudnessTargetLufsDesc: 'Reference loudness all tracks are matched to. Lower numbers = louder output. Streaming services typically sit around -14 LUFS.', + loudnessPreAnalysisAttenuation: 'Pre-analysis attenuation', + loudnessPreAnalysisAttenuationDesc: + 'Extra quieting until loudness for this track is saved. Streaming then uses rough guesses, not a full measurement. 0 dB = off; lower = quieter. The number on the right is the effective dB for your current target.', + loudnessPreAnalysisAttenuationRef: 'Effective {{eff}} dB with target {{tgt}} LUFS.', + loudnessPreAnalysisAttenuationReset: 'Reset to default', + loudnessFirstPlayNote: + 'First play of a brand-new track may briefly drift in volume while it is being measured. The next play uses the cached measurement and is rock-solid. Upcoming queue tracks are usually pre-analysed during the previous song, so this rarely happens in practice.', + crossfade: 'Crossfade', + crossfadeDesc: 'Fade between tracks', + crossfadeSecs: '{{n}} s', + notWithGapless: 'Not available while Gapless is active', + notWithCrossfade: 'Not available while Crossfade is active', + gapless: 'Gapless Playback', + gaplessDesc: 'Pre-buffer next track to eliminate gaps between songs', + preservePlayNextOrder: 'Preserve "Play Next" order', + preservePlayNextOrderDesc: 'Newly added Play Next items queue up behind earlier ones instead of jumping in front.', + trackPreviewsTitle: 'Track Previews', + trackPreviewsToggle: 'Enable track previews', + trackPreviewsDesc: 'Show inline Play and Preview buttons in tracklists for a quick mid-song sample.', + trackPreviewStart: 'Start position', + trackPreviewStartDesc: 'How far into the track the preview starts (% of track length).', + trackPreviewDuration: 'Duration', + trackPreviewDurationDesc: 'How long each preview plays before it stops.', + trackPreviewDurationSecs: '{{n}} s', + trackPreviewLocationsTitle: 'Where previews appear', + trackPreviewLocationsDesc: 'Pick which lists show inline preview buttons.', + trackPreviewLocation_suggestions: 'In playlist suggestions', + trackPreviewLocation_albums: 'In album tracklists', + trackPreviewLocation_playlists: 'In playlists', + trackPreviewLocation_favorites: 'In favorites', + trackPreviewLocation_artist: 'In artist top tracks', + trackPreviewLocation_randomMix: 'In Random Mix', + preloadMode: 'Preload Next Track', + preloadModeDesc: 'When to start buffering the next track in the queue', + nextTrackBufferingTitle: 'Buffering', + preloadHotCacheMutualExclusive: 'Preload and Hot Cache serve the same purpose — only one can be active at a time. Enabling one will automatically disable the other.', + preloadOff: 'Off', + preloadBalanced: 'Balanced (30 s before end)', + preloadEarly: 'Early (after 5 s of playback)', + preloadCustom: 'Custom', + preloadCustomSeconds: 'Seconds before end: {{n}}', + infiniteQueue: 'Infinite Queue', + infiniteQueueDesc: 'Automatically append random tracks when the queue runs out', + experimental: 'Experimental', + fsPlayerSection: 'Fullscreen Player', + fsLyricsStyle: 'Lyrics style', + fsLyricsStyleRail: 'Rail', + fsLyricsStyleRailDesc: 'Classic 5-line sliding rail.', + fsLyricsStyleApple: 'Scrolling', + fsLyricsStyleAppleDesc: 'Full-screen scrollable list.', + sidebarLyricsStyle: 'Lyrics scroll style', + sidebarLyricsStyleClassic: 'Classic', + sidebarLyricsStyleClassicDesc: 'Scroll active line to center.', + sidebarLyricsStyleApple: 'Apple Music-like', + sidebarLyricsStyleAppleDesc: 'Active line anchors near the top with smooth spring transitions.', + fsShowArtistPortrait: 'Show artist photo', + fsShowArtistPortraitDesc: 'Display the artist photo (or album art) on the right side of the fullscreen player.', + fsPortraitDim: 'Photo dimming', + seekbarStyle: 'Seekbar Style', + seekbarStyleDesc: 'Choose the look of the player seek bar', + seekbarTruewave: 'Truewave', + seekbarPseudowave: 'Pseudowave', + seekbarLinedot: 'Line & Dot', + seekbarBar: 'Bar', + seekbarThick: 'Thick Bar', + seekbarSegmented: 'Segmented', + seekbarNeon: 'Neon Glow', + seekbarPulsewave: 'Pulse Wave', + seekbarParticletrail: 'Particle Trail', + seekbarLiquidfill: 'Liquid Fill', + seekbarRetrotape: 'Retro Tape', + themeSchedulerTitle: 'Auto-Switch Theme', + themeSchedulerEnable: 'Enable Theme Scheduler', + themeSchedulerEnableSub: 'Automatically switch between two themes based on the time of day', + themeSchedulerDayTheme: 'Day Theme', + themeSchedulerDayStart: 'Day Starts At', + themeSchedulerNightTheme: 'Night Theme', + themeSchedulerNightStart: 'Night Starts At', + themeSchedulerActiveHint: 'Theme Scheduler is active - theme changes are managed automatically.', + visualOptionsTitle: 'Visual Options', + coverArtBackground: 'Cover Art Background', + coverArtBackgroundSub: 'Show blurred cover art as background in album/playlist headers', + playlistCoverPhoto: 'Playlist Cover Photo', + playlistCoverPhotoSub: 'Show cover photo grid in playlist detail view', + showBitrate: 'Show Bitrate', + showBitrateSub: 'Display audio bitrate in track listings', + floatingPlayerBar: 'Floating Player Bar', + floatingPlayerBarSub: 'Keep the player bar floating above content', + uiScaleTitle: 'Interface Scale', + uiScaleLabel: 'Zoom', +}; diff --git a/src/locales/en/sharePaste.ts b/src/locales/en/sharePaste.ts new file mode 100644 index 00000000..35becca2 --- /dev/null +++ b/src/locales/en/sharePaste.ts @@ -0,0 +1,18 @@ +export const sharePaste = { + notLoggedIn: 'Sign in and add the server before pasting a share link.', + noMatchingServer: 'No saved server matches this link. Add a server with this address: {{url}}', + trackUnavailable: 'This track was not found on the server.', + albumUnavailable: 'This album was not found on the server.', + artistUnavailable: 'This artist was not found on the server.', + composerUnavailable: 'This composer was not found on the server.', + openedTrack: 'Playing shared track.', + openedAlbum: 'Opening shared album.', + openedArtist: 'Opening shared artist.', + openedComposer: 'Opening shared composer.', + openedQueue_one: 'Playing {{count}} track from the share link.', + openedQueue_other: 'Playing {{count}} tracks from the share link.', + openedQueuePartial: + 'Playing {{played}} of {{total}} tracks from the link ({{skipped}} not found on this server).', + queueAllUnavailable: 'None of the tracks from this link were found on the server.', + genericError: 'Could not open the share link.', +}; diff --git a/src/locales/en/sidebar.ts b/src/locales/en/sidebar.ts new file mode 100644 index 00000000..1e1ac18d --- /dev/null +++ b/src/locales/en/sidebar.ts @@ -0,0 +1,39 @@ +export const sidebar = { + library: 'Library', + mainstage: 'Mainstage', + newReleases: 'New Releases', + allAlbums: 'All Albums', + randomAlbums: 'Random Albums', + randomPicker: 'Build a Mix', + artists: 'Artists', + composers: 'Composers', + randomMix: 'Random Mix', + favorites: 'Favorites', + nowPlaying: 'Now Playing', + system: 'System', + statistics: 'Statistics', + settings: 'Settings', + help: 'Help', + expand: 'Expand Sidebar', + collapse: 'Collapse Sidebar', + + downloadingTracks: 'Caching {{n}} tracks…', + syncingTracks: 'Syncing {{done}}/{{total}}…', + cancelDownload: 'Cancel download', + offlineLibrary: 'Offline Library', + genres: 'Genres', + tracks: 'Tracks', + playlists: 'Playlists', + smartPlaylists: 'Smart Playlists', + mostPlayed: 'Most Played', + losslessAlbums: 'Lossless', + radio: 'Internet Radio', + folderBrowser: 'Folder Browser', + deviceSync: 'Device Sync', + libraryScope: 'Library scope', + allLibraries: 'All libraries', + expandPlaylists: 'Expand playlists', + collapsePlaylists: 'Collapse playlists', + more: 'More', + feelingLucky: 'Lucky Mix', +}; diff --git a/src/locales/en/smartPlaylists.ts b/src/locales/en/smartPlaylists.ts new file mode 100644 index 00000000..285e4c44 --- /dev/null +++ b/src/locales/en/smartPlaylists.ts @@ -0,0 +1,41 @@ +export const smartPlaylists = { + sectionBasic: '1. Basic', + sectionGenres: '2. Genres', + sectionYearsAndFilters: '3. Years and filters', + genreMode: 'Genre mode', + genreModeInclude: 'Include genres', + genreModeExclude: 'Exclude genres', + genreSearchPlaceholder: 'Filter genres...', + availableGenres: 'Available', + selectedGenres: 'Selected', + yearMode: 'Year mode', + yearModeInclude: 'Include range', + yearModeExclude: 'Exclude range', + name: 'Name (without prefix)', + limit: 'Limit', + limitHint: 'How many tracks to include in playlist (1-{{max}}, usually 50).', + artistContains: 'Artist contains…', + albumContains: 'Album contains…', + titleContains: 'Title contains…', + minRating: 'Minimum rating', + minRatingAria: 'Minimum rating for smart playlist', + minRatingHint: '0 disables minimum threshold; 1-5 keeps tracks with rating above selected value.', + fromYear: 'From year', + toYear: 'To year', + excludeUnrated: 'Exclude unrated tracks', + compilationOnly: 'Only compilations', + create: 'New Smart Playlist', + save: 'Save Smart Playlist', + created: 'Created {{name}}', + updated: 'Updated {{name}}', + createFailed: 'Could not create smart playlist.', + updateFailed: 'Could not update smart playlist.', + navidromeOnly: 'Smart playlists can only be created on Navidrome servers.', + loadFailed: 'Could not load smart playlists from Navidrome.', + sortRandom: 'Sort: random', + sortTitleAsc: 'Sort: title A-Z', + sortTitleDesc: 'Sort: title Z-A', + sortYearDesc: 'Sort: year desc', + sortYearAsc: 'Sort: year asc', + sortPlayCountDesc: 'Sort: play count desc', +}; diff --git a/src/locales/en/songInfo.ts b/src/locales/en/songInfo.ts new file mode 100644 index 00000000..5d91bf4e --- /dev/null +++ b/src/locales/en/songInfo.ts @@ -0,0 +1,23 @@ +export const songInfo = { + title: 'Song Info', + songTitle: 'Title', + artist: 'Artist', + album: 'Album', + albumArtist: 'Album Artist', + year: 'Year', + genre: 'Genre', + duration: 'Duration', + track: 'Track', + format: 'Format', + bitrate: 'Bitrate', + sampleRate: 'Sample Rate', + bitDepth: 'Bit Depth', + channels: 'Channels', + fileSize: 'File Size', + path: 'Path', + replayGainTrack: 'RG Track Gain', + replayGainAlbum: 'RG Album Gain', + replayGainPeak: 'RG Track Peak', + mono: 'Mono', + stereo: 'Stereo', +}; diff --git a/src/locales/en/statistics.ts b/src/locales/en/statistics.ts new file mode 100644 index 00000000..8e4e928b --- /dev/null +++ b/src/locales/en/statistics.ts @@ -0,0 +1,65 @@ +export const statistics = { + title: 'Statistics', + recentlyPlayed: 'Recently Played', + mostPlayed: 'Most Played Albums', + highestRated: 'Highest Rated Albums', + genreDistribution: 'Genre Distribution (Top 20)', + loadMore: 'Load more', + statArtists: 'Artists', + statArtistsTooltip: 'Album artists only — artists appearing only as a track-level artist (featured, guest, etc.) without their own album are not included.', + statAlbums: 'Albums', + statSongs: 'Songs', + statGenres: 'Genres', + statPlaytime: 'Total Playtime', + genreInsights: 'Genre Insights', + formatDistribution: 'Format Distribution', + formatSample: 'Sample of {{n}} tracks', + computing: 'Computing…', + genreSongs: '{{count}} Songs', + genreAlbums: '{{count}} Albums', + recentlyAdded: 'Recently Added', + decadeDistribution: 'Albums by Decade', + decadeAlbums_one: '{{count}} Album', + decadeAlbums_other: '{{count}} Albums', + decadeUnknown: 'Unknown', + lfmTitle: 'Last.fm Stats', + lfmTopArtists: 'Top Artists', + lfmTopAlbums: 'Top Albums', + lfmTopTracks: 'Top Tracks', + lfmPlays: '{{count}} plays', + lfmPeriodOverall: 'All Time', + lfmPeriod7day: '7 Days', + lfmPeriod1month: '1 Month', + lfmPeriod3month: '3 Months', + lfmPeriod6month: '6 Months', + lfmPeriod12month: '12 Months', + lfmNotConnected: 'Connect Last.fm in Settings to see your stats.', + lfmRecentTracks: 'Recent Scrobbles', + lfmNowPlaying: 'Now Playing', + lfmJustNow: 'just now', + lfmMinutesAgo: '{{n}}m ago', + lfmHoursAgo: '{{n}}h ago', + lfmDaysAgo: '{{n}}d ago', + topRatedSongs: 'Top Rated Songs', + topRatedArtists: 'Top Rated Artists', + noRatedSongs: 'No rated songs yet. Rate songs in album or playlist view.', + noRatedArtists: 'No rated artists yet.', + exportShare: 'Share', + exportTitle: 'Share Top Albums', + exportSubtitle: 'Generate a shareable image of your most-played albums.', + exportFormat: 'Format', + exportFormatStory: 'Story', + exportFormatSquare: 'Square', + exportFormatTwitter: 'Twitter Card', + exportGrid: 'Grid', + exportGridLabel: '{{n}}×{{n}}', + exportPreview: 'Preview', + exportGenerate: 'Generate', + exportSave: 'Save image…', + exportCancel: 'Cancel', + exportFooterLabel: 'Top Albums', + exportNotEnough: 'Need at least {{count}} albums in your library for a {{n}}×{{n}} grid.', + exportSaving: 'Saving…', + exportSaved: 'Saved.', + exportSaveFailed: 'Could not save the image.', +}; diff --git a/src/locales/en/tracks.ts b/src/locales/en/tracks.ts new file mode 100644 index 00000000..7b6e0a88 --- /dev/null +++ b/src/locales/en/tracks.ts @@ -0,0 +1,15 @@ +export const tracks = { + title: 'Tracks', + subtitle: 'Browse. Search. Discover.', + heroEyebrow: 'Track of the moment', + heroReroll: 'Pick another', + playSong: 'Play', + enqueueSong: 'Add to queue', + railRandom: 'Random Pick', + railHighlyRated: 'Highly Rated', + browseTitle: 'Browse all tracks', + browseUnsupported: "This server doesn't list the whole library at once. Use the search above to find specific tracks.", + searchPlaceholder: 'Find a track by title, artist or album…', + count_one: '{{count}} track', + count_other: '{{count}} tracks', +}; diff --git a/src/locales/en/tray.ts b/src/locales/en/tray.ts new file mode 100644 index 00000000..82fe74bb --- /dev/null +++ b/src/locales/en/tray.ts @@ -0,0 +1,8 @@ +export const tray = { + playPause: 'Play / Pause', + nextTrack: 'Next Track', + previousTrack: 'Previous Track', + showHide: 'Show / Hide', + exitPsysonic: 'Exit Psysonic', + nothingPlaying: 'Nothing playing', +}; diff --git a/src/locales/en/whatsNew.ts b/src/locales/en/whatsNew.ts new file mode 100644 index 00000000..3c498b17 --- /dev/null +++ b/src/locales/en/whatsNew.ts @@ -0,0 +1,8 @@ +export const whatsNew = { + title: "What's New", + empty: 'No changelog entry for this version yet.', + bannerTitle: 'Changelog', + bannerCollapsed: "What's new in v{{version}}", + dismiss: 'Dismiss', + close: 'Close', +}; diff --git a/src/locales/es.ts b/src/locales/es.ts deleted file mode 100644 index 1e7dcb06..00000000 --- a/src/locales/es.ts +++ /dev/null @@ -1,1828 +0,0 @@ -export const esTranslation = { - sidebar: { - library: 'Biblioteca', - mainstage: 'Escenario Principal', - newReleases: 'Novedades', - allAlbums: 'Todos los Álbumes', - randomAlbums: 'Álbumes Aleatorios', - artists: 'Artistas', - composers: 'Compositores', - randomMix: 'Mezcla Aleatoria', - randomPicker: 'Crear Mezcla', - favorites: 'Favoritos', - nowPlaying: 'Reproduciendo Ahora', - system: 'Sistema', - statistics: 'Estadísticas', - settings: 'Configuración', - help: 'Ayuda', - expand: 'Expandir Barra Lateral', - collapse: 'Colapsar Barra Lateral', - - downloadingTracks: 'Descargando {{n}} pistas…', - syncingTracks: 'Sincronizando {{done}}/{{total}}…', - cancelDownload: 'Cancelar descarga', - offlineLibrary: 'Biblioteca Offline', - genres: 'Géneros', - tracks: 'Canciones', - playlists: 'Listas de Reproducción', - mostPlayed: 'Más Reproducidos', - losslessAlbums: 'Sin Pérdidas', - radio: 'Radio por Internet', - folderBrowser: 'Explorar Carpetas', - deviceSync: 'Sincronizar dispositivo', - libraryScope: 'Ámbito de biblioteca', - allLibraries: 'Todas las bibliotecas', - expandPlaylists: 'Expandir listas', - collapsePlaylists: 'Colapsar listas', - more: 'Más', - feelingLucky: 'Mezcla Suerte', - }, - home: { - hero: 'Destacado', - starred: 'Favoritos Personales', - recent: 'Agregados Recientemente', - mostPlayed: 'Más Reproducidos', - recentlyPlayed: 'Reproducidos Recientemente', - losslessAlbums: 'Álbumes sin Pérdidas', - discover: 'Descubrir', - discoverSongs: 'Descubrir canciones', - loadMore: 'Cargar Más', - discoverMore: 'Descubrir Más', - discoverArtists: 'Descubrir Artistas', - discoverArtistsMore: 'Todos los Artistas', - becauseYouLike: 'Porque escuchaste…', - becauseYouLikeFor: 'Porque escuchaste a {{artist}}', - similarTo: 'Similar a {{artist}}', - becauseYouLikeTracks_one: '{{count}} canción', - becauseYouLikeTracks_other: '{{count}} canciones' - }, - hero: { - eyebrow: 'Álbum Destacado', - playAlbum: 'Reproducir Álbum', - enqueue: 'Agregar a la Cola', - enqueueTooltip: 'Agregar álbum completo a la cola', - }, - search: { - placeholder: 'Buscar artista, álbum o canción…', - noResults: 'No hay resultados para "{{query}}"', - artists: 'Artistas', - albums: 'Álbumes', - songs: 'Canciones', - clearLabel: 'Limpiar búsqueda', - addedToQueueToast: '"{{title}}" añadido a la cola', - title: 'Buscar', - resultsFor: 'Resultados para "{{query}}"', - album: 'Álbum', - advanced: 'Búsqueda Avanzada', - advancedSearchTerm: 'Término de búsqueda', - advancedSearchPlaceholder: 'Título, álbum, artista…', - advancedGenre: 'Género', - advancedAllGenres: 'Todos los géneros', - advancedYear: 'Año', - advancedYearFrom: 'desde', - advancedYearTo: 'hasta', - advancedAll: 'Todos', - advancedSearch: 'Buscar', - advancedEmpty: 'Ingresa un término de búsqueda o selecciona un filtro para comenzar.', - advancedNoResults: 'No se encontraron resultados.', - advancedGenreNote: 'Las canciones se seleccionan aleatoriamente de este género.', - recentSearches: 'Búsquedas Recientes', - browse: 'Explorar', - emptyHint: '¿Qué quieres escuchar?', - genres: 'Géneros', - }, - nowPlaying: { - tooltip: '¿Quién está escuchando?', - title: '¿Quién está escuchando?', - loading: 'Cargando…', - nobody: 'Nadie está escuchando actualmente.', - minutesAgo: 'hace {{n}}m', - nothingPlaying: 'Aún no se está reproduciendo nada. ¡Empieza una canción!', - aboutArtist: 'Sobre el Artista', - fromAlbum: 'De este Álbum', - viewAlbum: 'Ver Álbum', - goToArtist: 'Ir al Artista', - readMore: 'Leer más', - showLess: 'Mostrar menos', - genreInfo: 'Género', - trackInfo: 'Información de la Pista', - topSongs: 'Más reproducidas de este artista', - topSongsCredit: 'Temas principales de {{name}}', - trackPosition: 'Pista {{pos}}', - playsCount_one: '{{count}} reproducción', - playsCount_other: '{{count}} reproducciones', - releasedYearsAgo_one: 'hace {{count}} año', - releasedYearsAgo_other: 'hace {{count}} años', - discography: 'Discografía', - lastfmStats: 'Estadísticas de Last.fm', - thisTrack: 'Este tema', - thisArtist: 'Este artista', - listeners: 'oyentes', - scrobbles: 'scrobbles', - yourScrobbles: 'por ti', - listenersN: '{{n}} oyentes', - scrobblesN: '{{n}} scrobbles', - playsByYouN: 'reproducido {{n}}× por ti', - openTrackOnLastfm: 'Tema en Last.fm', - openArtistOnLastfm: 'Artista en Last.fm', - rgTrackTooltip: 'ReplayGain (pista)', - rgAlbumTooltip: 'ReplayGain (álbum)', - rgAutoTooltip: 'ReplayGain (auto)', - showMoreTracks: 'Mostrar {{count}} más', - showLessTracks: 'Mostrar menos', - hideCard: 'Ocultar tarjeta', - layoutMenu: 'Diseño', - visibleCards: 'Tarjetas visibles', - hiddenCards: 'Tarjetas ocultas', - noHiddenCards: 'No hay tarjetas ocultas', - resetLayout: 'Restablecer diseño', - emptyColumn: 'Suelta tarjetas aquí', - }, - contextMenu: { - playNow: 'Reproducir Ahora', - playNext: 'Reproducir Siguiente', - addToQueue: 'Agregar a la Cola', - enqueueAlbum: 'Agregar Álbum a la Cola', - enqueueAlbums_one: 'Agregar {{count}} álbum a la cola', - enqueueAlbums_other: 'Agregar {{count}} álbumes a la cola', - startRadio: 'Iniciar Radio', - instantMix: 'Mezcla Instantánea', - instantMixFailed: 'No se pudo crear la Mezcla Instantánea — error del servidor o plugin.', - cliMixNeedsTrack: 'No hay nada en reproducción — inicia la reproducción y vuelve a ejecutar el comando de mezcla.', - lfmLove: 'Favorito en Last.fm', - lfmUnlove: 'Quitar favorito de Last.fm', - favorite: 'Favorito', - favoriteArtist: 'Artista Favorito', - favoriteAlbum: 'Álbum Favorito', - unfavorite: 'Quitar de Favoritos', - unfavoriteArtist: 'Quitar Artista de Favoritos', - unfavoriteAlbum: 'Quitar Álbum de Favoritos', - removeFromQueue: 'Quitar de la Cola', - removeFromPlaylist: 'Quitar de la Playlist', - openAlbum: 'Abrir Álbum', - goToArtist: 'Ir al Artista', - download: 'Descargar (ZIP)', - addToPlaylist: 'Agregar a Lista de Reproducción', - selectedPlaylists: '{{count}} listas seleccionadas', - selectedAlbums: '{{count}} álbumes seleccionados', - selectedArtists: '{{count}} artistas seleccionados', - songInfo: 'Información de la Canción', - shareLink: 'Copiar enlace para compartir', - shareCopied: 'Enlace copiado al portapapeles.', - shareCopyFailed: 'No se pudo copiar al portapapeles.', - }, - sharePaste: { - notLoggedIn: 'Inicia sesión y añade el servidor antes de pegar un enlace para compartir.', - noMatchingServer: 'Ningún servidor guardado coincide con este enlace. Añade un servidor con esta dirección: {{url}}', - trackUnavailable: 'No se encontró esta canción en el servidor.', - albumUnavailable: 'No se encontró este álbum en el servidor.', - artistUnavailable: 'No se encontró este artista en el servidor.', - composerUnavailable: 'No se encontró este compositor en el servidor.', - openedTrack: 'Reproduciendo la canción compartida.', - openedAlbum: 'Abriendo el álbum compartido.', - openedArtist: 'Abriendo el artista compartido.', - openedComposer: 'Abriendo el compositor compartido.', - openedQueue_one: 'Reproduciendo {{count}} pista del enlace para compartir.', - openedQueue_other: 'Reproduciendo {{count}} pistas del enlace para compartir.', - openedQueuePartial: - 'Reproduciendo {{played}} de {{total}} pistas del enlace ({{skipped}} no encontradas en este servidor).', - queueAllUnavailable: 'Ninguna pista de este enlace se encontró en el servidor.', - genericError: 'No se pudo abrir el enlace para compartir.', - }, - albumDetail: { - back: 'Volver', - orbitDoubleClickHint: 'Doble clic para añadir esta canción a la cola Orbit', - playAll: 'Reproducir Todo', - shareAlbum: 'Compartir álbum', - enqueue: 'Agregar a la Cola', - enqueueTooltip: 'Agregar álbum completo a la cola', - artistBio: 'Biografía del Artista', - download: 'Descargar (ZIP)', - downloading: 'Cargando…', - cacheOffline: 'Disponible offline', - offlineCached: 'Disponible offline', - offlineDownloading: 'Descargando… ({{n}}/{{total}})', - removeOffline: 'Quitar de offline', - offlineStorageFull: 'Almacenamiento offline lleno (límite: {{mb}} MB). Libera espacio eliminando un álbum de tu Biblioteca Offline, o aumenta el límite en Configuración.', - offlineStorageGoToLibrary: 'Biblioteca Offline', - offlineStorageGoToSettings: 'Configuración', - favoriteAdd: 'Agregar a Favoritos', - favoriteRemove: 'Quitar de Favoritos', - favorite: 'Favorito', - noBio: 'No hay biografía disponible.', - moreByArtist: 'Más de {{artist}}', - tracksCount: '{{n}} Pistas', - goToArtist: 'Ir a {{artist}}', - moreLabelAlbums: 'Más álbumes en {{label}}', - trackTitle: 'Título', - trackAlbum: 'Álbum', - trackArtist: 'Artista', - trackGenre: 'Género', - trackFormat: 'Formato', - trackFavorite: 'Favorito', - trackRating: 'Calificación', - trackDuration: 'Duración', - trackTotal: 'Total', - columns: 'Columnas', - resetColumns: 'Restablecer', - notFound: 'Álbum no encontrado.', - bioModal: 'Biografía del Artista', - bioClose: 'Cerrar', - ratingLabel: 'Calificación', - enlargeCover: 'Ampliar', - filterSongs: 'Filtrar canciones…', - sortNatural: 'Natural', - sortByTitle: 'A–Z (Título)', - sortByArtist: 'A–Z (Artista)', - sortByAlbum: 'A–Z (Álbum)', - }, - entityRating: { - albumShort: 'Calificación del álbum', - artistShort: 'Calificación del artista', - albumAriaLabel: 'Calificación del álbum', - artistAriaLabel: 'Calificación del artista', - selectedArtistsRatingAriaLabel: 'Calificación con estrellas para {{count}} artistas seleccionados', - selectedAlbumsRatingAriaLabel: 'Calificación con estrellas para {{count}} álbumes seleccionados', - saveFailed: 'No se pudo guardar la calificación.', - }, - artistDetail: { - back: 'Volver', - albums: 'Álbumes', - album: 'Álbum', - playAll: 'Reproducir Todo', - shareArtist: 'Compartir artista', - shuffle: 'Aleatorio', - radio: 'Radio', - loading: 'Cargando…', - noRadio: 'No se encontraron pistas similares para este artista.', - notFound: 'Artista no encontrado.', - albumsBy: 'Álbumes de {{name}}', - topTracks: 'Mejores Pistas', - noAlbums: 'No se encontraron álbumes.', - trackTitle: 'Título', - trackAlbum: 'Álbum', - trackDuration: 'Duración', - favoriteAdd: 'Agregar a Favoritos', - favoriteRemove: 'Quitar de Favoritos', - favorite: 'Favorito', - albumCount_one: '{{count}} Álbum', - albumCount_other: '{{count}} Álbumes', - openedInBrowser: 'Abierto en navegador', - featuredOn: 'También Aparece En', - similarArtists: 'Artistas Similares', - cacheOffline: 'Guardar discografía offline', - offlineCached: 'Discografía guardada', - offlineDownloading: 'Descargando… ({{done}}/{{total}} álbumes)', - uploadImage: 'Subir imagen del artista', - uploadImageError: 'Error al subir imagen', - releaseTypes: { - album: 'Álbum', - ep: 'EP', - single: 'Single', - compilation: 'Recopilación', - live: 'En vivo', - soundtrack: 'Banda sonora', - remix: 'Remix', - other: 'Otro', - }, - }, - favorites: { - title: 'Favoritos', - empty: "Aún no has guardado ningún favorito.", - artists: 'Artistas', - albums: 'Álbumes', - songs: 'Canciones', - enqueueAll: 'Agregar todo a la cola', - playAll: 'Reproducir todo', - removeSong: 'Quitar de favoritos', - stations: 'Estaciones de Radio', - showingFiltered: 'Mostrando {{filtered}} de {{total}} ({{artist}})', - showingCount: 'Mostrando {{filtered}} de {{total}}', - clearArtistFilter: 'Limpiar filtro de artista', - noFilterResults: 'No hay resultados con los filtros seleccionados.', - allArtists: 'Todos los Artistas', - topArtists: 'Artistas favoritos principales', - topArtistsSongCount_one: '{{count}} canción', - topArtistsSongCount_other: '{{count}} canciones', - }, - randomLanding: { - title: 'Crear Mezcla', - mixByTracks: 'Mezcla por Canciones', - mixByTracksDesc: 'Selección aleatoria de canciones de toda tu biblioteca', - mixByAlbums: 'Mezcla por Álbumes', - mixByAlbumsDesc: 'Álbumes aleatorios para tu próximo descubrimiento', - mixByLucky: 'Mezcla Suerte', - mixByLuckyDesc: 'Instant Mix inteligente con artistas, álbumes y valoraciones destacadas', - }, - randomAlbums: { - title: 'Álbumes Aleatorios', - refresh: 'Refrescar', - }, - genres: { - title: 'Géneros', - genreCount: 'Géneros', - albumCount_one: '{{count}} álbum', - albumCount_other: '{{count}} álbumes', - loading: 'Cargando géneros…', - empty: 'No se encontraron géneros.', - albumsLoading: 'Cargando álbumes…', - albumsEmpty: 'No se encontraron álbumes para este género.', - loadMore: 'Cargar más', - back: 'Volver', - }, - randomMix: { - title: 'Mezcla Aleatoria', - remix: 'Remezclar', - remixTooltip: 'Cargar nuevas canciones aleatorias', - remixGenre: 'Remezclar {{genre}}', - remixTooltipGenre: 'Cargar nuevas canciones de {{genre}}', - playAll: 'Reproducir Todo', - trackTitle: 'Título', - trackArtist: 'Artista', - trackAlbum: 'Álbum', - trackFavorite: 'Favorito', - trackDuration: 'Duración', - favoriteAdd: 'Agregar a Favoritos', - favoriteRemove: 'Quitar de Favoritos', - play: 'Reproducir', - trackGenre: 'Género', - mixSettingsHeader: 'Ajustes del mix', - exclusionsHeader: 'Exclusiones', - filterPanelInexactSizeNote: 'El tamaño del mix es un objetivo — las solicitudes grandes pueden devolver menos pistas únicas si el grupo aleatorio del servidor se agota.', - mixSize: 'Tamaño de lista', - excludeAudiobooks: 'Excluir audiolibros y radioteatros', - excludeAudiobooksDesc: 'Busca palabras clave en género, título, álbum y artista — ej. Hörbuch, Audiobook, Spoken Word, …', - genreBlocked: 'Palabra clave bloqueada', - genreAddedToBlacklist: 'Agregada a lista de filtros', - genreAlreadyBlocked: 'Ya está bloqueada', - artistBlocked: 'Artista bloqueado', - artistAddedToBlacklist: 'Artista agregado a lista de filtros', - artistClickHint: 'Click para bloquear este artista', - blacklistToggle: 'Filtro de Palabras Clave', - genreMixTitle: 'Mezcla por Género', - genreMixDesc: 'Top 20 géneros por cantidad de canciones — click para cargar mezcla aleatoria', - genreMixAll: 'Todas las Canciones', - genreMixLoadMore: 'Cargar 10 más', - genreMixNoGenres: 'No se encontraron géneros en el servidor.', - shuffleGenres: 'Mostrar géneros diferentes', - filterPanelTitle: 'Filtros', - filterPanelDesc: 'Click en una etiqueta de género o nombre de artista en la lista para bloquearlo de futuras mezclas.', - genreClickHint: 'Click en una etiqueta de género para agregarla\ncomo palabra clave filtrada.\nBusca en género, título, álbum y artista.', - }, - luckyMix: { - done: 'Mezcla Suerte lista: {{count}} canciones', - failed: 'No se pudo crear la Mezcla Suerte. Inténtalo de nuevo.', - unavailable: 'Mezcla Suerte no está disponible para este servidor.', - cancelTooltip: 'Cancelar creación de Mezcla Suerte', - }, - albums: { - title: 'Todos los Álbumes', - sortByName: 'A–Z (Álbum)', - sortByArtist: 'A–Z (Artista)', - sortNewest: 'Más recientes primero', - sortRandom: 'Aleatorio', - yearFrom: 'Desde', - yearTo: 'Hasta', - yearFilterClear: 'Limpiar filtro de año', - yearFilterLabel: 'Año', - compilationLabel: 'Recopilatorios', - compilationOnly: 'Solo recopilatorios', - compilationHide: 'Ocultar recopilatorios', - compilationTooltipAll: 'Todos los álbumes · clic: solo recopilatorios', - compilationTooltipOnly: 'Solo recopilatorios · clic: ocultar recopilatorios', - compilationTooltipHide: 'Recopilatorios ocultos · clic: mostrar todo', - select: 'Selección múltiple', - startSelect: 'Activar selección múltiple', - cancelSelect: 'Cancelar', - selectionCount: '{{count}} seleccionados', - downloadZips: 'Descargar ZIPs', - addOffline: 'Agregar Offline', - enqueueSelected_one: 'A la cola ({{count}})', - enqueueSelected_other: 'A la cola ({{count}})', - enqueueQueued_one: '{{count}} álbum añadido a la cola', - enqueueQueued_other: '{{count}} álbumes añadidos a la cola', - downloadingZip: 'Descargando {{current}}/{{total}}: {{name}}', - downloadZipDone: '{{count}} ZIP(s) descargado(s)', - downloadZipFailed: 'Error al descargar {{name}}', - offlineQueuing: 'Encolando {{count}} álbum(es) para offline…', - offlineFailed: 'Error al agregar {{name}} offline', - addToPlaylist: 'Agregar a Lista de Reproducción', - }, - tracks: { - title: 'Canciones', - subtitle: 'Explorar. Buscar. Descubrir.', - heroEyebrow: 'Canción del momento', - heroReroll: 'Elegir otra', - playSong: 'Reproducir', - enqueueSong: 'Añadir a la cola', - railRandom: 'Selección aleatoria', - railHighlyRated: 'Mejor valoradas', - browseTitle: 'Explorar todas las canciones', - browseUnsupported: 'Este servidor no lista toda la biblioteca de una vez. Usa la búsqueda de arriba para encontrar canciones concretas.', - searchPlaceholder: 'Busca una canción por título, artista o álbum…', - count_one: '{{count}} canción', - count_other: '{{count}} canciones', - }, - artists: { - title: 'Artistas', - search: 'Buscar…', - all: 'Todos', - gridView: 'Vista de cuadrícula', - listView: 'Vista de lista', - imagesOn: 'Imágenes de artistas activadas — puede aumentar la carga de red y sistema', - imagesOff: 'Imágenes de artistas desactivadas — mostrando solo iniciales', - loadMore: 'Cargar más', - notFound: 'No se encontraron artistas.', - albumCount_one: '{{count}} Álbum', - albumCount_other: '{{count}} Álbumes', - selectionCount: '{{count}} seleccionados', - select: 'Selección múltiple', - startSelect: 'Activar selección múltiple', - cancelSelect: 'Cancelar', - addToPlaylist: 'Agregar a Lista', - }, - composers: { - title: 'Compositores', - search: 'Buscar…', - notFound: 'No se encontraron compositores.', - unsupported: 'La navegación por compositor requiere Navidrome 0.55 o más reciente.', - loadFailed: 'No se pudieron cargar los compositores.', - retry: 'Reintentar', - involvedIn_one: 'Participa en {{count}} álbum', - involvedIn_other: 'Participa en {{count}} álbumes', - }, - composerDetail: { - back: 'Atrás', - notFound: 'Compositor no encontrado.', - about: 'Sobre este compositor', - works: 'Obras', - noWorks: 'No se encontraron obras.', - workCount_one: '{{count}} obra', - workCount_other: '{{count}} obras', - shareComposer: 'Compartir compositor', - unknownComposer: 'Compositor', - }, - login: { - subtitle: 'Tu Reproductor Navidrome para Escritorio', - serverName: 'Nombre del Servidor (opcional)', - serverNamePlaceholder: 'Mi Navidrome', - serverUrl: 'URL del Servidor', - serverUrlPlaceholder: '192.168.1.100:4533 o https://music.example.com', - username: 'Usuario', - usernamePlaceholder: 'admin', - password: 'Contraseña', - showPassword: 'Mostrar contraseña', - hidePassword: 'Ocultar contraseña', - connect: 'Conectar', - connecting: 'Conectando…', - connected: '¡Conectado!', - error: 'Conexión fallida — por favor verifica tus datos.', - urlRequired: 'Por favor ingresa una URL de servidor.', - savedServers: 'Servidores Guardados', - addNew: 'O agregar un nuevo servidor', - orMagicString: 'O cadena mágica', - magicStringPlaceholder: 'Pega una cadena de invitación (psysonic1-…)', - magicStringInvalid: 'Cadena mágica no válida o ilegible.', - }, - connection: { - connected: 'Conectado', - connectedTo: 'Conectado a {{server}}', - disconnected: 'Desconectado', - disconnectedFrom: 'No se puede alcanzar {{server}} — click para verificar configuración', - checking: 'Conectando…', - extern: 'Externo', - offlineTitle: 'Sin conexión al servidor', - offlineSubtitle: 'No se puede alcanzar {{server}}. Verifica tu red o servidor.', - offlineModeBanner: 'Modo Offline — reproduciendo desde caché local', - offlineNoCacheBanner: 'Sin conexión al servidor — no se puede acceder a {{server}}', - offlineLibraryTitle: 'Biblioteca Offline', - offlineLibraryEmpty: 'No hay álbumes en caché aún. Conéctate, abre un álbum y click en "Disponible offline".', - offlineAlbumCount: '{{n}} álbum', - offlineAlbumCount_plural: '{{n}} álbumes', - offlineFilterAll: 'Todos', - offlineFilterAlbums: 'Álbumes', - offlineFilterPlaylists: 'Listas', - offlineFilterArtists: 'Discografías', - retry: 'Reintentar', - serverSettings: 'Configuración del servidor', - switchServerTitle: 'Cambiar servidor', - switchServerHint: 'Clic para elegir otro servidor guardado.', - manageServers: 'Gestionar servidores…', - switchFailed: 'No se pudo cambiar — servidor inalcanzable.', - lastfmConnected: 'Last.fm conectado como @{{user}}', - lastfmSessionInvalid: 'Sesión inválida — click para reconectar', - }, - common: { - albums: 'Álbumes', - album: 'Álbum', - loading: 'Cargando…', - loadingMore: 'Cargando…', - loadingPlaylists: 'Cargando Listas…', - noAlbums: 'No se encontraron álbumes.', - downloading: 'Descargando…', - downloadZip: 'Descargar (ZIP)', - back: 'Volver', - cancel: 'Cancelar', - save: 'Guardar', - delete: 'Eliminar', - use: 'Usar', - add: 'Agregar', - new: 'Nuevo', - active: 'Activo', - download: 'Descargar', - chooseDownloadFolder: 'Elegir carpeta de descarga', - noFolderSelected: 'Ninguna carpeta seleccionada', - rememberDownloadFolder: 'Recordar esta carpeta', - filterGenre: 'Filtro de Género', - filterSearchGenres: 'Buscar géneros…', - filterNoGenres: 'Ningún género coincide', - filterClear: 'Limpiar', - favorites: 'Favoritos', - favoritesTooltipOff: 'Mostrar solo favoritos', - favoritesTooltipOn: 'Mostrar todo', - play: 'Reproducir', - bulkSelected: '{{count}} seleccionados', - clearSelection: 'Limpiar selección', - bulkAddToPlaylist: 'Agregar a Lista', - bulkRemoveFromPlaylist: 'Quitar de Lista', - bulkClear: 'Limpiar selección', - updaterAvailable: 'Actualización disponible', - updaterVersion: 'v{{version}} está disponible', - updaterWebsite: 'Sitio web', - updaterModalTitle: 'Nueva Versión Disponible', - updaterChangelog: 'Novedades', - updaterDownloadBtn: 'Descargar Ahora', - updaterSkipBtn: 'Omitir esta Versión', - updaterRemindBtn: 'Recordarme Después', - updaterDone: 'Descarga completada', - updaterShowFolder: 'Mostrar en Carpeta', - updaterInstallHint: 'Cierra Psysonic y ejecuta el instalador manualmente.', - updaterAurHint: 'Instala la actualización vía AUR:', - updaterErrorMsg: 'Error de descarga', - updaterRetryBtn: 'Reintentar', - durationHoursMinutes: '{{hours}}h {{minutes}}m', - durationMinutesOnly: '{{minutes}}m', - updaterOpenGitHub: 'Abrir en GitHub', - filters: 'Filtros', - more: 'más', - yearRange: 'Rango de años', - clearAll: 'Limpiar todo', - }, - settings: { - title: 'Configuración', - language: 'Idioma', - languageEn: 'English', - languageDe: 'Deutsch', - languageEs: 'Español', - languageFr: 'Français', - languageNl: 'Nederlands', - languageNb: 'Norsk', - languageRu: 'Русский', - languageZh: '中文', - languageRo: 'Română', - font: 'Fuente', - fontHintOpenDyslexic: 'Compatible con dislexia · sin soporte para chino', - theme: 'Tema', - appearance: 'Apariencia', - servers: 'Servidores', - serverName: 'Nombre del Servidor', - serverUrl: 'URL del Servidor', - serverUrlPlaceholder: '192.168.1.100:4533 o https://music.example.com', - serverUsername: 'Usuario', - serverPassword: 'Contraseña', - addServer: 'Agregar Servidor', - addServerTitle: 'Agregar Nuevo Servidor', - useServer: 'Usar', - deleteServer: 'Eliminar', - noServers: 'No hay servidores guardados.', - serverActive: 'Activo', - confirmDeleteServer: '¿Eliminar servidor "{{name}}"?', - serverConnecting: 'Conectando…', - serverConnected: '¡Conectado!', - serverFailed: 'Conexión fallida.', - testBtn: 'Probar Conexión', - testingBtn: 'Probando…', - serverCompatible: 'Diseñado para Navidrome. Otros servidores compatibles con Subsonic (Gonic, Airsonic, …) pueden funcionar con funcionalidad reducida, ya que Psysonic utiliza muchos endpoints específicos de la API de Navidrome.', - userMgmtTitle: 'Gestión de usuarios', - userMgmtDesc: 'Administra los usuarios de este servidor. Requiere privilegios de administrador.', - userMgmtNoAdmin: 'Necesitas privilegios de administrador para gestionar usuarios en este servidor.', - userMgmtLoadError: 'No se pudieron cargar los usuarios.', - userMgmtLoadFriendly: 'El servidor no respondió — suele ser algo puntual.', - userMgmtRetry: 'Reintentar', - userMgmtEmpty: 'No se encontraron usuarios.', - userMgmtYouBadge: 'Tú', - userMgmtAdminBadge: 'Admin', - userMgmtAddUser: 'Añadir usuario', - userMgmtAddUserTitle: 'Nuevo usuario', - userMgmtEditUserTitle: 'Editar usuario', - userMgmtUsername: 'Nombre de usuario', - userMgmtName: 'Nombre visible', - userMgmtEmail: 'Correo electrónico', - userMgmtPassword: 'Contraseña', - userMgmtPasswordEditHint: 'Introduce una nueva contraseña para actualizarla.', - userMgmtRoleAdmin: 'Admin', - userMgmtLibraries: 'Bibliotecas', - userMgmtLibrariesAdminHint: 'Los usuarios admin tienen acceso automáticamente a todas las bibliotecas.', - userMgmtLibrariesEmpty: 'No hay bibliotecas disponibles en este servidor.', - userMgmtLibrariesValidation: 'Selecciona al menos una biblioteca.', - userMgmtLibrariesUpdateError: 'Usuario guardado, pero la asignación de bibliotecas falló', - userMgmtNoLibraries: 'Sin bibliotecas asignadas', - userMgmtNeverSeen: 'Nunca', - userMgmtSave: 'Guardar', - userMgmtCancel: 'Cancelar', - userMgmtDelete: 'Eliminar', - userMgmtEdit: 'Editar', - userMgmtConfirmDelete: '¿Eliminar el usuario «{{username}}»? Esta acción no se puede deshacer.', - userMgmtCreateError: 'No se pudo crear el usuario.', - userMgmtUpdateError: 'No se pudo actualizar el usuario.', - userMgmtDeleteError: 'No se pudo eliminar el usuario.', - userMgmtCreated: 'Usuario creado.', - userMgmtUpdated: 'Usuario actualizado.', - userMgmtDeleted: 'Usuario eliminado.', - userMgmtValidationMissing: 'Se requieren nombre de usuario, nombre visible y contraseña.', - userMgmtValidationMissingIdentity: 'Se requieren nombre de usuario y nombre visible.', - userMgmtMagicStringGenerate: 'Generar cadena mágica', - userMgmtSaveAndMagicString: 'Guardar y obtener cadena mágica', - userMgmtMagicStringPasswordNavHint: - 'Navidrome guardará esta contraseña para el usuario. Si difiere de la actual, se actualizará la contraseña de acceso en el servidor.', - userMgmtMagicStringPlaintextWarning: - 'Comparte la cadena mágica con cuidado: contiene la contraseña sin cifrar (la codificación no es cifrado). Quien tenga la cadena completa puede iniciar sesión como este usuario.', - userMgmtMagicStringCopied: 'Cadena mágica copiada al portapapeles.', - userMgmtMagicStringCopyFailed: 'No se pudo copiar al portapapeles.', - userMgmtMagicStringLoginFailed: 'Falló la comprobación de la contraseña; no se pudieron verificar las credenciales.', - userMgmtMagicStringModalTitle: 'Generar cadena mágica', - userMgmtMagicStringModalDesc: 'Introduce la contraseña Subsonic de «{{username}}». Se incluirá en la cadena mágica copiada.', - userMgmtMagicStringModalConfirm: 'Copiar cadena', - audiomuseTitle: 'AudioMuse-AI (Navidrome)', - audiomuseDesc: - 'Activa si este servidor tiene el plugin AudioMuse-AI Navidrome configurado. Habilita Mezcla Instantánea desde pistas y usa artistas similares del servidor en lugar de Last.fm en páginas de artistas.', - audiomuseIssueHint: - 'La Mezcla Instantánea falló recientemente — verifica el plugin de Navidrome y la API de AudioMuse. Artistas similares usan Last.fm como respaldo cuando el servidor no devuelve ninguno.', - connected: 'Conectado', - failed: 'Fallido', - eqTitle: 'Ecualizador', - eqEnabled: 'Habilitar Ecualizador', - eqPreset: 'Preajuste', - eqPresetCustom: 'Personalizado', - eqPresetBuiltin: 'Preajustes Integrados', - eqPresetCustomGroup: 'Mis Preajustes', - eqSavePreset: 'Guardar como Preajuste', - eqPresetName: 'Nombre del preajuste…', - eqDeletePreset: 'Eliminar preajuste', - eqResetBands: 'Restablecer a Plano', - eqPreGain: 'Pre-ganancia', - eqResetPreGain: 'Restablecer pre-ganancia', - eqAutoEqTitle: 'Búsqueda AutoEQ de Auriculares', - eqAutoEqPlaceholder: 'Buscar modelo de auricular / IEM…', - eqAutoEqSearching: 'Buscando…', - eqAutoEqNoResults: 'No se encontraron resultados', - eqAutoEqError: 'Error de búsqueda', - eqAutoEqRateLimit: 'Límite de GitHub alcanzado — intenta de nuevo en un minuto', - eqAutoEqFetchError: 'Error al obtener perfil EQ', - lfmTitle: 'Last.fm', - lfmConnect: 'Conectar con Last.fm', - lfmConnecting: 'Esperando autorización…', - lfmConfirm: 'He autorizado la aplicación', - lfmConnected: 'Conectado como', - lfmDisconnect: 'Desconectar', - lfmConnectDesc: 'Conecta tu cuenta de Last.fm para habilitar scrobbling y actualizaciones de "Reproduciendo Ahora" directamente desde Psysonic — no requiere configuración de Navidrome.', - lfmOpenBrowser: 'Se abrirá una ventana del navegador. Autoriza Psysonic en Last.fm, luego click en el botón de abajo.', - lfmScrobbles: '{{n}} scrobbles', - lfmMemberSince: 'Miembro desde {{year}}', - scrobbleEnabled: 'Scrobbling habilitado', - scrobbleDesc: 'Enviar canciones a Last.fm después del 50% de reproducción', - behavior: 'Comportamiento de la App', - cacheTitle: 'Tamaño Máx. de Almacenamiento', - cacheDesc: 'Portadas e imágenes de artistas. Cuando está lleno, las entradas más antiguas se eliminan automáticamente. Los álbumes offline no se eliminan automáticamente, pero se borrarán al limpiar la caché manualmente.', - cacheUsedImages: 'Imágenes:', - cacheUsedOffline: 'Pistas offline:', - cacheUsedHot: 'Tamaño en disco:', - hotCacheTrackCount: 'Pistas en caché:', - cacheMaxLabel: 'Tamaño máx.', - cacheClearBtn: 'Limpiar Caché', - cacheClearWarning: 'Esto también eliminará todos los álbumes offline de la biblioteca.', - cacheClearConfirm: 'Limpiar Todo', - cacheClearCancel: 'Cancelar', - offlineDirTitle: 'Biblioteca Offline (En App)', - offlineDirDesc: 'Ubicación de almacenamiento para pistas que haces disponibles offline dentro de Psysonic.', - offlineDirDefault: 'Predeterminado (Datos de App)', - offlineDirChange: 'Cambiar Directorio', - offlineDirClear: 'Restablecer a Predeterminado', - offlineDirHint: 'Las nuevas descargas usarán esta ubicación. Las descargas existentes permanecen en su ruta original.', - hotCacheTitle: 'Caché de reproducción activa', - hotCacheDisclaimer: 'Precarga las siguientes pistas en cola y mantiene las anteriores. Cuando está activado, usa espacio en disco y red.', - hotCacheDirDefault: 'Predeterminado (Datos de App)', - hotCacheDirChange: 'Cambiar carpeta', - hotCacheDirClear: 'Restablecer a predeterminado', - hotCacheDirHint: 'Cambiar la carpeta restablece el índice en-app; los archivos ya en disco permanecen donde están hasta que los elimines.', - hotCacheEnabled: 'Habilitar caché de reproducción activa', - hotCacheMaxMb: 'Tamaño máximo de caché', - hotCacheDebounce: 'Espera de cambio de cola', - hotCacheDebounceImmediate: 'Inmediato', - hotCacheDebounceSeconds: '{{n}} s', - hotCacheClearBtn: 'Limpiar caché activa', - audioOutputDevice: 'Dispositivo de salida de audio', - audioOutputDeviceDesc: 'Selecciona el dispositivo de audio que usa Psysonic. Los cambios surten efecto de inmediato y reinician la pista actual.', - audioOutputDeviceDefault: 'Predeterminado del sistema', - audioOutputDeviceRefresh: 'Actualizar lista de dispositivos', - audioOutputDeviceOsDefaultNow: 'salida actual del sistema', - audioOutputDeviceListError: 'No se pudo cargar la lista de dispositivos de audio.', - audioOutputDeviceNotInCurrentList: 'no está en la lista actual', - audioOutputDeviceMacNotice: 'En macOS, la reproducción actualmente sigue siempre al dispositivo de salida del sistema por razones técnicas. Cambia el destino mediante Ajustes del Sistema → Sonido o el icono del altavoz en la barra de menús. Motivo: CoreAudio activa una solicitud de permiso de micrófono al abrir un stream no-predeterminado — lo evitamos usando siempre la salida por defecto del sistema.', - hiResTitle: 'Reproducción Nativa Hi-Res', - hiResEnabled: 'Habilitar reproducción nativa hi-res', - hiResDesc: "Fuerza 44.1 kHz de salida por defecto para máxima estabilidad. Habilita solo si tu hardware y red soportan confiablemente altas tasas de muestreo (88.2 kHz+).", - showArtistImages: 'Mostrar Imágenes de Artistas', - showArtistImagesDesc: 'Carga y muestra imágenes de artistas en el resumen de Artistas. Desactivado por defecto para reducir I/O de disco del servidor y carga de red en bibliotecas grandes.', - showOrbitTrigger: 'Mostrar "Orbit" en la cabecera', - showOrbitTriggerDesc: 'El botón en la cabecera para iniciar o unirse a una sesión de escucha compartida. Ocúltalo si no usas Orbit — puedes volver a activarlo aquí.', - showTrayIcon: 'Mostrar Icono en Bandeja', - showTrayIconDesc: 'Muestra el icono de Psysonic en el área de notificación / barra de menú.', - minimizeToTray: 'Minimizar a Bandeja', - minimizeToTrayDesc: 'Al cerrar la ventana, mantener Psysonic ejecutándose en la bandeja del sistema en lugar de salir.', - preloadMiniPlayer: 'Precargar mini reproductor', - preloadMiniPlayerDesc: 'Crea la ventana del mini reproductor en segundo plano al iniciar la aplicación para que muestre contenido al instante la primera vez que se abre. Consume un poco más de memoria.', - discordRichPresence: 'Discord Rich Presence', - discordRichPresenceDesc: 'Muestra la pista actual en tu perfil de Discord. Requiere que Discord esté ejecutándose.', - useCustomTitlebar: 'Barra de título personalizada', - useCustomTitlebarDesc: 'Reemplaza la barra de título del sistema con una integrada que coincide con el tema de la app. Desactiva para usar la barra nativa de GNOME/GTK.', - linuxWebkitSmoothScroll: 'Rueda suave (Linux)', - linuxWebkitSmoothScrollDesc: 'Activado: inercia. Desactivado: pasos por línea (estilo GTK).', - discordCoverSource: 'Fuente de portada', - discordCoverSourceDesc: 'De dónde obtener la portada del álbum para tu perfil de Discord.', - discordCoverNone: 'Ninguna (solo icono de la app)', - discordCoverServer: 'Servidor (vía info del álbum)', - discordCoverApple: 'Apple Music', - discordOptions: 'Opciones avanzadas de Discord', - discordTemplates: 'Plantillas de texto personalizadas', - discordTemplatesDesc: 'Personaliza qué información se muestra en tu perfil de Discord. Variables: {title}, {artist}, {album}', - discordTemplateDetails: 'Línea principal (details)', - discordTemplateState: 'Línea secundaria (state)', - discordTemplateLargeText: 'Tooltip del álbum (largeText)', - nowPlayingEnabled: 'Mostrar en Reproduciendo Ahora', - nowPlayingEnabledDesc: 'Transmite tu pista actual a la vista de oyentes en vivo del servidor. Desactiva para dejar de enviar datos de reproducción.', - enableBandsintown: 'Fechas de gira de Bandsintown', - enableBandsintownDesc: 'Muestra próximos conciertos del artista actual en la pestaña Info. Los datos se obtienen de la API pública de Bandsintown.', - lyricsServerFirst: 'Preferir letras del servidor', - lyricsServerFirstDesc: 'Verifica primero letras provistas por el servidor (etiquetas embebidas, archivos sidecar) antes de consultar LRCLIB. Desactiva para usar LRCLIB primero.', - enableNeteaselyrics: 'Letras de Netease Cloud Music', - enableNeteaselyricsDesc: 'Usa Netease Cloud Music como fuente de letras de último recurso cuando el servidor y LRCLIB no devuelvan nada. Mejor cobertura para música asiática e internacional.', - lyricsSourcesTitle: 'Fuentes de Letras', - lyricsSourcesDesc: 'Elige qué fuentes consultar para letras y en qué orden. Arrastra para reordenar. Las fuentes desactivadas se omiten completamente.', - lyricsSourceServer: 'Servidor', - lyricsSourceLrclib: 'LRCLIB', - lyricsSourceNetease: 'Netease Cloud Music', - lyricsModeStandard: 'Estándar', - lyricsModeStandardDesc: 'Tres fuentes con orden configurable: etiquetas del servidor, LRCLIB, Netease.', - lyricsModeLyricsplus: 'YouLyPlus (Karaoke)', - lyricsModeLyricsplusDesc: 'Sincronización palabra por palabra desde Apple Music, Spotify, Musixmatch y QQ (backend comunitario). Recurre silenciosamente a las fuentes estándar cuando no se encuentra nada.', - lyricsStaticOnly: 'Mostrar letras como texto estático', - lyricsStaticOnlyDesc: 'Muestra las letras sincronizadas sin desplazamiento automático ni resaltado por palabra.', - downloadsTitle: 'Exportación ZIP y Archivado', - downloadsFolderDesc: 'Carpeta de destino para álbumes que descargas como ZIP a tu computadora.', - downloadsDefault: 'Carpeta de Descargas Predeterminada', - pickFolder: 'Seleccionar', - pickFolderTitle: 'Seleccionar Carpeta de Descarga', - clearFolder: 'Limpiar carpeta de descarga', - logout: 'Cerrar Sesión', - aboutTitle: 'Acerca de Psysonic', - aboutDesc: 'Un reproductor de música de escritorio moderno creado para Navidrome. Utiliza la API de Subsonic más extensiones específicas de Navidrome. Construido en Tauri v2 con motor de audio nativo en Rust — ligero y rápido, pero lleno de características: barra de progreso tipo onda, letras sincronizadas, integración Last.fm, ecualizador de 10 bandas, crossfade, reproducción gapless, Replay Gain, navegación por géneros, y una gran biblioteca de temas.', - aboutLicense: 'Licencia', - aboutLicenseText: 'GNU GPL v3 — libre para usar, modificar y distribuir bajo la misma licencia.', - aboutRepo: 'Código Fuente en GitHub', - aboutVersion: 'Versión', - aboutBuiltWith: 'Construido con Tauri · React · TypeScript · Rust/rodio', - aboutReleaseNotesLabel: 'Notas de la versión', - aboutReleaseNotesLink: 'Abrir las novedades de esta versión', - aboutContributorsLabel: 'Contribuidores', - showChangelogOnUpdate: "Mostrar 'Novedades' al actualizar", - showChangelogOnUpdateDesc: 'Muestra un discreto banner de changelog encima de Now Playing tras una actualización. Clic abre las notas de la versión; X lo oculta.', - randomMixTitle: 'Lista negra de Mezcla Aleatoria', - luckyMixMenuTitle: 'Mostrar Mezcla Suerte en el menú', - luckyMixMenuDesc: 'Activa Mezcla Suerte en "Crear Mezcla" y como elemento de menú separado cuando la navegación dividida está activa. Solo visible cuando AudioMuse está activo en el servidor actual.', - randomMixBlacklistTitle: 'Palabras Clave de Filtro Personalizadas', - randomMixBlacklistDesc: 'Las canciones se excluyen cuando cualquier palabra clave coincide con su género, título, álbum o artista (activo cuando el checkbox de arriba está activado).', - randomMixBlacklistPlaceholder: 'Agregar palabra clave…', - randomMixBlacklistAdd: 'Agregar', - randomMixBlacklistEmpty: 'Aún no hay palabras clave personalizadas.', - randomMixHardcodedTitle: 'Palabras clave integradas (activas cuando el checkbox está activado)', - tabAudio: 'Audio', - tabStorage: 'Sin conexión y caché', - tabAppearance: 'Apariencia', - tabLibrary: 'Biblioteca', - tabServers: 'Servidores', - tabLyrics: 'Letras', - tabPersonalisation: 'Personalización', - tabIntegrations: 'Integraciones', - inputKeybindingsTitle: 'Atajos de teclado', - aboutContributorsCount_one: '{{count}} contribución', - aboutContributorsCount_other: '{{count}} contribuciones', - searchPlaceholder: 'Buscar en ajustes…', - searchNoResults: 'Ningún ajuste coincide con tu búsqueda.', - aboutMaintainersLabel: 'Mantenedores', - integrationsPrivacyTitle: 'Aviso de privacidad', - integrationsPrivacyBody: 'Todas las integraciones de esta pestaña son opt-in y, una vez activadas, envían datos a servicios externos o a tu servidor Navidrome. Last.fm recibe tu historial de escucha, Discord muestra la pista actual en tu perfil, Bandsintown se consulta por artista para obtener fechas de gira, y la compartición «En reproducción» publica tu pista actual para otros usuarios de tu servidor Navidrome. Si no quieres nada de esto, simplemente deja desactivada la sección correspondiente.', - homeCustomizerTitle: 'Página de Inicio', - queueToolbarTitle: 'Barra de herramientas de cola', - queueToolbarReset: 'Restablecer a predeterminado', - queueToolbarSeparator: 'Separador', - sidebarTitle: 'Barra Lateral', - sidebarReset: 'Restablecer a predeterminado', - artistLayoutTitle: 'Secciones de la página del artista', - artistLayoutDesc: 'Arrastra para reordenar, alterna para ocultar secciones individuales de la página del artista. Las secciones sin datos se omiten automáticamente.', - artistLayoutReset: 'Restablecer a predeterminado', - artistLayoutBio: 'Biografía del artista', - artistLayoutTopTracks: 'Mejores pistas', - artistLayoutSimilar: 'Artistas similares', - artistLayoutAlbums: 'Álbumes', - artistLayoutFeatured: 'También presente en', - sidebarDrag: 'Arrastra para reordenar', - sidebarFixed: 'Siempre visible', - randomNavSplitTitle: 'Dividir navegación Mix', - randomNavSplitDesc: 'Mostrar "Mezcla Aleatoria", "Álbumes Aleatorios" y "Mezcla Suerte" como entradas separadas en la barra lateral en lugar del hub "Crear Mezcla".', - tabInput: 'Entrada', - tabUsers: 'Usuarios', - tabSystem: 'Sistema', - loggingTitle: 'Registro', - loggingModeDesc: 'Controla la verbosidad de los logs del backend en la terminal.', - loggingModeOff: 'Apagado', - loggingModeNormal: 'Normal', - loggingModeDebug: 'Depuración', - loggingExport: 'Exportar logs', - loggingExportSuccess: 'Logs exportados ({{count}} líneas).', - loggingExportError: 'No se pudieron exportar los logs.', - ratingsSectionTitle: 'Calificaciones', - ratingsSkipStarTitle: 'Saltar para 1 estrella', - ratingsSkipStarDesc: - 'Después de varios saltos seguidos, asigna 1 estrella a la pista. Solo para pistas aún no calificadas.', - ratingsSkipStarThresholdLabel: 'Saltos', - ratingsMixFilterTitle: 'Filtrar por calificación', - ratingsMixFilterDesc: - 'Filtra elementos de baja calificación en {{mix}} y {{albums}}. Click en la estrella seleccionada nuevamente para desactivar el umbral.', - ratingsMixMinSong: 'Canciones', - ratingsMixMinAlbum: 'Álbumes', - ratingsMixMinArtist: 'Artistas', - ratingsMixMinThresholdAria: 'Estrellas mínimas: {{label}}', - backupTitle: 'Respaldo y Restauración', - backupExport: 'Exportar configuración', - backupExportDesc: 'Guarda toda la configuración, perfiles de servidor, configuración Last.fm, tema, EQ y atajos de teclado a un archivo .psybkp. Las contraseñas se almacenan en texto plano — mantén el archivo seguro.', - backupImport: 'Importar configuración', - backupImportDesc: 'Restaura configuración desde un archivo .psybkp. La app se recargará después de importar.', - backupImportConfirm: 'Esto sobrescribirá toda la configuración actual. ¿Continuar?', - backupSuccess: 'Respaldo guardado', - backupImportSuccess: 'Configuración restaurada — recargando…', - backupImportError: 'Archivo de respaldo inválido o corrupto.', - shortcutsReset: 'Restablecer a predeterminados', - shortcutListening: 'Presiona una tecla…', - shortcutUnbound: '—', - globalShortcutsTitle: 'Atajos Globales', - globalShortcutsNote: 'Funcionan en todo el sistema incluso cuando Psysonic está en segundo plano. Requieren Ctrl, Alt o Super como modificador.', - shortcutClear: 'Limpiar', - shortcutPlayPause: 'Reproducir / Pausa', - shortcutNext: 'Siguiente pista', - shortcutPrev: 'Pista anterior', - shortcutVolumeUp: 'Subir volumen', - shortcutVolumeDown: 'Bajar volumen', - shortcutSeekForward: 'Avanzar 10s', - shortcutSeekBackward: 'Retroceder 10s', - shortcutToggleQueue: 'Alternar cola', - shortcutOpenFolderBrowser: 'Abrir {{folderBrowser}}', - shortcutFullscreenPlayer: 'Reproductor pantalla completa', - shortcutNativeFullscreen: 'Pantalla completa nativa', - shortcutOpenMiniPlayer: 'Abrir mini reproductor', - shortcutStartSearch: 'Iniciar una búsqueda', - shortcutStartAdvancedSearch: 'Iniciar una búsqueda avanzada', - shortcutToggleSidebar: 'Alternar barra lateral', - shortcutMuteSound: 'Silenciar', - shortcutToggleEqualizer: 'Abrir / alternar ecualizador', - shortcutToggleRepeat: 'Alternar repetición', - shortcutOpenNowPlaying: 'Abrir "Reproduciendo ahora"', - shortcutShowLyrics: 'Mostrar letra', - shortcutFavoriteCurrentTrack: 'Añadir pista actual a favoritos', - shortcutOpenHelp: 'Ayuda', - playbackTitle: 'Reproducción', - replayGain: 'Replay Gain', - replayGainDesc: 'Normalizar volumen de pistas usando metadatos ReplayGain', - replayGainMode: 'Modo', - replayGainAuto: 'Auto', - replayGainAutoDesc: 'Usa la ganancia del álbum cuando las pistas adyacentes en la cola son del mismo álbum, si no la ganancia de pista.', - replayGainTrack: 'Pista', - replayGainAlbum: 'Álbum', - replayGainPreGain: 'Pre-Ganancia (archivos etiquetados)', - replayGainPreGainDesc: 'Aumento universal añadido a cada cálculo de ReplayGain. Útil si tu biblioteca te parece globalmente demasiado baja.', - replayGainFallback: 'Respaldo (sin etiquetar / radio)', - replayGainFallbackDesc: 'Se aplica a pistas (y emisoras de radio) sin etiquetas ReplayGain, para que el contenido sin etiquetar no salte más fuerte que el resto.', - normalization: 'Normalización', - normalizationDesc: 'Iguala el volumen percibido entre pistas, álbumes y radio.', - normalizationOff: 'Apagado', - normalizationReplayGain: 'ReplayGain', - normalizationLufs: 'LUFS', - loudnessTargetLufs: 'LUFS objetivo', - loudnessTargetLufsDesc: 'Volumen de referencia al que se ajustan todas las pistas. Valor más bajo = salida más fuerte. Los servicios de streaming suelen rondar los -14 LUFS.', - loudnessPreAnalysisAttenuation: 'Atenuación antes de medir', - loudnessPreAnalysisAttenuationDesc: - 'Atenúa hasta que la loudness del tema esté guardada. En streaming luego solo hay estimaciones aproximadas. 0 dB = ninguna; más negativo = más bajo. A la derecha se muestra el dB efectivo para el destino actual.', - loudnessPreAnalysisAttenuationRef: 'Efectivo {{eff}} dB con destino {{tgt}} LUFS.', - loudnessPreAnalysisAttenuationReset: 'Predeterminado', - loudnessFirstPlayNote: - 'En la primera reproducción de un tema nuevo el volumen puede oscilar brevemente mientras se mide. La siguiente vez se usa la medición guardada y todo permanece estable. Las pistas próximas en la cola suelen analizarse durante la canción anterior, por lo que en la práctica esto rara vez ocurre.', - crossfade: 'Crossfade', - crossfadeDesc: 'Transición entre pistas', - crossfadeSecs: '{{n}} s', - notWithGapless: 'No disponible mientras Gapless está activo', - notWithCrossfade: 'No disponible mientras Crossfade está activo', - gapless: 'Reproducción Gapless', - gaplessDesc: 'Precarga siguiente pista para eliminar silencios entre canciones', - preservePlayNextOrder: 'Mantener el orden de "Reproducir Siguiente"', - preservePlayNextOrderDesc: 'Los elementos añadidos a "Reproducir Siguiente" se encolan detrás de los anteriores en vez de saltar al principio.', - trackPreviewsTitle: 'Previsualizaciones de pistas', - trackPreviewsToggle: 'Activar previsualizaciones', - trackPreviewsDesc: 'Mostrar botones de Reproducir y Previsualización en las listas de pistas para una muestra rápida a mitad de canción.', - trackPreviewStart: 'Posición inicial', - trackPreviewStartDesc: 'Cuánto avanza la pista antes de iniciar la previsualización (% de la duración).', - trackPreviewDuration: 'Duración', - trackPreviewDurationDesc: 'Cuánto dura cada previsualización antes de detenerse.', - trackPreviewDurationSecs: '{{n}} s', - trackPreviewLocationsTitle: 'Dónde aparecen las previsualizaciones', - trackPreviewLocationsDesc: 'Elige en qué listas se muestran los botones de previsualización.', - trackPreviewLocation_suggestions: 'En sugerencias de listas', - trackPreviewLocation_albums: 'En listas de pistas de álbum', - trackPreviewLocation_playlists: 'En listas de reproducción', - trackPreviewLocation_favorites: 'En favoritos', - trackPreviewLocation_artist: 'En las mejores pistas del artista', - trackPreviewLocation_randomMix: 'En Random Mix', - preloadMode: 'Precargar Siguiente Pista', - preloadModeDesc: 'Cuándo comenzar a cargar la siguiente pista en cola', - nextTrackBufferingTitle: 'Buffer', - preloadHotCacheMutualExclusive: 'Precarga y Caché Activa sirven para lo mismo — solo uno puede estar activo a la vez. Habilitar uno desactivará automáticamente el otro.', - preloadOff: 'Apagado', - preloadBalanced: 'Balanceado (30 s antes del final)', - preloadEarly: 'Temprano (después de 5 s de reproducción)', - preloadCustom: 'Personalizado', - preloadCustomSeconds: 'Segundos antes del final: {{n}}', - infiniteQueue: 'Cola Infinita', - infiniteQueueDesc: 'Agregar automáticamente pistas aleatorias cuando la cola termina', - experimental: 'Experimental', - fsPlayerSection: 'Reproductor Pantalla Completa', - fsShowArtistPortrait: 'Mostrar foto del artista', - fsShowArtistPortraitDesc: 'Muestra la foto del artista (o portada del álbum) en el lado derecho del reproductor pantalla completa.', - fsPortraitDim: 'Oscurecimiento de foto', - fsLyricsStyle: 'Estilo de letra', - fsLyricsStyleRail: 'Carril', - fsLyricsStyleRailDesc: 'Carril deslizante clásico de 5 líneas.', - fsLyricsStyleApple: 'Desplazamiento', - fsLyricsStyleAppleDesc: 'Lista desplazable a pantalla completa.', - sidebarLyricsStyle: 'Estilo de desplazamiento de letra', - sidebarLyricsStyleClassic: 'Clásico', - sidebarLyricsStyleClassicDesc: 'La línea activa se centra.', - sidebarLyricsStyleApple: 'Apple Music-like', - sidebarLyricsStyleAppleDesc: 'La línea activa se ancla arriba con animación suave.', - seekbarStyle: 'Estilo de Barra de Progreso', - seekbarStyleDesc: 'Elige la apariencia de la barra de progreso del reproductor', - seekbarTruewave: 'Forma de Onda Real', - seekbarPseudowave: 'Forma de Onda Pseudo', - seekbarLinedot: 'Línea y Punto', - seekbarBar: 'Barra', - seekbarThick: 'Barra Gruesa', - seekbarSegmented: 'Segmentada', - seekbarNeon: 'Brillo Neón', - seekbarPulsewave: 'Onda Pulsante', - seekbarParticletrail: 'Estela de Partículas', - seekbarLiquidfill: 'Llenado Líquido', - seekbarRetrotape: 'Cinta Retro', - themeSchedulerTitle: 'Cambio Automático de Tema', - themeSchedulerEnable: 'Habilitar Programador de Temas', - themeSchedulerEnableSub: 'Cambia automáticamente entre dos temas según la hora del día', - themeSchedulerDayTheme: 'Tema de Día', - themeSchedulerDayStart: 'Comienza de Día A las', - themeSchedulerNightTheme: 'Tema de Noche', - themeSchedulerNightStart: 'Comienza de Noche A las', - themeSchedulerActiveHint: 'El Programador de Temas está activo — los cambios de tema se manejan automáticamente.', - visualOptionsTitle: 'Opciones Visuales', - coverArtBackground: 'Fondo de Portada', - coverArtBackgroundSub: 'Mostrar portada desenfocada como fondo en encabezados de álbumes y listas de reproducción', - playlistCoverPhoto: 'Foto de Portada de Playlist', - playlistCoverPhotoSub: 'Mostrar cuadrícula de fotos de portada en la vista detallada de playlists', - showBitrate: 'Mostrar Bitrate', - showBitrateSub: 'Mostrar bitrate de audio en las listas de pistas', - floatingPlayerBar: 'Barra del Reproductor Flotante', - floatingPlayerBarSub: 'Mantener la barra del reproductor flotando sobre el contenido', - uiScaleTitle: 'Escala de Interfaz', - uiScaleLabel: 'Zoom', - }, - changelog: { - modalTitle: 'Novedades', - dontShowAgain: 'No mostrar de nuevo', - close: 'Entendido', - }, - whatsNew: { - title: 'Novedades', - empty: 'Aún no hay entrada de changelog para esta versión.', - bannerTitle: 'Changelog', - bannerCollapsed: 'Novedades en v{{version}}', - dismiss: 'Ocultar', - close: 'Cerrar', - }, - help: { - title: 'Ayuda', - searchPlaceholder: 'Buscar en la ayuda…', - noResults: 'No hay temas coincidentes. Prueba con otro término.', - s1: 'Primeros Pasos', - q1: '¿Qué servidores son compatibles?', - a1: 'Psysonic está construido principalmente para Navidrome y es totalmente compatible con Subsonic — Gonic, Airsonic, LMS y otros servidores Subsonic-API también funcionan. Algunas funciones avanzadas (calificaciones, listas inteligentes, compartir Magic String, gestión de usuarios) requieren Navidrome.', - q2: '¿Cómo añado un servidor?', - a2: 'Configuración → Servidores → Añadir Servidor. Introduce la URL (p.ej. http://192.168.1.100:4533), nombre de usuario y contraseña. Psysonic prueba la conexión antes de guardar — nada se guarda si falla. Puedes añadir tantos servidores como quieras y cambiar entre ellos en la cabecera; sólo uno está activo a la vez.', - q3: '¿Recorrido rápido por la interfaz?', - a3: 'Barra lateral (izquierda) para navegación, Mainstage / páginas en el centro, barra del reproductor abajo, panel de Cola a la derecha (se abre con el icono arriba a la derecha junto al indicador Now-Playing). La barra de búsqueda arriba busca en toda la biblioteca; «Now Playing» muestra qué están escuchando otros usuarios del mismo servidor Navidrome.', - s2: 'Reproducción y Cola', - q4: '¿Cómo uso la cola?', - a4: 'Abre el panel de Cola desde la cabecera arriba a la derecha. Arrastra filas para reordenar, arrástralas fuera para eliminar, o usa la barra de herramientas para mezclar, guardar la cola como lista o saltar a una pista. Arrastra filas fuera del panel para soltarlas en otro lugar como transferencia.', - q5: 'Gapless vs Crossfade — ¿cuál es la diferencia?', - a5: 'Gapless prebuferiza la siguiente pista para que no haya silencio entre canciones (ideal para discos en directo y mezclas DJ). Crossfade desvanece la pista actual mientras la siguiente entra en 1–10 s (ideal para mezclas aleatorias). Son mutuamente exclusivos — activar uno desactiva el otro. Configura ambos en Configuración → Audio.', - q6: '¿Qué es Cola Infinita?', - a6: 'Cuando la cola se acaba y Repetir está desactivado, Psysonic añade silenciosamente pistas similares/aleatorias de tu biblioteca para que la reproducción no se detenga. Las pistas auto-añadidas aparecen bajo un divisor «— Añadido automáticamente —». Activa/desactiva con el icono de infinito en la cabecera de la cola; restringe a un género en Configuración → Cola.', - q7: '¿Selección múltiple y rango con Mayús-clic?', - a7: 'Activa «Seleccionar» en Álbumes / Nuevos lanzamientos / Random Albums / Listas. Haz clic en un elemento para alternar, mantén Mayús y haz clic en otro elemento — todo lo que esté entre ambos en el orden visible se selecciona. Los Mayús-clic extienden desde el ancla más recientemente clicada. La barra de herramientas ofrece acciones masivas (cola, descarga, eliminar, etc.).', - q8: '¿Atajos de teclado y hotkeys globales?', - a8: 'Teclas in-app por defecto: Espacio = Reproducir / Pausa, Esc = cerrar pantalla completa / modales, F1 = chuleta de atajos. Configuración → Entrada permite reasignar cada acción in-app (incluyendo combinaciones como Ctrl+Mayús+P) y establecer atajos globales del sistema que funcionan incluso con Psysonic en segundo plano. Las teclas multimedia (Reproducir/Pausa, Siguiente, Anterior) funcionan en todas las plataformas.', - s3: 'Herramientas de Audio', - q9: '¿Modos de Replay Gain?', - a9: 'Configuración → Audio → Replay Gain. El modo Pista normaliza cada canción a un nivel objetivo. El modo Álbum preserva la curva de volumen dentro de un álbum. El modo Auto elige Pista o Álbum según si la cola viene de un solo álbum. Las pistas sin etiquetas Replay Gain caen a un preamplificador configurable.', - q10: '¿Qué es Smart Loudness Normalization (LUFS)?', - a10: 'Una alternativa moderna a Replay Gain en Configuración → Audio. Psysonic analiza cada pista a LUFS / EBU R128 y guarda el resultado, para un volumen consistente en toda tu biblioteca — incluyendo pistas sin etiquetas Replay Gain. El análisis en frío corre en segundo plano y usa 35–40 % de CPU durante ~1 minuto, luego cae a 0. Establece tu objetivo (por defecto −10 LUFS) una vez.', - q11: '¿EQ y AutoEQ?', - a11: 'Un EQ paramétrico de 10 bandas en Configuración → Audio → Ecualizador, con bandas manuales y preajustes. AutoEQ a su lado obtiene un perfil de corrección medido para tu modelo de auriculares de la base de datos AutoEQ y lo aplica automáticamente a las bandas — elige tus auriculares y el EQ se ajusta a la curva correcta.', - q12: '¿Cómo cambio el dispositivo de salida de audio?', - a12: 'Configuración → Audio → Dispositivo de Salida. Psysonic lista todas las salidas disponibles y cambia instantáneamente al elegir. El botón Actualizar detecta dispositivos conectados después del inicio. En Linux los nombres ALSA como «sysdefault» se limpian automáticamente para legibilidad.', - q13: '¿Qué es Hot Cache?', - a13: 'Hot Cache precarga la pista actual y las siguientes en RAM y en disco para que la reproducción comience sin retraso de buffering — especialmente útil en servidores lentos / remotos. La eviction se activa cuando se alcanza el límite de tamaño. Configura tamaño y el retardo de debounce (para que saltos rápidos no sobrecarguen) en Configuración → Audio.', - s4: 'Biblioteca y Descubrimiento', - q14: '¿Cómo funcionan las calificaciones y Skip-to-1★?', - a14: 'Psysonic admite calificaciones de 1–5 estrellas vía OpenSubsonic (Navidrome ≥ 0.53). Califica pistas en listas, en el menú contextual, o en la barra del reproductor bajo el nombre del artista; álbumes en la página del álbum; artistas en la página del artista. Skip-to-1★ (Configuración → Biblioteca → Calificaciones) asigna automáticamente 1 estrella tras un número configurable de saltos consecutivos. El mismo panel permite establecer una calificación mínima como filtro para Mixes generados.', - q15: '¿Cómo navego — Carpetas, Géneros, Pistas?', - a15: 'El navegador de carpetas (barra lateral) recorre el directorio musical del servidor en disposición Miller-column — clic en una carpeta para entrar, clic en una pista o el icono de play de una carpeta para reproducir / añadir. Géneros usa una vista de nube de etiquetas escalada por número de pistas; clic en un género para abrirlo. Pistas es un hub plano con lista virtual ordenable por columnas y búsqueda en vivo.', - q16: '¿Búsqueda y búsqueda avanzada?', - a16: 'La barra de búsqueda en la cabecera ejecuta una búsqueda en vivo mientras escribes a través de artistas, álbumes y pistas. Abre la búsqueda avanzada (barra lateral) para una vista más rica: filtra por año, género, calificación, formato, canales, frecuencia de muestreo, BPM, mood, y combina criterios. Clic derecho en cualquier resultado abre el mismo menú contextual usado en otros lugares.', - q17: '¿Qué son los Mixes (Random / Género / Super Genre / Lucky)?', - a17: 'Random Mix construye una lista de pistas aleatorias de tu biblioteca; el filtro de palabras clave excluye audiolibros, comedia, etc. por subcadenas de género / título / álbum. Super Genre Mix agrupa tu biblioteca en estilos amplios (Rock, Metal, Electrónica, Jazz, Clásica…) y construye un mix enfocado. Lucky Mix usa tu historial de escucha, calificaciones y pistas similares de AudioMuse-AI para ensamblar una lista instantánea con un clic.', - q18: '¿Página de estadísticas?', - a18: 'Estadísticas (barra lateral) muestra los principales artistas, álbumes, pistas, distribución por género, tiempo de escucha a lo largo del tiempo, y alcance por biblioteca cuando tienes más de una carpeta de música configurada. Varias vistas son exportables como imagen de tarjeta compartible.', - q19: '¿Cómo descargo un álbum como ZIP?', - a19: 'Página del álbum → «Descargar (ZIP)». El servidor comprime el álbum primero — para álbumes grandes o sin pérdida (FLAC / WAV) la barra de progreso aparece sólo cuando el zipping termina y la transferencia comienza. Esto es normal.', - s5: 'Letras', - q20: '¿De dónde vienen las letras?', - a20: 'Tres fuentes, configurables en Configuración → Letras: tu servidor Navidrome (letras embebidas / OpenSubsonic), LRCLIB (letras sincronizadas comunitarias) y NetEase Cloud Music (gran catálogo asiático + internacional). Cada fuente puede activarse / desactivarse y reordenarse arrastrando.', - q21: '¿Cómo veo letras durante la reproducción?', - a21: 'Haz clic en el icono del micrófono en la barra del reproductor para abrir la pestaña Letras en el panel de cola. Las letras sincronizadas se desplazan automáticamente y soportan clic-para-saltar; las letras de texto plano se desplazan como bloque estático. Activa el reproductor de pantalla completa desde la portada de la barra para una vista inmersiva con fondo mesh-blob.', - s6: 'Compartir y Social', - q22: '¿Qué son las Magic Strings?', - a22: 'Las Magic Strings son tokens cortos copy-paste que comparten cosas entre usuarios de Psysonic sin servidor de terceros. Las strings de invitación de servidor permiten a un amigo registrarse en tu Navidrome con un solo pegado; las Magic Strings de Álbum / Artista / Cola abren el mismo álbum / artista / cola en el receptor. Genéralas desde el menú compartir, pégalas en la barra de búsqueda para consumirlas.', - q23: '¿Qué es Orbit?', - a23: 'Orbit es escucha sincronizada en grupo: un anfitrión reproduce una pista, cada invitado la oye sincronizada, y los invitados pueden sugerir canciones que el anfitrión puede aceptar en la cola. Inicia una sesión desde el botón Orbit en la cabecera, comparte el enlace de invitación, y otros pueden unirse desde cualquier instalación de Psysonic. El anfitrión controla la reproducción (saltar, buscar, cola) — los invitados ven en tiempo real y tienen una caja de sugerencias. Las sesiones son efímeras y terminan cuando el anfitrión las cierra.', - q24: '¿Qué es el desplegable Now Playing?', - a24: 'El icono de transmisión arriba a la derecha muestra qué están escuchando otros usuarios en tu servidor Navidrome ahora mismo, refrescado cada 10 segundos. Tu propia entrada desaparece en cuanto pausas. Por servidor, así que los usuarios de otro servidor activo no se muestran.', - s7: 'Personalización', - q25: '¿Temas y planificador de tema?', - a25: 'Configuración → Apariencia → Tema elige entre 60+ temas en 8 grupos (Psysonic, Mediaplayer, Sistemas operativos, Juegos, Películas, Series, Redes sociales, Open Source Classics — Catppuccin / Nord / Gruvbox / Nightfox / Dracula). Auto-Switch Theme te permite establecer un tema diurno y nocturno con horas de inicio para que Psysonic cambie automáticamente.', - q26: '¿Puedo personalizar la barra lateral, Inicio y página de artista?', - a26: 'Sí — Configuración → Personalización. El customizador de barra lateral permite arrastrar elementos de navegación al orden deseado y ocultar los que no usas. El customizador de Inicio activa/desactiva cada fila de Mainstage (Hero, Recent, Discover, Recently Played, Starred…). El customizador de página de artista reordena las secciones (Top Songs, Álbumes, Singles, Compilaciones, Artistas similares, etc.) y oculta las que nunca miras.', - q27: '¿Qué es el Mini Player?', - a27: 'Una pequeña ventana flotante con cover, controles de transporte y cola compacta. Ábrela desde el icono mini-player en la barra del reproductor o con su atajo de teclado. La ventana recuerda su posición y tamaño entre sesiones. En Windows la mini-webview se precrea al inicio para apertura instantánea; Linux / macOS la activan opcionalmente vía Configuración → Apariencia → Precargar mini player.', - q28: '¿Qué es la Floating Player Bar?', - a28: 'Un estilo opcional de barra del reproductor (Configuración → Apariencia) que se separa del borde inferior con fondo temático, borde de acento, portada redondeada y sección de volumen centrada. Útil en monitores altos o temas compactos.', - q29: '¿Vista previa de pista al pasar el ratón?', - a29: 'Pasa el ratón sobre una fila de pista, haz clic en el botón pequeño de vista previa en la portada, o activa la vista previa desde el menú contextual — Psysonic transmite los primeros ~15 s a través del mismo motor de audio Rust para que la normalización de loudness se aplique. Útil para hojear un álbum que no has oído antes.', - q30: '¿Temporizador de suspensión?', - a30: 'Haz clic en el icono de luna en la barra del reproductor para abrir el temporizador. Elige una duración (o «final de la pista actual») y Psysonic desvanece y pausa al final. El botón muestra un anillo circular y una cuenta regresiva mientras corre el temporizador.', - q31: '¿Escala UI, fuente, estilo de seekbar?', - a31: 'Configuración → Apariencia — Escala de Interfaz (80–125 % sin afectar el tamaño de fuente del sistema), Fuente (10 fuentes UI incluyendo IBM Plex Mono, Fira Code, Geist, Golos Text…), Estilo de Seekbar (Forma de onda analizada / pseudoonda determinista / Línea y Punto / Barra / Barra Gruesa / Segmentada / Brillo Neón / Onda Pulso / Estela de Partículas / Relleno Líquido / Cinta Retro).', - s8: 'Usuario Avanzado', - q32: '¿Controles del reproductor por línea de comandos?', - a32: 'El binario Psysonic también funciona como mando a distancia. Ejemplos: psysonic --player play / pause / next / prev, --player volume 75, --player seek 15, --player shuffle, --player repeat off|all|one, --player rating 1-5. Cambia servidores, dispositivos de audio, bibliotecas; activa Instant Mix; busca artistas / álbumes / pistas. Lista completa con psysonic --player --help. Autocompletado de shell para bash y zsh vía psysonic completions.', - q33: '¿Listas Inteligentes (Navidrome)?', - a33: 'Las Listas Inteligentes son listas dinámicas del lado de Navidrome definidas por reglas (género = Rock Y año > 2020, etc.). La página Listas en Psysonic permite crearlas, editarlas y eliminarlas con un editor visual de reglas — Psysonic habla con la API nativa de Navidrome para esto. Se comportan como listas normales en el resto de la app y se actualizan automáticamente cuando cambia tu biblioteca.', - q34: '¿Respaldar y restaurar configuración?', - a34: 'Configuración → Almacenamiento → Respaldo y Restauración exporta perfiles de servidor, temas, atajos y otras configuraciones a un único archivo JSON. Importa el archivo en otra máquina o tras una reinstalación para restaurar todo de una vez. Las contraseñas de servidores están incluidas — guarda el archivo en privado.', - q35: '¿Dónde veo todas las licencias open-source?', - a35: 'Configuración → Sistema → Open Source Licenses. La lista completa de dependencias (cargo crates y paquetes npm) se entrega con textos de licencia incluidos. Haz clic en una entrada para el texto completo; el bloque destacado arriba resalta las bibliotecas reconocibles (Tauri, React, rodio, symphonia, etc.).', - s9: 'Offline y Sync', - q36: 'Modo offline — ¿caché de álbumes y listas?', - a36: 'Abre cualquier álbum o lista y haz clic en el icono de descarga en la cabecera — Psysonic almacena cada pista localmente para que se reproduzca desde disco sin llamada de red. La página Biblioteca Offline (barra lateral) lista todo lo cacheado, muestra el progreso en curso, y permite eliminar entradas con el icono de papelera (que aparece tras completar una descarga).', - q37: '¿Límite de almacenamiento offline?', - a37: 'Configuración → Biblioteca → Offline permite establecer un tamaño máximo de caché. Cuando se alcanza el límite, el botón de descarga de la página del álbum muestra un banner de aviso. Libera espacio eliminando álbumes o listas desde la página Biblioteca Offline.', - q38: 'Device Sync — ¿copiar música a USB / SD?', - a38: 'Device Sync (barra lateral) copia álbumes, listas o artistas enteros a una unidad externa para escucha offline en otros dispositivos. Elige una carpeta destino, elige fuentes de las pestañas del navegador, haz clic en «Transferir al dispositivo». Psysonic escribe un manifiesto (psysonic-sync.json) para saber qué archivos ya están allí, incluso si reabres Device Sync en otro SO con otra plantilla. Las plantillas soportan tokens {artist} / {album} / {title} / {track_number} / {disc_number} / {year} con / como separador de carpeta.', - s10: 'Integraciones y Solución de Problemas', - q39: '¿Scrobbling de Last.fm?', - a39: 'Configuración → Integraciones → Last.fm. Conecta tu cuenta una vez y Psysonic scrobblea directamente a Last.fm — no se necesita configuración de Navidrome. Un scrobble se envía tras escuchar el 50 % de una pista. Los pings now-playing se envían al inicio.', - q40: '¿Discord Rich Presence?', - a40: 'Configuración → Integraciones → Discord muestra tu pista actual en tu perfil de Discord. Elige entre el icono de la app, las portadas de tu servidor (vía getAlbumInfo2 — requiere un servidor accesible públicamente), o portadas de Apple Music. Personaliza las cadenas mostradas (detalles, estado, tooltip) con plantillas de tokens.', - q41: '¿Fechas de gira de Bandsintown?', - a41: 'Opt-in en Configuración → Integraciones → Now-Playing Info. La pestaña Now Playing en la página Now Playing muestra entonces fechas de gira próximas para el artista en reproducción vía Bandsintown widget API. Desactivado por defecto — no se hacen peticiones hasta que actives.', - q42: 'Internet Radio — ¿reproducir streams en vivo?', - a42: 'Internet Radio (barra lateral) reproduce cualquier stream en vivo almacenado en tu servidor Navidrome (añade emisoras vía la UI admin de Navidrome). La reproducción corre por el motor HTML5 audio del navegador — la mayoría de configuraciones de EQ / Replay Gain / Loudness no se aplican a la radio, pero sí se muestran los metadatos ICY (nombre de canción actual). Soporta MP3, AAC, OGG Vorbis y la mayoría de streams HLS; el soporte de codec depende de la plataforma.', - q43: 'La prueba de conexión falla — ¿qué hago?', - a43: 'Verifica la URL incluyendo el puerto (p.ej. http://192.168.1.100:4533). En una red local http:// suele funcionar donde https:// no (sin certificado). Asegúrate de que ningún firewall bloquee el puerto y que usuario y contraseña sean correctos. Si tu servidor está detrás de un proxy inverso, prueba primero la URL directa para aislar la causa.', - q44: 'Las portadas e imágenes de artista cargan lentamente.', - a44: 'Las imágenes se obtienen del servidor en la primera vista y luego se almacenan localmente durante 30 días. Si el almacenamiento de tu servidor es lento, la primera visita a una página puede tardar un momento; las visitas posteriores son instantáneas. Hot Cache también ayuda con pistas pero el caché de imágenes es independiente.', - q45: 'Problemas en Linux — ¿pantalla negra o sin sonido?', - a45: 'La pantalla negra es generalmente un problema de driver GPU / EGL en WebKitGTK — lanza con GDK_BACKEND=x11 WEBKIT_DISABLE_COMPOSITING_MODE=1 WEBKIT_DISABLE_DMABUF_RENDERER=1 (los instaladores AUR / .deb / .rpm los configuran automáticamente). Para audio, asegúrate de que PipeWire o PulseAudio esté ejecutándose. Los cortes de audio tras suspensión / despertar ahora son manejados automáticamente por el hook de recuperación post-sleep.', - }, - queue: { - title: 'Cola', - savePlaylist: 'Guardar Lista', - updatePlaylist: 'Actualizar Lista', - filterPlaylists: 'Filtrar listas…', - playlistName: 'Nombre de Lista', - cancel: 'Cancelar', - save: 'Guardar', - loadPlaylist: 'Cargar Lista', - loading: 'Cargando…', - noPlaylists: 'No se encontraron listas.', - load: 'Reemplazar cola y reproducir', - appendToQueue: 'Agregar a cola', - delete: 'Eliminar', - deleteConfirm: '¿Eliminar lista "{{name}}"?', - clear: 'Limpiar', - shuffle: 'Mezclar cola', - gapless: 'Gapless', - crossfade: 'Crossfade', - infiniteQueue: 'Cola Infinita', - autoAdded: '— Agregado automáticamente —', - radioAdded: '— Radio —', - hide: 'Ocultar', - hideNowPlaying: 'Ocultar información de reproducción', - showNowPlaying: 'Mostrar información de reproducción', - close: 'Cerrar', - nextTracks: 'Siguientes', - shareQueue: 'Copiar enlace de la cola', - shareQueueEmpty: 'La cola está vacía — no hay nada que compartir.', - emptyQueue: 'La cola está vacía.', - trackSingular: 'pista', - trackPlural: 'pistas', - showRemaining: 'Mostrar tiempo restante', - showTotal: 'Mostrar tiempo total', - showEta: 'Mostrar hora estimada de fin', - replayGain: 'ReplayGain', - rgTrack: 'T {{db}} dB', - rgAlbum: 'A {{db}} dB', - rgPeak: 'Pico {{pk}}', - sourceOffline: 'Reproducción desde la biblioteca sin conexión', - sourceHot: 'Reproducción desde la caché', - sourceStream: 'Reproducción desde la transmisión en red', - clearCachedLoudnessWaveform: 'Clear cached loudness and waveform, then re-analyze this track', - recalculatingLoudnessWaveform: 'Recalculating loudness and waveform for this track…', - }, - miniPlayer: { - showQueue: 'Mostrar cola', - hideQueue: 'Ocultar cola', - pinOnTop: 'Mantener encima', - pinOff: 'Desfijar', - openMainWindow: 'Abrir ventana principal', - close: 'Cerrar', - emptyQueue: 'La cola está vacía', - }, - statistics: { - title: 'Estadísticas', - recentlyPlayed: 'Reproducidos Recientemente', - mostPlayed: 'Álbumes Más Reproducidos', - highestRated: 'Álbumes Mejor Calificados', - genreDistribution: 'Distribución de Géneros (Top 20)', - loadMore: 'Cargar más', - statArtists: 'Artistas', - statArtistsTooltip: 'Solo artistas de álbum — los artistas que aparecen únicamente como artistas de pista (featuring, invitado, etc.) sin álbum propio no se cuentan.', - statAlbums: 'Álbumes', - statSongs: 'Canciones', - statGenres: 'Géneros', - statPlaytime: 'Tiempo Total de Reproducción', - genreInsights: 'Información de Géneros', - formatDistribution: 'Distribución de Formatos', - formatSample: 'Muestra de {{n}} pistas', - computing: 'Calculando…', - genreSongs: '{{count}} Canciones', - genreAlbums: '{{count}} Álbumes', - recentlyAdded: 'Agregados Recientemente', - decadeDistribution: 'Álbumes por Década', - decadeAlbums_one: '{{count}} Álbum', - decadeAlbums_other: '{{count}} Álbumes', - decadeUnknown: 'Desconocido', - lfmTitle: 'Estadísticas de Last.fm', - lfmTopArtists: 'Artistas Principales', - lfmTopAlbums: 'Álbumes Principales', - lfmTopTracks: 'Pistas Principales', - lfmPlays: '{{count}} reproducciones', - lfmPeriodOverall: 'Todo el Tiempo', - lfmPeriod7day: '7 Días', - lfmPeriod1month: '1 Mes', - lfmPeriod3month: '3 Meses', - lfmPeriod6month: '6 Meses', - lfmPeriod12month: '12 Meses', - lfmNotConnected: 'Conecta Last.fm en Configuración para ver tus estadísticas.', - lfmRecentTracks: 'Scrobbles Recientes', - lfmNowPlaying: 'Reproduciendo Ahora', - lfmJustNow: 'ahora mismo', - lfmMinutesAgo: 'hace {{n}}m', - lfmHoursAgo: 'hace {{n}}h', - lfmDaysAgo: 'hace {{n}}d', - topRatedSongs: 'Canciones Mejor Calificadas', - topRatedArtists: 'Artistas Mejor Calificados', - noRatedSongs: 'Aún no hay canciones calificadas. Califica canciones en la vista de álbum o playlist.', - noRatedArtists: 'Aún no hay artistas calificados.', - }, - player: { - regionLabel: 'Reproductor de Música', - openFullscreen: 'Abrir Reproductor Pantalla Completa', - fullscreen: 'Reproductor Pantalla Completa', - closeFullscreen: 'Cerrar Pantalla Completa', - closeTooltip: 'Cerrar (Esc)', - noTitle: 'Sin Título', - stop: 'Detener', - prev: 'Pista Anterior', - play: 'Reproducir', - pause: 'Pausa', - previewActive: 'Vista previa activa', - previewLabel: 'Vista previa', - delayModalTitle: 'Temporizador', - delayPauseSection: 'Pausar después de', - delayStartSection: 'Iniciar después de', - delayPreviewPause: 'Pausa a las', - delayPreviewStart: 'Inicio a las', - delaySchedulePause: 'Programar pausa', - delayScheduleStart: 'Programar inicio', - delayCancelPause: 'Cancelar temporizador de pausa', - delayCancelStart: 'Cancelar temporizador de inicio', - delayInactivePause: 'Solo disponible durante la reproducción.', - delayInactiveStart: 'Solo en pausa con pista o radio cargada.', - delayCustomMinutes: 'Retraso personalizado (minutos)', - delayCustomPlaceholder: 'p. ej. 2,5', - closeDelayModal: 'Cerrar', - delayIn: 'en', - delayFmtSec: '{{n}} s', - delayFmtMin: '{{n}} min', - delayFmtHr: '{{n}} h', - delayCancel: 'Cancelar', - delayApply: 'Aplicar', - next: 'Pista Siguiente', - repeat: 'Repetir', - repeatOff: 'Apagado', - repeatAll: 'Todo', - repeatOne: 'Una', - progress: 'Progreso de Canción', - volume: 'Volumen', - toggleQueue: 'Alternar Cola', - collapseQueueResize: 'Contraer cola, cambiar ancho', - moreOptions: 'Más opciones', - equalizer: 'Ecualizador', - miniPlayer: 'Mini reproductor', - lyrics: 'Letras', - fsLyricsToggle: 'Letras en pantalla completa', - lyricsLoading: 'Cargando letras…', - lyricsNotFound: 'No se encontraron letras para esta pista', - lyricsSourceServer: 'Fuente: Servidor', - lyricsSourceLrclib: 'Fuente: LRCLIB', - lyricsSourceNetease: 'Fuente: Netease', - lyricsSourceLyricsplus: 'Fuente: YouLyPlus', - showDuration: 'Mostrar duración', - showRemainingTime: 'Mostrar tiempo restante', - }, - nowPlayingInfo: { - tab: 'Info', - empty: 'Reproduce algo para ver información', - artist: 'Artista', - songInfo: 'Info de la canción', - onTour: 'En gira', - noTourEvents: 'No hay próximos conciertos', - tourLoading: 'Cargando…', - poweredByBandsintown: 'Datos de gira vía Bandsintown', - bioReadMore: 'Leer más', - bioReadLess: 'Ver menos', - showMoreTours_one: 'Mostrar {{count}} más', - showMoreTours_other: 'Mostrar {{count}} más', - showLessTours: 'Ver menos', - enableBandsintownPrompt: '¿Ver próximas fechas de gira?', - enableBandsintownPromptDesc: 'Opcional. Carga conciertos del artista actual vía la API pública de Bandsintown.', - enableBandsintownPrivacy: 'Al activar, el nombre del artista actual se envía a la API de Bandsintown para obtener fechas de gira. No se envían datos de cuenta ni personales.', - enableBandsintownAction: 'Activar', - role: { - artist: 'Artista', - albumArtist: 'Artista del álbum', - composer: 'Compositor', - }, - }, - songInfo: { - title: 'Información de Canción', - songTitle: 'Título', - artist: 'Artista', - album: 'Álbum', - albumArtist: 'Artista del Álbum', - year: 'Año', - genre: 'Género', - duration: 'Duración', - track: 'Pista', - format: 'Formato', - bitrate: 'Bitrate', - sampleRate: 'Frecuencia de Muestreo', - bitDepth: 'Profundidad de Bits', - channels: 'Canales', - fileSize: 'Tamaño de Archivo', - path: 'Ruta', - replayGainTrack: 'RG Ganancia de Pista', - replayGainAlbum: 'RG Ganancia de Álbum', - replayGainPeak: 'RG Pico de Pista', - mono: 'Mono', - stereo: 'Estéreo', - }, - playlists: { - title: 'Listas de Reproducción', - newPlaylist: 'Nueva Lista', - unnamed: 'Lista sin nombre', - createName: 'Nombre de lista…', - create: 'Crear', - cancel: 'Cancelar', - empty: 'Aún no hay listas.', - emptyPlaylist: 'Esta lista está vacía.', - addFirstSong: 'Agrega tu primera canción', - notFound: 'Lista no encontrada.', - songs: '{{n}} canciones', - playAll: 'Reproducir Todo', - shuffle: 'Aleatorio', - addToQueue: 'Agregar a Cola', - back: 'Volver a Listas', - deletePlaylist: 'Eliminar', - confirmDelete: 'Click de nuevo para confirmar', - removeSong: 'Quitar de lista', - addSongs: 'Agregar Canciones', - searchPlaceholder: 'Buscar en tu biblioteca…', - noResults: 'Sin resultados.', - suggestions: 'Canciones Sugeridas', - noSuggestions: 'No hay sugerencias disponibles.', - titleBadge: 'Lista', - refreshSuggestions: 'Nuevas sugerencias', - addSong: 'Agregar a lista', - preview: 'Vista previa (30 s)', - previewStop: 'Detener vista previa', - playNextSuggestion: 'Reproducir a continuación', - suggestionsHint: 'Doble clic en una fila para añadirla a la lista', - addSelected: 'Agregar seleccionados', - cacheOffline: 'Guardar lista offline', - offlineCached: 'Lista guardada', - removeOffline: 'Quitar de caché offline', - offlineDownloading: 'Descargando… ({{done}}/{{total}} álbumes)', - publicLabel: 'Pública', - privateLabel: 'Privada', - editMeta: 'Editar lista', - editNamePlaceholder: 'Nombre de lista…', - editCommentPlaceholder: 'Agregar descripción…', - editPublic: 'Lista pública', - editSave: 'Guardar', - editCancel: 'Cancelar', - changeCover: 'Cambiar imagen de portada', - changeCoverLabel: 'Cambiar foto', - removeCover: 'Quitar foto', - coverUpdated: 'Portada actualizada', - metaSaved: 'Lista actualizada', - downloadZip: 'Descargar (ZIP)', - // Toast notifications for multi-select - addSuccess: '{{count}} canciones agregadas a {{playlist}}', - addPartial: '{{added}} agregadas, {{skipped}} skippeadas por duplicadas', - addAllSkipped: 'Todas skippeadas ({{count}} duplicadas)', - addedAsDuplicates: '{{count}} canciones añadidas a {{playlist}} (como duplicados)', - duplicateConfirmTitle: 'Ya en la lista', - duplicateConfirmMessage: 'Las {{count}} canciones ya están en "{{playlist}}". ¿Añadirlas igualmente como duplicados?', - duplicateConfirmAction: 'Añadir igualmente', - addError: 'Error al agregar canciones', - createAndAddSuccess: 'Lista "{{playlist}}" creada con {{count}} canciones', - createError: 'Error al crear lista', - deleteSuccess: '{{count}} listas eliminadas', - deleteFailed: 'Error al eliminar {{name}}', - deleteSelected: 'Eliminar seleccionadas', - deleteSelectedPartial: 'Solo {{n}} de {{total}} listas seleccionadas pueden eliminarse (las demás pertenecen a otro usuario).', - mergeSuccess: '{{count}} canciones unificadas en {{playlist}}', - mergeNoNewSongs: 'No hay canciones nuevas para agregar', - mergeError: 'Error al unificar listas', - mergeInto: 'Unificar en', - selectionCount: '{{count}} seleccionadas', - select: 'Seleccionar', - startSelect: 'Activar selección', - cancelSelect: 'Cancelar', - loadingAlbums: 'Resolviendo {{count}} álbumes…', - loadingArtists: 'Resolviendo {{count}} artistas…', - myPlaylists: 'Mis Listas', - noOtherPlaylists: 'No hay otras listas disponibles', - addToPlaylistSuccess: '{{count}} canciones agregadas a {{playlist}}', - addToPlaylistNoNew: 'No hay canciones nuevas para agregar a {{playlist}}', - addToPlaylistError: 'Error al agregar a la lista', - removeSuccess: 'Canción quitada de la playlist', - removeError: 'Error al quitar la canción de la playlist', - importCSV: 'Importar CSV', - importCSVTooltip: 'Importar desde CSV de Spotify', - csvImportReport: 'Reporte de Importación CSV', - csvImportTotal: 'Total', - csvImportAdded: 'Agregadas', - csvImportDuplicates: 'Duplicadas', - csvImportNotFound: 'No Encontradas', - csvImportNetworkErrors: 'Errores de Red', - csvImportDuplicatesTitle: 'Canciones Duplicadas (Ya en la Lista):', - csvImportNotFoundTitle: 'Canciones No Encontradas:', - csvImportNetworkErrorsTitle: 'Errores de Red (puede reintentar la importación):', - csvImportDownloadReport: 'Descargar Reporte', - csvImportClose: 'Cerrar', - csvImportNoValidTracks: 'No se encontraron canciones válidas en el archivo CSV', - csvImportFailed: 'Error al importar el archivo CSV', - csvImportToast: '{{added}} agregadas, {{notFound}} no encontradas, {{duplicates}} duplicadas', - csvImportDownloadSuccess: 'Reporte descargado exitosamente', - csvImportDownloadError: 'Error al descargar el reporte', - }, - smartPlaylists: { - sectionBasic: '1. Básico', - sectionGenres: '2. Géneros', - sectionYearsAndFilters: '3. Años y filtros', - genreMode: 'Modo de géneros', - genreModeInclude: 'Incluir géneros', - genreModeExclude: 'Excluir géneros', - genreSearchPlaceholder: 'Filtrar géneros...', - availableGenres: 'Disponibles', - selectedGenres: 'Seleccionados', - yearMode: 'Modo de años', - yearModeInclude: 'Incluir rango', - yearModeExclude: 'Excluir rango', - name: 'Nombre (sin prefijo)', - limit: 'Límite', - limitHint: 'Cuántas canciones incluir en la playlist (1-{{max}}, normalmente 50).', - artistContains: 'Artista contiene…', - albumContains: 'Álbum contiene…', - titleContains: 'Título contiene…', - minRating: 'Valoración mínima', - minRatingAria: 'Valoración mínima para la playlist inteligente', - minRatingHint: '0 desactiva el umbral mínimo; 1-5 mantiene canciones con valoración mayor que el valor seleccionado.', - fromYear: 'Desde año', - toYear: 'Hasta año', - excludeUnrated: 'Excluir canciones sin valoración', - compilationOnly: 'Solo compilaciones', - create: 'Nueva Smart Playlist', - save: 'Guardar Smart Playlist', - created: '{{name}} creada', - updated: '{{name}} actualizada', - createFailed: 'No se pudo crear la smart playlist.', - updateFailed: 'No se pudo actualizar la smart playlist.', - navidromeOnly: 'Las smart playlists solo se pueden crear en servidores Navidrome.', - loadFailed: 'No se pudieron cargar las smart playlists desde Navidrome.', - sortRandom: 'Ordenar: aleatorio', - sortTitleAsc: 'Ordenar: título A-Z', - sortTitleDesc: 'Ordenar: título Z-A', - sortYearDesc: 'Ordenar: año desc', - sortYearAsc: 'Ordenar: año asc', - sortPlayCountDesc: 'Ordenar: reproducciones desc', - }, - mostPlayed: { - title: 'Más Reproducidos', - topArtists: 'Artistas Principales', - topAlbums: 'Álbumes Principales', - plays: '{{n}} reproducciones', - sortMost: 'Más reproducciones primero', - sortLeast: 'Menos reproducciones primero', - loadMore: 'Cargar más álbumes', - noData: 'Aún no hay datos de reproducción. ¡Empieza a escuchar!', - noArtists: 'Todos los artistas filtrados.', - filterCompilations: 'Ocultar artistas de compilaciones (Various Artists, Soundtracks, etc.)', - filterCompilationsShort: 'Ocultar compilaciones', - }, - losslessAlbums: { - empty: 'Aún no hay álbumes sin pérdidas en esta biblioteca.', - unsupported: 'Este servidor no expone los metadatos necesarios para encontrar álbumes sin pérdidas.', - slowFetchHint: 'Carga más lento que otras páginas de álbumes — Psysonic recorre todo el catálogo de canciones por calidad.', - }, - radio: { - title: 'Radio por Internet', - empty: 'No hay estaciones de radio configuradas.', - addStation: 'Agregar Estación', - editStation: 'Editar', - deleteStation: 'Eliminar estación', - confirmDelete: 'Click de nuevo para confirmar', - stationName: 'Nombre de estación…', - streamUrl: 'URL de stream…', - homepageUrl: 'URL de página (opcional)', - save: 'Guardar', - cancel: 'Cancelar', - live: 'EN VIVO', - liveStream: 'Radio por Internet', - openHomepage: 'Abrir página', - changeCoverLabel: 'Cambiar portada', - removeCover: 'Quitar portada', - browseDirectory: 'Buscar en Directorio', - directoryPlaceholder: 'Buscar estaciones…', - noResults: 'No se encontraron estaciones.', - stationAdded: 'Estación agregada', - filterAll: 'Todas', - filterFavorites: 'Favoritos', - sortManual: 'Manual', - sortAZ: 'A → Z', - sortZA: 'Z → A', - sortNewest: 'Más recientes', - favorite: 'Agregar a favoritos', - unfavorite: 'Quitar de favoritos', - noFavorites: 'No hay estaciones favoritas.', - listenerCount_one: '{{count}} oyente', - listenerCount_other: '{{count}} oyentes', - recentlyPlayed: 'Reproducidos Recientemente', - upNext: 'Siguientes', - }, - folderBrowser: { - empty: 'Carpeta vacía', - error: 'Error al cargar', - }, - deviceSync: { - title: 'Sincronizar dispositivo', - targetFolder: 'Carpeta de destino', - noFolderChosen: 'Ninguna carpeta seleccionada', - selectDrive: 'Seleccionar unidad…', - refreshDrives: 'Actualizar unidades', - noDrivesDetected: 'No se detectaron unidades extraíbles', - browseManual: 'Explorar manualmente…', - free: 'libre', - notMountedVolume: 'El destino no está en un volumen montado. La unidad puede haberse desconectado.', - chooseFolder: 'Elegir…', - filenameTemplate: 'Plantilla de nombre de archivo', - targetDevice: 'Dispositivo de destino', - templateHint: 'Variables: {artist}, {album}, {title}, {track_number}, {disc_number}, {year}', - cleanupButton: 'Eliminar archivos fuera de la selección', - cleanupNothingToDelete: 'Nada que eliminar — el dispositivo ya está sincronizado.', - confirmCleanup: '¿Eliminar {{count}} archivo(s) del dispositivo que no están en la selección actual? ¿Continuar?', - cleanupComplete: '{{count}} archivo(s) eliminado(s) del dispositivo.', - selectedSources: 'Fuentes seleccionadas', - noSourcesSelected: 'No hay fuentes seleccionadas. Haz clic en elementos del navegador para agregarlos.', - clearAll: 'Limpiar todo', - tabPlaylists: 'Listas de reproducción', - tabAlbums: 'Álbumes', - tabArtists: 'Artistas', - searchPlaceholder: 'Buscar…', - syncButton: 'Sincronizar al dispositivo', - actionTransfer: 'Transferir al dispositivo', - actionDelete: 'Eliminar del dispositivo', - actionApplyAll: 'Aplicar todos los cambios', - templatePreview: 'Vista previa', - templatePresetStandard: 'Estándar', - templatePresetMultiDisc: 'Multi-Disco', - templatePresetAltFolder: 'Carpeta alt.', - tokenSlashHint: '/ = separador de carpeta', - cancel: 'Cancelar', - noTargetDir: 'Por favor, elige primero una carpeta de destino.', - noSources: 'Por favor, selecciona al menos una fuente.', - noTracks: 'No se encontraron pistas en las fuentes seleccionadas.', - fetchError: 'Error al obtener pistas del servidor.', - syncComplete: 'Sincronización completada.', - dismiss: 'Cerrar', - cancelSync: 'Cancelar', - syncCancelled: 'Sincronización cancelada ({{done}} / {{total}} transferidos).', - colName: 'Nombre', - colType: 'Tipo', - colStatus: 'Estado', - onDevice: 'Gestor de dispositivo', - addSources: 'Agregar…', - syncResult: '{{done}} transferido(s), {{skipped}} ya actualizado(s) ({{total}} total)', - deleteFromDevice: 'Marcar para eliminar ({{count}})', - confirmDelete: '¿Eliminar {{count}} elemento(s) del dispositivo: {{names}}?', - deleteComplete: '{{count}} elemento(s) eliminado(s) del dispositivo.', - manifestImported: '{{count}} fuente(s) importada(s) desde el manifiesto del dispositivo.', - statusSynced: 'Sincronizado', - statusPending: 'Pendiente', - statusDeletion: 'Eliminación', - markForDeletion: 'Marcar para eliminar', - removeSource: 'Eliminar', - undoDeletion: 'Deshacer eliminación', - syncInBackground: 'Sincronización iniciada en segundo plano — puedes navegar a otro lugar.', - syncInProgress: '{{done}} / {{total}} pistas…', - syncSummary: 'Resumen de sincronización', - calculating: 'Calculando la carga útil requerida…', - filesToAdd: 'Archivos a agregar:', - filesToDelete: 'Archivos a eliminar:', - netChange: 'Cambio neto:', - availableSpace: 'Espacio disponible en disco:', - spaceWarning: 'Advertencia: El dispositivo de destino no tiene suficiente espacio reportado.', - proceed: 'Proceder con la sincronización', - notEnoughSpace: '¡Espacio físico en disco insuficiente detectado!', - liveSearch: 'Live', - randomAlbumsLabel: 'Álbumes aleatorios', - }, - orbit: { - triggerLabel: 'Orbit', - triggerTooltip: 'Iniciar o unirse a una sesión de escucha compartida', - launchCreate: 'Crear una sesión', - launchJoin: 'Unirse a una sesión', - launchHelp: '¿Cómo funciona esto?', - launchHelpSoon: 'Próximamente', - joinModalTitle: 'Unirse a una sesión Orbit', - joinModalSub: 'Pega el enlace de invitación que te envió tu anfitrión.', - joinModalLinkLabel: 'Enlace de invitación', - joinModalLinkPlaceholder: 'psysonic2-…', - joinModalLinkHelper: 'Funciona con cualquier enlace Orbit válido. Debe apuntar al servidor al que estás conectado actualmente.', - joinModalPasteTooltip: 'Pegar desde el portapapeles', - joinModalSubmit: 'Unirse', - joinModalBusy: 'Uniéndose…', - joinErrEmpty: 'Pega un enlace de invitación.', - joinErrInvalid: 'Eso no parece un enlace de invitación Orbit.', - closeAria: 'Cerrar', - heroTitlePrefix: 'Escucha junto con', - heroTitleBrand: 'Orbit', - heroSub: 'Inicia una sesión — otros usuarios en {{server}} escucharán contigo y podrán sugerir canciones.', - fallbackServer: 'este servidor', - tipLan: 'Actualmente estás conectado mediante una dirección de red local. Los invitados fuera de tu red no pueden unirse — cambia a una dirección de servidor pública en los ajustes antes de empezar.', - tipRemote: 'Para que los invitados fuera de tu red doméstica puedan unirse, la dirección de tu servidor debe ser accesible públicamente. Si tu servidor es solo interno, cambia antes de empezar.', - labelName: 'Nombre de la sesión', - namePlaceholder: 'Velvet Orbit', - reshuffleTooltip: 'Nueva sugerencia', - reshuffleAria: 'Sugerir un nuevo nombre', - helperName: 'Cómo aparecerá la sesión a tus invitados — déjalo o escribe el tuyo.', - labelMax: 'Invitados máx.', - helperMax: 'Tú no cuentas — esto solo limita a los invitados entrantes.', - labelLink: 'Enlace de invitación', - tooltipCopied: 'Copiado', - tooltipCopy: 'Copiar', - ariaCopyLink: 'Copiar enlace de invitación', - helperLink: 'Envía este enlace a tus invitados. Pueden pegarlo en cualquier parte de Psysonic con Ctrl+V.', - labelClearQueue: 'Vaciar mi cola primero', - helperClearQueue: 'Empieza la sesión con una cola vacía. Desactivado: las canciones ya en cola se mantienen y se comparten con los invitados.', - btnCancel: 'Cancelar', - btnStarting: 'Iniciando…', - btnStart: 'Iniciar Orbit', - btnCopyAndStart: 'Copiar enlace e iniciar', - errNameRequired: 'Por favor, dale un nombre a tu sesión.', - errStartFailed: 'No se pudo iniciar.', - hostLabel: 'Anfitrión: {{name}}', - participantsTooltip: 'Participantes', - settingsTooltip: 'Ajustes de sesión', - shareTooltip: 'Compartir enlace de invitación', - shuffleLabel: 'Próximo mezclado en', - catchUpLabel: 'alcanzar', - catchUpTooltip: 'Saltar a la posición actual del anfitrión', - hostAway: 'Anfitrión desconectado', - hostOnline: 'Anfitrión en línea', - endTooltip: 'Terminar sesión', - leaveTooltip: 'Salir de la sesión', - helpTooltip: 'Cómo funciona Orbit', - diag: { - openTooltip: 'Diagnóstico — registro de eventos copiable', - title: 'Diagnóstico de Orbit', - role: 'Rol', - hostTrack: 'ID de pista del anfitrión', - hostPos: 'Posición del anfitrión', - guestTrack: 'Mi ID de pista', - guestPos: 'Mi posición', - drift: 'Desfase', - stateAge: 'Edad del estado', - eventLog: 'Registro de eventos ({{count}})', - copyLabel: 'Copiar', - copyTooltip: 'Copiar registro al portapapeles', - clearLabel: 'Borrar', - clearTooltip: 'Vaciar el búfer', - empty: 'Aún sin eventos — aparecen cuando Orbit sincroniza.', - hint: 'Abre esto antes de reproducir el problema, luego pulsa Copiar y pega en el reporte.', - copied: '{{count}} líneas copiadas', - copyFailed: 'No se pudo copiar al portapapeles', - cleared: 'Búfer vaciado', - }, - helpTitle: 'Cómo funciona Orbit', - helpIntro: 'Orbit convierte Psysonic en una sala de escucha compartida. Un anfitrión elige la música; los invitados escuchan en sincronía y pueden sugerir canciones.', - helpHostOnly: '(anfitrión)', - helpSec1Title: '¿Qué es Orbit?', - helpSec1Body: 'Un modo de "escuchar juntos" — el anfitrión maneja la reproducción, los invitados se conectan. Todo pasa por playlists en tu propio servidor Navidrome; sin infraestructura externa.', - helpSec2Title: 'Anfitrión e invitados', - helpSec2Body: 'El anfitrión controla la reproducción (play / pause / skip / seek) y decide cuándo termina la sesión. Los invitados siguen la reproducción, pueden sugerir canciones y salir o volver a unirse en cualquier momento. Solo el anfitrión puede expulsar o banear permanentemente a un participante.', - helpSec2WarnHead: 'Importante: cuentas separadas.', - helpSec2WarnBody: 'Cada participante necesita su propia cuenta Navidrome. Si anfitrión e invitado inician sesión con el mismo usuario, sus envíos chocan y el anfitrión nunca ve las sugerencias del invitado.', - helpSec3Title: 'Iniciar e invitar', - helpSec3Body: 'Haz clic en el botón "Orbit" → Crear una sesión → el modal muestra un enlace de invitación listo para copiar y te permite opcionalmente vaciar tu cola actual. Comparte el enlace como prefieras. Mientras una sesión está activa, el botón de compartir en la barra superior copia el enlace en cualquier momento.', - helpSec4Title: 'Unirse', - helpSec4Body: 'Pega el enlace de invitación en cualquier parte de Psysonic con Ctrl+V / Cmd+V — el aviso para unirse aparece automáticamente. Alternativa: "Orbit" → Unirse a una sesión → pega en el campo. Si el enlace apunta a un servidor donde tienes una cuenta, Psysonic cambia automáticamente. Si tienes más de una cuenta en ese servidor, un pequeño selector pregunta cuál usar.', - helpSec5Title: 'Sugerir canciones', - helpSec5Body: 'En cualquier lista: doble clic en una fila, o clic derecho → "Añadir a la sesión Orbit". Un clic simple muestra una pista en lugar de tirar todo el álbum a la cola compartida — es intencional. Las acciones masivas explícitas como "Reproducir todo" o "Reproducir álbum" piden confirmación primero y luego añaden (nunca reemplazan).', - helpSec6Title: 'La cola compartida', - helpSec6Body: 'La cola muestra las próximas canciones del anfitrión — visible para todos. Las adiciones masivas siempre se añaden al final, para que las sugerencias de los invitados no se pierdan. El mezclado automático reordena la cola periódicamente (configurable: 1 / 5 / 10 / 15 / 30 min). Si tu reproducción se desvía del anfitrión, el botón "Alcanzar" en la barra te devuelve a la posición en vivo del anfitrión.', - helpSec7Title: 'Aprobaciones', - helpSec7Body: 'Por defecto, las sugerencias de los invitados necesitan aprobación manual — aparecen en una barra de "Aprobaciones" en la parte superior del panel con botones aceptar / rechazar. La aprobación automática puede activarse en los ajustes de sesión para que todo entre directamente.', - helpSec8Title: 'Participantes y ajustes', - helpSec8Body: 'Abre el icono de ajustes en la barra de sesión para la frecuencia de mezclado, la aprobación automática y el atajo "Mezclar ahora". Haz clic en el número de participantes para ver quién está conectado — expulsar (puede volver a unirse por el enlace) o banear (bloqueado para la sesión). Los invitados también ven la lista de participantes, pero solo de lectura.', - helpSec9Title: 'Terminar la sesión', - helpSec9Body: 'X del anfitrión → diálogo de confirmación → la sesión se cierra para todos y las playlists del servidor se limpian automáticamente. X del invitado → el invitado sale, la sesión sigue. Si el anfitrión queda en silencio 5 minutos, el invitado sale automáticamente con un aviso; las reconexiones cortas en esa ventana son invisibles.', - participantsInviteLabel: 'Enlace de invitación', - participantsCountLabel: '{{count}} en sesión', - participantsHost: 'anfitrión', - participantsEmpty: 'Aún no hay invitados', - participantsKickTooltip: 'Quitar de la sesión', - participantsKickAria: 'Quitar a {{user}}', - participantsRemoveTooltip: 'Quitar de la sesión', - participantsRemoveAria: 'Quitar a {{user}} de esta sesión', - participantsBanTooltip: 'Banear permanentemente', - participantsBanAria: 'Banear permanentemente a {{user}}', - participantsMuteTooltip: 'Silenciar sugerencias', - participantsUnmuteTooltip: 'Permitir sugerencias', - participantsMuteAria: 'Silenciar las sugerencias de {{user}}', - participantsUnmuteAria: 'Volver a permitir las sugerencias de {{user}}', - confirmRemoveTitle: '¿Quitar de la sesión?', - confirmRemoveBody: '{{user}} será expulsado de la sesión, pero puede volver a unirse por tu enlace de invitación.', - confirmRemoveConfirm: 'Quitar', - confirmBanTitle: '¿Banear permanentemente?', - confirmBanBody: '{{user}} será expulsado y bloqueado para volver a unirse a esta sesión. No se puede deshacer durante la sesión.', - confirmBanConfirm: 'Banear', - confirmCancel: 'Cancelar', - confirmJoinTitle: '¿Unirse a la sesión Orbit?', - confirmJoinBody: '{{host}} te ha invitado a "{{name}}". ¿Unirse a la sesión?', - confirmJoinConfirm: 'Unirse', - confirmLeaveTitle: '¿Salir de la sesión?', - confirmLeaveBody: '¿Salir de "{{name}}"? Puedes volver a unirte en cualquier momento por el enlace de invitación de {{host}}.', - confirmLeaveConfirm: 'Salir', - confirmEndTitle: '¿Terminar la sesión para todos?', - confirmEndBody: '"{{name}}" se cerrará para todos los participantes. Las playlists de la sesión se limpian automáticamente.', - confirmEndConfirm: 'Terminar sesión', - invalidLinkTitle: 'El enlace de invitación ya no es válido', - invalidLinkBody: 'Esta sesión Orbit ya no existe o ya ha terminado. Pide al anfitrión un nuevo enlace de invitación.', - settingsTitle: 'Ajustes de sesión', - settingAutoApprove: 'Aprobar sugerencias automáticamente', - settingAutoApproveHint: 'Las sugerencias de los invitados entran instantáneamente en tu cola. Desactivado: se quedan en la lista de sesión para revisión posterior.', - settingAutoShuffle: 'Mezclado automático', - settingAutoShuffleHint: 'Mezclado Fisher-Yates periódico de la cola próxima. Desactivado: el orden solo cambia cuando lo reorganizas.', - settingShuffleInterval: 'Remezclar cada', - settingShuffleIntervalHint: 'Con qué frecuencia se remezcla la cola próxima durante la sesión.', - suggestBlockedMuted: 'El anfitrión te silenció en esta sesión — sugerencias desactivadas.', - settingShuffleIntervalValue_one: '{{count}} min', - settingShuffleIntervalValue_other: '{{count}} min', - settingShuffleNow: 'Mezclar ahora', - toastSuggested: '{{user}} sugirió "{{title}}"', - toastSuggestedMany: '{{count}} nuevas sugerencias en la cola', - toastShuffled: 'Cola mezclada', - toastJoined: 'Te has unido a la sesión', - toastLoginFirst: 'Inicia sesión antes de unirte a una sesión', - toastSwitchServer: 'Cambia primero a {{url}}, luego pega de nuevo', - toastNoAccountForServer: 'No tienes acceso a {{url}}. Pide al anfitrión una invitación.', - toastSwitchFailed: 'No se pudo cambiar a {{url}}', - accountPickerTitle: '¿Qué cuenta?', - accountPickerSub: 'Tienes más de una cuenta para {{url}}. Elige con cuál unirte a la sesión.', - toastJoinFail: 'No se pudo unir a la sesión', - joinErrNotFound: 'Sesión no encontrada', - joinErrEnded: 'La sesión ha terminado', - joinErrFull: 'La sesión está llena', - joinErrKicked: 'No puedes volver a unirte a esta sesión', - joinErrNoUser: 'Sin servidor activo', - joinErrServerError: 'No se pudo unir', - ctxAddToSession: 'Añadir a la sesión Orbit', - ctxSuggestedToast: 'Sugerido a la sesión', - ctxSuggestFailed: 'No se pudo sugerir — no unido', - ctxAddToSessionHost: 'Añadir a la sesión Orbit', - ctxAddedHostToast: 'Añadido a la sesión', - ctxAddHostFailed: 'No se pudo añadir a la sesión', - bulkConfirmTitle: '¿Añadir todo esto a la cola Orbit?', - bulkConfirmBody: 'Esto lanzaría {{count}} canciones a la cola compartida de una vez. Es mucho para tus invitados. ¿Continuar?', - bulkConfirmYes: 'Añadir todas', - bulkConfirmNo: 'Cancelar', - guestLive: 'En vivo', - guestPlaying: 'Reproduciendo ahora', - guestPaused: 'En pausa', - guestLoading: 'Cargando…', - guestSuggestions: 'Sugerencias', - guestUpNext: 'A continuación', - guestUpNextEmpty: 'Nada en cola. Abre el menú contextual de una canción y elige "Añadir a la sesión Orbit" para sugerir una.', - guestPendingTitle: 'Esperando al anfitrión', - guestPendingHint: 'Sugerido — aparecerá en la cola cuando el anfitrión lo acepte.', - approvalTitle: 'Pendiente de aprobación', - approvalFrom: 'Sugerido por {{user}}', - approvalAccept: 'Aceptar', - approvalDecline: 'Rechazar', - guestUpNextMore: '+ {{count}} más en la cola del anfitrión', - guestSubmitter: 'de {{user}}', - queueAddedByHost: 'Añadido por el anfitrión', - queueAddedByYou: 'Añadido por ti', - queueAddedByUser: 'Añadido por {{user}}', - guestEmpty: 'Aún no hay sugerencias. Abre el menú contextual de una canción y elige "Añadir a la sesión Orbit".', - guestFooter: 'El anfitrión controla la reproducción — no puedes cambiar la lista.', - exitKickedTitle: 'Has sido baneado de la sesión', - exitRemovedTitle: 'Has sido quitado de la sesión', - exitEndedTitle: 'El anfitrión ha terminado la sesión', - exitHostTimeoutTitle: 'Anfitrión en silencio', - exitHostTimeoutBody: '{{host}} no ha enviado una actualización durante un rato, así que "{{name}}" se cerró en tu lado. Puedes volver a unirte en cualquier momento con el enlace de invitación.', - exitKickedBody: '{{host}} te ha baneado de "{{name}}". No puedes volver a unirte.', - exitRemovedBody: '{{host}} te ha quitado de "{{name}}". Puedes volver a unirte en cualquier momento por el enlace.', - exitEndedBody: '"{{name}}" ha terminado. Espero que te hayas divertido.', - exitOk: 'OK', - }, - tray: { - playPause: 'Reproducir / Pausa', - nextTrack: 'Pista siguiente', - previousTrack: 'Pista anterior', - showHide: 'Mostrar / Ocultar', - exitPsysonic: 'Salir de Psysonic', - nothingPlaying: 'Nada en reproducción', - }, - licenses: { - title: 'Licencias de Código Abierto', - intro: 'Psysonic se basa en software de código abierto. La lista siguiente muestra cada dependencia incluida con la aplicación, con su versión, licencia y el texto completo de la licencia.', - highlights: 'Dependencias principales', - searchPlaceholder: 'Buscar por nombre, versión o licencia…', - noResults: 'Sin resultados.', - loading: 'Cargando licencias…', - loadError: 'No se pudieron cargar los datos de licencia.', - noLicenseText: 'No hay texto de licencia incluido para esta dependencia.', - viewSource: 'Ver fuente', - totalLine: '{{total}} dependencias — {{cargo}} cargo, {{npm}} npm', - generatedAt: 'Última generación {{date}}', - }, -}; diff --git a/src/locales/es/albumDetail.ts b/src/locales/es/albumDetail.ts new file mode 100644 index 00000000..d76135ee --- /dev/null +++ b/src/locales/es/albumDetail.ts @@ -0,0 +1,47 @@ +export const albumDetail = { + back: 'Volver', + orbitDoubleClickHint: 'Doble clic para añadir esta canción a la cola Orbit', + playAll: 'Reproducir Todo', + shareAlbum: 'Compartir álbum', + enqueue: 'Agregar a la Cola', + enqueueTooltip: 'Agregar álbum completo a la cola', + artistBio: 'Biografía del Artista', + download: 'Descargar (ZIP)', + downloading: 'Cargando…', + cacheOffline: 'Disponible offline', + offlineCached: 'Disponible offline', + offlineDownloading: 'Descargando… ({{n}}/{{total}})', + removeOffline: 'Quitar de offline', + offlineStorageFull: 'Almacenamiento offline lleno (límite: {{mb}} MB). Libera espacio eliminando un álbum de tu Biblioteca Offline, o aumenta el límite en Configuración.', + offlineStorageGoToLibrary: 'Biblioteca Offline', + offlineStorageGoToSettings: 'Configuración', + favoriteAdd: 'Agregar a Favoritos', + favoriteRemove: 'Quitar de Favoritos', + favorite: 'Favorito', + noBio: 'No hay biografía disponible.', + moreByArtist: 'Más de {{artist}}', + tracksCount: '{{n}} Pistas', + goToArtist: 'Ir a {{artist}}', + moreLabelAlbums: 'Más álbumes en {{label}}', + trackTitle: 'Título', + trackAlbum: 'Álbum', + trackArtist: 'Artista', + trackGenre: 'Género', + trackFormat: 'Formato', + trackFavorite: 'Favorito', + trackRating: 'Calificación', + trackDuration: 'Duración', + trackTotal: 'Total', + columns: 'Columnas', + resetColumns: 'Restablecer', + notFound: 'Álbum no encontrado.', + bioModal: 'Biografía del Artista', + bioClose: 'Cerrar', + ratingLabel: 'Calificación', + enlargeCover: 'Ampliar', + filterSongs: 'Filtrar canciones…', + sortNatural: 'Natural', + sortByTitle: 'A–Z (Título)', + sortByArtist: 'A–Z (Artista)', + sortByAlbum: 'A–Z (Álbum)', +}; diff --git a/src/locales/es/albums.ts b/src/locales/es/albums.ts new file mode 100644 index 00000000..a6765e46 --- /dev/null +++ b/src/locales/es/albums.ts @@ -0,0 +1,33 @@ +export const albums = { + title: 'Todos los Álbumes', + sortByName: 'A–Z (Álbum)', + sortByArtist: 'A–Z (Artista)', + sortNewest: 'Más recientes primero', + sortRandom: 'Aleatorio', + yearFrom: 'Desde', + yearTo: 'Hasta', + yearFilterClear: 'Limpiar filtro de año', + yearFilterLabel: 'Año', + compilationLabel: 'Recopilatorios', + compilationOnly: 'Solo recopilatorios', + compilationHide: 'Ocultar recopilatorios', + compilationTooltipAll: 'Todos los álbumes · clic: solo recopilatorios', + compilationTooltipOnly: 'Solo recopilatorios · clic: ocultar recopilatorios', + compilationTooltipHide: 'Recopilatorios ocultos · clic: mostrar todo', + select: 'Selección múltiple', + startSelect: 'Activar selección múltiple', + cancelSelect: 'Cancelar', + selectionCount: '{{count}} seleccionados', + downloadZips: 'Descargar ZIPs', + addOffline: 'Agregar Offline', + enqueueSelected_one: 'A la cola ({{count}})', + enqueueSelected_other: 'A la cola ({{count}})', + enqueueQueued_one: '{{count}} álbum añadido a la cola', + enqueueQueued_other: '{{count}} álbumes añadidos a la cola', + downloadingZip: 'Descargando {{current}}/{{total}}: {{name}}', + downloadZipDone: '{{count}} ZIP(s) descargado(s)', + downloadZipFailed: 'Error al descargar {{name}}', + offlineQueuing: 'Encolando {{count}} álbum(es) para offline…', + offlineFailed: 'Error al agregar {{name}} offline', + addToPlaylist: 'Agregar a Lista de Reproducción', +}; diff --git a/src/locales/es/artistDetail.ts b/src/locales/es/artistDetail.ts new file mode 100644 index 00000000..78ff70e2 --- /dev/null +++ b/src/locales/es/artistDetail.ts @@ -0,0 +1,41 @@ +export const artistDetail = { + back: 'Volver', + albums: 'Álbumes', + album: 'Álbum', + playAll: 'Reproducir Todo', + shareArtist: 'Compartir artista', + shuffle: 'Aleatorio', + radio: 'Radio', + loading: 'Cargando…', + noRadio: 'No se encontraron pistas similares para este artista.', + notFound: 'Artista no encontrado.', + albumsBy: 'Álbumes de {{name}}', + topTracks: 'Mejores Pistas', + noAlbums: 'No se encontraron álbumes.', + trackTitle: 'Título', + trackAlbum: 'Álbum', + trackDuration: 'Duración', + favoriteAdd: 'Agregar a Favoritos', + favoriteRemove: 'Quitar de Favoritos', + favorite: 'Favorito', + albumCount_one: '{{count}} Álbum', + albumCount_other: '{{count}} Álbumes', + openedInBrowser: 'Abierto en navegador', + featuredOn: 'También Aparece En', + similarArtists: 'Artistas Similares', + cacheOffline: 'Guardar discografía offline', + offlineCached: 'Discografía guardada', + offlineDownloading: 'Descargando… ({{done}}/{{total}} álbumes)', + uploadImage: 'Subir imagen del artista', + uploadImageError: 'Error al subir imagen', + releaseTypes: { + album: 'Álbum', + ep: 'EP', + single: 'Single', + compilation: 'Recopilación', + live: 'En vivo', + soundtrack: 'Banda sonora', + remix: 'Remix', + other: 'Otro', + }, +}; diff --git a/src/locales/es/artists.ts b/src/locales/es/artists.ts new file mode 100644 index 00000000..a7b78747 --- /dev/null +++ b/src/locales/es/artists.ts @@ -0,0 +1,18 @@ +export const artists = { + title: 'Artistas', + search: 'Buscar…', + all: 'Todos', + gridView: 'Vista de cuadrícula', + listView: 'Vista de lista', + imagesOn: 'Imágenes de artistas activadas — puede aumentar la carga de red y sistema', + imagesOff: 'Imágenes de artistas desactivadas — mostrando solo iniciales', + loadMore: 'Cargar más', + notFound: 'No se encontraron artistas.', + albumCount_one: '{{count}} Álbum', + albumCount_other: '{{count}} Álbumes', + selectionCount: '{{count}} seleccionados', + select: 'Selección múltiple', + startSelect: 'Activar selección múltiple', + cancelSelect: 'Cancelar', + addToPlaylist: 'Agregar a Lista', +}; diff --git a/src/locales/es/changelog.ts b/src/locales/es/changelog.ts new file mode 100644 index 00000000..14cb939d --- /dev/null +++ b/src/locales/es/changelog.ts @@ -0,0 +1,5 @@ +export const changelog = { + modalTitle: 'Novedades', + dontShowAgain: 'No mostrar de nuevo', + close: 'Entendido', +}; diff --git a/src/locales/es/common.ts b/src/locales/es/common.ts new file mode 100644 index 00000000..3ab8dd9d --- /dev/null +++ b/src/locales/es/common.ts @@ -0,0 +1,56 @@ +export const common = { + albums: 'Álbumes', + album: 'Álbum', + loading: 'Cargando…', + loadingMore: 'Cargando…', + loadingPlaylists: 'Cargando Listas…', + noAlbums: 'No se encontraron álbumes.', + downloading: 'Descargando…', + downloadZip: 'Descargar (ZIP)', + back: 'Volver', + cancel: 'Cancelar', + save: 'Guardar', + delete: 'Eliminar', + use: 'Usar', + add: 'Agregar', + new: 'Nuevo', + active: 'Activo', + download: 'Descargar', + chooseDownloadFolder: 'Elegir carpeta de descarga', + noFolderSelected: 'Ninguna carpeta seleccionada', + rememberDownloadFolder: 'Recordar esta carpeta', + filterGenre: 'Filtro de Género', + filterSearchGenres: 'Buscar géneros…', + filterNoGenres: 'Ningún género coincide', + filterClear: 'Limpiar', + favorites: 'Favoritos', + favoritesTooltipOff: 'Mostrar solo favoritos', + favoritesTooltipOn: 'Mostrar todo', + play: 'Reproducir', + bulkSelected: '{{count}} seleccionados', + clearSelection: 'Limpiar selección', + bulkAddToPlaylist: 'Agregar a Lista', + bulkRemoveFromPlaylist: 'Quitar de Lista', + bulkClear: 'Limpiar selección', + updaterAvailable: 'Actualización disponible', + updaterVersion: 'v{{version}} está disponible', + updaterWebsite: 'Sitio web', + updaterModalTitle: 'Nueva Versión Disponible', + updaterChangelog: 'Novedades', + updaterDownloadBtn: 'Descargar Ahora', + updaterSkipBtn: 'Omitir esta Versión', + updaterRemindBtn: 'Recordarme Después', + updaterDone: 'Descarga completada', + updaterShowFolder: 'Mostrar en Carpeta', + updaterInstallHint: 'Cierra Psysonic y ejecuta el instalador manualmente.', + updaterAurHint: 'Instala la actualización vía AUR:', + updaterErrorMsg: 'Error de descarga', + updaterRetryBtn: 'Reintentar', + durationHoursMinutes: '{{hours}}h {{minutes}}m', + durationMinutesOnly: '{{minutes}}m', + updaterOpenGitHub: 'Abrir en GitHub', + filters: 'Filtros', + more: 'más', + yearRange: 'Rango de años', + clearAll: 'Limpiar todo', +}; diff --git a/src/locales/es/composerDetail.ts b/src/locales/es/composerDetail.ts new file mode 100644 index 00000000..3d2cd5b3 --- /dev/null +++ b/src/locales/es/composerDetail.ts @@ -0,0 +1,11 @@ +export const composerDetail = { + back: 'Atrás', + notFound: 'Compositor no encontrado.', + about: 'Sobre este compositor', + works: 'Obras', + noWorks: 'No se encontraron obras.', + workCount_one: '{{count}} obra', + workCount_other: '{{count}} obras', + shareComposer: 'Compartir compositor', + unknownComposer: 'Compositor', +}; diff --git a/src/locales/es/composers.ts b/src/locales/es/composers.ts new file mode 100644 index 00000000..6da7530a --- /dev/null +++ b/src/locales/es/composers.ts @@ -0,0 +1,10 @@ +export const composers = { + title: 'Compositores', + search: 'Buscar…', + notFound: 'No se encontraron compositores.', + unsupported: 'La navegación por compositor requiere Navidrome 0.55 o más reciente.', + loadFailed: 'No se pudieron cargar los compositores.', + retry: 'Reintentar', + involvedIn_one: 'Participa en {{count}} álbum', + involvedIn_other: 'Participa en {{count}} álbumes', +}; diff --git a/src/locales/es/connection.ts b/src/locales/es/connection.ts new file mode 100644 index 00000000..d403c9a6 --- /dev/null +++ b/src/locales/es/connection.ts @@ -0,0 +1,28 @@ +export const connection = { + connected: 'Conectado', + connectedTo: 'Conectado a {{server}}', + disconnected: 'Desconectado', + disconnectedFrom: 'No se puede alcanzar {{server}} — click para verificar configuración', + checking: 'Conectando…', + extern: 'Externo', + offlineTitle: 'Sin conexión al servidor', + offlineSubtitle: 'No se puede alcanzar {{server}}. Verifica tu red o servidor.', + offlineModeBanner: 'Modo Offline — reproduciendo desde caché local', + offlineNoCacheBanner: 'Sin conexión al servidor — no se puede acceder a {{server}}', + offlineLibraryTitle: 'Biblioteca Offline', + offlineLibraryEmpty: 'No hay álbumes en caché aún. Conéctate, abre un álbum y click en "Disponible offline".', + offlineAlbumCount: '{{n}} álbum', + offlineAlbumCount_plural: '{{n}} álbumes', + offlineFilterAll: 'Todos', + offlineFilterAlbums: 'Álbumes', + offlineFilterPlaylists: 'Listas', + offlineFilterArtists: 'Discografías', + retry: 'Reintentar', + serverSettings: 'Configuración del servidor', + switchServerTitle: 'Cambiar servidor', + switchServerHint: 'Clic para elegir otro servidor guardado.', + manageServers: 'Gestionar servidores…', + switchFailed: 'No se pudo cambiar — servidor inalcanzable.', + lastfmConnected: 'Last.fm conectado como @{{user}}', + lastfmSessionInvalid: 'Sesión inválida — click para reconectar', +}; diff --git a/src/locales/es/contextMenu.ts b/src/locales/es/contextMenu.ts new file mode 100644 index 00000000..73edd119 --- /dev/null +++ b/src/locales/es/contextMenu.ts @@ -0,0 +1,33 @@ +export const contextMenu = { + playNow: 'Reproducir Ahora', + playNext: 'Reproducir Siguiente', + addToQueue: 'Agregar a la Cola', + enqueueAlbum: 'Agregar Álbum a la Cola', + enqueueAlbums_one: 'Agregar {{count}} álbum a la cola', + enqueueAlbums_other: 'Agregar {{count}} álbumes a la cola', + startRadio: 'Iniciar Radio', + instantMix: 'Mezcla Instantánea', + instantMixFailed: 'No se pudo crear la Mezcla Instantánea — error del servidor o plugin.', + cliMixNeedsTrack: 'No hay nada en reproducción — inicia la reproducción y vuelve a ejecutar el comando de mezcla.', + lfmLove: 'Favorito en Last.fm', + lfmUnlove: 'Quitar favorito de Last.fm', + favorite: 'Favorito', + favoriteArtist: 'Artista Favorito', + favoriteAlbum: 'Álbum Favorito', + unfavorite: 'Quitar de Favoritos', + unfavoriteArtist: 'Quitar Artista de Favoritos', + unfavoriteAlbum: 'Quitar Álbum de Favoritos', + removeFromQueue: 'Quitar de la Cola', + removeFromPlaylist: 'Quitar de la Playlist', + openAlbum: 'Abrir Álbum', + goToArtist: 'Ir al Artista', + download: 'Descargar (ZIP)', + addToPlaylist: 'Agregar a Lista de Reproducción', + selectedPlaylists: '{{count}} listas seleccionadas', + selectedAlbums: '{{count}} álbumes seleccionados', + selectedArtists: '{{count}} artistas seleccionados', + songInfo: 'Información de la Canción', + shareLink: 'Copiar enlace para compartir', + shareCopied: 'Enlace copiado al portapapeles.', + shareCopyFailed: 'No se pudo copiar al portapapeles.', +}; diff --git a/src/locales/es/deviceSync.ts b/src/locales/es/deviceSync.ts new file mode 100644 index 00000000..91d969c0 --- /dev/null +++ b/src/locales/es/deviceSync.ts @@ -0,0 +1,73 @@ +export const deviceSync = { + title: 'Sincronizar dispositivo', + targetFolder: 'Carpeta de destino', + noFolderChosen: 'Ninguna carpeta seleccionada', + selectDrive: 'Seleccionar unidad…', + refreshDrives: 'Actualizar unidades', + noDrivesDetected: 'No se detectaron unidades extraíbles', + browseManual: 'Explorar manualmente…', + free: 'libre', + notMountedVolume: 'El destino no está en un volumen montado. La unidad puede haberse desconectado.', + chooseFolder: 'Elegir…', + filenameTemplate: 'Plantilla de nombre de archivo', + targetDevice: 'Dispositivo de destino', + templateHint: 'Variables: {artist}, {album}, {title}, {track_number}, {disc_number}, {year}', + cleanupButton: 'Eliminar archivos fuera de la selección', + cleanupNothingToDelete: 'Nada que eliminar — el dispositivo ya está sincronizado.', + confirmCleanup: '¿Eliminar {{count}} archivo(s) del dispositivo que no están en la selección actual? ¿Continuar?', + cleanupComplete: '{{count}} archivo(s) eliminado(s) del dispositivo.', + selectedSources: 'Fuentes seleccionadas', + noSourcesSelected: 'No hay fuentes seleccionadas. Haz clic en elementos del navegador para agregarlos.', + clearAll: 'Limpiar todo', + tabPlaylists: 'Listas de reproducción', + tabAlbums: 'Álbumes', + tabArtists: 'Artistas', + searchPlaceholder: 'Buscar…', + syncButton: 'Sincronizar al dispositivo', + actionTransfer: 'Transferir al dispositivo', + actionDelete: 'Eliminar del dispositivo', + actionApplyAll: 'Aplicar todos los cambios', + templatePreview: 'Vista previa', + templatePresetStandard: 'Estándar', + templatePresetMultiDisc: 'Multi-Disco', + templatePresetAltFolder: 'Carpeta alt.', + tokenSlashHint: '/ = separador de carpeta', + cancel: 'Cancelar', + noTargetDir: 'Por favor, elige primero una carpeta de destino.', + noSources: 'Por favor, selecciona al menos una fuente.', + noTracks: 'No se encontraron pistas en las fuentes seleccionadas.', + fetchError: 'Error al obtener pistas del servidor.', + syncComplete: 'Sincronización completada.', + dismiss: 'Cerrar', + cancelSync: 'Cancelar', + syncCancelled: 'Sincronización cancelada ({{done}} / {{total}} transferidos).', + colName: 'Nombre', + colType: 'Tipo', + colStatus: 'Estado', + onDevice: 'Gestor de dispositivo', + addSources: 'Agregar…', + syncResult: '{{done}} transferido(s), {{skipped}} ya actualizado(s) ({{total}} total)', + deleteFromDevice: 'Marcar para eliminar ({{count}})', + confirmDelete: '¿Eliminar {{count}} elemento(s) del dispositivo: {{names}}?', + deleteComplete: '{{count}} elemento(s) eliminado(s) del dispositivo.', + manifestImported: '{{count}} fuente(s) importada(s) desde el manifiesto del dispositivo.', + statusSynced: 'Sincronizado', + statusPending: 'Pendiente', + statusDeletion: 'Eliminación', + markForDeletion: 'Marcar para eliminar', + removeSource: 'Eliminar', + undoDeletion: 'Deshacer eliminación', + syncInBackground: 'Sincronización iniciada en segundo plano — puedes navegar a otro lugar.', + syncInProgress: '{{done}} / {{total}} pistas…', + syncSummary: 'Resumen de sincronización', + calculating: 'Calculando la carga útil requerida…', + filesToAdd: 'Archivos a agregar:', + filesToDelete: 'Archivos a eliminar:', + netChange: 'Cambio neto:', + availableSpace: 'Espacio disponible en disco:', + spaceWarning: 'Advertencia: El dispositivo de destino no tiene suficiente espacio reportado.', + proceed: 'Proceder con la sincronización', + notEnoughSpace: '¡Espacio físico en disco insuficiente detectado!', + liveSearch: 'Live', + randomAlbumsLabel: 'Álbumes aleatorios', +}; diff --git a/src/locales/es/entityRating.ts b/src/locales/es/entityRating.ts new file mode 100644 index 00000000..9673d3b3 --- /dev/null +++ b/src/locales/es/entityRating.ts @@ -0,0 +1,9 @@ +export const entityRating = { + albumShort: 'Calificación del álbum', + artistShort: 'Calificación del artista', + albumAriaLabel: 'Calificación del álbum', + artistAriaLabel: 'Calificación del artista', + selectedArtistsRatingAriaLabel: 'Calificación con estrellas para {{count}} artistas seleccionados', + selectedAlbumsRatingAriaLabel: 'Calificación con estrellas para {{count}} álbumes seleccionados', + saveFailed: 'No se pudo guardar la calificación.', +}; diff --git a/src/locales/es/favorites.ts b/src/locales/es/favorites.ts new file mode 100644 index 00000000..99e21f13 --- /dev/null +++ b/src/locales/es/favorites.ts @@ -0,0 +1,19 @@ +export const favorites = { + title: 'Favoritos', + empty: "Aún no has guardado ningún favorito.", + artists: 'Artistas', + albums: 'Álbumes', + songs: 'Canciones', + enqueueAll: 'Agregar todo a la cola', + playAll: 'Reproducir todo', + removeSong: 'Quitar de favoritos', + stations: 'Estaciones de Radio', + showingFiltered: 'Mostrando {{filtered}} de {{total}} ({{artist}})', + showingCount: 'Mostrando {{filtered}} de {{total}}', + clearArtistFilter: 'Limpiar filtro de artista', + noFilterResults: 'No hay resultados con los filtros seleccionados.', + allArtists: 'Todos los Artistas', + topArtists: 'Artistas favoritos principales', + topArtistsSongCount_one: '{{count}} canción', + topArtistsSongCount_other: '{{count}} canciones', +}; diff --git a/src/locales/es/folderBrowser.ts b/src/locales/es/folderBrowser.ts new file mode 100644 index 00000000..9bcedc81 --- /dev/null +++ b/src/locales/es/folderBrowser.ts @@ -0,0 +1,4 @@ +export const folderBrowser = { + empty: 'Carpeta vacía', + error: 'Error al cargar', +}; diff --git a/src/locales/es/genres.ts b/src/locales/es/genres.ts new file mode 100644 index 00000000..59270632 --- /dev/null +++ b/src/locales/es/genres.ts @@ -0,0 +1,12 @@ +export const genres = { + title: 'Géneros', + genreCount: 'Géneros', + albumCount_one: '{{count}} álbum', + albumCount_other: '{{count}} álbumes', + loading: 'Cargando géneros…', + empty: 'No se encontraron géneros.', + albumsLoading: 'Cargando álbumes…', + albumsEmpty: 'No se encontraron álbumes para este género.', + loadMore: 'Cargar más', + back: 'Volver', +}; diff --git a/src/locales/es/help.ts b/src/locales/es/help.ts new file mode 100644 index 00000000..baf2d8aa --- /dev/null +++ b/src/locales/es/help.ts @@ -0,0 +1,105 @@ +export const help = { + title: 'Ayuda', + searchPlaceholder: 'Buscar en la ayuda…', + noResults: 'No hay temas coincidentes. Prueba con otro término.', + s1: 'Primeros Pasos', + q1: '¿Qué servidores son compatibles?', + a1: 'Psysonic está construido principalmente para Navidrome y es totalmente compatible con Subsonic — Gonic, Airsonic, LMS y otros servidores Subsonic-API también funcionan. Algunas funciones avanzadas (calificaciones, listas inteligentes, compartir Magic String, gestión de usuarios) requieren Navidrome.', + q2: '¿Cómo añado un servidor?', + a2: 'Configuración → Servidores → Añadir Servidor. Introduce la URL (p.ej. http://192.168.1.100:4533), nombre de usuario y contraseña. Psysonic prueba la conexión antes de guardar — nada se guarda si falla. Puedes añadir tantos servidores como quieras y cambiar entre ellos en la cabecera; sólo uno está activo a la vez.', + q3: '¿Recorrido rápido por la interfaz?', + a3: 'Barra lateral (izquierda) para navegación, Mainstage / páginas en el centro, barra del reproductor abajo, panel de Cola a la derecha (se abre con el icono arriba a la derecha junto al indicador Now-Playing). La barra de búsqueda arriba busca en toda la biblioteca; «Now Playing» muestra qué están escuchando otros usuarios del mismo servidor Navidrome.', + s2: 'Reproducción y Cola', + q4: '¿Cómo uso la cola?', + a4: 'Abre el panel de Cola desde la cabecera arriba a la derecha. Arrastra filas para reordenar, arrástralas fuera para eliminar, o usa la barra de herramientas para mezclar, guardar la cola como lista o saltar a una pista. Arrastra filas fuera del panel para soltarlas en otro lugar como transferencia.', + q5: 'Gapless vs Crossfade — ¿cuál es la diferencia?', + a5: 'Gapless prebuferiza la siguiente pista para que no haya silencio entre canciones (ideal para discos en directo y mezclas DJ). Crossfade desvanece la pista actual mientras la siguiente entra en 1–10 s (ideal para mezclas aleatorias). Son mutuamente exclusivos — activar uno desactiva el otro. Configura ambos en Configuración → Audio.', + q6: '¿Qué es Cola Infinita?', + a6: 'Cuando la cola se acaba y Repetir está desactivado, Psysonic añade silenciosamente pistas similares/aleatorias de tu biblioteca para que la reproducción no se detenga. Las pistas auto-añadidas aparecen bajo un divisor «— Añadido automáticamente —». Activa/desactiva con el icono de infinito en la cabecera de la cola; restringe a un género en Configuración → Cola.', + q7: '¿Selección múltiple y rango con Mayús-clic?', + a7: 'Activa «Seleccionar» en Álbumes / Nuevos lanzamientos / Random Albums / Listas. Haz clic en un elemento para alternar, mantén Mayús y haz clic en otro elemento — todo lo que esté entre ambos en el orden visible se selecciona. Los Mayús-clic extienden desde el ancla más recientemente clicada. La barra de herramientas ofrece acciones masivas (cola, descarga, eliminar, etc.).', + q8: '¿Atajos de teclado y hotkeys globales?', + a8: 'Teclas in-app por defecto: Espacio = Reproducir / Pausa, Esc = cerrar pantalla completa / modales, F1 = chuleta de atajos. Configuración → Entrada permite reasignar cada acción in-app (incluyendo combinaciones como Ctrl+Mayús+P) y establecer atajos globales del sistema que funcionan incluso con Psysonic en segundo plano. Las teclas multimedia (Reproducir/Pausa, Siguiente, Anterior) funcionan en todas las plataformas.', + s3: 'Herramientas de Audio', + q9: '¿Modos de Replay Gain?', + a9: 'Configuración → Audio → Replay Gain. El modo Pista normaliza cada canción a un nivel objetivo. El modo Álbum preserva la curva de volumen dentro de un álbum. El modo Auto elige Pista o Álbum según si la cola viene de un solo álbum. Las pistas sin etiquetas Replay Gain caen a un preamplificador configurable.', + q10: '¿Qué es Smart Loudness Normalization (LUFS)?', + a10: 'Una alternativa moderna a Replay Gain en Configuración → Audio. Psysonic analiza cada pista a LUFS / EBU R128 y guarda el resultado, para un volumen consistente en toda tu biblioteca — incluyendo pistas sin etiquetas Replay Gain. El análisis en frío corre en segundo plano y usa 35–40 % de CPU durante ~1 minuto, luego cae a 0. Establece tu objetivo (por defecto −10 LUFS) una vez.', + q11: '¿EQ y AutoEQ?', + a11: 'Un EQ paramétrico de 10 bandas en Configuración → Audio → Ecualizador, con bandas manuales y preajustes. AutoEQ a su lado obtiene un perfil de corrección medido para tu modelo de auriculares de la base de datos AutoEQ y lo aplica automáticamente a las bandas — elige tus auriculares y el EQ se ajusta a la curva correcta.', + q12: '¿Cómo cambio el dispositivo de salida de audio?', + a12: 'Configuración → Audio → Dispositivo de Salida. Psysonic lista todas las salidas disponibles y cambia instantáneamente al elegir. El botón Actualizar detecta dispositivos conectados después del inicio. En Linux los nombres ALSA como «sysdefault» se limpian automáticamente para legibilidad.', + q13: '¿Qué es Hot Cache?', + a13: 'Hot Cache precarga la pista actual y las siguientes en RAM y en disco para que la reproducción comience sin retraso de buffering — especialmente útil en servidores lentos / remotos. La eviction se activa cuando se alcanza el límite de tamaño. Configura tamaño y el retardo de debounce (para que saltos rápidos no sobrecarguen) en Configuración → Audio.', + s4: 'Biblioteca y Descubrimiento', + q14: '¿Cómo funcionan las calificaciones y Skip-to-1★?', + a14: 'Psysonic admite calificaciones de 1–5 estrellas vía OpenSubsonic (Navidrome ≥ 0.53). Califica pistas en listas, en el menú contextual, o en la barra del reproductor bajo el nombre del artista; álbumes en la página del álbum; artistas en la página del artista. Skip-to-1★ (Configuración → Biblioteca → Calificaciones) asigna automáticamente 1 estrella tras un número configurable de saltos consecutivos. El mismo panel permite establecer una calificación mínima como filtro para Mixes generados.', + q15: '¿Cómo navego — Carpetas, Géneros, Pistas?', + a15: 'El navegador de carpetas (barra lateral) recorre el directorio musical del servidor en disposición Miller-column — clic en una carpeta para entrar, clic en una pista o el icono de play de una carpeta para reproducir / añadir. Géneros usa una vista de nube de etiquetas escalada por número de pistas; clic en un género para abrirlo. Pistas es un hub plano con lista virtual ordenable por columnas y búsqueda en vivo.', + q16: '¿Búsqueda y búsqueda avanzada?', + a16: 'La barra de búsqueda en la cabecera ejecuta una búsqueda en vivo mientras escribes a través de artistas, álbumes y pistas. Abre la búsqueda avanzada (barra lateral) para una vista más rica: filtra por año, género, calificación, formato, canales, frecuencia de muestreo, BPM, mood, y combina criterios. Clic derecho en cualquier resultado abre el mismo menú contextual usado en otros lugares.', + q17: '¿Qué son los Mixes (Random / Género / Super Genre / Lucky)?', + a17: 'Random Mix construye una lista de pistas aleatorias de tu biblioteca; el filtro de palabras clave excluye audiolibros, comedia, etc. por subcadenas de género / título / álbum. Super Genre Mix agrupa tu biblioteca en estilos amplios (Rock, Metal, Electrónica, Jazz, Clásica…) y construye un mix enfocado. Lucky Mix usa tu historial de escucha, calificaciones y pistas similares de AudioMuse-AI para ensamblar una lista instantánea con un clic.', + q18: '¿Página de estadísticas?', + a18: 'Estadísticas (barra lateral) muestra los principales artistas, álbumes, pistas, distribución por género, tiempo de escucha a lo largo del tiempo, y alcance por biblioteca cuando tienes más de una carpeta de música configurada. Varias vistas son exportables como imagen de tarjeta compartible.', + q19: '¿Cómo descargo un álbum como ZIP?', + a19: 'Página del álbum → «Descargar (ZIP)». El servidor comprime el álbum primero — para álbumes grandes o sin pérdida (FLAC / WAV) la barra de progreso aparece sólo cuando el zipping termina y la transferencia comienza. Esto es normal.', + s5: 'Letras', + q20: '¿De dónde vienen las letras?', + a20: 'Tres fuentes, configurables en Configuración → Letras: tu servidor Navidrome (letras embebidas / OpenSubsonic), LRCLIB (letras sincronizadas comunitarias) y NetEase Cloud Music (gran catálogo asiático + internacional). Cada fuente puede activarse / desactivarse y reordenarse arrastrando.', + q21: '¿Cómo veo letras durante la reproducción?', + a21: 'Haz clic en el icono del micrófono en la barra del reproductor para abrir la pestaña Letras en el panel de cola. Las letras sincronizadas se desplazan automáticamente y soportan clic-para-saltar; las letras de texto plano se desplazan como bloque estático. Activa el reproductor de pantalla completa desde la portada de la barra para una vista inmersiva con fondo mesh-blob.', + s6: 'Compartir y Social', + q22: '¿Qué son las Magic Strings?', + a22: 'Las Magic Strings son tokens cortos copy-paste que comparten cosas entre usuarios de Psysonic sin servidor de terceros. Las strings de invitación de servidor permiten a un amigo registrarse en tu Navidrome con un solo pegado; las Magic Strings de Álbum / Artista / Cola abren el mismo álbum / artista / cola en el receptor. Genéralas desde el menú compartir, pégalas en la barra de búsqueda para consumirlas.', + q23: '¿Qué es Orbit?', + a23: 'Orbit es escucha sincronizada en grupo: un anfitrión reproduce una pista, cada invitado la oye sincronizada, y los invitados pueden sugerir canciones que el anfitrión puede aceptar en la cola. Inicia una sesión desde el botón Orbit en la cabecera, comparte el enlace de invitación, y otros pueden unirse desde cualquier instalación de Psysonic. El anfitrión controla la reproducción (saltar, buscar, cola) — los invitados ven en tiempo real y tienen una caja de sugerencias. Las sesiones son efímeras y terminan cuando el anfitrión las cierra.', + q24: '¿Qué es el desplegable Now Playing?', + a24: 'El icono de transmisión arriba a la derecha muestra qué están escuchando otros usuarios en tu servidor Navidrome ahora mismo, refrescado cada 10 segundos. Tu propia entrada desaparece en cuanto pausas. Por servidor, así que los usuarios de otro servidor activo no se muestran.', + s7: 'Personalización', + q25: '¿Temas y planificador de tema?', + a25: 'Configuración → Apariencia → Tema elige entre 60+ temas en 8 grupos (Psysonic, Mediaplayer, Sistemas operativos, Juegos, Películas, Series, Redes sociales, Open Source Classics — Catppuccin / Nord / Gruvbox / Nightfox / Dracula). Auto-Switch Theme te permite establecer un tema diurno y nocturno con horas de inicio para que Psysonic cambie automáticamente.', + q26: '¿Puedo personalizar la barra lateral, Inicio y página de artista?', + a26: 'Sí — Configuración → Personalización. El customizador de barra lateral permite arrastrar elementos de navegación al orden deseado y ocultar los que no usas. El customizador de Inicio activa/desactiva cada fila de Mainstage (Hero, Recent, Discover, Recently Played, Starred…). El customizador de página de artista reordena las secciones (Top Songs, Álbumes, Singles, Compilaciones, Artistas similares, etc.) y oculta las que nunca miras.', + q27: '¿Qué es el Mini Player?', + a27: 'Una pequeña ventana flotante con cover, controles de transporte y cola compacta. Ábrela desde el icono mini-player en la barra del reproductor o con su atajo de teclado. La ventana recuerda su posición y tamaño entre sesiones. En Windows la mini-webview se precrea al inicio para apertura instantánea; Linux / macOS la activan opcionalmente vía Configuración → Apariencia → Precargar mini player.', + q28: '¿Qué es la Floating Player Bar?', + a28: 'Un estilo opcional de barra del reproductor (Configuración → Apariencia) que se separa del borde inferior con fondo temático, borde de acento, portada redondeada y sección de volumen centrada. Útil en monitores altos o temas compactos.', + q29: '¿Vista previa de pista al pasar el ratón?', + a29: 'Pasa el ratón sobre una fila de pista, haz clic en el botón pequeño de vista previa en la portada, o activa la vista previa desde el menú contextual — Psysonic transmite los primeros ~15 s a través del mismo motor de audio Rust para que la normalización de loudness se aplique. Útil para hojear un álbum que no has oído antes.', + q30: '¿Temporizador de suspensión?', + a30: 'Haz clic en el icono de luna en la barra del reproductor para abrir el temporizador. Elige una duración (o «final de la pista actual») y Psysonic desvanece y pausa al final. El botón muestra un anillo circular y una cuenta regresiva mientras corre el temporizador.', + q31: '¿Escala UI, fuente, estilo de seekbar?', + a31: 'Configuración → Apariencia — Escala de Interfaz (80–125 % sin afectar el tamaño de fuente del sistema), Fuente (10 fuentes UI incluyendo IBM Plex Mono, Fira Code, Geist, Golos Text…), Estilo de Seekbar (Forma de onda analizada / pseudoonda determinista / Línea y Punto / Barra / Barra Gruesa / Segmentada / Brillo Neón / Onda Pulso / Estela de Partículas / Relleno Líquido / Cinta Retro).', + s8: 'Usuario Avanzado', + q32: '¿Controles del reproductor por línea de comandos?', + a32: 'El binario Psysonic también funciona como mando a distancia. Ejemplos: psysonic --player play / pause / next / prev, --player volume 75, --player seek 15, --player shuffle, --player repeat off|all|one, --player rating 1-5. Cambia servidores, dispositivos de audio, bibliotecas; activa Instant Mix; busca artistas / álbumes / pistas. Lista completa con psysonic --player --help. Autocompletado de shell para bash y zsh vía psysonic completions.', + q33: '¿Listas Inteligentes (Navidrome)?', + a33: 'Las Listas Inteligentes son listas dinámicas del lado de Navidrome definidas por reglas (género = Rock Y año > 2020, etc.). La página Listas en Psysonic permite crearlas, editarlas y eliminarlas con un editor visual de reglas — Psysonic habla con la API nativa de Navidrome para esto. Se comportan como listas normales en el resto de la app y se actualizan automáticamente cuando cambia tu biblioteca.', + q34: '¿Respaldar y restaurar configuración?', + a34: 'Configuración → Almacenamiento → Respaldo y Restauración exporta perfiles de servidor, temas, atajos y otras configuraciones a un único archivo JSON. Importa el archivo en otra máquina o tras una reinstalación para restaurar todo de una vez. Las contraseñas de servidores están incluidas — guarda el archivo en privado.', + q35: '¿Dónde veo todas las licencias open-source?', + a35: 'Configuración → Sistema → Open Source Licenses. La lista completa de dependencias (cargo crates y paquetes npm) se entrega con textos de licencia incluidos. Haz clic en una entrada para el texto completo; el bloque destacado arriba resalta las bibliotecas reconocibles (Tauri, React, rodio, symphonia, etc.).', + s9: 'Offline y Sync', + q36: 'Modo offline — ¿caché de álbumes y listas?', + a36: 'Abre cualquier álbum o lista y haz clic en el icono de descarga en la cabecera — Psysonic almacena cada pista localmente para que se reproduzca desde disco sin llamada de red. La página Biblioteca Offline (barra lateral) lista todo lo cacheado, muestra el progreso en curso, y permite eliminar entradas con el icono de papelera (que aparece tras completar una descarga).', + q37: '¿Límite de almacenamiento offline?', + a37: 'Configuración → Biblioteca → Offline permite establecer un tamaño máximo de caché. Cuando se alcanza el límite, el botón de descarga de la página del álbum muestra un banner de aviso. Libera espacio eliminando álbumes o listas desde la página Biblioteca Offline.', + q38: 'Device Sync — ¿copiar música a USB / SD?', + a38: 'Device Sync (barra lateral) copia álbumes, listas o artistas enteros a una unidad externa para escucha offline en otros dispositivos. Elige una carpeta destino, elige fuentes de las pestañas del navegador, haz clic en «Transferir al dispositivo». Psysonic escribe un manifiesto (psysonic-sync.json) para saber qué archivos ya están allí, incluso si reabres Device Sync en otro SO con otra plantilla. Las plantillas soportan tokens {artist} / {album} / {title} / {track_number} / {disc_number} / {year} con / como separador de carpeta.', + s10: 'Integraciones y Solución de Problemas', + q39: '¿Scrobbling de Last.fm?', + a39: 'Configuración → Integraciones → Last.fm. Conecta tu cuenta una vez y Psysonic scrobblea directamente a Last.fm — no se necesita configuración de Navidrome. Un scrobble se envía tras escuchar el 50 % de una pista. Los pings now-playing se envían al inicio.', + q40: '¿Discord Rich Presence?', + a40: 'Configuración → Integraciones → Discord muestra tu pista actual en tu perfil de Discord. Elige entre el icono de la app, las portadas de tu servidor (vía getAlbumInfo2 — requiere un servidor accesible públicamente), o portadas de Apple Music. Personaliza las cadenas mostradas (detalles, estado, tooltip) con plantillas de tokens.', + q41: '¿Fechas de gira de Bandsintown?', + a41: 'Opt-in en Configuración → Integraciones → Now-Playing Info. La pestaña Now Playing en la página Now Playing muestra entonces fechas de gira próximas para el artista en reproducción vía Bandsintown widget API. Desactivado por defecto — no se hacen peticiones hasta que actives.', + q42: 'Internet Radio — ¿reproducir streams en vivo?', + a42: 'Internet Radio (barra lateral) reproduce cualquier stream en vivo almacenado en tu servidor Navidrome (añade emisoras vía la UI admin de Navidrome). La reproducción corre por el motor HTML5 audio del navegador — la mayoría de configuraciones de EQ / Replay Gain / Loudness no se aplican a la radio, pero sí se muestran los metadatos ICY (nombre de canción actual). Soporta MP3, AAC, OGG Vorbis y la mayoría de streams HLS; el soporte de codec depende de la plataforma.', + q43: 'La prueba de conexión falla — ¿qué hago?', + a43: 'Verifica la URL incluyendo el puerto (p.ej. http://192.168.1.100:4533). En una red local http:// suele funcionar donde https:// no (sin certificado). Asegúrate de que ningún firewall bloquee el puerto y que usuario y contraseña sean correctos. Si tu servidor está detrás de un proxy inverso, prueba primero la URL directa para aislar la causa.', + q44: 'Las portadas e imágenes de artista cargan lentamente.', + a44: 'Las imágenes se obtienen del servidor en la primera vista y luego se almacenan localmente durante 30 días. Si el almacenamiento de tu servidor es lento, la primera visita a una página puede tardar un momento; las visitas posteriores son instantáneas. Hot Cache también ayuda con pistas pero el caché de imágenes es independiente.', + q45: 'Problemas en Linux — ¿pantalla negra o sin sonido?', + a45: 'La pantalla negra es generalmente un problema de driver GPU / EGL en WebKitGTK — lanza con GDK_BACKEND=x11 WEBKIT_DISABLE_COMPOSITING_MODE=1 WEBKIT_DISABLE_DMABUF_RENDERER=1 (los instaladores AUR / .deb / .rpm los configuran automáticamente). Para audio, asegúrate de que PipeWire o PulseAudio esté ejecutándose. Los cortes de audio tras suspensión / despertar ahora son manejados automáticamente por el hook de recuperación post-sleep.', +}; diff --git a/src/locales/es/hero.ts b/src/locales/es/hero.ts new file mode 100644 index 00000000..cd50a669 --- /dev/null +++ b/src/locales/es/hero.ts @@ -0,0 +1,6 @@ +export const hero = { + eyebrow: 'Álbum Destacado', + playAlbum: 'Reproducir Álbum', + enqueue: 'Agregar a la Cola', + enqueueTooltip: 'Agregar álbum completo a la cola', +}; diff --git a/src/locales/es/home.ts b/src/locales/es/home.ts new file mode 100644 index 00000000..e27809c5 --- /dev/null +++ b/src/locales/es/home.ts @@ -0,0 +1,19 @@ +export const home = { + hero: 'Destacado', + starred: 'Favoritos Personales', + recent: 'Agregados Recientemente', + mostPlayed: 'Más Reproducidos', + recentlyPlayed: 'Reproducidos Recientemente', + losslessAlbums: 'Álbumes sin Pérdidas', + discover: 'Descubrir', + discoverSongs: 'Descubrir canciones', + loadMore: 'Cargar Más', + discoverMore: 'Descubrir Más', + discoverArtists: 'Descubrir Artistas', + discoverArtistsMore: 'Todos los Artistas', + becauseYouLike: 'Porque escuchaste…', + becauseYouLikeFor: 'Porque escuchaste a {{artist}}', + similarTo: 'Similar a {{artist}}', + becauseYouLikeTracks_one: '{{count}} canción', + becauseYouLikeTracks_other: '{{count}} canciones' +}; diff --git a/src/locales/es/index.ts b/src/locales/es/index.ts new file mode 100644 index 00000000..ff27ade2 --- /dev/null +++ b/src/locales/es/index.ts @@ -0,0 +1,91 @@ +import { sidebar } from './sidebar'; +import { home } from './home'; +import { hero } from './hero'; +import { search } from './search'; +import { nowPlaying } from './nowPlaying'; +import { contextMenu } from './contextMenu'; +import { sharePaste } from './sharePaste'; +import { albumDetail } from './albumDetail'; +import { entityRating } from './entityRating'; +import { artistDetail } from './artistDetail'; +import { favorites } from './favorites'; +import { randomLanding } from './randomLanding'; +import { randomAlbums } from './randomAlbums'; +import { genres } from './genres'; +import { randomMix } from './randomMix'; +import { luckyMix } from './luckyMix'; +import { albums } from './albums'; +import { tracks } from './tracks'; +import { artists } from './artists'; +import { composers } from './composers'; +import { composerDetail } from './composerDetail'; +import { login } from './login'; +import { connection } from './connection'; +import { common } from './common'; +import { settings } from './settings'; +import { changelog } from './changelog'; +import { whatsNew } from './whatsNew'; +import { help } from './help'; +import { queue } from './queue'; +import { miniPlayer } from './miniPlayer'; +import { statistics } from './statistics'; +import { player } from './player'; +import { nowPlayingInfo } from './nowPlayingInfo'; +import { songInfo } from './songInfo'; +import { playlists } from './playlists'; +import { smartPlaylists } from './smartPlaylists'; +import { mostPlayed } from './mostPlayed'; +import { losslessAlbums } from './losslessAlbums'; +import { radio } from './radio'; +import { folderBrowser } from './folderBrowser'; +import { deviceSync } from './deviceSync'; +import { orbit } from './orbit'; +import { tray } from './tray'; +import { licenses } from './licenses'; + +export const esTranslation = { + sidebar, + home, + hero, + search, + nowPlaying, + contextMenu, + sharePaste, + albumDetail, + entityRating, + artistDetail, + favorites, + randomLanding, + randomAlbums, + genres, + randomMix, + luckyMix, + albums, + tracks, + artists, + composers, + composerDetail, + login, + connection, + common, + settings, + changelog, + whatsNew, + help, + queue, + miniPlayer, + statistics, + player, + nowPlayingInfo, + songInfo, + playlists, + smartPlaylists, + mostPlayed, + losslessAlbums, + radio, + folderBrowser, + deviceSync, + orbit, + tray, + licenses, +}; diff --git a/src/locales/es/licenses.ts b/src/locales/es/licenses.ts new file mode 100644 index 00000000..8aa4df8e --- /dev/null +++ b/src/locales/es/licenses.ts @@ -0,0 +1,13 @@ +export const licenses = { + title: 'Licencias de Código Abierto', + intro: 'Psysonic se basa en software de código abierto. La lista siguiente muestra cada dependencia incluida con la aplicación, con su versión, licencia y el texto completo de la licencia.', + highlights: 'Dependencias principales', + searchPlaceholder: 'Buscar por nombre, versión o licencia…', + noResults: 'Sin resultados.', + loading: 'Cargando licencias…', + loadError: 'No se pudieron cargar los datos de licencia.', + noLicenseText: 'No hay texto de licencia incluido para esta dependencia.', + viewSource: 'Ver fuente', + totalLine: '{{total}} dependencias — {{cargo}} cargo, {{npm}} npm', + generatedAt: 'Última generación {{date}}', +}; diff --git a/src/locales/es/login.ts b/src/locales/es/login.ts new file mode 100644 index 00000000..231ce79e --- /dev/null +++ b/src/locales/es/login.ts @@ -0,0 +1,22 @@ +export const login = { + subtitle: 'Tu Reproductor Navidrome para Escritorio', + serverName: 'Nombre del Servidor (opcional)', + serverNamePlaceholder: 'Mi Navidrome', + serverUrl: 'URL del Servidor', + serverUrlPlaceholder: '192.168.1.100:4533 o https://music.example.com', + username: 'Usuario', + usernamePlaceholder: 'admin', + password: 'Contraseña', + showPassword: 'Mostrar contraseña', + hidePassword: 'Ocultar contraseña', + connect: 'Conectar', + connecting: 'Conectando…', + connected: '¡Conectado!', + error: 'Conexión fallida — por favor verifica tus datos.', + urlRequired: 'Por favor ingresa una URL de servidor.', + savedServers: 'Servidores Guardados', + addNew: 'O agregar un nuevo servidor', + orMagicString: 'O cadena mágica', + magicStringPlaceholder: 'Pega una cadena de invitación (psysonic1-…)', + magicStringInvalid: 'Cadena mágica no válida o ilegible.', +}; diff --git a/src/locales/es/losslessAlbums.ts b/src/locales/es/losslessAlbums.ts new file mode 100644 index 00000000..210c6468 --- /dev/null +++ b/src/locales/es/losslessAlbums.ts @@ -0,0 +1,5 @@ +export const losslessAlbums = { + empty: 'Aún no hay álbumes sin pérdidas en esta biblioteca.', + unsupported: 'Este servidor no expone los metadatos necesarios para encontrar álbumes sin pérdidas.', + slowFetchHint: 'Carga más lento que otras páginas de álbumes — Psysonic recorre todo el catálogo de canciones por calidad.', +}; diff --git a/src/locales/es/luckyMix.ts b/src/locales/es/luckyMix.ts new file mode 100644 index 00000000..81e10ced --- /dev/null +++ b/src/locales/es/luckyMix.ts @@ -0,0 +1,6 @@ +export const luckyMix = { + done: 'Mezcla Suerte lista: {{count}} canciones', + failed: 'No se pudo crear la Mezcla Suerte. Inténtalo de nuevo.', + unavailable: 'Mezcla Suerte no está disponible para este servidor.', + cancelTooltip: 'Cancelar creación de Mezcla Suerte', +}; diff --git a/src/locales/es/miniPlayer.ts b/src/locales/es/miniPlayer.ts new file mode 100644 index 00000000..48d1f65a --- /dev/null +++ b/src/locales/es/miniPlayer.ts @@ -0,0 +1,9 @@ +export const miniPlayer = { + showQueue: 'Mostrar cola', + hideQueue: 'Ocultar cola', + pinOnTop: 'Mantener encima', + pinOff: 'Desfijar', + openMainWindow: 'Abrir ventana principal', + close: 'Cerrar', + emptyQueue: 'La cola está vacía', +}; diff --git a/src/locales/es/mostPlayed.ts b/src/locales/es/mostPlayed.ts new file mode 100644 index 00000000..e381097b --- /dev/null +++ b/src/locales/es/mostPlayed.ts @@ -0,0 +1,13 @@ +export const mostPlayed = { + title: 'Más Reproducidos', + topArtists: 'Artistas Principales', + topAlbums: 'Álbumes Principales', + plays: '{{n}} reproducciones', + sortMost: 'Más reproducciones primero', + sortLeast: 'Menos reproducciones primero', + loadMore: 'Cargar más álbumes', + noData: 'Aún no hay datos de reproducción. ¡Empieza a escuchar!', + noArtists: 'Todos los artistas filtrados.', + filterCompilations: 'Ocultar artistas de compilaciones (Various Artists, Soundtracks, etc.)', + filterCompilationsShort: 'Ocultar compilaciones', +}; diff --git a/src/locales/es/nowPlaying.ts b/src/locales/es/nowPlaying.ts new file mode 100644 index 00000000..22726605 --- /dev/null +++ b/src/locales/es/nowPlaying.ts @@ -0,0 +1,47 @@ +export const nowPlaying = { + tooltip: '¿Quién está escuchando?', + title: '¿Quién está escuchando?', + loading: 'Cargando…', + nobody: 'Nadie está escuchando actualmente.', + minutesAgo: 'hace {{n}}m', + nothingPlaying: 'Aún no se está reproduciendo nada. ¡Empieza una canción!', + aboutArtist: 'Sobre el Artista', + fromAlbum: 'De este Álbum', + viewAlbum: 'Ver Álbum', + goToArtist: 'Ir al Artista', + readMore: 'Leer más', + showLess: 'Mostrar menos', + genreInfo: 'Género', + trackInfo: 'Información de la Pista', + topSongs: 'Más reproducidas de este artista', + topSongsCredit: 'Temas principales de {{name}}', + trackPosition: 'Pista {{pos}}', + playsCount_one: '{{count}} reproducción', + playsCount_other: '{{count}} reproducciones', + releasedYearsAgo_one: 'hace {{count}} año', + releasedYearsAgo_other: 'hace {{count}} años', + discography: 'Discografía', + lastfmStats: 'Estadísticas de Last.fm', + thisTrack: 'Este tema', + thisArtist: 'Este artista', + listeners: 'oyentes', + scrobbles: 'scrobbles', + yourScrobbles: 'por ti', + listenersN: '{{n}} oyentes', + scrobblesN: '{{n}} scrobbles', + playsByYouN: 'reproducido {{n}}× por ti', + openTrackOnLastfm: 'Tema en Last.fm', + openArtistOnLastfm: 'Artista en Last.fm', + rgTrackTooltip: 'ReplayGain (pista)', + rgAlbumTooltip: 'ReplayGain (álbum)', + rgAutoTooltip: 'ReplayGain (auto)', + showMoreTracks: 'Mostrar {{count}} más', + showLessTracks: 'Mostrar menos', + hideCard: 'Ocultar tarjeta', + layoutMenu: 'Diseño', + visibleCards: 'Tarjetas visibles', + hiddenCards: 'Tarjetas ocultas', + noHiddenCards: 'No hay tarjetas ocultas', + resetLayout: 'Restablecer diseño', + emptyColumn: 'Suelta tarjetas aquí', +}; diff --git a/src/locales/es/nowPlayingInfo.ts b/src/locales/es/nowPlayingInfo.ts new file mode 100644 index 00000000..689743ea --- /dev/null +++ b/src/locales/es/nowPlayingInfo.ts @@ -0,0 +1,24 @@ +export const nowPlayingInfo = { + tab: 'Info', + empty: 'Reproduce algo para ver información', + artist: 'Artista', + songInfo: 'Info de la canción', + onTour: 'En gira', + noTourEvents: 'No hay próximos conciertos', + tourLoading: 'Cargando…', + poweredByBandsintown: 'Datos de gira vía Bandsintown', + bioReadMore: 'Leer más', + bioReadLess: 'Ver menos', + showMoreTours_one: 'Mostrar {{count}} más', + showMoreTours_other: 'Mostrar {{count}} más', + showLessTours: 'Ver menos', + enableBandsintownPrompt: '¿Ver próximas fechas de gira?', + enableBandsintownPromptDesc: 'Opcional. Carga conciertos del artista actual vía la API pública de Bandsintown.', + enableBandsintownPrivacy: 'Al activar, el nombre del artista actual se envía a la API de Bandsintown para obtener fechas de gira. No se envían datos de cuenta ni personales.', + enableBandsintownAction: 'Activar', + role: { + artist: 'Artista', + albumArtist: 'Artista del álbum', + composer: 'Compositor', + }, +}; diff --git a/src/locales/es/orbit.ts b/src/locales/es/orbit.ts new file mode 100644 index 00000000..fbc27850 --- /dev/null +++ b/src/locales/es/orbit.ts @@ -0,0 +1,200 @@ +export const orbit = { + triggerLabel: 'Orbit', + triggerTooltip: 'Iniciar o unirse a una sesión de escucha compartida', + launchCreate: 'Crear una sesión', + launchJoin: 'Unirse a una sesión', + launchHelp: '¿Cómo funciona esto?', + launchHelpSoon: 'Próximamente', + joinModalTitle: 'Unirse a una sesión Orbit', + joinModalSub: 'Pega el enlace de invitación que te envió tu anfitrión.', + joinModalLinkLabel: 'Enlace de invitación', + joinModalLinkPlaceholder: 'psysonic2-…', + joinModalLinkHelper: 'Funciona con cualquier enlace Orbit válido. Debe apuntar al servidor al que estás conectado actualmente.', + joinModalPasteTooltip: 'Pegar desde el portapapeles', + joinModalSubmit: 'Unirse', + joinModalBusy: 'Uniéndose…', + joinErrEmpty: 'Pega un enlace de invitación.', + joinErrInvalid: 'Eso no parece un enlace de invitación Orbit.', + closeAria: 'Cerrar', + heroTitlePrefix: 'Escucha junto con', + heroTitleBrand: 'Orbit', + heroSub: 'Inicia una sesión — otros usuarios en {{server}} escucharán contigo y podrán sugerir canciones.', + fallbackServer: 'este servidor', + tipLan: 'Actualmente estás conectado mediante una dirección de red local. Los invitados fuera de tu red no pueden unirse — cambia a una dirección de servidor pública en los ajustes antes de empezar.', + tipRemote: 'Para que los invitados fuera de tu red doméstica puedan unirse, la dirección de tu servidor debe ser accesible públicamente. Si tu servidor es solo interno, cambia antes de empezar.', + labelName: 'Nombre de la sesión', + namePlaceholder: 'Velvet Orbit', + reshuffleTooltip: 'Nueva sugerencia', + reshuffleAria: 'Sugerir un nuevo nombre', + helperName: 'Cómo aparecerá la sesión a tus invitados — déjalo o escribe el tuyo.', + labelMax: 'Invitados máx.', + helperMax: 'Tú no cuentas — esto solo limita a los invitados entrantes.', + labelLink: 'Enlace de invitación', + tooltipCopied: 'Copiado', + tooltipCopy: 'Copiar', + ariaCopyLink: 'Copiar enlace de invitación', + helperLink: 'Envía este enlace a tus invitados. Pueden pegarlo en cualquier parte de Psysonic con Ctrl+V.', + labelClearQueue: 'Vaciar mi cola primero', + helperClearQueue: 'Empieza la sesión con una cola vacía. Desactivado: las canciones ya en cola se mantienen y se comparten con los invitados.', + btnCancel: 'Cancelar', + btnStarting: 'Iniciando…', + btnStart: 'Iniciar Orbit', + btnCopyAndStart: 'Copiar enlace e iniciar', + errNameRequired: 'Por favor, dale un nombre a tu sesión.', + errStartFailed: 'No se pudo iniciar.', + hostLabel: 'Anfitrión: {{name}}', + participantsTooltip: 'Participantes', + settingsTooltip: 'Ajustes de sesión', + shareTooltip: 'Compartir enlace de invitación', + shuffleLabel: 'Próximo mezclado en', + catchUpLabel: 'alcanzar', + catchUpTooltip: 'Saltar a la posición actual del anfitrión', + hostAway: 'Anfitrión desconectado', + hostOnline: 'Anfitrión en línea', + endTooltip: 'Terminar sesión', + leaveTooltip: 'Salir de la sesión', + helpTooltip: 'Cómo funciona Orbit', + diag: { + openTooltip: 'Diagnóstico — registro de eventos copiable', + title: 'Diagnóstico de Orbit', + role: 'Rol', + hostTrack: 'ID de pista del anfitrión', + hostPos: 'Posición del anfitrión', + guestTrack: 'Mi ID de pista', + guestPos: 'Mi posición', + drift: 'Desfase', + stateAge: 'Edad del estado', + eventLog: 'Registro de eventos ({{count}})', + copyLabel: 'Copiar', + copyTooltip: 'Copiar registro al portapapeles', + clearLabel: 'Borrar', + clearTooltip: 'Vaciar el búfer', + empty: 'Aún sin eventos — aparecen cuando Orbit sincroniza.', + hint: 'Abre esto antes de reproducir el problema, luego pulsa Copiar y pega en el reporte.', + copied: '{{count}} líneas copiadas', + copyFailed: 'No se pudo copiar al portapapeles', + cleared: 'Búfer vaciado', + }, + helpTitle: 'Cómo funciona Orbit', + helpIntro: 'Orbit convierte Psysonic en una sala de escucha compartida. Un anfitrión elige la música; los invitados escuchan en sincronía y pueden sugerir canciones.', + helpHostOnly: '(anfitrión)', + helpSec1Title: '¿Qué es Orbit?', + helpSec1Body: 'Un modo de "escuchar juntos" — el anfitrión maneja la reproducción, los invitados se conectan. Todo pasa por playlists en tu propio servidor Navidrome; sin infraestructura externa.', + helpSec2Title: 'Anfitrión e invitados', + helpSec2Body: 'El anfitrión controla la reproducción (play / pause / skip / seek) y decide cuándo termina la sesión. Los invitados siguen la reproducción, pueden sugerir canciones y salir o volver a unirse en cualquier momento. Solo el anfitrión puede expulsar o banear permanentemente a un participante.', + helpSec2WarnHead: 'Importante: cuentas separadas.', + helpSec2WarnBody: 'Cada participante necesita su propia cuenta Navidrome. Si anfitrión e invitado inician sesión con el mismo usuario, sus envíos chocan y el anfitrión nunca ve las sugerencias del invitado.', + helpSec3Title: 'Iniciar e invitar', + helpSec3Body: 'Haz clic en el botón "Orbit" → Crear una sesión → el modal muestra un enlace de invitación listo para copiar y te permite opcionalmente vaciar tu cola actual. Comparte el enlace como prefieras. Mientras una sesión está activa, el botón de compartir en la barra superior copia el enlace en cualquier momento.', + helpSec4Title: 'Unirse', + helpSec4Body: 'Pega el enlace de invitación en cualquier parte de Psysonic con Ctrl+V / Cmd+V — el aviso para unirse aparece automáticamente. Alternativa: "Orbit" → Unirse a una sesión → pega en el campo. Si el enlace apunta a un servidor donde tienes una cuenta, Psysonic cambia automáticamente. Si tienes más de una cuenta en ese servidor, un pequeño selector pregunta cuál usar.', + helpSec5Title: 'Sugerir canciones', + helpSec5Body: 'En cualquier lista: doble clic en una fila, o clic derecho → "Añadir a la sesión Orbit". Un clic simple muestra una pista en lugar de tirar todo el álbum a la cola compartida — es intencional. Las acciones masivas explícitas como "Reproducir todo" o "Reproducir álbum" piden confirmación primero y luego añaden (nunca reemplazan).', + helpSec6Title: 'La cola compartida', + helpSec6Body: 'La cola muestra las próximas canciones del anfitrión — visible para todos. Las adiciones masivas siempre se añaden al final, para que las sugerencias de los invitados no se pierdan. El mezclado automático reordena la cola periódicamente (configurable: 1 / 5 / 10 / 15 / 30 min). Si tu reproducción se desvía del anfitrión, el botón "Alcanzar" en la barra te devuelve a la posición en vivo del anfitrión.', + helpSec7Title: 'Aprobaciones', + helpSec7Body: 'Por defecto, las sugerencias de los invitados necesitan aprobación manual — aparecen en una barra de "Aprobaciones" en la parte superior del panel con botones aceptar / rechazar. La aprobación automática puede activarse en los ajustes de sesión para que todo entre directamente.', + helpSec8Title: 'Participantes y ajustes', + helpSec8Body: 'Abre el icono de ajustes en la barra de sesión para la frecuencia de mezclado, la aprobación automática y el atajo "Mezclar ahora". Haz clic en el número de participantes para ver quién está conectado — expulsar (puede volver a unirse por el enlace) o banear (bloqueado para la sesión). Los invitados también ven la lista de participantes, pero solo de lectura.', + helpSec9Title: 'Terminar la sesión', + helpSec9Body: 'X del anfitrión → diálogo de confirmación → la sesión se cierra para todos y las playlists del servidor se limpian automáticamente. X del invitado → el invitado sale, la sesión sigue. Si el anfitrión queda en silencio 5 minutos, el invitado sale automáticamente con un aviso; las reconexiones cortas en esa ventana son invisibles.', + participantsInviteLabel: 'Enlace de invitación', + participantsCountLabel: '{{count}} en sesión', + participantsHost: 'anfitrión', + participantsEmpty: 'Aún no hay invitados', + participantsKickTooltip: 'Quitar de la sesión', + participantsKickAria: 'Quitar a {{user}}', + participantsRemoveTooltip: 'Quitar de la sesión', + participantsRemoveAria: 'Quitar a {{user}} de esta sesión', + participantsBanTooltip: 'Banear permanentemente', + participantsBanAria: 'Banear permanentemente a {{user}}', + participantsMuteTooltip: 'Silenciar sugerencias', + participantsUnmuteTooltip: 'Permitir sugerencias', + participantsMuteAria: 'Silenciar las sugerencias de {{user}}', + participantsUnmuteAria: 'Volver a permitir las sugerencias de {{user}}', + confirmRemoveTitle: '¿Quitar de la sesión?', + confirmRemoveBody: '{{user}} será expulsado de la sesión, pero puede volver a unirse por tu enlace de invitación.', + confirmRemoveConfirm: 'Quitar', + confirmBanTitle: '¿Banear permanentemente?', + confirmBanBody: '{{user}} será expulsado y bloqueado para volver a unirse a esta sesión. No se puede deshacer durante la sesión.', + confirmBanConfirm: 'Banear', + confirmCancel: 'Cancelar', + confirmJoinTitle: '¿Unirse a la sesión Orbit?', + confirmJoinBody: '{{host}} te ha invitado a "{{name}}". ¿Unirse a la sesión?', + confirmJoinConfirm: 'Unirse', + confirmLeaveTitle: '¿Salir de la sesión?', + confirmLeaveBody: '¿Salir de "{{name}}"? Puedes volver a unirte en cualquier momento por el enlace de invitación de {{host}}.', + confirmLeaveConfirm: 'Salir', + confirmEndTitle: '¿Terminar la sesión para todos?', + confirmEndBody: '"{{name}}" se cerrará para todos los participantes. Las playlists de la sesión se limpian automáticamente.', + confirmEndConfirm: 'Terminar sesión', + invalidLinkTitle: 'El enlace de invitación ya no es válido', + invalidLinkBody: 'Esta sesión Orbit ya no existe o ya ha terminado. Pide al anfitrión un nuevo enlace de invitación.', + settingsTitle: 'Ajustes de sesión', + settingAutoApprove: 'Aprobar sugerencias automáticamente', + settingAutoApproveHint: 'Las sugerencias de los invitados entran instantáneamente en tu cola. Desactivado: se quedan en la lista de sesión para revisión posterior.', + settingAutoShuffle: 'Mezclado automático', + settingAutoShuffleHint: 'Mezclado Fisher-Yates periódico de la cola próxima. Desactivado: el orden solo cambia cuando lo reorganizas.', + settingShuffleInterval: 'Remezclar cada', + settingShuffleIntervalHint: 'Con qué frecuencia se remezcla la cola próxima durante la sesión.', + suggestBlockedMuted: 'El anfitrión te silenció en esta sesión — sugerencias desactivadas.', + settingShuffleIntervalValue_one: '{{count}} min', + settingShuffleIntervalValue_other: '{{count}} min', + settingShuffleNow: 'Mezclar ahora', + toastSuggested: '{{user}} sugirió "{{title}}"', + toastSuggestedMany: '{{count}} nuevas sugerencias en la cola', + toastShuffled: 'Cola mezclada', + toastJoined: 'Te has unido a la sesión', + toastLoginFirst: 'Inicia sesión antes de unirte a una sesión', + toastSwitchServer: 'Cambia primero a {{url}}, luego pega de nuevo', + toastNoAccountForServer: 'No tienes acceso a {{url}}. Pide al anfitrión una invitación.', + toastSwitchFailed: 'No se pudo cambiar a {{url}}', + accountPickerTitle: '¿Qué cuenta?', + accountPickerSub: 'Tienes más de una cuenta para {{url}}. Elige con cuál unirte a la sesión.', + toastJoinFail: 'No se pudo unir a la sesión', + joinErrNotFound: 'Sesión no encontrada', + joinErrEnded: 'La sesión ha terminado', + joinErrFull: 'La sesión está llena', + joinErrKicked: 'No puedes volver a unirte a esta sesión', + joinErrNoUser: 'Sin servidor activo', + joinErrServerError: 'No se pudo unir', + ctxAddToSession: 'Añadir a la sesión Orbit', + ctxSuggestedToast: 'Sugerido a la sesión', + ctxSuggestFailed: 'No se pudo sugerir — no unido', + ctxAddToSessionHost: 'Añadir a la sesión Orbit', + ctxAddedHostToast: 'Añadido a la sesión', + ctxAddHostFailed: 'No se pudo añadir a la sesión', + bulkConfirmTitle: '¿Añadir todo esto a la cola Orbit?', + bulkConfirmBody: 'Esto lanzaría {{count}} canciones a la cola compartida de una vez. Es mucho para tus invitados. ¿Continuar?', + bulkConfirmYes: 'Añadir todas', + bulkConfirmNo: 'Cancelar', + guestLive: 'En vivo', + guestPlaying: 'Reproduciendo ahora', + guestPaused: 'En pausa', + guestLoading: 'Cargando…', + guestSuggestions: 'Sugerencias', + guestUpNext: 'A continuación', + guestUpNextEmpty: 'Nada en cola. Abre el menú contextual de una canción y elige "Añadir a la sesión Orbit" para sugerir una.', + guestPendingTitle: 'Esperando al anfitrión', + guestPendingHint: 'Sugerido — aparecerá en la cola cuando el anfitrión lo acepte.', + approvalTitle: 'Pendiente de aprobación', + approvalFrom: 'Sugerido por {{user}}', + approvalAccept: 'Aceptar', + approvalDecline: 'Rechazar', + guestUpNextMore: '+ {{count}} más en la cola del anfitrión', + guestSubmitter: 'de {{user}}', + queueAddedByHost: 'Añadido por el anfitrión', + queueAddedByYou: 'Añadido por ti', + queueAddedByUser: 'Añadido por {{user}}', + guestEmpty: 'Aún no hay sugerencias. Abre el menú contextual de una canción y elige "Añadir a la sesión Orbit".', + guestFooter: 'El anfitrión controla la reproducción — no puedes cambiar la lista.', + exitKickedTitle: 'Has sido baneado de la sesión', + exitRemovedTitle: 'Has sido quitado de la sesión', + exitEndedTitle: 'El anfitrión ha terminado la sesión', + exitHostTimeoutTitle: 'Anfitrión en silencio', + exitHostTimeoutBody: '{{host}} no ha enviado una actualización durante un rato, así que "{{name}}" se cerró en tu lado. Puedes volver a unirte en cualquier momento con el enlace de invitación.', + exitKickedBody: '{{host}} te ha baneado de "{{name}}". No puedes volver a unirte.', + exitRemovedBody: '{{host}} te ha quitado de "{{name}}". Puedes volver a unirte en cualquier momento por el enlace.', + exitEndedBody: '"{{name}}" ha terminado. Espero que te hayas divertido.', + exitOk: 'OK', +}; diff --git a/src/locales/es/player.ts b/src/locales/es/player.ts new file mode 100644 index 00000000..64e8638f --- /dev/null +++ b/src/locales/es/player.ts @@ -0,0 +1,56 @@ +export const player = { + regionLabel: 'Reproductor de Música', + openFullscreen: 'Abrir Reproductor Pantalla Completa', + fullscreen: 'Reproductor Pantalla Completa', + closeFullscreen: 'Cerrar Pantalla Completa', + closeTooltip: 'Cerrar (Esc)', + noTitle: 'Sin Título', + stop: 'Detener', + prev: 'Pista Anterior', + play: 'Reproducir', + pause: 'Pausa', + previewActive: 'Vista previa activa', + previewLabel: 'Vista previa', + delayModalTitle: 'Temporizador', + delayPauseSection: 'Pausar después de', + delayStartSection: 'Iniciar después de', + delayPreviewPause: 'Pausa a las', + delayPreviewStart: 'Inicio a las', + delaySchedulePause: 'Programar pausa', + delayScheduleStart: 'Programar inicio', + delayCancelPause: 'Cancelar temporizador de pausa', + delayCancelStart: 'Cancelar temporizador de inicio', + delayInactivePause: 'Solo disponible durante la reproducción.', + delayInactiveStart: 'Solo en pausa con pista o radio cargada.', + delayCustomMinutes: 'Retraso personalizado (minutos)', + delayCustomPlaceholder: 'p. ej. 2,5', + closeDelayModal: 'Cerrar', + delayIn: 'en', + delayFmtSec: '{{n}} s', + delayFmtMin: '{{n}} min', + delayFmtHr: '{{n}} h', + delayCancel: 'Cancelar', + delayApply: 'Aplicar', + next: 'Pista Siguiente', + repeat: 'Repetir', + repeatOff: 'Apagado', + repeatAll: 'Todo', + repeatOne: 'Una', + progress: 'Progreso de Canción', + volume: 'Volumen', + toggleQueue: 'Alternar Cola', + collapseQueueResize: 'Contraer cola, cambiar ancho', + moreOptions: 'Más opciones', + equalizer: 'Ecualizador', + miniPlayer: 'Mini reproductor', + lyrics: 'Letras', + fsLyricsToggle: 'Letras en pantalla completa', + lyricsLoading: 'Cargando letras…', + lyricsNotFound: 'No se encontraron letras para esta pista', + lyricsSourceServer: 'Fuente: Servidor', + lyricsSourceLrclib: 'Fuente: LRCLIB', + lyricsSourceNetease: 'Fuente: Netease', + lyricsSourceLyricsplus: 'Fuente: YouLyPlus', + showDuration: 'Mostrar duración', + showRemainingTime: 'Mostrar tiempo restante', +}; diff --git a/src/locales/es/playlists.ts b/src/locales/es/playlists.ts new file mode 100644 index 00000000..2f7e015e --- /dev/null +++ b/src/locales/es/playlists.ts @@ -0,0 +1,101 @@ +export const playlists = { + title: 'Listas de Reproducción', + newPlaylist: 'Nueva Lista', + unnamed: 'Lista sin nombre', + createName: 'Nombre de lista…', + create: 'Crear', + cancel: 'Cancelar', + empty: 'Aún no hay listas.', + emptyPlaylist: 'Esta lista está vacía.', + addFirstSong: 'Agrega tu primera canción', + notFound: 'Lista no encontrada.', + songs: '{{n}} canciones', + playAll: 'Reproducir Todo', + shuffle: 'Aleatorio', + addToQueue: 'Agregar a Cola', + back: 'Volver a Listas', + deletePlaylist: 'Eliminar', + confirmDelete: 'Click de nuevo para confirmar', + removeSong: 'Quitar de lista', + addSongs: 'Agregar Canciones', + searchPlaceholder: 'Buscar en tu biblioteca…', + noResults: 'Sin resultados.', + suggestions: 'Canciones Sugeridas', + noSuggestions: 'No hay sugerencias disponibles.', + titleBadge: 'Lista', + refreshSuggestions: 'Nuevas sugerencias', + addSong: 'Agregar a lista', + preview: 'Vista previa (30 s)', + previewStop: 'Detener vista previa', + playNextSuggestion: 'Reproducir a continuación', + suggestionsHint: 'Doble clic en una fila para añadirla a la lista', + addSelected: 'Agregar seleccionados', + cacheOffline: 'Guardar lista offline', + offlineCached: 'Lista guardada', + removeOffline: 'Quitar de caché offline', + offlineDownloading: 'Descargando… ({{done}}/{{total}} álbumes)', + publicLabel: 'Pública', + privateLabel: 'Privada', + editMeta: 'Editar lista', + editNamePlaceholder: 'Nombre de lista…', + editCommentPlaceholder: 'Agregar descripción…', + editPublic: 'Lista pública', + editSave: 'Guardar', + editCancel: 'Cancelar', + changeCover: 'Cambiar imagen de portada', + changeCoverLabel: 'Cambiar foto', + removeCover: 'Quitar foto', + coverUpdated: 'Portada actualizada', + metaSaved: 'Lista actualizada', + downloadZip: 'Descargar (ZIP)', + // Toast notifications for multi-select + addSuccess: '{{count}} canciones agregadas a {{playlist}}', + addPartial: '{{added}} agregadas, {{skipped}} skippeadas por duplicadas', + addAllSkipped: 'Todas skippeadas ({{count}} duplicadas)', + addedAsDuplicates: '{{count}} canciones añadidas a {{playlist}} (como duplicados)', + duplicateConfirmTitle: 'Ya en la lista', + duplicateConfirmMessage: 'Las {{count}} canciones ya están en "{{playlist}}". ¿Añadirlas igualmente como duplicados?', + duplicateConfirmAction: 'Añadir igualmente', + addError: 'Error al agregar canciones', + createAndAddSuccess: 'Lista "{{playlist}}" creada con {{count}} canciones', + createError: 'Error al crear lista', + deleteSuccess: '{{count}} listas eliminadas', + deleteFailed: 'Error al eliminar {{name}}', + deleteSelected: 'Eliminar seleccionadas', + deleteSelectedPartial: 'Solo {{n}} de {{total}} listas seleccionadas pueden eliminarse (las demás pertenecen a otro usuario).', + mergeSuccess: '{{count}} canciones unificadas en {{playlist}}', + mergeNoNewSongs: 'No hay canciones nuevas para agregar', + mergeError: 'Error al unificar listas', + mergeInto: 'Unificar en', + selectionCount: '{{count}} seleccionadas', + select: 'Seleccionar', + startSelect: 'Activar selección', + cancelSelect: 'Cancelar', + loadingAlbums: 'Resolviendo {{count}} álbumes…', + loadingArtists: 'Resolviendo {{count}} artistas…', + myPlaylists: 'Mis Listas', + noOtherPlaylists: 'No hay otras listas disponibles', + addToPlaylistSuccess: '{{count}} canciones agregadas a {{playlist}}', + addToPlaylistNoNew: 'No hay canciones nuevas para agregar a {{playlist}}', + addToPlaylistError: 'Error al agregar a la lista', + removeSuccess: 'Canción quitada de la playlist', + removeError: 'Error al quitar la canción de la playlist', + importCSV: 'Importar CSV', + importCSVTooltip: 'Importar desde CSV de Spotify', + csvImportReport: 'Reporte de Importación CSV', + csvImportTotal: 'Total', + csvImportAdded: 'Agregadas', + csvImportDuplicates: 'Duplicadas', + csvImportNotFound: 'No Encontradas', + csvImportNetworkErrors: 'Errores de Red', + csvImportDuplicatesTitle: 'Canciones Duplicadas (Ya en la Lista):', + csvImportNotFoundTitle: 'Canciones No Encontradas:', + csvImportNetworkErrorsTitle: 'Errores de Red (puede reintentar la importación):', + csvImportDownloadReport: 'Descargar Reporte', + csvImportClose: 'Cerrar', + csvImportNoValidTracks: 'No se encontraron canciones válidas en el archivo CSV', + csvImportFailed: 'Error al importar el archivo CSV', + csvImportToast: '{{added}} agregadas, {{notFound}} no encontradas, {{duplicates}} duplicadas', + csvImportDownloadSuccess: 'Reporte descargado exitosamente', + csvImportDownloadError: 'Error al descargar el reporte', +}; diff --git a/src/locales/es/queue.ts b/src/locales/es/queue.ts new file mode 100644 index 00000000..89a3a578 --- /dev/null +++ b/src/locales/es/queue.ts @@ -0,0 +1,45 @@ +export const queue = { + title: 'Cola', + savePlaylist: 'Guardar Lista', + updatePlaylist: 'Actualizar Lista', + filterPlaylists: 'Filtrar listas…', + playlistName: 'Nombre de Lista', + cancel: 'Cancelar', + save: 'Guardar', + loadPlaylist: 'Cargar Lista', + loading: 'Cargando…', + noPlaylists: 'No se encontraron listas.', + load: 'Reemplazar cola y reproducir', + appendToQueue: 'Agregar a cola', + delete: 'Eliminar', + deleteConfirm: '¿Eliminar lista "{{name}}"?', + clear: 'Limpiar', + shuffle: 'Mezclar cola', + gapless: 'Gapless', + crossfade: 'Crossfade', + infiniteQueue: 'Cola Infinita', + autoAdded: '— Agregado automáticamente —', + radioAdded: '— Radio —', + hide: 'Ocultar', + hideNowPlaying: 'Ocultar información de reproducción', + showNowPlaying: 'Mostrar información de reproducción', + close: 'Cerrar', + nextTracks: 'Siguientes', + shareQueue: 'Copiar enlace de la cola', + shareQueueEmpty: 'La cola está vacía — no hay nada que compartir.', + emptyQueue: 'La cola está vacía.', + trackSingular: 'pista', + trackPlural: 'pistas', + showRemaining: 'Mostrar tiempo restante', + showTotal: 'Mostrar tiempo total', + showEta: 'Mostrar hora estimada de fin', + replayGain: 'ReplayGain', + rgTrack: 'T {{db}} dB', + rgAlbum: 'A {{db}} dB', + rgPeak: 'Pico {{pk}}', + sourceOffline: 'Reproducción desde la biblioteca sin conexión', + sourceHot: 'Reproducción desde la caché', + sourceStream: 'Reproducción desde la transmisión en red', + clearCachedLoudnessWaveform: 'Clear cached loudness and waveform, then re-analyze this track', + recalculatingLoudnessWaveform: 'Recalculating loudness and waveform for this track…', +}; diff --git a/src/locales/es/radio.ts b/src/locales/es/radio.ts new file mode 100644 index 00000000..33f67133 --- /dev/null +++ b/src/locales/es/radio.ts @@ -0,0 +1,35 @@ +export const radio = { + title: 'Radio por Internet', + empty: 'No hay estaciones de radio configuradas.', + addStation: 'Agregar Estación', + editStation: 'Editar', + deleteStation: 'Eliminar estación', + confirmDelete: 'Click de nuevo para confirmar', + stationName: 'Nombre de estación…', + streamUrl: 'URL de stream…', + homepageUrl: 'URL de página (opcional)', + save: 'Guardar', + cancel: 'Cancelar', + live: 'EN VIVO', + liveStream: 'Radio por Internet', + openHomepage: 'Abrir página', + changeCoverLabel: 'Cambiar portada', + removeCover: 'Quitar portada', + browseDirectory: 'Buscar en Directorio', + directoryPlaceholder: 'Buscar estaciones…', + noResults: 'No se encontraron estaciones.', + stationAdded: 'Estación agregada', + filterAll: 'Todas', + filterFavorites: 'Favoritos', + sortManual: 'Manual', + sortAZ: 'A → Z', + sortZA: 'Z → A', + sortNewest: 'Más recientes', + favorite: 'Agregar a favoritos', + unfavorite: 'Quitar de favoritos', + noFavorites: 'No hay estaciones favoritas.', + listenerCount_one: '{{count}} oyente', + listenerCount_other: '{{count}} oyentes', + recentlyPlayed: 'Reproducidos Recientemente', + upNext: 'Siguientes', +}; diff --git a/src/locales/es/randomAlbums.ts b/src/locales/es/randomAlbums.ts new file mode 100644 index 00000000..0a03d2d7 --- /dev/null +++ b/src/locales/es/randomAlbums.ts @@ -0,0 +1,4 @@ +export const randomAlbums = { + title: 'Álbumes Aleatorios', + refresh: 'Refrescar', +}; diff --git a/src/locales/es/randomLanding.ts b/src/locales/es/randomLanding.ts new file mode 100644 index 00000000..3909a9db --- /dev/null +++ b/src/locales/es/randomLanding.ts @@ -0,0 +1,9 @@ +export const randomLanding = { + title: 'Crear Mezcla', + mixByTracks: 'Mezcla por Canciones', + mixByTracksDesc: 'Selección aleatoria de canciones de toda tu biblioteca', + mixByAlbums: 'Mezcla por Álbumes', + mixByAlbumsDesc: 'Álbumes aleatorios para tu próximo descubrimiento', + mixByLucky: 'Mezcla Suerte', + mixByLuckyDesc: 'Instant Mix inteligente con artistas, álbumes y valoraciones destacadas', +}; diff --git a/src/locales/es/randomMix.ts b/src/locales/es/randomMix.ts new file mode 100644 index 00000000..7f6ba37a --- /dev/null +++ b/src/locales/es/randomMix.ts @@ -0,0 +1,39 @@ +export const randomMix = { + title: 'Mezcla Aleatoria', + remix: 'Remezclar', + remixTooltip: 'Cargar nuevas canciones aleatorias', + remixGenre: 'Remezclar {{genre}}', + remixTooltipGenre: 'Cargar nuevas canciones de {{genre}}', + playAll: 'Reproducir Todo', + trackTitle: 'Título', + trackArtist: 'Artista', + trackAlbum: 'Álbum', + trackFavorite: 'Favorito', + trackDuration: 'Duración', + favoriteAdd: 'Agregar a Favoritos', + favoriteRemove: 'Quitar de Favoritos', + play: 'Reproducir', + trackGenre: 'Género', + mixSettingsHeader: 'Ajustes del mix', + exclusionsHeader: 'Exclusiones', + filterPanelInexactSizeNote: 'El tamaño del mix es un objetivo — las solicitudes grandes pueden devolver menos pistas únicas si el grupo aleatorio del servidor se agota.', + mixSize: 'Tamaño de lista', + excludeAudiobooks: 'Excluir audiolibros y radioteatros', + excludeAudiobooksDesc: 'Busca palabras clave en género, título, álbum y artista — ej. Hörbuch, Audiobook, Spoken Word, …', + genreBlocked: 'Palabra clave bloqueada', + genreAddedToBlacklist: 'Agregada a lista de filtros', + genreAlreadyBlocked: 'Ya está bloqueada', + artistBlocked: 'Artista bloqueado', + artistAddedToBlacklist: 'Artista agregado a lista de filtros', + artistClickHint: 'Click para bloquear este artista', + blacklistToggle: 'Filtro de Palabras Clave', + genreMixTitle: 'Mezcla por Género', + genreMixDesc: 'Top 20 géneros por cantidad de canciones — click para cargar mezcla aleatoria', + genreMixAll: 'Todas las Canciones', + genreMixLoadMore: 'Cargar 10 más', + genreMixNoGenres: 'No se encontraron géneros en el servidor.', + shuffleGenres: 'Mostrar géneros diferentes', + filterPanelTitle: 'Filtros', + filterPanelDesc: 'Click en una etiqueta de género o nombre de artista en la lista para bloquearlo de futuras mezclas.', + genreClickHint: 'Click en una etiqueta de género para agregarla\ncomo palabra clave filtrada.\nBusca en género, título, álbum y artista.', +}; diff --git a/src/locales/es/search.ts b/src/locales/es/search.ts new file mode 100644 index 00000000..ebb23ff1 --- /dev/null +++ b/src/locales/es/search.ts @@ -0,0 +1,29 @@ +export const search = { + placeholder: 'Buscar artista, álbum o canción…', + noResults: 'No hay resultados para "{{query}}"', + artists: 'Artistas', + albums: 'Álbumes', + songs: 'Canciones', + clearLabel: 'Limpiar búsqueda', + addedToQueueToast: '"{{title}}" añadido a la cola', + title: 'Buscar', + resultsFor: 'Resultados para "{{query}}"', + album: 'Álbum', + advanced: 'Búsqueda Avanzada', + advancedSearchTerm: 'Término de búsqueda', + advancedSearchPlaceholder: 'Título, álbum, artista…', + advancedGenre: 'Género', + advancedAllGenres: 'Todos los géneros', + advancedYear: 'Año', + advancedYearFrom: 'desde', + advancedYearTo: 'hasta', + advancedAll: 'Todos', + advancedSearch: 'Buscar', + advancedEmpty: 'Ingresa un término de búsqueda o selecciona un filtro para comenzar.', + advancedNoResults: 'No se encontraron resultados.', + advancedGenreNote: 'Las canciones se seleccionan aleatoriamente de este género.', + recentSearches: 'Búsquedas Recientes', + browse: 'Explorar', + emptyHint: '¿Qué quieres escuchar?', + genres: 'Géneros', +}; diff --git a/src/locales/es/settings.ts b/src/locales/es/settings.ts new file mode 100644 index 00000000..56dadc00 --- /dev/null +++ b/src/locales/es/settings.ts @@ -0,0 +1,442 @@ +export const settings = { + title: 'Configuración', + language: 'Idioma', + languageEn: 'English', + languageDe: 'Deutsch', + languageEs: 'Español', + languageFr: 'Français', + languageNl: 'Nederlands', + languageNb: 'Norsk', + languageRu: 'Русский', + languageZh: '中文', + languageRo: 'Română', + font: 'Fuente', + fontHintOpenDyslexic: 'Compatible con dislexia · sin soporte para chino', + theme: 'Tema', + appearance: 'Apariencia', + servers: 'Servidores', + serverName: 'Nombre del Servidor', + serverUrl: 'URL del Servidor', + serverUrlPlaceholder: '192.168.1.100:4533 o https://music.example.com', + serverUsername: 'Usuario', + serverPassword: 'Contraseña', + addServer: 'Agregar Servidor', + addServerTitle: 'Agregar Nuevo Servidor', + useServer: 'Usar', + deleteServer: 'Eliminar', + noServers: 'No hay servidores guardados.', + serverActive: 'Activo', + confirmDeleteServer: '¿Eliminar servidor "{{name}}"?', + serverConnecting: 'Conectando…', + serverConnected: '¡Conectado!', + serverFailed: 'Conexión fallida.', + testBtn: 'Probar Conexión', + testingBtn: 'Probando…', + serverCompatible: 'Diseñado para Navidrome. Otros servidores compatibles con Subsonic (Gonic, Airsonic, …) pueden funcionar con funcionalidad reducida, ya que Psysonic utiliza muchos endpoints específicos de la API de Navidrome.', + userMgmtTitle: 'Gestión de usuarios', + userMgmtDesc: 'Administra los usuarios de este servidor. Requiere privilegios de administrador.', + userMgmtNoAdmin: 'Necesitas privilegios de administrador para gestionar usuarios en este servidor.', + userMgmtLoadError: 'No se pudieron cargar los usuarios.', + userMgmtLoadFriendly: 'El servidor no respondió — suele ser algo puntual.', + userMgmtRetry: 'Reintentar', + userMgmtEmpty: 'No se encontraron usuarios.', + userMgmtYouBadge: 'Tú', + userMgmtAdminBadge: 'Admin', + userMgmtAddUser: 'Añadir usuario', + userMgmtAddUserTitle: 'Nuevo usuario', + userMgmtEditUserTitle: 'Editar usuario', + userMgmtUsername: 'Nombre de usuario', + userMgmtName: 'Nombre visible', + userMgmtEmail: 'Correo electrónico', + userMgmtPassword: 'Contraseña', + userMgmtPasswordEditHint: 'Introduce una nueva contraseña para actualizarla.', + userMgmtRoleAdmin: 'Admin', + userMgmtLibraries: 'Bibliotecas', + userMgmtLibrariesAdminHint: 'Los usuarios admin tienen acceso automáticamente a todas las bibliotecas.', + userMgmtLibrariesEmpty: 'No hay bibliotecas disponibles en este servidor.', + userMgmtLibrariesValidation: 'Selecciona al menos una biblioteca.', + userMgmtLibrariesUpdateError: 'Usuario guardado, pero la asignación de bibliotecas falló', + userMgmtNoLibraries: 'Sin bibliotecas asignadas', + userMgmtNeverSeen: 'Nunca', + userMgmtSave: 'Guardar', + userMgmtCancel: 'Cancelar', + userMgmtDelete: 'Eliminar', + userMgmtEdit: 'Editar', + userMgmtConfirmDelete: '¿Eliminar el usuario «{{username}}»? Esta acción no se puede deshacer.', + userMgmtCreateError: 'No se pudo crear el usuario.', + userMgmtUpdateError: 'No se pudo actualizar el usuario.', + userMgmtDeleteError: 'No se pudo eliminar el usuario.', + userMgmtCreated: 'Usuario creado.', + userMgmtUpdated: 'Usuario actualizado.', + userMgmtDeleted: 'Usuario eliminado.', + userMgmtValidationMissing: 'Se requieren nombre de usuario, nombre visible y contraseña.', + userMgmtValidationMissingIdentity: 'Se requieren nombre de usuario y nombre visible.', + userMgmtMagicStringGenerate: 'Generar cadena mágica', + userMgmtSaveAndMagicString: 'Guardar y obtener cadena mágica', + userMgmtMagicStringPasswordNavHint: + 'Navidrome guardará esta contraseña para el usuario. Si difiere de la actual, se actualizará la contraseña de acceso en el servidor.', + userMgmtMagicStringPlaintextWarning: + 'Comparte la cadena mágica con cuidado: contiene la contraseña sin cifrar (la codificación no es cifrado). Quien tenga la cadena completa puede iniciar sesión como este usuario.', + userMgmtMagicStringCopied: 'Cadena mágica copiada al portapapeles.', + userMgmtMagicStringCopyFailed: 'No se pudo copiar al portapapeles.', + userMgmtMagicStringLoginFailed: 'Falló la comprobación de la contraseña; no se pudieron verificar las credenciales.', + userMgmtMagicStringModalTitle: 'Generar cadena mágica', + userMgmtMagicStringModalDesc: 'Introduce la contraseña Subsonic de «{{username}}». Se incluirá en la cadena mágica copiada.', + userMgmtMagicStringModalConfirm: 'Copiar cadena', + audiomuseTitle: 'AudioMuse-AI (Navidrome)', + audiomuseDesc: + 'Activa si este servidor tiene el plugin AudioMuse-AI Navidrome configurado. Habilita Mezcla Instantánea desde pistas y usa artistas similares del servidor en lugar de Last.fm en páginas de artistas.', + audiomuseIssueHint: + 'La Mezcla Instantánea falló recientemente — verifica el plugin de Navidrome y la API de AudioMuse. Artistas similares usan Last.fm como respaldo cuando el servidor no devuelve ninguno.', + connected: 'Conectado', + failed: 'Fallido', + eqTitle: 'Ecualizador', + eqEnabled: 'Habilitar Ecualizador', + eqPreset: 'Preajuste', + eqPresetCustom: 'Personalizado', + eqPresetBuiltin: 'Preajustes Integrados', + eqPresetCustomGroup: 'Mis Preajustes', + eqSavePreset: 'Guardar como Preajuste', + eqPresetName: 'Nombre del preajuste…', + eqDeletePreset: 'Eliminar preajuste', + eqResetBands: 'Restablecer a Plano', + eqPreGain: 'Pre-ganancia', + eqResetPreGain: 'Restablecer pre-ganancia', + eqAutoEqTitle: 'Búsqueda AutoEQ de Auriculares', + eqAutoEqPlaceholder: 'Buscar modelo de auricular / IEM…', + eqAutoEqSearching: 'Buscando…', + eqAutoEqNoResults: 'No se encontraron resultados', + eqAutoEqError: 'Error de búsqueda', + eqAutoEqRateLimit: 'Límite de GitHub alcanzado — intenta de nuevo en un minuto', + eqAutoEqFetchError: 'Error al obtener perfil EQ', + lfmTitle: 'Last.fm', + lfmConnect: 'Conectar con Last.fm', + lfmConnecting: 'Esperando autorización…', + lfmConfirm: 'He autorizado la aplicación', + lfmConnected: 'Conectado como', + lfmDisconnect: 'Desconectar', + lfmConnectDesc: 'Conecta tu cuenta de Last.fm para habilitar scrobbling y actualizaciones de "Reproduciendo Ahora" directamente desde Psysonic — no requiere configuración de Navidrome.', + lfmOpenBrowser: 'Se abrirá una ventana del navegador. Autoriza Psysonic en Last.fm, luego click en el botón de abajo.', + lfmScrobbles: '{{n}} scrobbles', + lfmMemberSince: 'Miembro desde {{year}}', + scrobbleEnabled: 'Scrobbling habilitado', + scrobbleDesc: 'Enviar canciones a Last.fm después del 50% de reproducción', + behavior: 'Comportamiento de la App', + cacheTitle: 'Tamaño Máx. de Almacenamiento', + cacheDesc: 'Portadas e imágenes de artistas. Cuando está lleno, las entradas más antiguas se eliminan automáticamente. Los álbumes offline no se eliminan automáticamente, pero se borrarán al limpiar la caché manualmente.', + cacheUsedImages: 'Imágenes:', + cacheUsedOffline: 'Pistas offline:', + cacheUsedHot: 'Tamaño en disco:', + hotCacheTrackCount: 'Pistas en caché:', + cacheMaxLabel: 'Tamaño máx.', + cacheClearBtn: 'Limpiar Caché', + cacheClearWarning: 'Esto también eliminará todos los álbumes offline de la biblioteca.', + cacheClearConfirm: 'Limpiar Todo', + cacheClearCancel: 'Cancelar', + offlineDirTitle: 'Biblioteca Offline (En App)', + offlineDirDesc: 'Ubicación de almacenamiento para pistas que haces disponibles offline dentro de Psysonic.', + offlineDirDefault: 'Predeterminado (Datos de App)', + offlineDirChange: 'Cambiar Directorio', + offlineDirClear: 'Restablecer a Predeterminado', + offlineDirHint: 'Las nuevas descargas usarán esta ubicación. Las descargas existentes permanecen en su ruta original.', + hotCacheTitle: 'Caché de reproducción activa', + hotCacheDisclaimer: 'Precarga las siguientes pistas en cola y mantiene las anteriores. Cuando está activado, usa espacio en disco y red.', + hotCacheDirDefault: 'Predeterminado (Datos de App)', + hotCacheDirChange: 'Cambiar carpeta', + hotCacheDirClear: 'Restablecer a predeterminado', + hotCacheDirHint: 'Cambiar la carpeta restablece el índice en-app; los archivos ya en disco permanecen donde están hasta que los elimines.', + hotCacheEnabled: 'Habilitar caché de reproducción activa', + hotCacheMaxMb: 'Tamaño máximo de caché', + hotCacheDebounce: 'Espera de cambio de cola', + hotCacheDebounceImmediate: 'Inmediato', + hotCacheDebounceSeconds: '{{n}} s', + hotCacheClearBtn: 'Limpiar caché activa', + audioOutputDevice: 'Dispositivo de salida de audio', + audioOutputDeviceDesc: 'Selecciona el dispositivo de audio que usa Psysonic. Los cambios surten efecto de inmediato y reinician la pista actual.', + audioOutputDeviceDefault: 'Predeterminado del sistema', + audioOutputDeviceRefresh: 'Actualizar lista de dispositivos', + audioOutputDeviceOsDefaultNow: 'salida actual del sistema', + audioOutputDeviceListError: 'No se pudo cargar la lista de dispositivos de audio.', + audioOutputDeviceNotInCurrentList: 'no está en la lista actual', + audioOutputDeviceMacNotice: 'En macOS, la reproducción actualmente sigue siempre al dispositivo de salida del sistema por razones técnicas. Cambia el destino mediante Ajustes del Sistema → Sonido o el icono del altavoz en la barra de menús. Motivo: CoreAudio activa una solicitud de permiso de micrófono al abrir un stream no-predeterminado — lo evitamos usando siempre la salida por defecto del sistema.', + hiResTitle: 'Reproducción Nativa Hi-Res', + hiResEnabled: 'Habilitar reproducción nativa hi-res', + hiResDesc: "Fuerza 44.1 kHz de salida por defecto para máxima estabilidad. Habilita solo si tu hardware y red soportan confiablemente altas tasas de muestreo (88.2 kHz+).", + showArtistImages: 'Mostrar Imágenes de Artistas', + showArtistImagesDesc: 'Carga y muestra imágenes de artistas en el resumen de Artistas. Desactivado por defecto para reducir I/O de disco del servidor y carga de red en bibliotecas grandes.', + showOrbitTrigger: 'Mostrar "Orbit" en la cabecera', + showOrbitTriggerDesc: 'El botón en la cabecera para iniciar o unirse a una sesión de escucha compartida. Ocúltalo si no usas Orbit — puedes volver a activarlo aquí.', + showTrayIcon: 'Mostrar Icono en Bandeja', + showTrayIconDesc: 'Muestra el icono de Psysonic en el área de notificación / barra de menú.', + minimizeToTray: 'Minimizar a Bandeja', + minimizeToTrayDesc: 'Al cerrar la ventana, mantener Psysonic ejecutándose en la bandeja del sistema en lugar de salir.', + preloadMiniPlayer: 'Precargar mini reproductor', + preloadMiniPlayerDesc: 'Crea la ventana del mini reproductor en segundo plano al iniciar la aplicación para que muestre contenido al instante la primera vez que se abre. Consume un poco más de memoria.', + discordRichPresence: 'Discord Rich Presence', + discordRichPresenceDesc: 'Muestra la pista actual en tu perfil de Discord. Requiere que Discord esté ejecutándose.', + useCustomTitlebar: 'Barra de título personalizada', + useCustomTitlebarDesc: 'Reemplaza la barra de título del sistema con una integrada que coincide con el tema de la app. Desactiva para usar la barra nativa de GNOME/GTK.', + linuxWebkitSmoothScroll: 'Rueda suave (Linux)', + linuxWebkitSmoothScrollDesc: 'Activado: inercia. Desactivado: pasos por línea (estilo GTK).', + discordCoverSource: 'Fuente de portada', + discordCoverSourceDesc: 'De dónde obtener la portada del álbum para tu perfil de Discord.', + discordCoverNone: 'Ninguna (solo icono de la app)', + discordCoverServer: 'Servidor (vía info del álbum)', + discordCoverApple: 'Apple Music', + discordOptions: 'Opciones avanzadas de Discord', + discordTemplates: 'Plantillas de texto personalizadas', + discordTemplatesDesc: 'Personaliza qué información se muestra en tu perfil de Discord. Variables: {title}, {artist}, {album}', + discordTemplateDetails: 'Línea principal (details)', + discordTemplateState: 'Línea secundaria (state)', + discordTemplateLargeText: 'Tooltip del álbum (largeText)', + nowPlayingEnabled: 'Mostrar en Reproduciendo Ahora', + nowPlayingEnabledDesc: 'Transmite tu pista actual a la vista de oyentes en vivo del servidor. Desactiva para dejar de enviar datos de reproducción.', + enableBandsintown: 'Fechas de gira de Bandsintown', + enableBandsintownDesc: 'Muestra próximos conciertos del artista actual en la pestaña Info. Los datos se obtienen de la API pública de Bandsintown.', + lyricsServerFirst: 'Preferir letras del servidor', + lyricsServerFirstDesc: 'Verifica primero letras provistas por el servidor (etiquetas embebidas, archivos sidecar) antes de consultar LRCLIB. Desactiva para usar LRCLIB primero.', + enableNeteaselyrics: 'Letras de Netease Cloud Music', + enableNeteaselyricsDesc: 'Usa Netease Cloud Music como fuente de letras de último recurso cuando el servidor y LRCLIB no devuelvan nada. Mejor cobertura para música asiática e internacional.', + lyricsSourcesTitle: 'Fuentes de Letras', + lyricsSourcesDesc: 'Elige qué fuentes consultar para letras y en qué orden. Arrastra para reordenar. Las fuentes desactivadas se omiten completamente.', + lyricsSourceServer: 'Servidor', + lyricsSourceLrclib: 'LRCLIB', + lyricsSourceNetease: 'Netease Cloud Music', + lyricsModeStandard: 'Estándar', + lyricsModeStandardDesc: 'Tres fuentes con orden configurable: etiquetas del servidor, LRCLIB, Netease.', + lyricsModeLyricsplus: 'YouLyPlus (Karaoke)', + lyricsModeLyricsplusDesc: 'Sincronización palabra por palabra desde Apple Music, Spotify, Musixmatch y QQ (backend comunitario). Recurre silenciosamente a las fuentes estándar cuando no se encuentra nada.', + lyricsStaticOnly: 'Mostrar letras como texto estático', + lyricsStaticOnlyDesc: 'Muestra las letras sincronizadas sin desplazamiento automático ni resaltado por palabra.', + downloadsTitle: 'Exportación ZIP y Archivado', + downloadsFolderDesc: 'Carpeta de destino para álbumes que descargas como ZIP a tu computadora.', + downloadsDefault: 'Carpeta de Descargas Predeterminada', + pickFolder: 'Seleccionar', + pickFolderTitle: 'Seleccionar Carpeta de Descarga', + clearFolder: 'Limpiar carpeta de descarga', + logout: 'Cerrar Sesión', + aboutTitle: 'Acerca de Psysonic', + aboutDesc: 'Un reproductor de música de escritorio moderno creado para Navidrome. Utiliza la API de Subsonic más extensiones específicas de Navidrome. Construido en Tauri v2 con motor de audio nativo en Rust — ligero y rápido, pero lleno de características: barra de progreso tipo onda, letras sincronizadas, integración Last.fm, ecualizador de 10 bandas, crossfade, reproducción gapless, Replay Gain, navegación por géneros, y una gran biblioteca de temas.', + aboutLicense: 'Licencia', + aboutLicenseText: 'GNU GPL v3 — libre para usar, modificar y distribuir bajo la misma licencia.', + aboutRepo: 'Código Fuente en GitHub', + aboutVersion: 'Versión', + aboutBuiltWith: 'Construido con Tauri · React · TypeScript · Rust/rodio', + aboutReleaseNotesLabel: 'Notas de la versión', + aboutReleaseNotesLink: 'Abrir las novedades de esta versión', + aboutContributorsLabel: 'Contribuidores', + showChangelogOnUpdate: "Mostrar 'Novedades' al actualizar", + showChangelogOnUpdateDesc: 'Muestra un discreto banner de changelog encima de Now Playing tras una actualización. Clic abre las notas de la versión; X lo oculta.', + randomMixTitle: 'Lista negra de Mezcla Aleatoria', + luckyMixMenuTitle: 'Mostrar Mezcla Suerte en el menú', + luckyMixMenuDesc: 'Activa Mezcla Suerte en "Crear Mezcla" y como elemento de menú separado cuando la navegación dividida está activa. Solo visible cuando AudioMuse está activo en el servidor actual.', + randomMixBlacklistTitle: 'Palabras Clave de Filtro Personalizadas', + randomMixBlacklistDesc: 'Las canciones se excluyen cuando cualquier palabra clave coincide con su género, título, álbum o artista (activo cuando el checkbox de arriba está activado).', + randomMixBlacklistPlaceholder: 'Agregar palabra clave…', + randomMixBlacklistAdd: 'Agregar', + randomMixBlacklistEmpty: 'Aún no hay palabras clave personalizadas.', + randomMixHardcodedTitle: 'Palabras clave integradas (activas cuando el checkbox está activado)', + tabAudio: 'Audio', + tabStorage: 'Sin conexión y caché', + tabAppearance: 'Apariencia', + tabLibrary: 'Biblioteca', + tabServers: 'Servidores', + tabLyrics: 'Letras', + tabPersonalisation: 'Personalización', + tabIntegrations: 'Integraciones', + inputKeybindingsTitle: 'Atajos de teclado', + aboutContributorsCount_one: '{{count}} contribución', + aboutContributorsCount_other: '{{count}} contribuciones', + searchPlaceholder: 'Buscar en ajustes…', + searchNoResults: 'Ningún ajuste coincide con tu búsqueda.', + aboutMaintainersLabel: 'Mantenedores', + integrationsPrivacyTitle: 'Aviso de privacidad', + integrationsPrivacyBody: 'Todas las integraciones de esta pestaña son opt-in y, una vez activadas, envían datos a servicios externos o a tu servidor Navidrome. Last.fm recibe tu historial de escucha, Discord muestra la pista actual en tu perfil, Bandsintown se consulta por artista para obtener fechas de gira, y la compartición «En reproducción» publica tu pista actual para otros usuarios de tu servidor Navidrome. Si no quieres nada de esto, simplemente deja desactivada la sección correspondiente.', + homeCustomizerTitle: 'Página de Inicio', + queueToolbarTitle: 'Barra de herramientas de cola', + queueToolbarReset: 'Restablecer a predeterminado', + queueToolbarSeparator: 'Separador', + sidebarTitle: 'Barra Lateral', + sidebarReset: 'Restablecer a predeterminado', + artistLayoutTitle: 'Secciones de la página del artista', + artistLayoutDesc: 'Arrastra para reordenar, alterna para ocultar secciones individuales de la página del artista. Las secciones sin datos se omiten automáticamente.', + artistLayoutReset: 'Restablecer a predeterminado', + artistLayoutBio: 'Biografía del artista', + artistLayoutTopTracks: 'Mejores pistas', + artistLayoutSimilar: 'Artistas similares', + artistLayoutAlbums: 'Álbumes', + artistLayoutFeatured: 'También presente en', + sidebarDrag: 'Arrastra para reordenar', + sidebarFixed: 'Siempre visible', + randomNavSplitTitle: 'Dividir navegación Mix', + randomNavSplitDesc: 'Mostrar "Mezcla Aleatoria", "Álbumes Aleatorios" y "Mezcla Suerte" como entradas separadas en la barra lateral en lugar del hub "Crear Mezcla".', + tabInput: 'Entrada', + tabUsers: 'Usuarios', + tabSystem: 'Sistema', + loggingTitle: 'Registro', + loggingModeDesc: 'Controla la verbosidad de los logs del backend en la terminal.', + loggingModeOff: 'Apagado', + loggingModeNormal: 'Normal', + loggingModeDebug: 'Depuración', + loggingExport: 'Exportar logs', + loggingExportSuccess: 'Logs exportados ({{count}} líneas).', + loggingExportError: 'No se pudieron exportar los logs.', + ratingsSectionTitle: 'Calificaciones', + ratingsSkipStarTitle: 'Saltar para 1 estrella', + ratingsSkipStarDesc: + 'Después de varios saltos seguidos, asigna 1 estrella a la pista. Solo para pistas aún no calificadas.', + ratingsSkipStarThresholdLabel: 'Saltos', + ratingsMixFilterTitle: 'Filtrar por calificación', + ratingsMixFilterDesc: + 'Filtra elementos de baja calificación en {{mix}} y {{albums}}. Click en la estrella seleccionada nuevamente para desactivar el umbral.', + ratingsMixMinSong: 'Canciones', + ratingsMixMinAlbum: 'Álbumes', + ratingsMixMinArtist: 'Artistas', + ratingsMixMinThresholdAria: 'Estrellas mínimas: {{label}}', + backupTitle: 'Respaldo y Restauración', + backupExport: 'Exportar configuración', + backupExportDesc: 'Guarda toda la configuración, perfiles de servidor, configuración Last.fm, tema, EQ y atajos de teclado a un archivo .psybkp. Las contraseñas se almacenan en texto plano — mantén el archivo seguro.', + backupImport: 'Importar configuración', + backupImportDesc: 'Restaura configuración desde un archivo .psybkp. La app se recargará después de importar.', + backupImportConfirm: 'Esto sobrescribirá toda la configuración actual. ¿Continuar?', + backupSuccess: 'Respaldo guardado', + backupImportSuccess: 'Configuración restaurada — recargando…', + backupImportError: 'Archivo de respaldo inválido o corrupto.', + shortcutsReset: 'Restablecer a predeterminados', + shortcutListening: 'Presiona una tecla…', + shortcutUnbound: '—', + globalShortcutsTitle: 'Atajos Globales', + globalShortcutsNote: 'Funcionan en todo el sistema incluso cuando Psysonic está en segundo plano. Requieren Ctrl, Alt o Super como modificador.', + shortcutClear: 'Limpiar', + shortcutPlayPause: 'Reproducir / Pausa', + shortcutNext: 'Siguiente pista', + shortcutPrev: 'Pista anterior', + shortcutVolumeUp: 'Subir volumen', + shortcutVolumeDown: 'Bajar volumen', + shortcutSeekForward: 'Avanzar 10s', + shortcutSeekBackward: 'Retroceder 10s', + shortcutToggleQueue: 'Alternar cola', + shortcutOpenFolderBrowser: 'Abrir {{folderBrowser}}', + shortcutFullscreenPlayer: 'Reproductor pantalla completa', + shortcutNativeFullscreen: 'Pantalla completa nativa', + shortcutOpenMiniPlayer: 'Abrir mini reproductor', + shortcutStartSearch: 'Iniciar una búsqueda', + shortcutStartAdvancedSearch: 'Iniciar una búsqueda avanzada', + shortcutToggleSidebar: 'Alternar barra lateral', + shortcutMuteSound: 'Silenciar', + shortcutToggleEqualizer: 'Abrir / alternar ecualizador', + shortcutToggleRepeat: 'Alternar repetición', + shortcutOpenNowPlaying: 'Abrir "Reproduciendo ahora"', + shortcutShowLyrics: 'Mostrar letra', + shortcutFavoriteCurrentTrack: 'Añadir pista actual a favoritos', + shortcutOpenHelp: 'Ayuda', + playbackTitle: 'Reproducción', + replayGain: 'Replay Gain', + replayGainDesc: 'Normalizar volumen de pistas usando metadatos ReplayGain', + replayGainMode: 'Modo', + replayGainAuto: 'Auto', + replayGainAutoDesc: 'Usa la ganancia del álbum cuando las pistas adyacentes en la cola son del mismo álbum, si no la ganancia de pista.', + replayGainTrack: 'Pista', + replayGainAlbum: 'Álbum', + replayGainPreGain: 'Pre-Ganancia (archivos etiquetados)', + replayGainPreGainDesc: 'Aumento universal añadido a cada cálculo de ReplayGain. Útil si tu biblioteca te parece globalmente demasiado baja.', + replayGainFallback: 'Respaldo (sin etiquetar / radio)', + replayGainFallbackDesc: 'Se aplica a pistas (y emisoras de radio) sin etiquetas ReplayGain, para que el contenido sin etiquetar no salte más fuerte que el resto.', + normalization: 'Normalización', + normalizationDesc: 'Iguala el volumen percibido entre pistas, álbumes y radio.', + normalizationOff: 'Apagado', + normalizationReplayGain: 'ReplayGain', + normalizationLufs: 'LUFS', + loudnessTargetLufs: 'LUFS objetivo', + loudnessTargetLufsDesc: 'Volumen de referencia al que se ajustan todas las pistas. Valor más bajo = salida más fuerte. Los servicios de streaming suelen rondar los -14 LUFS.', + loudnessPreAnalysisAttenuation: 'Atenuación antes de medir', + loudnessPreAnalysisAttenuationDesc: + 'Atenúa hasta que la loudness del tema esté guardada. En streaming luego solo hay estimaciones aproximadas. 0 dB = ninguna; más negativo = más bajo. A la derecha se muestra el dB efectivo para el destino actual.', + loudnessPreAnalysisAttenuationRef: 'Efectivo {{eff}} dB con destino {{tgt}} LUFS.', + loudnessPreAnalysisAttenuationReset: 'Predeterminado', + loudnessFirstPlayNote: + 'En la primera reproducción de un tema nuevo el volumen puede oscilar brevemente mientras se mide. La siguiente vez se usa la medición guardada y todo permanece estable. Las pistas próximas en la cola suelen analizarse durante la canción anterior, por lo que en la práctica esto rara vez ocurre.', + crossfade: 'Crossfade', + crossfadeDesc: 'Transición entre pistas', + crossfadeSecs: '{{n}} s', + notWithGapless: 'No disponible mientras Gapless está activo', + notWithCrossfade: 'No disponible mientras Crossfade está activo', + gapless: 'Reproducción Gapless', + gaplessDesc: 'Precarga siguiente pista para eliminar silencios entre canciones', + preservePlayNextOrder: 'Mantener el orden de "Reproducir Siguiente"', + preservePlayNextOrderDesc: 'Los elementos añadidos a "Reproducir Siguiente" se encolan detrás de los anteriores en vez de saltar al principio.', + trackPreviewsTitle: 'Previsualizaciones de pistas', + trackPreviewsToggle: 'Activar previsualizaciones', + trackPreviewsDesc: 'Mostrar botones de Reproducir y Previsualización en las listas de pistas para una muestra rápida a mitad de canción.', + trackPreviewStart: 'Posición inicial', + trackPreviewStartDesc: 'Cuánto avanza la pista antes de iniciar la previsualización (% de la duración).', + trackPreviewDuration: 'Duración', + trackPreviewDurationDesc: 'Cuánto dura cada previsualización antes de detenerse.', + trackPreviewDurationSecs: '{{n}} s', + trackPreviewLocationsTitle: 'Dónde aparecen las previsualizaciones', + trackPreviewLocationsDesc: 'Elige en qué listas se muestran los botones de previsualización.', + trackPreviewLocation_suggestions: 'En sugerencias de listas', + trackPreviewLocation_albums: 'En listas de pistas de álbum', + trackPreviewLocation_playlists: 'En listas de reproducción', + trackPreviewLocation_favorites: 'En favoritos', + trackPreviewLocation_artist: 'En las mejores pistas del artista', + trackPreviewLocation_randomMix: 'En Random Mix', + preloadMode: 'Precargar Siguiente Pista', + preloadModeDesc: 'Cuándo comenzar a cargar la siguiente pista en cola', + nextTrackBufferingTitle: 'Buffer', + preloadHotCacheMutualExclusive: 'Precarga y Caché Activa sirven para lo mismo — solo uno puede estar activo a la vez. Habilitar uno desactivará automáticamente el otro.', + preloadOff: 'Apagado', + preloadBalanced: 'Balanceado (30 s antes del final)', + preloadEarly: 'Temprano (después de 5 s de reproducción)', + preloadCustom: 'Personalizado', + preloadCustomSeconds: 'Segundos antes del final: {{n}}', + infiniteQueue: 'Cola Infinita', + infiniteQueueDesc: 'Agregar automáticamente pistas aleatorias cuando la cola termina', + experimental: 'Experimental', + fsPlayerSection: 'Reproductor Pantalla Completa', + fsShowArtistPortrait: 'Mostrar foto del artista', + fsShowArtistPortraitDesc: 'Muestra la foto del artista (o portada del álbum) en el lado derecho del reproductor pantalla completa.', + fsPortraitDim: 'Oscurecimiento de foto', + fsLyricsStyle: 'Estilo de letra', + fsLyricsStyleRail: 'Carril', + fsLyricsStyleRailDesc: 'Carril deslizante clásico de 5 líneas.', + fsLyricsStyleApple: 'Desplazamiento', + fsLyricsStyleAppleDesc: 'Lista desplazable a pantalla completa.', + sidebarLyricsStyle: 'Estilo de desplazamiento de letra', + sidebarLyricsStyleClassic: 'Clásico', + sidebarLyricsStyleClassicDesc: 'La línea activa se centra.', + sidebarLyricsStyleApple: 'Apple Music-like', + sidebarLyricsStyleAppleDesc: 'La línea activa se ancla arriba con animación suave.', + seekbarStyle: 'Estilo de Barra de Progreso', + seekbarStyleDesc: 'Elige la apariencia de la barra de progreso del reproductor', + seekbarTruewave: 'Forma de Onda Real', + seekbarPseudowave: 'Forma de Onda Pseudo', + seekbarLinedot: 'Línea y Punto', + seekbarBar: 'Barra', + seekbarThick: 'Barra Gruesa', + seekbarSegmented: 'Segmentada', + seekbarNeon: 'Brillo Neón', + seekbarPulsewave: 'Onda Pulsante', + seekbarParticletrail: 'Estela de Partículas', + seekbarLiquidfill: 'Llenado Líquido', + seekbarRetrotape: 'Cinta Retro', + themeSchedulerTitle: 'Cambio Automático de Tema', + themeSchedulerEnable: 'Habilitar Programador de Temas', + themeSchedulerEnableSub: 'Cambia automáticamente entre dos temas según la hora del día', + themeSchedulerDayTheme: 'Tema de Día', + themeSchedulerDayStart: 'Comienza de Día A las', + themeSchedulerNightTheme: 'Tema de Noche', + themeSchedulerNightStart: 'Comienza de Noche A las', + themeSchedulerActiveHint: 'El Programador de Temas está activo — los cambios de tema se manejan automáticamente.', + visualOptionsTitle: 'Opciones Visuales', + coverArtBackground: 'Fondo de Portada', + coverArtBackgroundSub: 'Mostrar portada desenfocada como fondo en encabezados de álbumes y listas de reproducción', + playlistCoverPhoto: 'Foto de Portada de Playlist', + playlistCoverPhotoSub: 'Mostrar cuadrícula de fotos de portada en la vista detallada de playlists', + showBitrate: 'Mostrar Bitrate', + showBitrateSub: 'Mostrar bitrate de audio en las listas de pistas', + floatingPlayerBar: 'Barra del Reproductor Flotante', + floatingPlayerBarSub: 'Mantener la barra del reproductor flotando sobre el contenido', + uiScaleTitle: 'Escala de Interfaz', + uiScaleLabel: 'Zoom', +}; diff --git a/src/locales/es/sharePaste.ts b/src/locales/es/sharePaste.ts new file mode 100644 index 00000000..464bdf84 --- /dev/null +++ b/src/locales/es/sharePaste.ts @@ -0,0 +1,18 @@ +export const sharePaste = { + notLoggedIn: 'Inicia sesión y añade el servidor antes de pegar un enlace para compartir.', + noMatchingServer: 'Ningún servidor guardado coincide con este enlace. Añade un servidor con esta dirección: {{url}}', + trackUnavailable: 'No se encontró esta canción en el servidor.', + albumUnavailable: 'No se encontró este álbum en el servidor.', + artistUnavailable: 'No se encontró este artista en el servidor.', + composerUnavailable: 'No se encontró este compositor en el servidor.', + openedTrack: 'Reproduciendo la canción compartida.', + openedAlbum: 'Abriendo el álbum compartido.', + openedArtist: 'Abriendo el artista compartido.', + openedComposer: 'Abriendo el compositor compartido.', + openedQueue_one: 'Reproduciendo {{count}} pista del enlace para compartir.', + openedQueue_other: 'Reproduciendo {{count}} pistas del enlace para compartir.', + openedQueuePartial: + 'Reproduciendo {{played}} de {{total}} pistas del enlace ({{skipped}} no encontradas en este servidor).', + queueAllUnavailable: 'Ninguna pista de este enlace se encontró en el servidor.', + genericError: 'No se pudo abrir el enlace para compartir.', +}; diff --git a/src/locales/es/sidebar.ts b/src/locales/es/sidebar.ts new file mode 100644 index 00000000..a44f44d8 --- /dev/null +++ b/src/locales/es/sidebar.ts @@ -0,0 +1,38 @@ +export const sidebar = { + library: 'Biblioteca', + mainstage: 'Escenario Principal', + newReleases: 'Novedades', + allAlbums: 'Todos los Álbumes', + randomAlbums: 'Álbumes Aleatorios', + artists: 'Artistas', + composers: 'Compositores', + randomMix: 'Mezcla Aleatoria', + randomPicker: 'Crear Mezcla', + favorites: 'Favoritos', + nowPlaying: 'Reproduciendo Ahora', + system: 'Sistema', + statistics: 'Estadísticas', + settings: 'Configuración', + help: 'Ayuda', + expand: 'Expandir Barra Lateral', + collapse: 'Colapsar Barra Lateral', + + downloadingTracks: 'Descargando {{n}} pistas…', + syncingTracks: 'Sincronizando {{done}}/{{total}}…', + cancelDownload: 'Cancelar descarga', + offlineLibrary: 'Biblioteca Offline', + genres: 'Géneros', + tracks: 'Canciones', + playlists: 'Listas de Reproducción', + mostPlayed: 'Más Reproducidos', + losslessAlbums: 'Sin Pérdidas', + radio: 'Radio por Internet', + folderBrowser: 'Explorar Carpetas', + deviceSync: 'Sincronizar dispositivo', + libraryScope: 'Ámbito de biblioteca', + allLibraries: 'Todas las bibliotecas', + expandPlaylists: 'Expandir listas', + collapsePlaylists: 'Colapsar listas', + more: 'Más', + feelingLucky: 'Mezcla Suerte', +}; diff --git a/src/locales/es/smartPlaylists.ts b/src/locales/es/smartPlaylists.ts new file mode 100644 index 00000000..8cb1c7b9 --- /dev/null +++ b/src/locales/es/smartPlaylists.ts @@ -0,0 +1,41 @@ +export const smartPlaylists = { + sectionBasic: '1. Básico', + sectionGenres: '2. Géneros', + sectionYearsAndFilters: '3. Años y filtros', + genreMode: 'Modo de géneros', + genreModeInclude: 'Incluir géneros', + genreModeExclude: 'Excluir géneros', + genreSearchPlaceholder: 'Filtrar géneros...', + availableGenres: 'Disponibles', + selectedGenres: 'Seleccionados', + yearMode: 'Modo de años', + yearModeInclude: 'Incluir rango', + yearModeExclude: 'Excluir rango', + name: 'Nombre (sin prefijo)', + limit: 'Límite', + limitHint: 'Cuántas canciones incluir en la playlist (1-{{max}}, normalmente 50).', + artistContains: 'Artista contiene…', + albumContains: 'Álbum contiene…', + titleContains: 'Título contiene…', + minRating: 'Valoración mínima', + minRatingAria: 'Valoración mínima para la playlist inteligente', + minRatingHint: '0 desactiva el umbral mínimo; 1-5 mantiene canciones con valoración mayor que el valor seleccionado.', + fromYear: 'Desde año', + toYear: 'Hasta año', + excludeUnrated: 'Excluir canciones sin valoración', + compilationOnly: 'Solo compilaciones', + create: 'Nueva Smart Playlist', + save: 'Guardar Smart Playlist', + created: '{{name}} creada', + updated: '{{name}} actualizada', + createFailed: 'No se pudo crear la smart playlist.', + updateFailed: 'No se pudo actualizar la smart playlist.', + navidromeOnly: 'Las smart playlists solo se pueden crear en servidores Navidrome.', + loadFailed: 'No se pudieron cargar las smart playlists desde Navidrome.', + sortRandom: 'Ordenar: aleatorio', + sortTitleAsc: 'Ordenar: título A-Z', + sortTitleDesc: 'Ordenar: título Z-A', + sortYearDesc: 'Ordenar: año desc', + sortYearAsc: 'Ordenar: año asc', + sortPlayCountDesc: 'Ordenar: reproducciones desc', +}; diff --git a/src/locales/es/songInfo.ts b/src/locales/es/songInfo.ts new file mode 100644 index 00000000..b51fcaa1 --- /dev/null +++ b/src/locales/es/songInfo.ts @@ -0,0 +1,23 @@ +export const songInfo = { + title: 'Información de Canción', + songTitle: 'Título', + artist: 'Artista', + album: 'Álbum', + albumArtist: 'Artista del Álbum', + year: 'Año', + genre: 'Género', + duration: 'Duración', + track: 'Pista', + format: 'Formato', + bitrate: 'Bitrate', + sampleRate: 'Frecuencia de Muestreo', + bitDepth: 'Profundidad de Bits', + channels: 'Canales', + fileSize: 'Tamaño de Archivo', + path: 'Ruta', + replayGainTrack: 'RG Ganancia de Pista', + replayGainAlbum: 'RG Ganancia de Álbum', + replayGainPeak: 'RG Pico de Pista', + mono: 'Mono', + stereo: 'Estéreo', +}; diff --git a/src/locales/es/statistics.ts b/src/locales/es/statistics.ts new file mode 100644 index 00000000..ef6562af --- /dev/null +++ b/src/locales/es/statistics.ts @@ -0,0 +1,47 @@ +export const statistics = { + title: 'Estadísticas', + recentlyPlayed: 'Reproducidos Recientemente', + mostPlayed: 'Álbumes Más Reproducidos', + highestRated: 'Álbumes Mejor Calificados', + genreDistribution: 'Distribución de Géneros (Top 20)', + loadMore: 'Cargar más', + statArtists: 'Artistas', + statArtistsTooltip: 'Solo artistas de álbum — los artistas que aparecen únicamente como artistas de pista (featuring, invitado, etc.) sin álbum propio no se cuentan.', + statAlbums: 'Álbumes', + statSongs: 'Canciones', + statGenres: 'Géneros', + statPlaytime: 'Tiempo Total de Reproducción', + genreInsights: 'Información de Géneros', + formatDistribution: 'Distribución de Formatos', + formatSample: 'Muestra de {{n}} pistas', + computing: 'Calculando…', + genreSongs: '{{count}} Canciones', + genreAlbums: '{{count}} Álbumes', + recentlyAdded: 'Agregados Recientemente', + decadeDistribution: 'Álbumes por Década', + decadeAlbums_one: '{{count}} Álbum', + decadeAlbums_other: '{{count}} Álbumes', + decadeUnknown: 'Desconocido', + lfmTitle: 'Estadísticas de Last.fm', + lfmTopArtists: 'Artistas Principales', + lfmTopAlbums: 'Álbumes Principales', + lfmTopTracks: 'Pistas Principales', + lfmPlays: '{{count}} reproducciones', + lfmPeriodOverall: 'Todo el Tiempo', + lfmPeriod7day: '7 Días', + lfmPeriod1month: '1 Mes', + lfmPeriod3month: '3 Meses', + lfmPeriod6month: '6 Meses', + lfmPeriod12month: '12 Meses', + lfmNotConnected: 'Conecta Last.fm en Configuración para ver tus estadísticas.', + lfmRecentTracks: 'Scrobbles Recientes', + lfmNowPlaying: 'Reproduciendo Ahora', + lfmJustNow: 'ahora mismo', + lfmMinutesAgo: 'hace {{n}}m', + lfmHoursAgo: 'hace {{n}}h', + lfmDaysAgo: 'hace {{n}}d', + topRatedSongs: 'Canciones Mejor Calificadas', + topRatedArtists: 'Artistas Mejor Calificados', + noRatedSongs: 'Aún no hay canciones calificadas. Califica canciones en la vista de álbum o playlist.', + noRatedArtists: 'Aún no hay artistas calificados.', +}; diff --git a/src/locales/es/tracks.ts b/src/locales/es/tracks.ts new file mode 100644 index 00000000..5fe4d6c2 --- /dev/null +++ b/src/locales/es/tracks.ts @@ -0,0 +1,15 @@ +export const tracks = { + title: 'Canciones', + subtitle: 'Explorar. Buscar. Descubrir.', + heroEyebrow: 'Canción del momento', + heroReroll: 'Elegir otra', + playSong: 'Reproducir', + enqueueSong: 'Añadir a la cola', + railRandom: 'Selección aleatoria', + railHighlyRated: 'Mejor valoradas', + browseTitle: 'Explorar todas las canciones', + browseUnsupported: 'Este servidor no lista toda la biblioteca de una vez. Usa la búsqueda de arriba para encontrar canciones concretas.', + searchPlaceholder: 'Busca una canción por título, artista o álbum…', + count_one: '{{count}} canción', + count_other: '{{count}} canciones', +}; diff --git a/src/locales/es/tray.ts b/src/locales/es/tray.ts new file mode 100644 index 00000000..47e79cba --- /dev/null +++ b/src/locales/es/tray.ts @@ -0,0 +1,8 @@ +export const tray = { + playPause: 'Reproducir / Pausa', + nextTrack: 'Pista siguiente', + previousTrack: 'Pista anterior', + showHide: 'Mostrar / Ocultar', + exitPsysonic: 'Salir de Psysonic', + nothingPlaying: 'Nada en reproducción', +}; diff --git a/src/locales/es/whatsNew.ts b/src/locales/es/whatsNew.ts new file mode 100644 index 00000000..ecefb313 --- /dev/null +++ b/src/locales/es/whatsNew.ts @@ -0,0 +1,8 @@ +export const whatsNew = { + title: 'Novedades', + empty: 'Aún no hay entrada de changelog para esta versión.', + bannerTitle: 'Changelog', + bannerCollapsed: 'Novedades en v{{version}}', + dismiss: 'Ocultar', + close: 'Cerrar', +}; diff --git a/src/locales/fr.ts b/src/locales/fr.ts deleted file mode 100644 index 1db700ae..00000000 --- a/src/locales/fr.ts +++ /dev/null @@ -1,1824 +0,0 @@ -export const frTranslation = { - sidebar: { - library: 'Bibliothèque', - mainstage: 'Scène principale', - newReleases: 'Nouveautés', - allAlbums: 'Tous les albums', - randomAlbums: 'Albums aléatoires', - randomPicker: 'Créer un mix', - artists: 'Artistes', - composers: 'Compositeurs', - randomMix: 'Mix aléatoire', - favorites: 'Favoris', - nowPlaying: 'En cours', - system: 'Système', - statistics: 'Statistiques', - settings: 'Paramètres', - help: 'Aide', - expand: 'Développer la barre latérale', - collapse: 'Réduire la barre latérale', - downloadingTracks: '{{n}} pistes en cache…', - syncingTracks: 'Synchro {{done}}/{{total}}…', - cancelDownload: 'Annuler le téléchargement', - offlineLibrary: 'Bibliothèque hors ligne', - genres: 'Genres', - tracks: 'Titres', - playlists: 'Playlists', - mostPlayed: 'Les plus joués', - losslessAlbums: 'Lossless', - radio: 'Radio Internet', - folderBrowser: 'Explorateur de dossiers', - deviceSync: 'Sync appareil', - libraryScope: 'Portée de la bibliothèque', - allLibraries: 'Toutes les bibliothèques', - expandPlaylists: 'Développer les playlists', - collapsePlaylists: 'Réduire les playlists', - more: 'Plus', - feelingLucky: 'Mix Chance', - }, - home: { - hero: 'En vedette', - starred: 'Favoris personnels', - recent: 'Ajoutés récemment', - mostPlayed: 'Les plus écoutés', - recentlyPlayed: 'Récemment écoutés', - losslessAlbums: 'Albums lossless', - discover: 'Découvrir', - discoverSongs: 'Découvrir des titres', - loadMore: 'Charger plus', - discoverMore: 'Découvrir plus', - discoverArtists: 'Découvrir des artistes', - discoverArtistsMore: 'Tous les artistes', - becauseYouLike: 'Parce que tu as écouté…', - becauseYouLikeFor: 'Parce que tu as écouté {{artist}}', - similarTo: 'Similaire à {{artist}}', - becauseYouLikeTracks_one: '{{count}} titre', - becauseYouLikeTracks_other: '{{count}} titres' - }, - hero: { - eyebrow: 'Album en vedette', - playAlbum: 'Lire l\'album', - enqueue: 'Mettre en file', - enqueueTooltip: 'Ajouter l\'album entier à la file d\'attente', - }, - search: { - placeholder: 'Rechercher un artiste, album ou morceau…', - noResults: 'Aucun résultat pour « {{query}} »', - artists: 'Artistes', - albums: 'Albums', - songs: 'Morceaux', - clearLabel: 'Effacer la recherche', - addedToQueueToast: '« {{title}} » ajouté à la file', - title: 'Recherche', - resultsFor: 'Résultats pour « {{query}} »', - album: 'Album', - advanced: 'Recherche avancée', - advancedSearchTerm: 'Terme de recherche', - advancedSearchPlaceholder: 'Titre, album, artiste…', - advancedGenre: 'Genre', - advancedAllGenres: 'Tous les genres', - advancedYear: 'Année', - advancedYearFrom: 'de', - advancedYearTo: 'à', - advancedAll: 'Tous', - advancedSearch: 'Rechercher', - advancedEmpty: 'Entrez un terme de recherche ou sélectionnez un filtre.', - advancedNoResults: 'Aucun résultat trouvé.', - advancedGenreNote: 'Les morceaux sont sélectionnés aléatoirement dans ce genre.', - recentSearches: 'Recherches récentes', - browse: 'Parcourir', - emptyHint: 'Que veux-tu écouter ?', - genres: 'Genres', - }, - nowPlaying: { - tooltip: 'Qui écoute ?', - title: 'Qui écoute ?', - loading: 'Chargement…', - nobody: 'Personne n\'écoute en ce moment.', - minutesAgo: 'il y a {{n}} min', - nothingPlaying: 'Rien en cours. Lancez un morceau !', - aboutArtist: "À propos de l'artiste", - fromAlbum: 'De cet album', - viewAlbum: "Voir l'album", - goToArtist: "Aller à l'artiste", - readMore: 'Lire la suite', - showLess: 'Réduire', - genreInfo: 'Genre', - trackInfo: 'Infos piste', - topSongs: 'Le plus joué de cet artiste', - topSongsCredit: 'Top titres de {{name}}', - trackPosition: 'Piste {{pos}}', - playsCount_one: '{{count}} écoute', - playsCount_other: '{{count}} écoutes', - releasedYearsAgo_one: 'il y a {{count}} an', - releasedYearsAgo_other: 'il y a {{count}} ans', - discography: 'Discographie', - lastfmStats: 'Statistiques Last.fm', - thisTrack: 'Ce titre', - thisArtist: 'Cet artiste', - listeners: 'auditeurs', - scrobbles: 'scrobbles', - yourScrobbles: 'par vous', - listenersN: '{{n}} auditeurs', - scrobblesN: '{{n}} scrobbles', - playsByYouN: 'écouté {{n}}× par vous', - openTrackOnLastfm: 'Titre sur Last.fm', - openArtistOnLastfm: 'Artiste sur Last.fm', - rgTrackTooltip: 'ReplayGain (piste)', - rgAlbumTooltip: 'ReplayGain (album)', - rgAutoTooltip: 'ReplayGain (auto)', - showMoreTracks: 'Afficher {{count}} de plus', - showLessTracks: 'Réduire', - hideCard: 'Masquer la carte', - layoutMenu: 'Disposition', - visibleCards: 'Cartes visibles', - hiddenCards: 'Cartes masquées', - noHiddenCards: 'Aucune carte masquée', - resetLayout: 'Réinitialiser la disposition', - emptyColumn: 'Déposez des cartes ici', - }, - contextMenu: { - playNow: 'Lire maintenant', - playNext: 'Lire ensuite', - addToQueue: 'Ajouter à la file', - enqueueAlbum: 'Mettre l\'album en file', - enqueueAlbums_one: 'Mettre {{count}} album en file', - enqueueAlbums_other: 'Mettre {{count}} albums en file', - startRadio: 'Démarrer la radio', - instantMix: 'Mix instantané', - instantMixFailed: 'Impossible de créer le mix instantané — erreur serveur ou plugin.', - cliMixNeedsTrack: 'Aucune lecture en cours — lancez d’abord la lecture, puis relancez la commande de mix.', - lfmLove: 'Aimer sur Last.fm', - lfmUnlove: 'Ne plus aimer sur Last.fm', - favorite: 'Favori', - favoriteArtist: 'Artiste favori', - favoriteAlbum: 'Album favori', - unfavorite: 'Retirer des favoris', - unfavoriteArtist: 'Retirer l\'artiste des favoris', - unfavoriteAlbum: 'Retirer l\'album des favoris', - removeFromQueue: 'Retirer de la file', - removeFromPlaylist: 'Retirer de la playlist', - openAlbum: 'Ouvrir l\'album', - goToArtist: 'Aller à l\'artiste', - download: 'Télécharger (ZIP)', - addToPlaylist: 'Ajouter à la playlist', - selectedPlaylists: '{{count}} playlists sélectionnées', - selectedAlbums: '{{count}} albums sélectionnés', - selectedArtists: '{{count}} artistes sélectionnés', - songInfo: 'Infos du morceau', - shareLink: 'Copier le lien de partage', - shareCopied: 'Lien de partage copié dans le presse-papiers.', - shareCopyFailed: 'Impossible de copier dans le presse-papiers.', - }, - sharePaste: { - notLoggedIn: 'Connectez-vous et ajoutez le serveur avant de coller un lien de partage.', - noMatchingServer: 'Aucun serveur enregistré ne correspond à ce lien. Ajoutez un serveur avec cette adresse : {{url}}', - trackUnavailable: 'Ce morceau est introuvable sur le serveur.', - albumUnavailable: 'Cet album est introuvable sur le serveur.', - artistUnavailable: 'Cet artiste est introuvable sur le serveur.', - composerUnavailable: 'Ce compositeur est introuvable sur le serveur.', - openedTrack: 'Lecture du morceau partagé.', - openedAlbum: 'Ouverture de l’album partagé.', - openedArtist: 'Ouverture de l’artiste partagé.', - openedComposer: 'Ouverture du compositeur partagé.', - openedQueue_one: 'Lecture de {{count}} morceau depuis le lien de partage.', - openedQueue_other: 'Lecture de {{count}} morceaux depuis le lien de partage.', - openedQueuePartial: - '{{played}} sur {{total}} morceaux du lien : {{skipped}} introuvable(s) sur ce serveur.', - queueAllUnavailable: 'Aucun morceau de ce lien n’a été trouvé sur le serveur.', - genericError: 'Impossible d’ouvrir le lien de partage.', - }, - albumDetail: { - back: 'Retour', - orbitDoubleClickHint: 'Double-clic pour ajouter ce morceau à la file Orbit', - playAll: 'Tout lire', - shareAlbum: 'Partager l\'album', - enqueue: 'Mettre en file', - enqueueTooltip: 'Ajouter l\'album entier à la file d\'attente', - artistBio: 'Biographie', - download: 'Télécharger (ZIP)', - downloading: 'Chargement…', - cacheOffline: 'Rendre disponible hors ligne', - offlineCached: 'Disponible hors ligne', - offlineDownloading: 'Mise en cache… ({{n}}/{{total}})', - removeOffline: 'Supprimer le cache hors ligne', - offlineStorageFull: 'Stockage hors ligne plein (limite : {{mb}} Mo). Supprimez un album de votre bibliothèque hors ligne ou augmentez la limite dans les paramètres.', - offlineStorageGoToSettings: 'Paramètres', - offlineStorageGoToLibrary: 'Bibliothèque hors ligne', - favoriteAdd: 'Ajouter aux favoris', - favoriteRemove: 'Retirer des favoris', - favorite: 'Favori', - noBio: 'Aucune biographie disponible.', - moreByArtist: 'Plus de {{artist}}', - tracksCount: '{{n}} pistes', - goToArtist: 'Aller à {{artist}}', - moreLabelAlbums: 'Plus d\'albums sur {{label}}', - trackTitle: 'Titre', - trackAlbum: 'Album', - trackArtist: 'Artiste', - trackGenre: 'Genre', - trackFormat: 'Format', - trackFavorite: 'Favori', - trackRating: 'Note', - trackDuration: 'Durée', - trackTotal: 'Total', - columns: 'Colonnes', - resetColumns: 'Réinitialiser', - notFound: 'Album introuvable.', - bioModal: 'Biographie de l\'artiste', - bioClose: 'Fermer', - ratingLabel: 'Note', - enlargeCover: 'Agrandir', - filterSongs: 'Filtrer…', - sortNatural: 'Naturel', - sortByTitle: 'A–Z (Titre)', - sortByArtist: 'A–Z (Artiste)', - sortByAlbum: 'A–Z (Album)', - }, - entityRating: { - albumShort: 'Note de l’album', - artistShort: 'Note de l’artiste', - albumAriaLabel: 'Note de l’album', - artistAriaLabel: 'Note de l’artiste', - selectedArtistsRatingAriaLabel: 'Note sur {{count}} artistes sélectionnés', - selectedAlbumsRatingAriaLabel: 'Note sur {{count}} albums sélectionnés', - saveFailed: 'Impossible d’enregistrer la note.', - }, - artistDetail: { - back: 'Retour', - albums: 'Albums', - album: 'Album', - playAll: 'Tout lire', - shareArtist: 'Partager l\'artiste', - shuffle: 'Aléatoire', - radio: 'Radio', - loading: 'Chargement…', - noRadio: 'Aucun morceau similaire trouvé pour cet artiste.', - notFound: 'Artiste introuvable.', - albumsBy: 'Albums de {{name}}', - topTracks: 'Morceaux populaires', - noAlbums: 'Aucun album trouvé.', - trackTitle: 'Titre', - trackAlbum: 'Album', - trackDuration: 'Durée', - favoriteAdd: 'Ajouter aux favoris', - favoriteRemove: 'Retirer des favoris', - favorite: 'Favori', - albumCount_one: '{{count}} album', - albumCount_other: '{{count}} albums', - openedInBrowser: 'Ouvert dans le navigateur', - featuredOn: 'Également sur', - similarArtists: 'Artistes similaires', - cacheOffline: 'Enregistrer la discographie hors ligne', - offlineCached: 'Discographie en cache', - offlineDownloading: 'En cache… ({{done}}/{{total}} albums)', - uploadImage: "Téléverser l'image de l'artiste", - uploadImageError: "Échec du téléversement de l'image", - releaseTypes: { - album: 'Album', - ep: 'EP', - single: 'Single', - compilation: 'Compilation', - live: 'Live', - soundtrack: 'Bande originale', - remix: 'Remix', - other: 'Autre', - }, - }, - favorites: { - title: 'Favoris', - empty: 'Vous n\'avez pas encore de favoris.', - artists: 'Artistes', - albums: 'Albums', - songs: 'Morceaux', - enqueueAll: 'Tout ajouter à la file', - playAll: 'Tout lire', - removeSong: 'Retirer des favoris', - stations: 'Stations de radio', - showingFiltered: 'Affichage de {{filtered}} sur {{total}} ({{artist}})', - showingCount: 'Affichage de {{filtered}} sur {{total}}', - clearArtistFilter: 'Effacer le filtre artiste', - noFilterResults: 'Aucun résultat avec les filtres sélectionnés.', - allArtists: 'Tous les artistes', - topArtists: 'Artistes favoris principaux', - topArtistsSongCount_one: '{{count}} morceau', - topArtistsSongCount_other: '{{count}} morceaux', - }, - randomLanding: { - title: 'Créer un mix', - mixByTracks: 'Mix par pistes', - mixByTracksDesc: 'Sélection aléatoire de titres depuis toute votre médiathèque', - mixByAlbums: 'Mix par albums', - mixByAlbumsDesc: 'Albums aléatoires pour vos prochaines découvertes', - mixByLucky: 'Mix Chance', - mixByLuckyDesc: 'Instant Mix intelligent basé sur artistes, albums et notes élevées', - }, - randomAlbums: { - title: 'Albums aléatoires', - refresh: 'Actualiser', - }, - genres: { - title: 'Genres', - genreCount: 'genres', - albumCount_one: '{{count}} album', - albumCount_other: '{{count}} albums', - loading: 'Chargement des genres…', - empty: 'Aucun genre trouvé.', - albumsLoading: 'Chargement des albums…', - albumsEmpty: 'Aucun album trouvé pour ce genre.', - loadMore: 'Charger plus', - back: 'Retour', - }, - randomMix: { - title: 'Mix aléatoire', - remix: 'Remixer', - remixTooltip: 'Charger de nouveaux morceaux aléatoires', - remixGenre: 'Remixer {{genre}}', - remixTooltipGenre: 'Charger de nouveaux morceaux {{genre}}', - playAll: 'Tout lire', - trackTitle: 'Titre', - trackArtist: 'Artiste', - trackAlbum: 'Album', - trackFavorite: 'Favori', - trackDuration: 'Durée', - favoriteAdd: 'Ajouter aux favoris', - favoriteRemove: 'Retirer des favoris', - play: 'Lire', - trackGenre: 'Genre', - mixSettingsHeader: 'Réglages du mix', - exclusionsHeader: 'Exclusions', - filterPanelInexactSizeNote: 'La taille du mix est une cible — les grandes requêtes peuvent renvoyer moins de morceaux uniques si le pool aléatoire du serveur s\'épuise.', - mixSize: 'Taille de liste', - excludeAudiobooks: 'Exclure les livres audio et pièces radiophoniques', - excludeAudiobooksDesc: 'Correspond aux mots-clés dans le genre, le titre, l\'album et l\'artiste — ex. Hörbuch, Audiobook, Spoken Word, …', - genreBlocked: 'Mot-clé bloqué', - genreAddedToBlacklist: 'Ajouté à la liste de filtres', - genreAlreadyBlocked: 'Déjà bloqué', - artistBlocked: 'Artiste bloqué', - artistAddedToBlacklist: 'Artiste ajouté à la liste de filtres', - artistClickHint: 'Cliquer pour bloquer cet artiste', - blacklistToggle: 'Filtre par mot-clé', - genreMixTitle: 'Mix par genre', - genreMixDesc: 'Top 20 genres par nombre de morceaux — cliquer pour un mix aléatoire', - genreMixAll: 'Tous les morceaux', - genreMixLoadMore: 'Charger 10 de plus', - genreMixNoGenres: 'Aucun genre trouvé sur le serveur.', - shuffleGenres: 'Afficher d\'autres genres', - filterPanelTitle: 'Filtres', - filterPanelDesc: 'Cliquez sur un tag de genre ou un nom d\'artiste dans la liste pour l\'exclure des futurs mix.', - genreClickHint: 'Cliquez sur un tag de genre pour l\'ajouter\ncomme mot-clé de filtre.\nCorrespond au genre, titre, album et artiste.', - }, - luckyMix: { - done: 'Mix Chance prêt : {{count}} titres', - failed: 'Impossible de créer le Mix Chance. Réessayez.', - unavailable: 'Mix Chance n\'est pas disponible pour ce serveur.', - cancelTooltip: 'Annuler la création du Mix Chance', - }, - albums: { - title: 'Tous les albums', - sortByName: 'A–Z (Album)', - sortByArtist: 'A–Z (Artiste)', - sortNewest: 'Plus récents', - sortRandom: 'Aléatoire', - yearFrom: 'De', - yearTo: 'À', - yearFilterClear: 'Effacer le filtre année', - yearFilterLabel: 'Année', - compilationLabel: 'Compilations', - compilationOnly: 'Uniquement compilations', - compilationHide: 'Masquer compilations', - compilationTooltipAll: 'Tous les albums · clic : uniquement compilations', - compilationTooltipOnly: 'Uniquement compilations · clic : masquer compilations', - compilationTooltipHide: 'Compilations masquées · clic : tout afficher', - select: 'Sélection multiple', - startSelect: 'Activer la sélection multiple', - cancelSelect: 'Annuler', - selectionCount: '{{count}} sélectionnés', - downloadZips: 'Télécharger les ZIPs', - addOffline: 'Ajouter hors ligne', - enqueueSelected_one: 'Mettre en file ({{count}})', - enqueueSelected_other: 'Mettre en file ({{count}})', - enqueueQueued_one: '{{count}} album ajouté à la file', - enqueueQueued_other: '{{count}} albums ajoutés à la file', - downloadingZip: 'Téléchargement {{current}}/{{total}} : {{name}}', - downloadZipDone: '{{count}} ZIP(s) téléchargé(s)', - downloadZipFailed: 'Échec du téléchargement de {{name}}', - offlineQueuing: 'Mise en file d\'attente de {{count}} album(s) hors ligne…', - offlineFailed: 'Échec de l\'ajout de {{name}} hors ligne', - }, - tracks: { - title: 'Titres', - subtitle: 'Parcourir. Chercher. Découvrir.', - heroEyebrow: 'Titre du moment', - heroReroll: 'En choisir un autre', - playSong: 'Lire', - enqueueSong: 'Ajouter à la file', - railRandom: 'Sélection aléatoire', - railHighlyRated: 'Mieux notés', - browseTitle: 'Parcourir tous les titres', - browseUnsupported: 'Ce serveur ne liste pas toute la bibliothèque d\'un coup. Utilisez la recherche ci-dessus pour trouver des titres précis.', - searchPlaceholder: 'Chercher un titre par titre, artiste ou album…', - count_one: '{{count}} titre', - count_other: '{{count}} titres', - }, - artists: { - title: 'Artistes', - search: 'Rechercher…', - all: 'Tous', - gridView: 'Vue en grille', - listView: 'Vue en liste', - imagesOn: 'Images d\'artistes activées — peut augmenter la charge réseau et système', - imagesOff: 'Images d\'artistes désactivées — affichage des initiales uniquement', - loadMore: 'Charger plus', - notFound: 'Aucun artiste trouvé.', - albumCount_one: '{{count}} album', - albumCount_other: '{{count}} albums', - selectionCount: '{{count}} sélectionnés', - select: 'Sélection multiple', - startSelect: 'Activer la sélection multiple', - cancelSelect: 'Annuler', - addToPlaylist: 'Ajouter à la playlist', - }, - composers: { - title: 'Compositeurs', - search: 'Rechercher…', - notFound: 'Aucun compositeur trouvé.', - unsupported: 'La navigation par compositeur nécessite Navidrome 0.55 ou plus récent.', - loadFailed: 'Impossible de charger les compositeurs.', - retry: 'Réessayer', - involvedIn_one: 'Présent sur {{count}} album', - involvedIn_other: 'Présent sur {{count}} albums', - }, - composerDetail: { - back: 'Retour', - notFound: 'Compositeur introuvable.', - about: 'À propos de ce compositeur', - works: 'Œuvres', - noWorks: 'Aucune œuvre trouvée.', - workCount_one: '{{count}} œuvre', - workCount_other: '{{count}} œuvres', - shareComposer: 'Partager le compositeur', - unknownComposer: 'Compositeur', - }, - login: { - subtitle: 'Votre lecteur de bureau Navidrome', - serverName: 'Nom du serveur (facultatif)', - serverNamePlaceholder: 'Mon Navidrome', - serverUrl: 'URL du serveur', - serverUrlPlaceholder: '192.168.1.100:4533 ou https://music.exemple.com', - username: 'Nom d\'utilisateur', - usernamePlaceholder: 'admin', - password: 'Mot de passe', - showPassword: 'Afficher le mot de passe', - hidePassword: 'Masquer le mot de passe', - connect: 'Se connecter', - connecting: 'Connexion…', - connected: 'Connecté !', - error: 'Connexion échouée — vérifiez vos informations.', - urlRequired: 'Veuillez saisir une URL de serveur.', - savedServers: 'Serveurs enregistrés', - addNew: 'Ou ajouter un nouveau serveur', - orMagicString: 'Ou chaîne magique', - magicStringPlaceholder: 'Collez une chaîne de partage (psysonic1-…)', - magicStringInvalid: 'Chaîne magique invalide ou illisible.', - }, - connection: { - connected: 'Connecté', - connectedTo: 'Connecté à {{server}}', - disconnected: 'Déconnecté', - disconnectedFrom: 'Impossible d\'atteindre {{server}} — cliquez pour vérifier les paramètres', - checking: 'Connexion…', - extern: 'Externe', - offlineTitle: 'Pas de connexion au serveur', - offlineSubtitle: 'Impossible d\'atteindre {{server}}. Vérifiez votre réseau ou le serveur.', - offlineModeBanner: 'Mode hors ligne — lecture depuis le cache local', - offlineNoCacheBanner: 'Pas de connexion au serveur — {{server}} inaccessible', - offlineLibraryTitle: 'Bibliothèque hors ligne', - offlineLibraryEmpty: 'Aucun album en cache. Connectez-vous, ouvrez un album et cliquez sur "Rendre disponible hors ligne".', - offlineAlbumCount: '{{n}} album', - offlineAlbumCount_plural: '{{n}} albums', - offlineFilterAll: 'Tout', - offlineFilterAlbums: 'Albums', - offlineFilterPlaylists: 'Playlists', - offlineFilterArtists: 'Discographies', - retry: 'Réessayer', - serverSettings: 'Paramètres serveur', - switchServerTitle: 'Changer de serveur', - switchServerHint: 'Cliquez pour choisir un autre serveur enregistré.', - manageServers: 'Gérer les serveurs…', - switchFailed: 'Impossible de changer — serveur injoignable.', - lastfmConnected: 'Last.fm connecté en tant que @{{user}}', - lastfmSessionInvalid: 'Session invalide — cliquez pour vous reconnecter', - }, - common: { - albums: 'Albums', - album: 'Album', - loading: 'Chargement…', - loadingMore: 'Chargement…', - loadingPlaylists: 'Chargement des listes…', - noAlbums: 'Aucun album trouvé.', - downloading: 'Téléchargement…', - downloadZip: 'Télécharger (ZIP)', - back: 'Retour', - cancel: 'Annuler', - save: 'Enregistrer', - delete: 'Supprimer', - use: 'Utiliser', - add: 'Ajouter', - new: 'Nouveau', - active: 'Actif', - download: 'Télécharger', - chooseDownloadFolder: 'Choisir le dossier de téléchargement', - noFolderSelected: 'Aucun dossier sélectionné', - rememberDownloadFolder: 'Mémoriser ce dossier', - filterGenre: 'Filtre genre', - filterSearchGenres: 'Rechercher des genres…', - filterNoGenres: 'Aucun genre trouvé', - filterClear: 'Effacer', - favorites: 'Favoris', - favoritesTooltipOff: 'Afficher uniquement les favoris', - favoritesTooltipOn: 'Tout afficher', - play: 'Lire', - bulkSelected: '{{count}} sélectionné(s)', - clearSelection: 'Effacer la sélection', - bulkAddToPlaylist: 'Ajouter à la playlist', - bulkRemoveFromPlaylist: 'Retirer de la playlist', - bulkClear: 'Désélectionner', - updaterAvailable: 'Mise à jour disponible', - updaterVersion: 'v{{version}} est disponible', - updaterWebsite: 'Site Web', - updaterModalTitle: 'Nouvelle version disponible', - updaterChangelog: 'Nouveautés', - updaterDownloadBtn: 'Télécharger maintenant', - updaterSkipBtn: 'Ignorer cette version', - updaterRemindBtn: 'Me rappeler plus tard', - updaterDone: 'Téléchargement terminé', - updaterShowFolder: 'Afficher dans le dossier', - updaterInstallHint: 'Fermez Psysonic et lancez le programme d\'installation manuellement.', - updaterAurHint: 'Installer la mise à jour via AUR :', - updaterErrorMsg: 'Échec du téléchargement', - updaterRetryBtn: 'Réessayer', - durationHoursMinutes: '{{hours}} h {{minutes}} min', - durationMinutesOnly: '{{minutes}} min', - updaterOpenGitHub: 'Ouvrir sur GitHub', - filters: 'Filtres', - more: 'plus', - yearRange: 'Plage d\'années', - clearAll: 'Tout effacer', - }, - settings: { - title: 'Paramètres', - language: 'Langue', - languageEn: 'English', - languageDe: 'Deutsch', - languageEs: 'Español', - languageFr: 'Français', - languageNl: 'Nederlands', - languageNb: 'Norsk', - languageRu: 'Русский', - languageZh: '中文', - languageRo: 'Română', - font: 'Police', - fontHintOpenDyslexic: 'Adapté à la dyslexie · sans prise en charge du chinois', - theme: 'Thème', - appearance: 'Apparence', - servers: 'Serveurs', - serverName: 'Nom du serveur', - serverUrl: 'URL du serveur', - serverUrlPlaceholder: '192.168.1.100:4533 ou https://music.exemple.com', - serverUsername: 'Nom d\'utilisateur', - serverPassword: 'Mot de passe', - addServer: 'Ajouter un serveur', - addServerTitle: 'Ajouter un nouveau serveur', - useServer: 'Utiliser', - deleteServer: 'Supprimer', - noServers: 'Aucun serveur enregistré.', - serverActive: 'Actif', - confirmDeleteServer: 'Supprimer le serveur « {{name}} » ?', - serverConnecting: 'Connexion…', - serverConnected: 'Connecté !', - serverFailed: 'Connexion échouée.', - testBtn: 'Tester la connexion', - testingBtn: 'Test en cours…', - serverCompatible: 'Conçu pour Navidrome. Les autres serveurs compatibles Subsonic (Gonic, Airsonic, …) peuvent fonctionner avec des fonctionnalités réduites, car Psysonic utilise de nombreux endpoints d’API spécifiques à Navidrome.', - userMgmtTitle: 'Gestion des utilisateurs', - userMgmtDesc: 'Gérer les utilisateurs sur ce serveur. Nécessite des privilèges administrateur.', - userMgmtNoAdmin: 'Vous devez être administrateur pour gérer les utilisateurs sur ce serveur.', - userMgmtLoadError: 'Impossible de charger les utilisateurs.', - userMgmtLoadFriendly: 'Le serveur n\'a pas répondu — généralement ponctuel.', - userMgmtRetry: 'Réessayer', - userMgmtEmpty: 'Aucun utilisateur trouvé.', - userMgmtYouBadge: 'Vous', - userMgmtAdminBadge: 'Admin', - userMgmtAddUser: 'Ajouter un utilisateur', - userMgmtAddUserTitle: 'Nouvel utilisateur', - userMgmtEditUserTitle: 'Modifier l’utilisateur', - userMgmtUsername: 'Nom d’utilisateur', - userMgmtName: 'Nom affiché', - userMgmtEmail: 'E-mail', - userMgmtPassword: 'Mot de passe', - userMgmtPasswordEditHint: 'Saisir un nouveau mot de passe pour le modifier.', - userMgmtRoleAdmin: 'Admin', - userMgmtLibraries: 'Bibliothèques', - userMgmtLibrariesAdminHint: 'Les utilisateurs admin ont automatiquement accès à toutes les bibliothèques.', - userMgmtLibrariesEmpty: 'Aucune bibliothèque disponible sur ce serveur.', - userMgmtLibrariesValidation: 'Sélectionnez au moins une bibliothèque.', - userMgmtLibrariesUpdateError: 'Utilisateur enregistré, mais l\u2019attribution des bibliothèques a échoué', - userMgmtNoLibraries: 'Aucune bibliothèque attribuée', - userMgmtNeverSeen: 'Jamais', - userMgmtSave: 'Enregistrer', - userMgmtCancel: 'Annuler', - userMgmtDelete: 'Supprimer', - userMgmtEdit: 'Modifier', - userMgmtConfirmDelete: 'Supprimer l’utilisateur « {{username}} » ? Action irréversible.', - userMgmtCreateError: 'Impossible de créer l’utilisateur.', - userMgmtUpdateError: 'Impossible de mettre à jour l’utilisateur.', - userMgmtDeleteError: 'Impossible de supprimer l’utilisateur.', - userMgmtCreated: 'Utilisateur créé.', - userMgmtUpdated: 'Utilisateur mis à jour.', - userMgmtDeleted: 'Utilisateur supprimé.', - userMgmtValidationMissing: 'Nom d’utilisateur, nom affiché et mot de passe sont requis.', - userMgmtValidationMissingIdentity: 'Le nom d’utilisateur et le nom affiché sont requis.', - userMgmtMagicStringGenerate: 'Générer la chaîne magique', - userMgmtSaveAndMagicString: 'Enregistrer et obtenir la chaîne magique', - userMgmtMagicStringPasswordNavHint: - 'Navidrome enregistrera ce mot de passe pour l’utilisateur. S’il diffère de l’actuel, le mot de passe de connexion sur le serveur sera mis à jour.', - userMgmtMagicStringPlaintextWarning: - 'Partagez la chaîne magique avec prudence : elle contient un mot de passe non chiffré (l’encodage n’est pas du chiffrement). Quiconque possède la chaîne complète peut se connecter en tant que cet utilisateur.', - userMgmtMagicStringCopied: 'Chaîne magique copiée dans le presse-papiers.', - userMgmtMagicStringCopyFailed: 'Impossible de copier dans le presse-papiers.', - userMgmtMagicStringLoginFailed: 'Échec de la vérification du mot de passe — identifiants non confirmés.', - userMgmtMagicStringModalTitle: 'Générer la chaîne magique', - userMgmtMagicStringModalDesc: 'Saisissez le mot de passe Subsonic de « {{username}} ». Il est inclus dans la chaîne magique copiée.', - userMgmtMagicStringModalConfirm: 'Copier la chaîne', - audiomuseTitle: 'AudioMuse-AI (Navidrome)', - audiomuseDesc: - 'Activez si ce serveur utilise le plugin Navidrome AudioMuse-AI. Active le mix instantané depuis un morceau et affiche les artistes similaires côté serveur au lieu de Last.fm sur les pages artiste.', - audiomuseIssueHint: - 'Le mix instantané a échoué récemment — vérifiez le plugin Navidrome et l’API AudioMuse. Les artistes similaires utilisent Last.fm si le serveur ne renvoie rien.', - connected: 'Connecté', - failed: 'Échec', - eqTitle: 'Égaliseur', - eqEnabled: 'Activer l\'égaliseur', - eqPreset: 'Préréglage', - eqPresetCustom: 'Personnalisé', - eqPresetBuiltin: 'Préréglages intégrés', - eqPresetCustomGroup: 'Mes préréglages', - eqSavePreset: 'Enregistrer comme préréglage', - eqPresetName: 'Nom du préréglage…', - eqDeletePreset: 'Supprimer le préréglage', - eqResetBands: 'Réinitialiser à plat', - eqPreGain: 'Pré-amplification', - eqResetPreGain: 'Réinitialiser la pré-amplification', - eqAutoEqTitle: 'Recherche AutoEQ', - eqAutoEqPlaceholder: 'Rechercher un casque / IEM…', - eqAutoEqSearching: 'Recherche…', - eqAutoEqNoResults: 'Aucun résultat', - eqAutoEqError: 'Échec de la recherche', - eqAutoEqRateLimit: 'Limite GitHub atteinte — réessayez dans une minute', - eqAutoEqFetchError: 'Impossible de charger le profil EQ', - lfmTitle: 'Last.fm', - lfmConnect: 'Connecter avec Last.fm', - lfmConnecting: 'En attente d\'autorisation…', - lfmConfirm: 'J\'ai autorisé l\'application', - lfmConnected: 'Connecté en tant que', - lfmDisconnect: 'Déconnecter', - lfmConnectDesc: 'Connectez votre compte Last.fm pour activer le scrobbling et les mises à jour « En cours de lecture » depuis Psysonic — aucune configuration Navidrome requise.', - lfmOpenBrowser: 'Une fenêtre de navigateur s\'ouvrira. Autorisez Psysonic sur Last.fm, puis cliquez sur le bouton ci-dessous.', - lfmScrobbles: '{{n}} scrobbles', - lfmMemberSince: 'Membre depuis {{year}}', - scrobbleEnabled: 'Scrobbling activé', - scrobbleDesc: 'Envoyer les morceaux à Last.fm après 50% d\'écoute', - behavior: 'Comportement de l\'application', - cacheTitle: 'Taille max. du stockage', - cacheDesc: 'Pochettes et images d\'artistes. Quand le cache est plein, les entrées les plus anciennes sont supprimées automatiquement. Les albums hors ligne ne sont pas supprimés automatiquement, mais le seront lors d\'un nettoyage manuel.', - cacheUsedImages: 'Images :', - cacheUsedOffline: 'Pistes hors ligne :', - cacheUsedHot: 'Espace disque :', - hotCacheTrackCount: 'Pistes en cache :', - cacheMaxLabel: 'Taille max.', - cacheClearBtn: 'Vider le cache', - cacheClearWarning: 'Cela supprimera aussi tous les albums hors ligne de la bibliothèque.', - cacheClearConfirm: 'Tout supprimer', - cacheClearCancel: 'Annuler', - offlineDirTitle: 'Bibliothèque hors ligne (intégrée)', - offlineDirDesc: 'Emplacement de stockage des titres rendus disponibles hors ligne dans Psysonic.', - offlineDirDefault: 'Par défaut (données d\'application)', - offlineDirChange: 'Changer le dossier', - offlineDirClear: 'Réinitialiser', - offlineDirHint: 'Les nouveaux téléchargements utiliseront cet emplacement. Les téléchargements existants restent à leur emplacement d\'origine.', - hotCacheTitle: 'Cache de lecture à chaud', - hotCacheDisclaimer: 'Précharge les titres à venir dans la file et conserve les précédents. Si activé : espace disque et réseau.', - hotCacheDirDefault: 'Par défaut (données d\'application)', - hotCacheDirChange: 'Changer le dossier', - hotCacheDirClear: 'Réinitialiser', - hotCacheDirHint: 'Changer de dossier réinitialise l’index dans l’app ; les fichiers déjà écrits restent à l’ancien emplacement.', - hotCacheEnabled: 'Activer le cache de lecture à chaud', - hotCacheMaxMb: 'Taille maximale du cache', - hotCacheDebounce: 'Délai après changement de file', - hotCacheDebounceImmediate: 'Immédiat', - hotCacheDebounceSeconds: '{{n}} s', - hotCacheClearBtn: 'Vider le cache à chaud', - audioOutputDevice: 'Périphérique de sortie audio', - audioOutputDeviceDesc: 'Choisissez le périphérique audio utilisé par Psysonic. Les changements sont immédiats et relancent la piste en cours.', - audioOutputDeviceDefault: 'Défaut système', - audioOutputDeviceRefresh: 'Actualiser la liste', - audioOutputDeviceOsDefaultNow: 'sortie système actuelle', - audioOutputDeviceListError: 'Impossible de charger la liste des périphériques audio.', - audioOutputDeviceNotInCurrentList: 'absent de la liste actuelle', - audioOutputDeviceMacNotice: 'Sur macOS, la lecture suit actuellement toujours la sortie audio du système pour des raisons techniques. Changez la cible via Réglages Système → Son ou l\'icône haut-parleur de la barre de menus. Contexte : CoreAudio déclenche une demande d\'autorisation du microphone à l\'ouverture d\'un flux non par défaut — nous l\'évitons en utilisant toujours la sortie système par défaut.', - hiResTitle: 'Lecture haute résolution native', - hiResEnabled: 'Activer la lecture haute résolution native', - hiResDesc: "Force une sortie à 44,1 kHz par défaut pour une stabilité maximale. N'activer que si le matériel et le réseau prennent en charge les hautes fréquences d'échantillonnage (88,2 kHz+).", - showArtistImages: 'Afficher les images d\'artistes', - showArtistImagesDesc: 'Charge et affiche les images d\'artistes dans la vue d\'ensemble. Désactivé par défaut pour réduire les E/S disque serveur et la charge réseau sur les grandes bibliothèques.', - showOrbitTrigger: 'Afficher « Orbit » dans l\'en-tête', - showOrbitTriggerDesc: 'Le bouton d\'en-tête pour démarrer ou rejoindre une session d\'écoute partagée. Masque-le si tu n\'utilises pas Orbit — tu peux le réactiver ici.', - showTrayIcon: 'Afficher l\'icône dans la barre système', - showTrayIconDesc: 'Affiche l\'icône Psysonic dans la zone de notification / barre des menus.', - minimizeToTray: 'Réduire dans la barre système', - minimizeToTrayDesc: 'Lors de la fermeture, Psysonic continue de fonctionner dans la barre système au lieu de se fermer.', - preloadMiniPlayer: 'Précharger le mini-lecteur', - preloadMiniPlayerDesc: 'Construit la fenêtre du mini-lecteur en arrière-plan au démarrage de l\'application afin qu\'elle affiche son contenu instantanément à la première ouverture. Utilise un peu plus de mémoire.', - linuxWebkitSmoothScroll: 'Molette fluide (Linux)', - linuxWebkitSmoothScrollDesc: 'Activé : inertie. Désactivé : pas à la ligne, style GTK.', - discordRichPresence: 'Discord Rich Presence', - discordRichPresenceDesc: 'Affiche le titre en cours de lecture sur votre profil Discord. Discord doit être ouvert.', - discordCoverSource: 'Source de pochette', - discordCoverSourceDesc: 'D\'où récupérer la pochette pour votre profil Discord.', - discordCoverNone: 'Aucune (icône de l\'app uniquement)', - discordCoverServer: 'Serveur (via infos album)', - discordCoverApple: 'Apple Music', - discordOptions: 'Options Discord avancées', - discordTemplates: 'Modèles de texte personnalisés', - discordTemplatesDesc: 'Personnalisez les informations affichées sur votre profil Discord. Variables : {title}, {artist}, {album}', - discordTemplateDetails: 'Ligne principale (details)', - discordTemplateState: 'Ligne secondaire (state)', - discordTemplateLargeText: 'Info-bulle album (largeText)', - nowPlayingEnabled: 'Afficher dans la fenêtre live', - nowPlayingEnabledDesc: 'Diffuse le titre en cours de lecture vers la vue des auditeurs en direct du serveur. Désactiver pour ne pas envoyer de données de lecture.', - enableBandsintown: 'Dates de tournée Bandsintown', - enableBandsintownDesc: 'Affiche les concerts à venir de l\'artiste actuel dans l\'onglet Info. Les données proviennent de l\'API publique Bandsintown.', - lyricsServerFirst: 'Préférer les paroles du serveur', - lyricsServerFirstDesc: 'Consulter d\'abord les paroles fournies par le serveur (tags intégrés, fichiers sidecar) avant LRCLIB. Désactiver pour utiliser LRCLIB en priorité.', - enableNeteaselyrics: 'Paroles Netease Cloud Music', - enableNeteaselyricsDesc: 'Utiliser Netease Cloud Music en dernier recours lorsque le serveur et LRCLIB ne retournent rien. Meilleure couverture pour la musique asiatique et internationale.', - lyricsSourcesTitle: 'Sources de paroles', - lyricsSourcesDesc: 'Choisissez quelles sources interroger et dans quel ordre. Glissez pour réordonner. Les sources désactivées sont ignorées.', - lyricsSourceServer: 'Serveur', - lyricsSourceLrclib: 'LRCLIB', - lyricsSourceNetease: 'Netease Cloud Music', - lyricsModeStandard: 'Standard', - lyricsModeStandardDesc: 'Trois sources avec ordre librement configurable : tags du serveur, LRCLIB, Netease.', - lyricsModeLyricsplus: 'YouLyPlus (Karaoké)', - lyricsModeLyricsplusDesc: 'Synchronisation mot à mot depuis Apple Music, Spotify, Musixmatch et QQ (backend communautaire). Retombe silencieusement sur les sources standard si rien n\'est trouvé.', - lyricsStaticOnly: 'Afficher les paroles en texte statique uniquement', - lyricsStaticOnlyDesc: 'Affiche les paroles synchronisées sans défilement automatique ni surlignage des mots.', - downloadsTitle: 'Export ZIP & Archivage', - downloadsFolderDesc: 'Dossier de destination pour les albums téléchargés en tant que fichier ZIP sur votre ordinateur.', - downloadsDefault: 'Dossier de téléchargement par défaut', - pickFolder: 'Sélectionner', - pickFolderTitle: 'Sélectionner le dossier de téléchargement', - clearFolder: 'Effacer le dossier', - logout: 'Se déconnecter', - aboutTitle: 'À propos de Psysonic', - aboutDesc: 'Un lecteur de musique de bureau moderne conçu pour Navidrome. Utilise l\'API Subsonic ainsi que des extensions spécifiques à Navidrome. Basé sur Tauri v2 avec un moteur audio Rust natif — léger et rapide, mais riche en fonctionnalités : barre waveform, paroles synchronisées, intégration Last.fm, égaliseur 10 bandes, crossfade, lecture sans blanc, Replay Gain, navigation par genre et une grande bibliothèque de thèmes.', - aboutLicense: 'Licence', - aboutLicenseText: 'GNU GPL v3 — libre d\'utilisation, de modification et de distribution sous la même licence.', - aboutRepo: 'Code source sur GitHub', - aboutVersion: 'Version', - aboutBuiltWith: 'Construit avec Tauri · React · TypeScript · Rust/rodio', - aboutReleaseNotesLabel: 'Notes de version', - aboutReleaseNotesLink: 'Ouvrir les nouveautés de cette version', - aboutContributorsLabel: 'Contributeurs', - showChangelogOnUpdate: "Afficher 'Quoi de neuf' lors des mises à jour", - showChangelogOnUpdateDesc: "Affiche une bannière discrète du changelog au-dessus de Now Playing après une mise à jour. Un clic ouvre les notes de version, le X la masque.", - randomMixTitle: 'Liste noire du mix aléatoire', - luckyMixMenuTitle: 'Afficher Mix Chance dans le menu', - luckyMixMenuDesc: 'Active Mix Chance dans "Créer un mix" et comme entrée séparée quand la navigation est scindée. Visible uniquement si AudioMuse est actif sur le serveur courant.', - randomMixBlacklistTitle: 'Mots-clés de filtre personnalisés', - randomMixBlacklistDesc: 'Les morceaux sont exclus si un mot-clé correspond à leur genre, titre, album ou artiste (actif quand la case ci-dessus est cochée).', - randomMixBlacklistPlaceholder: 'Ajouter un mot-clé…', - randomMixBlacklistAdd: 'Ajouter', - randomMixBlacklistEmpty: 'Aucun mot-clé personnalisé ajouté.', - randomMixHardcodedTitle: 'Mots-clés intégrés (actifs quand la case est cochée)', - tabAudio: 'Audio', - tabStorage: 'Hors ligne & Cache', - tabAppearance: 'Apparence', - tabLibrary: 'Bibliothèque', - tabServers: 'Serveurs', - tabLyrics: 'Paroles', - tabPersonalisation: 'Personnalisation', - tabIntegrations: 'Intégrations', - inputKeybindingsTitle: 'Raccourcis clavier', - aboutContributorsCount_one: '{{count}} contribution', - aboutContributorsCount_other: '{{count}} contributions', - searchPlaceholder: 'Rechercher dans les paramètres…', - searchNoResults: 'Aucun réglage ne correspond à votre recherche.', - aboutMaintainersLabel: 'Mainteneurs', - integrationsPrivacyTitle: 'Avis de confidentialité', - integrationsPrivacyBody: 'Toutes les intégrations de cet onglet sont facultatives et, une fois activées, envoient des données à des services externes ou à votre serveur Navidrome. Last.fm reçoit votre historique d\'écoute, Discord affiche le morceau en cours dans votre profil, Bandsintown est interrogé par artiste pour récupérer les dates de tournée, et le partage « En cours de lecture » publie votre morceau actuel auprès des autres utilisateurs de votre serveur Navidrome. Si vous ne voulez rien de tout cela, laissez simplement la section correspondante désactivée.', - homeCustomizerTitle: 'Page d\'accueil', - queueToolbarTitle: 'Barre d\'outils de file d\'attente', - queueToolbarReset: 'Réinitialiser', - queueToolbarSeparator: 'Séparateur', - sidebarTitle: 'Barre latérale', - sidebarReset: 'Réinitialiser', - artistLayoutTitle: 'Sections de la page artiste', - artistLayoutDesc: 'Glissez pour réorganiser, basculez pour masquer des sections individuelles de la page artiste. Les sections sans données sont ignorées automatiquement.', - artistLayoutReset: 'Réinitialiser', - artistLayoutBio: 'Biographie de l\'artiste', - artistLayoutTopTracks: 'Titres populaires', - artistLayoutSimilar: 'Artistes similaires', - artistLayoutAlbums: 'Albums', - artistLayoutFeatured: 'Apparaît aussi sur', - sidebarDrag: 'Glisser pour réorganiser', - sidebarFixed: 'Toujours visible', - randomNavSplitTitle: 'Diviser la navigation Mix', - randomNavSplitDesc: 'Afficher "Mix Aléatoire", "Albums Aléatoires" et "Mix Chance" comme entrées séparées dans la barre latérale plutôt que le hub "Créer un Mix".', - tabInput: 'Entrée', - tabUsers: 'Utilisateurs', - shortcutsReset: 'Réinitialiser', - shortcutListening: 'Appuyez sur une touche…', - shortcutUnbound: '—', - shortcutClear: 'Effacer', - globalShortcutsTitle: 'Raccourcis globaux', - globalShortcutsNote: 'Fonctionnent à l\'échelle du système, même quand Psysonic est en arrière-plan. Nécessite Ctrl, Alt ou Super comme modificateur.', - shortcutPlayPause: 'Lecture / Pause', - shortcutNext: 'Piste suivante', - shortcutPrev: 'Piste précédente', - shortcutVolumeUp: 'Volume +', - shortcutVolumeDown: 'Volume -', - shortcutSeekForward: 'Avancer de 10s', - shortcutSeekBackward: 'Reculer de 10s', - shortcutToggleQueue: 'Afficher/masquer la file', - shortcutOpenFolderBrowser: 'Ouvrir {{folderBrowser}}', - shortcutFullscreenPlayer: 'Lecteur plein écran', - shortcutNativeFullscreen: 'Plein écran natif', - shortcutOpenMiniPlayer: 'Ouvrir le mini-lecteur', - shortcutStartSearch: 'Lancer une recherche', - shortcutStartAdvancedSearch: 'Lancer une recherche avancée', - shortcutToggleSidebar: 'Afficher / masquer la barre latérale', - shortcutMuteSound: 'Couper le son', - shortcutToggleEqualizer: 'Ouvrir / basculer l\'égaliseur', - shortcutToggleRepeat: 'Basculer la répétition', - shortcutOpenNowPlaying: 'Ouvrir « En cours »', - shortcutShowLyrics: 'Afficher les paroles', - shortcutFavoriteCurrentTrack: 'Ajouter la piste actuelle aux favoris', - shortcutOpenHelp: 'Aide', - tabSystem: 'Système', - loggingTitle: 'Journalisation', - loggingModeDesc: 'Contrôle le niveau de verbosité des journaux backend dans le terminal.', - loggingModeOff: 'Désactivé', - loggingModeNormal: 'Normal', - loggingModeDebug: 'Débogage', - loggingExport: 'Exporter les journaux', - loggingExportSuccess: 'Journaux exportés ({{count}} lignes).', - loggingExportError: 'Impossible d\'exporter les journaux.', - ratingsSectionTitle: 'Notes', - ratingsSkipStarTitle: 'Passer pour 1 étoile', - ratingsSkipStarDesc: - "Après plusieurs sauts d’affilée, le morceau passe à 1 étoile. Uniquement s’il n’était pas encore noté.", - ratingsSkipStarThresholdLabel: 'Sauts', - ratingsMixFilterTitle: 'Filtrage par note', - ratingsMixFilterDesc: - "Filtrer le contenu peu noté dans {{mix}} et {{albums}}. Cliquer de nouveau sur l’étoile choisie désactive le seuil.", - ratingsMixMinSong: 'Morceaux', - ratingsMixMinAlbum: 'Albums', - ratingsMixMinArtist: 'Artistes', - ratingsMixMinThresholdAria: 'Étoiles minimum : {{label}}', - backupTitle: 'Sauvegarde & Restauration', - backupExport: 'Exporter les paramètres', - backupExportDesc: 'Enregistre tous les paramètres, profils serveur, configuration Last.fm, thème, EQ et raccourcis dans un fichier .psybkp. Les mots de passe sont stockés en clair — conservez le fichier en sécurité.', - backupImport: 'Importer les paramètres', - backupImportDesc: 'Restaure les paramètres depuis un fichier .psybkp. L\'application sera rechargée après l\'import.', - backupImportConfirm: 'Tous les paramètres actuels seront écrasés. Continuer ?', - backupSuccess: 'Sauvegarde enregistrée', - backupImportSuccess: 'Paramètres restaurés — rechargement…', - backupImportError: 'Fichier de sauvegarde invalide ou corrompu.', - playbackTitle: 'Lecture', - replayGain: 'Replay Gain', - replayGainDesc: 'Normaliser le volume des pistes avec les métadonnées ReplayGain', - replayGainMode: 'Mode', - replayGainAuto: 'Auto', - replayGainAutoDesc: 'Utilise le gain d\'album quand les pistes voisines de la file proviennent du même album, sinon le gain de piste.', - replayGainTrack: 'Piste', - replayGainAlbum: 'Album', - replayGainPreGain: 'Pré-Gain (fichiers taggés)', - replayGainPreGainDesc: 'Boost universel ajouté à chaque calcul ReplayGain. Utile si votre bibliothèque semble globalement trop discrète.', - replayGainFallback: 'Repli (sans tags / radio)', - replayGainFallbackDesc: 'Appliqué aux pistes (et flux radio) sans tags ReplayGain, pour que le contenu non taggé ne sorte pas plus fort que le reste.', - normalization: 'Normalisation', - normalizationDesc: 'Égalise la sonie perçue entre pistes, albums et radio.', - normalizationOff: 'Désactivé', - normalizationReplayGain: 'ReplayGain', - normalizationLufs: 'LUFS', - loudnessTargetLufs: 'LUFS cible', - loudnessTargetLufsDesc: 'Sonie de référence sur laquelle toutes les pistes sont calées. Valeur plus basse = sortie plus forte. Les services de streaming tournent autour de -14 LUFS.', - loudnessPreAnalysisAttenuation: 'Atténuation avant mesure', - loudnessPreAnalysisAttenuationDesc: - 'Réduit le volume tant que la loudness du morceau n’est pas enregistrée. En streaming, des estimations grossières suivent, pas une mesure complète. 0 dB = rien ; plus négatif = plus discret. À droite, le dB effectif pour la cible actuelle.', - loudnessPreAnalysisAttenuationRef: 'Effectif {{eff}} dB avec cible {{tgt}} LUFS.', - loudnessPreAnalysisAttenuationReset: 'Valeur par défaut', - loudnessFirstPlayNote: - 'À la première lecture d’un nouveau morceau, le volume peut brièvement varier pendant la mesure. La fois suivante, la mesure mise en cache prend le relais et tout reste stable. Les pistes à venir dans la file sont en général pré-analysées pendant la lecture précédente, ce cas est donc rare en pratique.', - crossfade: 'Fondu enchaîné', - crossfadeDesc: 'Fondu entre les pistes', - crossfadeSecs: '{{n}} s', - notWithGapless: 'Non disponible quand la lecture sans blanc est active', - notWithCrossfade: 'Non disponible quand le fondu enchaîné est actif', - gapless: 'Lecture sans blanc', - gaplessDesc: 'Préparer la piste suivante pour éliminer les silences entre les morceaux', - preservePlayNextOrder: "Préserver l'ordre « Lire ensuite »", - preservePlayNextOrderDesc: 'Les nouveaux éléments « Lire ensuite » s\'ajoutent à la fin de la file existante au lieu de la doubler.', - trackPreviewsTitle: 'Aperçus de pistes', - trackPreviewsToggle: 'Activer les aperçus de pistes', - trackPreviewsDesc: 'Affiche les boutons Lecture et Aperçu dans les listes pour un court extrait au milieu du morceau.', - trackPreviewStart: 'Position de départ', - trackPreviewStartDesc: 'À quel point du morceau l\'aperçu commence (% de la durée).', - trackPreviewDuration: 'Durée', - trackPreviewDurationDesc: 'Combien de temps chaque aperçu joue avant de s\'arrêter.', - trackPreviewDurationSecs: '{{n}} s', - trackPreviewLocationsTitle: 'Où afficher les aperçus', - trackPreviewLocationsDesc: 'Choisissez dans quelles listes afficher les boutons d\'aperçu.', - trackPreviewLocation_suggestions: 'Dans les suggestions de playlist', - trackPreviewLocation_albums: 'Dans les listes d\'albums', - trackPreviewLocation_playlists: 'Dans les playlists', - trackPreviewLocation_favorites: 'Dans les favoris', - trackPreviewLocation_artist: 'Dans les meilleurs morceaux de l\'artiste', - trackPreviewLocation_randomMix: 'Dans Random Mix', - preloadMode: 'Précharger la piste suivante', - preloadModeDesc: 'Quand commencer à mettre en mémoire tampon la piste suivante', - nextTrackBufferingTitle: 'Mise en mémoire tampon', - preloadHotCacheMutualExclusive: "Preload et Hot Cache remplissent le même rôle — un seul peut être actif à la fois. Activer l'un désactive automatiquement l'autre.", - preloadOff: 'Désactivé', - preloadBalanced: 'Équilibré (30 s avant la fin)', - preloadEarly: 'Tôt (après 5 s de lecture)', - preloadCustom: 'Personnalisé', - preloadCustomSeconds: 'Secondes avant la fin : {{n}}', - infiniteQueue: 'File infinie', - infiniteQueueDesc: 'Ajouter automatiquement des morceaux aléatoires quand la file est épuisée', - experimental: 'Expérimental', - fsPlayerSection: 'Lecteur plein écran', - fsShowArtistPortrait: "Afficher la photo de l'artiste", - fsShowArtistPortraitDesc: "Afficher la photo de l'artiste (ou la pochette) sur le côté droit du lecteur plein écran.", - fsPortraitDim: "Assombrissement de la photo", - fsLyricsStyle: "Style des paroles", - fsLyricsStyleRail: "Rail", - fsLyricsStyleRailDesc: "Rail glissant classique de 5 lignes.", - fsLyricsStyleApple: "Défilement", - fsLyricsStyleAppleDesc: "Liste déroulante plein écran.", - sidebarLyricsStyle: "Style de défilement des paroles", - sidebarLyricsStyleClassic: "Classique", - sidebarLyricsStyleClassicDesc: "La ligne active est centrée.", - sidebarLyricsStyleApple: "Apple Music-like", - sidebarLyricsStyleAppleDesc: "La ligne active reste en haut avec une animation fluide.", - seekbarStyle: 'Style de la barre de lecture', - seekbarStyleDesc: 'Choisir l\'apparence de la barre de progression', - seekbarTruewave: 'Forme d\'onde réelle', - seekbarPseudowave: 'Forme d\'onde pseudo', - seekbarLinedot: 'Ligne & point', - seekbarBar: 'Barre', - seekbarThick: 'Barre épaisse', - seekbarSegmented: 'Segmentée', - seekbarNeon: 'Néon', - seekbarPulsewave: 'Onde pulsée', - seekbarParticletrail: 'Traînée de particules', - seekbarLiquidfill: 'Tube liquide', - seekbarRetrotape: 'Bande rétro', - themeSchedulerTitle: 'Planificateur de thème', - themeSchedulerEnable: 'Activer le planificateur de thème', - themeSchedulerEnableSub: 'Bascule automatiquement entre deux thèmes selon l\'heure', - themeSchedulerDayTheme: 'Thème de jour', - themeSchedulerDayStart: 'Début du jour', - themeSchedulerNightTheme: 'Thème de nuit', - themeSchedulerNightStart: 'Début de la nuit', - themeSchedulerActiveHint: 'Le planificateur de thème est actif - les thèmes changent automatiquement.', - visualOptionsTitle: 'Options Visuelles', - coverArtBackground: "Fond d'Art de Poche", - coverArtBackgroundSub: "Afficher la pochette floutée comme fond dans les en-têtes d'albums et de playlists", - playlistCoverPhoto: 'Photo de Couverture de Playlist', - playlistCoverPhotoSub: 'Afficher la grille de photos de couverture dans la vue détaillée des playlists', - showBitrate: 'Afficher le Débit', - showBitrateSub: 'Afficher le débit audio dans les listes de pistes', - floatingPlayerBar: 'Barre de Lecteur Flottante', - floatingPlayerBarSub: 'Garder la barre du lecteur flottante au-dessus du contenu', - uiScaleTitle: "Mise à l'échelle de l'interface", - uiScaleLabel: 'Zoom', - }, - changelog: { - modalTitle: 'Quoi de neuf', - dontShowAgain: 'Ne plus afficher', - close: 'Compris', - }, - whatsNew: { - title: 'Quoi de neuf', - empty: 'Aucune entrée de changelog pour cette version.', - bannerTitle: 'Changelog', - bannerCollapsed: 'Nouveau dans v{{version}}', - dismiss: 'Ignorer', - close: 'Fermer', - }, - help: { - title: 'Aide', - searchPlaceholder: 'Rechercher dans l\'aide…', - noResults: 'Aucun sujet correspondant. Essayez un autre terme.', - s1: 'Démarrage', - q1: 'Quels serveurs sont compatibles ?', - a1: 'Psysonic est conçu en priorité pour Navidrome et est entièrement compatible Subsonic — Gonic, Airsonic, LMS et autres serveurs Subsonic-API fonctionnent aussi. Certaines fonctionnalités avancées (notes, listes intelligentes, partage Magic String, gestion des utilisateurs) nécessitent Navidrome.', - q2: 'Comment ajouter un serveur ?', - a2: 'Paramètres → Serveurs → Ajouter un serveur. Saisissez l\'URL (ex. http://192.168.1.100:4533), le nom d\'utilisateur et le mot de passe. Psysonic teste la connexion avant d\'enregistrer — rien n\'est sauvegardé en cas d\'échec. Vous pouvez ajouter autant de serveurs que vous voulez et basculer entre eux dans l\'en-tête ; un seul est actif à la fois.', - q3: 'Visite rapide de l\'interface ?', - a3: 'Barre latérale (gauche) pour la navigation, Mainstage / pages au centre, barre du lecteur en bas, panneau File d\'attente à droite (icône en haut à droite, à côté de l\'indicateur Now Playing). La barre de recherche en haut couvre toute la bibliothèque ; « Now Playing » montre ce que les autres utilisateurs du même serveur Navidrome écoutent.', - s2: 'Lecture & File d\'attente', - q4: 'Comment utiliser la file d\'attente ?', - a4: 'Ouvrez le panneau File d\'attente depuis l\'en-tête en haut à droite. Glissez les lignes pour réordonner, faites-les glisser à l\'extérieur pour les supprimer, ou utilisez la barre d\'outils pour mélanger, enregistrer la file en liste de lecture ou sauter à une piste. Faites glisser une ligne hors du panneau pour la déposer ailleurs comme transfert.', - q5: 'Gapless vs Crossfade — quelle différence ?', - a5: 'Gapless pré-bufferise la piste suivante pour éliminer tout silence (idéal pour les albums live et les mixes DJ). Crossfade fait un fondu entre la piste actuelle et la suivante sur 1 à 10 s (idéal pour les mixes aléatoires). Les deux sont mutuellement exclusifs — activer l\'un désactive l\'autre. Configuration dans Paramètres → Audio.', - q6: 'Qu\'est-ce que la File infinie ?', - a6: 'Quand la file se termine et que la répétition est désactivée, Psysonic ajoute discrètement des pistes similaires/aléatoires de votre bibliothèque pour que la lecture ne s\'arrête jamais. Les pistes auto-ajoutées apparaissent sous le séparateur « — Ajouté automatiquement —». Activable/désactivable via l\'icône infini dans l\'en-tête de la file ; restreignable à un genre dans Paramètres → File d\'attente.', - q7: 'Sélection multiple et plage Maj-clic ?', - a7: 'Activez « Sélectionner » sur Albums / Nouveautés / Albums aléatoires / Listes de lecture. Cliquez un élément pour le basculer, puis maintenez Maj et cliquez un autre élément — tout ce qui se trouve entre les deux dans l\'ordre visible est sélectionné. Les Maj-clics étendent depuis l\'ancre la plus récemment cliquée. La barre d\'outils en haut propose des actions groupées (file, téléchargement, suppression, etc.).', - q8: 'Raccourcis clavier et hotkeys globaux ?', - a8: 'Touches par défaut : Espace = Lecture / Pause, Échap = fermer le mode plein écran / les modales, F1 = aide-mémoire des raccourcis. Paramètres → Entrée permet de réassigner chaque action interne (y compris des accords comme Ctrl+Maj+P) et de définir des raccourcis globaux qui fonctionnent même en arrière-plan. Les touches multimédia (Lecture/Pause, Suivant, Précédent) fonctionnent partout.', - s3: 'Outils audio', - q9: 'Modes Replay Gain ?', - a9: 'Paramètres → Audio → Replay Gain. Le mode Piste normalise chaque morceau au niveau cible. Le mode Album préserve la dynamique relative au sein d\'un album. Le mode Auto choisit Piste ou Album selon que la file vient d\'un album unique. Les pistes sans tags Replay Gain retombent sur un préampli configurable.', - q10: 'Qu\'est-ce que la normalisation intelligente (LUFS) ?', - a10: 'Une alternative moderne au Replay Gain dans Paramètres → Audio. Psysonic analyse chaque piste en LUFS / EBU R128 et stocke le résultat, pour un volume cohérent dans toute la bibliothèque — y compris les pistes sans tags Replay Gain. L\'analyse à froid tourne en arrière-plan et utilise 35–40 % du CPU pendant ~1 minute, puis 0. Définissez votre cible (par défaut −10 LUFS) une fois.', - q11: 'EQ et AutoEQ ?', - a11: 'Un égaliseur paramétrique 10 bandes dans Paramètres → Audio → Égaliseur, avec bandes manuelles et préréglages. AutoEQ à côté récupère un profil de correction mesuré pour votre modèle de casque depuis la base AutoEQ et l\'applique automatiquement aux bandes — choisissez votre casque, l\'égaliseur s\'aligne sur la bonne courbe.', - q12: 'Comment changer le périphérique de sortie audio ?', - a12: 'Paramètres → Audio → Périphérique de sortie. Psysonic liste toutes les sorties disponibles et bascule instantanément lors du choix. Le bouton Actualiser détecte les périphériques branchés après le démarrage. Sur Linux, les noms ALSA comme « sysdefault » sont auto-nettoyés pour la lisibilité.', - q13: 'Qu\'est-ce que le Hot Cache ?', - a13: 'Le Hot Cache précharge la piste actuelle plus les suivantes en RAM et sur disque pour que la lecture démarre sans buffering — particulièrement utile sur les serveurs lents/distants. L\'éviction se déclenche quand la limite de taille est atteinte. Configurez la taille et le délai de debounce (pour éviter les pré-fetchs à chaque saut rapide) dans Paramètres → Audio.', - s4: 'Bibliothèque & Découverte', - q14: 'Notes et Skip-to-1★ ?', - a14: 'Psysonic prend en charge les notes 1 à 5 étoiles via OpenSubsonic (Navidrome ≥ 0.53). Notez les pistes dans les listes, dans le menu contextuel ou dans la barre du lecteur sous le nom de l\'artiste ; les albums sur leur page ; les artistes sur la page artiste. Skip-to-1★ (Paramètres → Bibliothèque → Notes) attribue automatiquement 1 étoile après un nombre configurable de sauts consécutifs. Le même panneau permet de définir une note minimale pour les Mixes générés.', - q15: 'Comment naviguer — Dossiers, Genres, Pistes ?', - a15: 'Le navigateur de dossiers (barre latérale) parcourt l\'arborescence du serveur en colonnes Miller — clic sur un dossier pour entrer, clic sur une piste ou l\'icône lecture d\'un dossier pour jouer/ajouter. Genres utilise un nuage de tags dimensionné par le nombre de pistes ; clic sur un genre pour l\'ouvrir. Pistes est un hub plat avec liste virtuelle triable par colonnes et recherche en direct.', - q16: 'Recherche et recherche avancée ?', - a16: 'La barre de recherche d\'en-tête lance une recherche live en tapant à travers artistes, albums et pistes. Ouvrez la recherche avancée (barre latérale) pour une vue plus riche : filtres par année, genre, note, format, canaux, taux d\'échantillonnage, BPM, ambiance — combinables. Clic droit sur un résultat ouvre le même menu contextuel qu\'ailleurs.', - q17: 'Les Mixes (Aléatoire / Genre / Super Genre / Lucky) ?', - a17: 'Le Mix aléatoire crée une liste de pistes aléatoires de votre bibliothèque ; le filtre par mots-clés exclut audiobooks, comédie, etc. par sous-chaînes de genre/titre/album. Super Genre Mix regroupe votre bibliothèque par grands styles (Rock, Metal, Électronique, Jazz, Classique…) et bâtit un mix focalisé. Lucky Mix utilise votre historique d\'écoute, les notes et les pistes similaires AudioMuse-AI pour assembler une liste instantanée d\'un clic.', - q18: 'Page Statistiques ?', - a18: 'Statistiques (barre latérale) montre les top artistes, top albums, top pistes, répartition par genre, temps d\'écoute dans le temps, et un périmètre par bibliothèque si vous avez plusieurs dossiers configurés. Plusieurs vues sont exportables en image partageable.', - q19: 'Comment télécharger un album en ZIP ?', - a19: 'Page album → « Télécharger (ZIP) ». Le serveur compresse l\'album d\'abord — pour les albums volumineux ou sans perte (FLAC / WAV) la barre de progression n\'apparaît qu\'une fois le zip terminé et le transfert démarré. C\'est normal.', - s5: 'Paroles', - q20: 'D\'où viennent les paroles ?', - a20: 'Trois sources configurables dans Paramètres → Paroles : votre serveur Navidrome (paroles intégrées / OpenSubsonic), LRCLIB (paroles synchronisées communautaires) et NetEase Cloud Music (vaste catalogue asiatique + international). Chaque source est activable/désactivable et priorisable par glisser-déposer.', - q21: 'Comment voir les paroles pendant la lecture ?', - a21: 'Cliquez sur l\'icône micro de la barre du lecteur pour ouvrir l\'onglet Paroles dans le panneau de file. Les paroles synchronisées défilent automatiquement et supportent le clic-pour-aller-à ; les paroles en texte brut défilent en bloc statique. Activez le lecteur plein écran via la pochette pour une vue immersive avec fond mesh.', - s6: 'Partage & Social', - q22: 'Que sont les Magic Strings ?', - a22: 'Les Magic Strings sont de courts jetons à copier-coller qui partagent des choses entre utilisateurs Psysonic sans serveur tiers. Les chaînes d\'invitation de serveur permettent à un ami de s\'enregistrer sur votre Navidrome en un collage ; les Magic Strings d\'album / artiste / file ouvrent le même album / artiste / file chez le destinataire. Générez-les depuis le menu Partager, collez-les dans la barre de recherche pour les consommer.', - q23: 'Qu\'est-ce qu\'Orbit ?', - a23: 'Orbit, c\'est l\'écoute synchronisée à plusieurs : un hôte joue une piste, tous les invités l\'entendent en sync, et les invités peuvent suggérer des morceaux que l\'hôte peut accepter dans la file. Démarrez une session depuis le bouton Orbit dans l\'en-tête, partagez le lien d\'invitation, les autres rejoignent depuis n\'importe quelle installation Psysonic. L\'hôte contrôle la lecture (saut, recherche, file) — les invités ont une vue temps réel et une boîte à suggestions. Les sessions sont éphémères et se terminent à la fermeture par l\'hôte.', - q24: 'Qu\'est-ce que la liste déroulante Now Playing ?', - a24: 'L\'icône de diffusion en haut à droite affiche ce que les autres utilisateurs du serveur Navidrome écoutent en ce moment, rafraîchi toutes les 10 secondes. Votre propre entrée disparaît dès la pause. Par serveur — les utilisateurs sur un autre serveur actif n\'apparaissent pas.', - s7: 'Personnalisation', - q25: 'Thèmes et planificateur de thème ?', - a25: 'Paramètres → Apparence → Thème offre 60+ thèmes en 8 groupes (Psysonic, Lecteurs multimédias, Systèmes d\'exploitation, Jeux, Films, Séries, Réseaux sociaux, Open Source Classics — Catppuccin / Nord / Gruvbox / Nightfox / Dracula). Auto-Switch Theme permet de définir un thème de jour et un thème de nuit avec heures de bascule pour un changement automatique.', - q26: 'Puis-je personnaliser barre latérale, accueil et page artiste ?', - a26: 'Oui — Paramètres → Personnalisation. Le customiseur de barre latérale permet de réordonner les éléments par glisser et de masquer ceux que vous n\'utilisez pas. Le customiseur d\'accueil bascule chaque rangée Mainstage (Hero, Récent, Découvrir, Récemment écoutés, Favoris…). Le customiseur de page artiste réordonne les sections (Top morceaux, Albums, Singles, Compilations, Artistes similaires, etc.) et masque celles que vous ignorez.', - q27: 'Qu\'est-ce que le Mini Player ?', - a27: 'Une petite fenêtre flottante avec pochette, contrôles de transport et file compacte. Ouvrez-la depuis l\'icône mini-player de la barre du lecteur ou avec son raccourci. La fenêtre mémorise sa position et sa taille entre les sessions. Sous Windows, la mini-webview est précréée au démarrage pour une ouverture instantanée ; Linux / macOS doivent activer l\'option dans Paramètres → Apparence → Précharger le mini-player.', - q28: 'Qu\'est-ce que la barre de lecture flottante ?', - a28: 'Un style optionnel de barre du lecteur (Paramètres → Apparence) qui se détache du bord inférieur avec fond thématique, bordure d\'accentuation, pochette arrondie et section volume centrée. Utile sur les écrans hauts ou avec des thèmes compacts.', - q29: 'Aperçu de piste au survol ?', - a29: 'Survolez une ligne de piste, cliquez sur le petit bouton Aperçu sur la pochette, ou déclenchez l\'aperçu depuis le menu contextuel — Psysonic diffuse les ~15 premières secondes via le même moteur audio Rust afin que la normalisation de loudness s\'applique. Pratique pour parcourir un album inconnu.', - q30: 'Minuteur de mise en veille ?', - a30: 'Cliquez sur l\'icône lune de la barre du lecteur pour ouvrir le minuteur. Choisissez une durée (ou « fin de la piste actuelle ») et Psysonic fait un fondu et met en pause à la fin. Le bouton affiche un anneau circulaire et un compte à rebours pendant que le minuteur tourne.', - q31: 'Échelle UI, police, style de seekbar ?', - a31: 'Paramètres → Apparence — Échelle de l\'interface (80–125 % sans toucher à la taille système), Police (10 polices UI dont IBM Plex Mono, Fira Code, Geist, Golos Text…), Style de seekbar (Forme d\'onde analysée / pseudowave déterministe / Ligne & Point / Barre / Barre épaisse / Segmenté / Néon / Onde pulsée / Traînée de particules / Remplissage liquide / Bande rétro).', - s8: 'Utilisateur avancé', - q32: 'Contrôles du lecteur en ligne de commande ?', - a32: 'Le binaire Psysonic sert aussi de télécommande. Exemples : psysonic --player play / pause / next / prev, --player volume 75, --player seek 15, --player shuffle, --player repeat off|all|one, --player rating 1-5. Changer de serveur, périphérique audio, bibliothèque ; déclencher un Instant Mix ; rechercher artistes / albums / pistes. Liste complète : psysonic --player --help. Complétions shell pour bash et zsh via psysonic completions.', - q33: 'Listes intelligentes (Navidrome) ?', - a33: 'Les listes intelligentes sont des listes dynamiques côté Navidrome définies par des règles (genre = Rock ET année > 2020, etc.). La page Listes de lecture de Psysonic permet de les créer, modifier et supprimer avec un éditeur de règles visuel — Psysonic utilise l\'API native de Navidrome. Elles se comportent comme des listes normales dans le reste de l\'app et se mettent à jour automatiquement.', - q34: 'Sauvegarder et restaurer les paramètres ?', - a34: 'Paramètres → Stockage → Sauvegarder & Restaurer exporte les profils de serveur, thèmes, raccourcis et autres réglages dans un seul fichier JSON. Importez-le sur une autre machine ou après une réinstallation pour tout restaurer d\'un coup. Les mots de passe des serveurs sont inclus — gardez le fichier privé.', - q35: 'Où voir toutes les licences open source ?', - a35: 'Paramètres → Système → Licences open source. La liste complète des dépendances (crates Cargo et paquets npm) est livrée avec les textes de licence inclus. Cliquez sur une entrée pour voir le texte complet ; le bloc en surbrillance en haut met en avant les bibliothèques connues (Tauri, React, rodio, symphonia, etc.).', - s9: 'Hors ligne & Sync', - q36: 'Mode hors ligne — mettre en cache albums et listes ?', - a36: 'Ouvrez un album ou une liste et cliquez sur l\'icône de téléchargement dans l\'en-tête — Psysonic met chaque piste en cache localement pour une lecture sans appel réseau. La page Bibliothèque hors ligne (barre latérale) liste tout ce qui est en cache, montre les téléchargements en cours, et permet de supprimer via l\'icône poubelle (qui apparaît une fois le téléchargement terminé).', - q37: 'Limite de stockage hors ligne ?', - a37: 'Paramètres → Bibliothèque → Hors ligne permet de définir une taille maximale de cache. Quand la limite est atteinte, le bouton de téléchargement de la page album affiche un avertissement. Libérez de l\'espace en supprimant des albums ou listes depuis la page Bibliothèque hors ligne.', - q38: 'Device Sync — copier la musique sur USB / SD ?', - a38: 'Device Sync (barre latérale) copie albums, listes ou artistes entiers vers un disque externe pour l\'écoute hors ligne sur d\'autres appareils. Choisissez un dossier cible, sélectionnez les sources dans les onglets de navigation, cliquez « Transférer vers le périphérique ». Psysonic écrit un manifeste (psysonic-sync.json) pour savoir quels fichiers sont déjà là, même si vous rouvrez Device Sync sur un autre OS avec un autre modèle de nom. Les modèles supportent les jetons {artist} / {album} / {title} / {track_number} / {disc_number} / {year} avec / comme séparateur de dossier.', - s10: 'Intégrations & Dépannage', - q39: 'Scrobbling Last.fm ?', - a39: 'Paramètres → Intégrations → Last.fm. Connectez votre compte une fois et Psysonic scrobble directement vers Last.fm — pas besoin de configurer Navidrome. Un scrobble est envoyé après 50 % d\'écoute. Les pings « now playing » partent au début.', - q40: 'Discord Rich Presence ?', - a40: 'Paramètres → Intégrations → Discord affiche la piste en cours sur votre profil Discord. Choisissez entre l\'icône de l\'app, la pochette de votre serveur (via getAlbumInfo2 — serveur publiquement joignable nécessaire) ou les pochettes Apple Music. Personnalisez les chaînes affichées (détails, état, info-bulle) avec des templates de jetons.', - q41: 'Dates de tournée Bandsintown ?', - a41: 'Activation dans Paramètres → Intégrations → Now Playing Info. L\'onglet Now Playing sur la page éponyme affiche alors les dates de tournée à venir pour l\'artiste en cours via l\'API widget Bandsintown. Désactivé par défaut — aucune requête tant que vous n\'activez pas.', - q42: 'Internet Radio — lecture de flux en direct ?', - a42: 'Internet Radio (barre latérale) lit n\'importe quel flux en direct stocké sur votre serveur Navidrome (ajoutez les stations via l\'admin Navidrome). La lecture passe par le moteur HTML5 du navigateur — la plupart des réglages EQ / Replay Gain / Loudness ne s\'appliquent pas à la radio, mais les métadonnées ICY (titre courant) s\'affichent. Supporte MP3, AAC, OGG Vorbis et la plupart des flux HLS ; le support codec dépend de la plateforme.', - q43: 'Le test de connexion échoue — que faire ?', - a43: 'Vérifiez l\'URL avec le port (ex. http://192.168.1.100:4533). Sur le réseau local, http:// fonctionne souvent là où https:// ne marche pas (pas de certificat). Assurez-vous qu\'aucun pare-feu ne bloque le port et que nom d\'utilisateur et mot de passe sont corrects. Avec un reverse-proxy, essayez d\'abord l\'URL directe pour isoler la cause.', - q44: 'Les pochettes et images d\'artiste se chargent lentement.', - a44: 'Les images sont récupérées du serveur à la première vue puis mises en cache localement pour 30 jours. Si le stockage du serveur est lent, la première visite d\'une page peut prendre un instant ; les visites suivantes sont instantanées. Le Hot Cache aide aussi pour les pistes mais le cache d\'images est indépendant.', - q45: 'Problèmes Linux — écran noir ou pas de son ?', - a45: 'L\'écran noir est généralement un souci de pilote GPU / EGL dans WebKitGTK — lancez avec GDK_BACKEND=x11 WEBKIT_DISABLE_COMPOSITING_MODE=1 WEBKIT_DISABLE_DMABUF_RENDERER=1 (les installeurs AUR / .deb / .rpm le font automatiquement). Pour le son, vérifiez que PipeWire ou PulseAudio tourne. Les coupures audio après mise en veille sont désormais gérées automatiquement par le hook de récupération post-sleep.', - }, - queue: { - title: 'File d\'attente', - savePlaylist: 'Enregistrer la liste', - updatePlaylist: 'Mettre à jour la liste', - filterPlaylists: 'Filtrer les listes…', - playlistName: 'Nom de la liste', - cancel: 'Annuler', - save: 'Enregistrer', - loadPlaylist: 'Charger une liste', - loading: 'Chargement…', - noPlaylists: 'Aucune liste trouvée.', - load: 'Remplacer la file et lire', - appendToQueue: 'Ajouter à la file', - delete: 'Supprimer', - deleteConfirm: 'Supprimer la liste « {{name}} » ?', - clear: 'Vider', - shuffle: 'Mélanger la file', - gapless: 'Sans blanc', - crossfade: 'Fondu', - infiniteQueue: 'File infinie', - autoAdded: '— Ajouté automatiquement —', - radioAdded: '— Radio —', - hide: 'Masquer', - hideNowPlaying: 'Masquer les infos de lecture', - showNowPlaying: 'Afficher les infos de lecture', - close: 'Fermer', - nextTracks: 'Pistes suivantes', - shareQueue: 'Copier le lien de la file d’attente', - shareQueueEmpty: 'La file d’attente est vide — rien à partager.', - emptyQueue: 'La file d\'attente est vide.', - trackSingular: 'piste', - trackPlural: 'pistes', - showRemaining: 'Afficher le temps restant', - showTotal: 'Afficher la durée totale', - showEta: 'Afficher l\'heure de fin estimée', - replayGain: 'ReplayGain', - rgTrack: 'T {{db}} dB', - rgAlbum: 'A {{db}} dB', - rgPeak: 'Pic {{pk}}', - sourceOffline: 'Lecture depuis la bibliothèque hors ligne', - sourceHot: 'Lecture depuis le cache', - sourceStream: 'Lecture depuis le flux réseau', - clearCachedLoudnessWaveform: 'Clear cached loudness and waveform, then re-analyze this track', - recalculatingLoudnessWaveform: 'Recalculating loudness and waveform for this track…', - }, - miniPlayer: { - showQueue: 'Afficher la file', - hideQueue: 'Masquer la file', - pinOnTop: 'Toujours visible', - pinOff: 'Désépingler', - openMainWindow: 'Ouvrir la fenêtre principale', - close: 'Fermer', - emptyQueue: 'La file est vide', - }, - statistics: { - title: 'Statistiques', - recentlyPlayed: 'Écoutés récemment', - mostPlayed: 'Albums les plus écoutés', - highestRated: 'Albums les mieux notés', - genreDistribution: 'Répartition par genre (Top 20)', - loadMore: 'Charger plus', - statArtists: 'Artistes', - statArtistsTooltip: 'Artistes d\'album uniquement — les artistes apparaissant seulement sur des pistes (featuring, invité, etc.) sans album propre ne sont pas comptés.', - statAlbums: 'Albums', - statSongs: 'Morceaux', - statGenres: 'Genres', - statPlaytime: 'Durée totale', - genreInsights: 'Aperçu des genres', - formatDistribution: 'Distribution des formats', - formatSample: 'Échantillon de {{n}} pistes', - computing: 'Calcul en cours…', - genreSongs: '{{count}} morceaux', - genreAlbums: '{{count}} albums', - recentlyAdded: 'Ajoutés récemment', - decadeDistribution: 'Albums par décennie', - decadeAlbums_one: '{{count}} album', - decadeAlbums_other: '{{count}} albums', - decadeUnknown: 'Inconnu', - lfmTitle: 'Stats Last.fm', - lfmTopArtists: 'Artistes favoris', - lfmTopAlbums: 'Albums favoris', - lfmTopTracks: 'Morceaux favoris', - lfmPlays: '{{count}} écoutes', - lfmPeriodOverall: 'Tout le temps', - lfmPeriod7day: '7 jours', - lfmPeriod1month: '1 mois', - lfmPeriod3month: '3 mois', - lfmPeriod6month: '6 mois', - lfmPeriod12month: '12 mois', - lfmNotConnected: 'Connectez Last.fm dans les Paramètres pour voir vos stats.', - lfmRecentTracks: 'Scrobbles récents', - lfmNowPlaying: 'En cours de lecture', - lfmJustNow: 'à l\'instant', - lfmMinutesAgo: 'il y a {{n}} min', - lfmHoursAgo: 'il y a {{n}}h', - lfmDaysAgo: 'il y a {{n}}j', - topRatedSongs: 'Morceaux les mieux notés', - topRatedArtists: 'Artistes les mieux notés', - noRatedSongs: 'Aucun morceau noté. Notez des morceaux dans la vue album ou playlist.', - noRatedArtists: 'Aucun artiste noté.', - }, - player: { - regionLabel: 'Lecteur de musique', - openFullscreen: 'Ouvrir le lecteur plein écran', - fullscreen: 'Lecteur plein écran', - closeFullscreen: 'Fermer le plein écran', - closeTooltip: 'Fermer (Échap)', - noTitle: 'Sans titre', - stop: 'Arrêter', - prev: 'Piste précédente', - play: 'Lecture', - pause: 'Pause', - previewActive: 'Aperçu en cours', - previewLabel: 'Aperçu', - delayModalTitle: 'Minuteur', - delayPauseSection: 'Pause après', - delayStartSection: 'Démarrage après', - delayPreviewPause: 'Pause à', - delayPreviewStart: 'Démarrage à', - delaySchedulePause: 'Programmer la pause', - delayScheduleStart: 'Programmer le démarrage', - delayCancelPause: 'Annuler le minuteur de pause', - delayCancelStart: 'Annuler le minuteur de démarrage', - delayInactivePause: 'Disponible uniquement pendant la lecture.', - delayInactiveStart: 'Disponible en pause avec une piste ou une radio chargée.', - delayCustomMinutes: 'Délai personnalisé (minutes)', - delayCustomPlaceholder: 'ex. 2,5', - closeDelayModal: 'Fermer', - delayIn: 'dans', - delayFmtSec: '{{n}} s', - delayFmtMin: '{{n}} min', - delayFmtHr: '{{n}} h', - delayCancel: 'Annuler', - delayApply: 'Appliquer', - next: 'Piste suivante', - repeat: 'Répéter', - repeatOff: 'Désactivé', - repeatAll: 'Tout', - repeatOne: 'Un', - progress: 'Progression', - volume: 'Volume', - toggleQueue: 'Afficher/masquer la file', - collapseQueueResize: 'Réduire la file, redimensionner', - moreOptions: 'Plus d’options', - equalizer: 'Égaliseur', - miniPlayer: 'Mini-lecteur', - lyrics: 'Paroles', - fsLyricsToggle: 'Paroles en plein écran', - lyricsLoading: 'Chargement des paroles…', - lyricsNotFound: 'Aucune parole trouvée pour ce titre', - lyricsSourceServer: 'Source : Serveur', - lyricsSourceLrclib: 'Source : LRCLIB', - lyricsSourceNetease: 'Source : Netease', - lyricsSourceLyricsplus: 'Source : YouLyPlus', - showDuration: 'Afficher la durée', - showRemainingTime: 'Afficher le temps restant', - }, - nowPlayingInfo: { - tab: 'Info', - empty: 'Lancez une lecture pour voir les infos', - artist: 'Artiste', - songInfo: 'Infos du morceau', - onTour: 'En tournée', - noTourEvents: 'Aucun concert à venir', - tourLoading: 'Chargement…', - poweredByBandsintown: 'Données de tournée via Bandsintown', - bioReadMore: 'En lire plus', - bioReadLess: 'Réduire', - showMoreTours_one: 'Afficher {{count}} de plus', - showMoreTours_other: 'Afficher {{count}} de plus', - showLessTours: 'Réduire', - enableBandsintownPrompt: 'Afficher les prochaines dates de tournée ?', - enableBandsintownPromptDesc: 'Optionnel. Charge les concerts de l\'artiste via l\'API publique Bandsintown.', - enableBandsintownPrivacy: 'Lors de l\'activation, le nom de l\'artiste en cours de lecture est envoyé à l\'API Bandsintown pour récupérer les dates de tournée. Aucun compte ni données personnelles ne quittent votre appareil.', - enableBandsintownAction: 'Activer', - role: { - artist: 'Artiste', - albumArtist: 'Artiste de l\'album', - composer: 'Compositeur', - }, - }, - songInfo: { - title: 'Infos du morceau', - songTitle: 'Titre', - artist: 'Artiste', - album: 'Album', - albumArtist: 'Artiste de l\'album', - year: 'Année', - genre: 'Genre', - duration: 'Durée', - track: 'Piste', - format: 'Format', - bitrate: 'Débit', - sampleRate: 'Fréquence d\'échantillonnage', - bitDepth: 'Profondeur de bits', - channels: 'Canaux', - fileSize: 'Taille du fichier', - path: 'Emplacement', - replayGainTrack: 'RG Gain de piste', - replayGainAlbum: 'RG Gain d\'album', - replayGainPeak: 'RG Crête de piste', - mono: 'Mono', - stereo: 'Stéréo', - }, - playlists: { - title: 'Playlists', - newPlaylist: 'Nouvelle playlist', - unnamed: 'Playlist sans nom', - createName: 'Nom de la playlist…', - create: 'Créer', - cancel: 'Annuler', - empty: 'Aucune playlist pour l\'instant.', - emptyPlaylist: 'Cette playlist est vide.', - addFirstSong: 'Ajouter votre premier titre', - notFound: 'Playlist introuvable.', - songs: '{{n}} titres', - playAll: 'Tout lire', - shuffle: 'Aléatoire', - addToQueue: 'Ajouter à la file', - back: 'Retour aux playlists', - deletePlaylist: 'Supprimer', - confirmDelete: 'Cliquer à nouveau pour confirmer', - removeSong: 'Retirer de la playlist', - addSongs: 'Ajouter des titres', - searchPlaceholder: 'Rechercher dans la bibliothèque…', - noResults: 'Aucun résultat.', - suggestions: 'Titres suggérés', - noSuggestions: 'Aucune suggestion disponible.', - titleBadge: 'Playlist', - refreshSuggestions: 'Nouvelles suggestions', - addSong: 'Ajouter à la playlist', - preview: 'Aperçu (30 s)', - previewStop: 'Arrêter l\'aperçu', - playNextSuggestion: 'Lire ensuite', - suggestionsHint: "Double-cliquez sur une ligne pour l'ajouter à la playlist", - addSelected: 'Ajouter la sélection', - cacheOffline: 'Mettre la playlist hors ligne', - offlineCached: 'Playlist en cache', - removeOffline: 'Retirer du cache hors ligne', - offlineDownloading: 'En cache… ({{done}}/{{total}} albums)', - publicLabel: 'Publique', - privateLabel: 'Privée', - editMeta: 'Modifier la playlist', - editNamePlaceholder: 'Nom de la playlist…', - editCommentPlaceholder: 'Ajouter une description…', - editPublic: 'Playlist publique', - editSave: 'Enregistrer', - editCancel: 'Annuler', - changeCover: 'Changer la pochette', - changeCoverLabel: 'Changer la photo', - removeCover: 'Supprimer la photo', - coverUpdated: 'Pochette mise à jour', - metaSaved: 'Playlist mise à jour', - downloadZip: 'Télécharger (ZIP)', - // Toast notifications for multi-select - addSuccess: '{{count}} morceaux ajoutés à {{playlist}}', - addPartial: '{{added}} ajoutés, {{skipped}} ignorés (doublons)', - addAllSkipped: 'Tous ignorés ({{count}} doublons)', - addedAsDuplicates: '{{count}} morceaux ajoutés à {{playlist}} (en doublons)', - duplicateConfirmTitle: 'Déjà dans la playlist', - duplicateConfirmMessage: 'Les {{count}} morceaux sont déjà dans « {{playlist}} ». Les ajouter quand même en doublons ?', - duplicateConfirmAction: 'Ajouter quand même', - addError: 'Erreur lors de l\'ajout des morceaux', - createAndAddSuccess: 'Playlist "{{playlist}}" créée avec {{count}} morceaux', - createError: 'Erreur lors de la création de la playlist', - deleteSuccess: '{{count}} playlists supprimées', - deleteFailed: 'Erreur lors de la suppression de {{name}}', - deleteSelected: 'Supprimer la sélection', - deleteSelectedPartial: 'Seulement {{n}} des {{total}} playlists sélectionnées peuvent être supprimées (les autres appartiennent à quelqu\'un d\'autre).', - mergeSuccess: '{{count}} morceaux fusionnés dans {{playlist}}', - mergeNoNewSongs: 'Aucun nouveau morceau à ajouter', - mergeError: 'Erreur lors de la fusion des playlists', - mergeInto: 'Fusionner dans', - selectionCount: '{{count}} sélectionnés', - select: 'Sélectionner', - startSelect: 'Activer la sélection', - cancelSelect: 'Annuler', - loadingAlbums: 'Résolution de {{count}} albums…', - loadingArtists: 'Résolution de {{count}} artistes…', - myPlaylists: 'Mes Playlists', - noOtherPlaylists: 'Aucune autre playlist disponible', - addToPlaylistSuccess: '{{count}} morceaux ajoutés à {{playlist}}', - addToPlaylistNoNew: 'Aucun nouveau morceau pour {{playlist}}', - addToPlaylistError: 'Erreur lors de l\'ajout à la playlist', - removeSuccess: 'Morceau retiré de la playlist', - removeError: 'Erreur lors du retrait de la playlist', - importCSV: 'Importer CSV', - importCSVTooltip: 'Importer depuis CSV Spotify', - csvImportReport: 'Rapport d\'Import CSV', - csvImportTotal: 'Total', - csvImportAdded: 'Ajoutés', - csvImportDuplicates: 'Doublons', - csvImportNotFound: 'Non Trouvés', - csvImportNetworkErrors: 'Erreurs Réseau', - csvImportDuplicatesTitle: 'Titres en Doublon (Déjà dans la Playlist):', - csvImportNotFoundTitle: 'Titres Non Trouvés:', - csvImportNetworkErrorsTitle: 'Erreurs Réseau (peut réessayer l\'import):', - csvImportDownloadReport: 'Télécharger le Rapport', - csvImportClose: 'Fermer', - csvImportNoValidTracks: 'Aucun titre valide trouvé dans le fichier CSV', - csvImportFailed: 'Échec de l\'import CSV', - csvImportToast: '{{added}} ajoutés, {{notFound}} non trouvés, {{duplicates}} doublons', - csvImportDownloadSuccess: 'Rapport téléchargé avec succès', - csvImportDownloadError: 'Échec du téléchargement du rapport', - }, - smartPlaylists: { - sectionBasic: '1. Base', - sectionGenres: '2. Genres', - sectionYearsAndFilters: '3. Années et filtres', - genreMode: 'Mode des genres', - genreModeInclude: 'Inclure les genres', - genreModeExclude: 'Exclure les genres', - genreSearchPlaceholder: 'Filtrer les genres...', - availableGenres: 'Disponibles', - selectedGenres: 'Sélectionnés', - yearMode: 'Mode des années', - yearModeInclude: 'Inclure la plage', - yearModeExclude: 'Exclure la plage', - name: 'Nom (sans préfixe)', - limit: 'Limite', - limitHint: 'Nombre de morceaux à inclure dans la playlist (1-{{max}}, généralement 50).', - artistContains: 'Artiste contient…', - albumContains: 'Album contient…', - titleContains: 'Titre contient…', - minRating: 'Note minimale', - minRatingAria: 'Note minimale pour playlist intelligente', - minRatingHint: '0 désactive le seuil minimum; 1-5 conserve les morceaux avec une note supérieure à la valeur choisie.', - fromYear: 'Depuis l\'année', - toYear: 'Jusqu\'à l\'année', - excludeUnrated: 'Exclure les morceaux non notés', - compilationOnly: 'Compilations uniquement', - create: 'Nouvelle Smart Playlist', - save: 'Enregistrer la Smart Playlist', - created: '{{name}} créée', - updated: '{{name}} mise à jour', - createFailed: 'Impossible de créer la smart playlist.', - updateFailed: 'Impossible de mettre à jour la smart playlist.', - navidromeOnly: 'Les smart playlists ne peuvent être créées que sur des serveurs Navidrome.', - loadFailed: 'Impossible de charger les smart playlists depuis Navidrome.', - sortRandom: 'Tri : aléatoire', - sortTitleAsc: 'Tri : titre A-Z', - sortTitleDesc: 'Tri : titre Z-A', - sortYearDesc: 'Tri : année décroissante', - sortYearAsc: 'Tri : année croissante', - sortPlayCountDesc: 'Tri : nombre d\'écoutes décroissant', - }, - mostPlayed: { - title: 'Les plus joués', - topArtists: 'Artistes populaires', - topAlbums: 'Albums populaires', - plays: '{{n}} écoutes', - sortMost: 'Plus joués en premier', - sortLeast: 'Moins joués en premier', - loadMore: 'Charger plus d\'albums', - noData: 'Aucune donnée d\'écoute. Commencez à écouter !', - noArtists: 'Tous les artistes filtrés.', - filterCompilations: 'Masquer les artistes de compilations (Various Artists, Soundtracks, etc.)', - filterCompilationsShort: 'Masquer les compilations', - }, - losslessAlbums: { - empty: 'Aucun album lossless dans cette bibliothèque pour l\'instant.', - unsupported: 'Ce serveur n\'expose pas les métadonnées nécessaires pour trouver des albums lossless.', - slowFetchHint: 'Chargement plus lent que les autres pages d\'albums — Psysonic parcourt tout le catalogue par qualité.', - }, - radio: { - title: 'Radio Internet', - empty: 'Aucune station radio configurée.', - addStation: 'Ajouter une station', - editStation: 'Modifier', - deleteStation: 'Supprimer la station', - confirmDelete: 'Cliquer à nouveau pour confirmer', - stationName: 'Nom de la station…', - streamUrl: 'URL du flux…', - homepageUrl: 'URL de la page d\'accueil (optionnel)', - save: 'Enregistrer', - cancel: 'Annuler', - live: 'LIVE', - liveStream: 'Radio Internet', - openHomepage: 'Ouvrir la page d\'accueil', - changeCoverLabel: 'Changer la pochette', - removeCover: 'Supprimer la pochette', - browseDirectory: 'Parcourir l\'annuaire', - directoryPlaceholder: 'Rechercher des stations…', - noResults: 'Aucune station trouvée.', - stationAdded: 'Station ajoutée', - filterAll: 'Toutes', - filterFavorites: 'Favoris', - sortManual: 'Manuel', - sortAZ: 'A → Z', - sortZA: 'Z → A', - sortNewest: 'Plus récentes', - favorite: 'Ajouter aux favoris', - unfavorite: 'Retirer des favoris', - noFavorites: 'Aucune station favorite.', - listenerCount_one: '{{count}} auditeur', - listenerCount_other: '{{count}} auditeurs', - recentlyPlayed: 'Récemment joués', - upNext: 'À suivre', - }, - folderBrowser: { - empty: 'Dossier vide', - error: 'Échec du chargement', - }, - deviceSync: { - title: 'Sync appareil', - targetFolder: 'Dossier cible', - noFolderChosen: 'Aucun dossier sélectionné', - selectDrive: 'Sélectionner un lecteur…', - refreshDrives: 'Actualiser les lecteurs', - noDrivesDetected: 'Aucun lecteur amovible détecté', - browseManual: 'Parcourir manuellement…', - free: 'libre', - notMountedVolume: 'La cible n\u0027est pas sur un volume monté. Le lecteur a peut-être été déconnecté.', - chooseFolder: 'Choisir…', - filenameTemplate: 'Modèle de nom de fichier', - targetDevice: 'Appareil cible', - templateHint: 'Variables : {artist}, {album}, {title}, {track_number}, {disc_number}, {year}', - cleanupButton: 'Supprimer les fichiers absents', - cleanupNothingToDelete: 'Rien à supprimer — l\'appareil est déjà synchronisé.', - confirmCleanup: 'Supprimer {{count}} fichier(s) de l\'appareil qui ne font pas partie de la sélection actuelle. Continuer ?', - cleanupComplete: '{{count}} fichier(s) supprimé(s) de l\'appareil.', - selectedSources: 'Sources sélectionnées', - noSourcesSelected: 'Aucune source sélectionnée. Cliquez sur des éléments dans le navigateur pour les ajouter.', - clearAll: 'Tout effacer', - tabPlaylists: 'Listes de lecture', - tabAlbums: 'Albums', - tabArtists: 'Artistes', - searchPlaceholder: 'Rechercher…', - syncButton: 'Synchroniser vers l\'appareil', - actionTransfer: 'Transférer vers l\'appareil', - actionDelete: 'Supprimer de l\'appareil', - actionApplyAll: 'Appliquer toutes les modifications', - templatePreview: 'Aperçu', - templatePresetStandard: 'Standard', - templatePresetMultiDisc: 'Multi-Disc', - templatePresetAltFolder: 'Dossier alt.', - tokenSlashHint: '/ = séparateur de dossier', - cancel: 'Annuler', - noTargetDir: 'Veuillez d\'abord choisir un dossier cible.', - noSources: 'Veuillez sélectionner au moins une source.', - noTracks: 'Aucune piste trouvée dans les sources sélectionnées.', - fetchError: 'Échec du chargement des pistes depuis le serveur.', - syncComplete: 'Synchronisation terminée.', - dismiss: 'Fermer', - cancelSync: 'Annuler', - syncCancelled: 'Synchronisation annulée ({{done}} / {{total}} transférés).', - colName: 'Nom', - colType: 'Type', - colStatus: 'Statut', - onDevice: 'Gestionnaire d\'appareil', - addSources: 'Ajouter…', - syncResult: '{{done}} transféré(s), {{skipped}} déjà à jour ({{total}} au total)', - deleteFromDevice: 'Marquer pour suppression ({{count}})', - confirmDelete: 'Supprimer {{count}} élément(s) du périphérique : {{names}} ?', - deleteComplete: '{{count}} élément(s) supprimé(s) du périphérique.', - manifestImported: '{{count}} source(s) importée(s) depuis le manifeste du périphérique.', - statusSynced: 'Synchronisé', - statusPending: 'En attente', - statusDeletion: 'Suppression', - markForDeletion: 'Marquer pour suppression', - removeSource: 'Supprimer', - undoDeletion: 'Annuler la suppression', - syncInBackground: 'Sync démarré en arrière-plan — vous pouvez naviguer ailleurs.', - syncInProgress: '{{done}} / {{total}} pistes…', - syncSummary: 'Résumé de la synchronisation', - calculating: 'Calcul de la charge utile…', - filesToAdd: 'Fichiers à ajouter :', - filesToDelete: 'Fichiers à supprimer :', - netChange: 'Variation nette :', - availableSpace: 'Espace disque disponible :', - spaceWarning: 'Attention : L\'appareil cible ne dispose pas d\'assez d\'espace signalé.', - proceed: 'Procéder à la synchronisation', - notEnoughSpace: 'Espace disque physique insuffisant détecté !', - liveSearch: 'Live', - randomAlbumsLabel: 'Albums aléatoires', - }, - orbit: { - triggerLabel: 'Orbit', - triggerTooltip: 'Démarrer ou rejoindre une session d\'écoute partagée', - launchCreate: 'Créer une session', - launchJoin: 'Rejoindre une session', - launchHelp: 'Comment ça marche ?', - launchHelpSoon: 'Bientôt disponible', - joinModalTitle: 'Rejoindre une session Orbit', - joinModalSub: 'Colle le lien d\'invitation que ton hôte t\'a envoyé.', - joinModalLinkLabel: 'Lien d\'invitation', - joinModalLinkPlaceholder: 'psysonic2-…', - joinModalLinkHelper: 'Fonctionne avec tout lien Orbit valide. Doit pointer vers le serveur auquel tu es actuellement connecté.', - joinModalPasteTooltip: 'Coller depuis le presse-papiers', - joinModalSubmit: 'Rejoindre', - joinModalBusy: 'Connexion…', - joinErrEmpty: 'Veuillez coller un lien d\'invitation.', - joinErrInvalid: 'Cela ne ressemble pas à un lien d\'invitation Orbit.', - closeAria: 'Fermer', - heroTitlePrefix: 'Écoute ensemble avec', - heroTitleBrand: 'Orbit', - heroSub: 'Démarre une session — les autres utilisateurs de {{server}} écouteront en même temps et pourront suggérer des morceaux.', - fallbackServer: 'ce serveur', - tipLan: 'Tu es actuellement connecté via une adresse de réseau local. Les invités hors de ton réseau ne peuvent pas rejoindre — bascule vers une adresse publique dans les paramètres avant de démarrer.', - tipRemote: 'Pour que des invités hors de ton réseau domestique puissent rejoindre, l\'adresse de ton serveur doit être publiquement accessible. Si ton serveur est interne, bascule avant de démarrer.', - labelName: 'Nom de la session', - namePlaceholder: 'Velvet Orbit', - reshuffleTooltip: 'Nouvelle suggestion', - reshuffleAria: 'Suggérer un nouveau nom', - helperName: 'Comment la session apparaîtra à tes invités — garde-le ou saisis le tien.', - labelMax: 'Invités max.', - helperMax: 'Tu ne comptes pas — ceci limite uniquement les invités entrants.', - labelLink: 'Lien d\'invitation', - tooltipCopied: 'Copié', - tooltipCopy: 'Copier', - ariaCopyLink: 'Copier le lien d\'invitation', - helperLink: 'Envoie ce lien à tes invités. Ils peuvent le coller n\'importe où dans Psysonic avec Ctrl+V.', - labelClearQueue: 'Vider ma file d\'attente d\'abord', - helperClearQueue: 'Démarre la session avec une file d\'attente vide. Désactivé : les titres déjà en file restent et sont partagés avec les invités.', - btnCancel: 'Annuler', - btnStarting: 'Démarrage…', - btnStart: 'Démarrer Orbit', - btnCopyAndStart: 'Copier le lien & démarrer', - errNameRequired: 'Veuillez donner un nom à ta session.', - errStartFailed: 'Impossible de démarrer.', - hostLabel: 'Hôte : {{name}}', - participantsTooltip: 'Participants', - settingsTooltip: 'Paramètres de session', - shareTooltip: 'Partager le lien d\'invitation', - shuffleLabel: 'Prochain mélange dans', - catchUpLabel: 'rattraper', - catchUpTooltip: 'Sauter à la position actuelle de l\'hôte', - hostAway: 'Hôte hors ligne', - hostOnline: 'Hôte en ligne', - endTooltip: 'Terminer la session', - leaveTooltip: 'Quitter la session', - helpTooltip: 'Fonctionnement d\'Orbit', - diag: { - openTooltip: 'Diagnostic — journal d\'événements copiable', - title: 'Diagnostic Orbit', - role: 'Rôle', - hostTrack: 'ID de piste de l\'hôte', - hostPos: 'Position de l\'hôte', - guestTrack: 'Mon ID de piste', - guestPos: 'Ma position', - drift: 'Décalage', - stateAge: 'Âge de l\'état', - eventLog: 'Journal d\'événements ({{count}})', - copyLabel: 'Copier', - copyTooltip: 'Copier le journal dans le presse-papiers', - clearLabel: 'Effacer', - clearTooltip: 'Vider le tampon', - empty: 'Aucun événement — ils apparaissent dès qu\'Orbit synchronise.', - hint: 'Ouvre ceci avant de reproduire le problème, puis clique Copier et colle dans le rapport.', - copied: '{{count}} lignes copiées', - copyFailed: 'Impossible de copier dans le presse-papiers', - cleared: 'Tampon vidé', - }, - helpTitle: 'Fonctionnement d\'Orbit', - helpIntro: 'Orbit transforme Psysonic en salle d\'écoute partagée. Un hôte choisit la musique ; les invités écoutent en synchro et peuvent suggérer des morceaux.', - helpHostOnly: '(hôte)', - helpSec1Title: 'Qu\'est-ce qu\'Orbit ?', - helpSec1Body: 'Un mode « écouter ensemble » — l\'hôte dirige la lecture, les invités écoutent. Tout passe par des playlists sur ton propre serveur Navidrome ; aucune infrastructure externe.', - helpSec2Title: 'Hôte et invités', - helpSec2Body: 'L\'hôte contrôle la lecture (play / pause / skip / seek) et décide quand la session se termine. Les invités suivent la lecture, peuvent suggérer des morceaux et quitter ou rejoindre à tout moment. Seul l\'hôte peut exclure ou bannir un participant.', - helpSec2WarnHead: 'Important : comptes séparés.', - helpSec2WarnBody: 'Chaque participant a besoin de son propre compte Navidrome. Si l\'hôte et l\'invité utilisent le même utilisateur, leurs soumissions entrent en conflit et l\'hôte ne voit jamais les suggestions de l\'invité.', - helpSec3Title: 'Démarrer et inviter', - helpSec3Body: 'Clique sur le bouton « Orbit » → Créer une session → le modal affiche un lien d\'invitation prêt à copier et permet optionnellement de vider ta file actuelle. Partage le lien comme tu veux. Pendant qu\'une session est active, le bouton de partage dans la barre en haut copie le lien à tout moment.', - helpSec4Title: 'Rejoindre', - helpSec4Body: 'Colle le lien d\'invitation n\'importe où dans Psysonic avec Ctrl+V / Cmd+V — l\'invite apparaît automatiquement. Alternative : « Orbit » → Rejoindre une session → colle dans le champ. Si le lien pointe vers un serveur où tu as un compte, Psysonic bascule automatiquement. Si tu as plusieurs comptes sur ce serveur, un sélecteur demande lequel utiliser.', - helpSec5Title: 'Suggérer des morceaux', - helpSec5Body: 'Dans n\'importe quelle liste : double-clic sur une ligne, ou clic droit → « Ajouter à la session Orbit ». Un simple clic affiche un indice au lieu de jeter tout l\'album dans la file partagée — c\'est intentionnel. Les actions groupées explicites comme « Tout lire » ou « Lire l\'album » demandent d\'abord confirmation puis ajoutent (ne remplacent jamais).', - helpSec6Title: 'La file d\'attente partagée', - helpSec6Body: 'La file affiche les morceaux à venir de l\'hôte — visible par tous. Les ajouts groupés sont toujours ajoutés à la fin, pour ne pas perdre les suggestions des invités. Le mélange automatique réorganise la file périodiquement (configurable : 1 / 5 / 10 / 15 / 30 min). Si ta lecture dévie, le bouton « Rattraper » dans la barre te ramène à la position en direct de l\'hôte.', - helpSec7Title: 'Approbations', - helpSec7Body: 'Par défaut, les suggestions des invités nécessitent une approbation manuelle — elles apparaissent dans une bande « Approbations » en haut du panneau avec des boutons accepter / refuser. L\'approbation automatique peut être activée dans les paramètres.', - helpSec8Title: 'Participants et paramètres', - helpSec8Body: 'Ouvre l\'icône des paramètres dans la barre pour la cadence de mélange, l\'approbation automatique et le raccourci « Mélanger maintenant ». Clique sur le nombre de participants pour voir qui est connecté — exclure (peut rejoindre via le lien) ou bannir (exclu pour la session). Les invités voient la liste en lecture seule.', - helpSec9Title: 'Terminer la session', - helpSec9Body: 'X de l\'hôte → dialogue de confirmation → la session se ferme pour tout le monde, les playlists serveur sont nettoyées automatiquement. X de l\'invité → l\'invité part, la session continue. Si l\'hôte reste silencieux 5 minutes, l\'invité part automatiquement avec un avis ; les reconnexions courtes dans ce laps sont invisibles.', - participantsInviteLabel: 'Lien d\'invitation', - participantsCountLabel: '{{count}} en session', - participantsHost: 'hôte', - participantsEmpty: 'Pas encore d\'invités', - participantsKickTooltip: 'Retirer de la session', - participantsKickAria: 'Retirer {{user}}', - participantsRemoveTooltip: 'Retirer de la session', - participantsRemoveAria: 'Retirer {{user}} de cette session', - participantsBanTooltip: 'Bannir définitivement', - participantsBanAria: 'Bannir définitivement {{user}}', - participantsMuteTooltip: 'Bloquer les suggestions', - participantsUnmuteTooltip: 'Autoriser les suggestions', - participantsMuteAria: 'Bloquer les suggestions de {{user}}', - participantsUnmuteAria: 'Autoriser à nouveau les suggestions de {{user}}', - confirmRemoveTitle: 'Retirer de la session ?', - confirmRemoveBody: '{{user}} sera retiré de la session mais peut rejoindre via ton lien d\'invitation.', - confirmRemoveConfirm: 'Retirer', - confirmBanTitle: 'Bannir définitivement ?', - confirmBanBody: '{{user}} sera retiré et empêché de rejoindre cette session. Irréversible pour la durée de la session.', - confirmBanConfirm: 'Bannir', - confirmCancel: 'Annuler', - confirmJoinTitle: 'Rejoindre la session Orbit ?', - confirmJoinBody: '{{host}} t\'a invité à « {{name}} ». Rejoindre la session ?', - confirmJoinConfirm: 'Rejoindre', - confirmLeaveTitle: 'Quitter la session ?', - confirmLeaveBody: 'Quitter « {{name}} » ? Tu peux rejoindre à tout moment via le lien d\'invitation de {{host}}.', - confirmLeaveConfirm: 'Quitter', - confirmEndTitle: 'Terminer la session pour tout le monde ?', - confirmEndBody: '« {{name}} » se fermera pour tous les participants. Les playlists de session sont nettoyées automatiquement.', - confirmEndConfirm: 'Terminer la session', - invalidLinkTitle: 'Le lien d\'invitation n\'est plus valide', - invalidLinkBody: 'Cette session Orbit n\'existe plus ou est déjà terminée. Demande à l\'hôte un nouveau lien.', - settingsTitle: 'Paramètres de session', - settingAutoApprove: 'Approuver automatiquement les suggestions', - settingAutoApproveHint: 'Les suggestions arrivent instantanément dans ta file. Désactivé : elles restent dans la liste de session pour révision.', - settingAutoShuffle: 'Mélange automatique', - settingAutoShuffleHint: 'Mélange Fisher-Yates périodique de la file à venir. Désactivé : l\'ordre ne change que lorsque tu le réorganises.', - settingShuffleInterval: 'Remélanger toutes les', - settingShuffleIntervalHint: 'Fréquence de remélange de la file pendant la session.', - suggestBlockedMuted: 'L\'hôte t\'a coupé le micro pour cette session — suggestions désactivées.', - settingShuffleIntervalValue_one: '{{count}} min', - settingShuffleIntervalValue_other: '{{count}} min', - settingShuffleNow: 'Mélanger maintenant', - toastSuggested: '{{user}} a suggéré « {{title}} »', - toastSuggestedMany: '{{count}} nouvelles suggestions dans la file', - toastShuffled: 'File mélangée', - toastJoined: 'Session rejointe', - toastLoginFirst: 'Connecte-toi avant de rejoindre une session', - toastSwitchServer: 'Bascule d\'abord vers {{url}}, puis colle à nouveau', - toastNoAccountForServer: 'Tu n\'as pas accès à {{url}}. Demande à l\'hôte une invitation.', - toastSwitchFailed: 'Impossible de basculer vers {{url}}', - accountPickerTitle: 'Quel compte ?', - accountPickerSub: 'Tu as plusieurs comptes pour {{url}}. Choisis celui avec lequel rejoindre la session.', - toastJoinFail: 'Impossible de rejoindre la session', - joinErrNotFound: 'Session introuvable', - joinErrEnded: 'La session est terminée', - joinErrFull: 'La session est pleine', - joinErrKicked: 'Tu ne peux pas rejoindre cette session', - joinErrNoUser: 'Aucun serveur actif', - joinErrServerError: 'Impossible de rejoindre', - ctxAddToSession: 'Ajouter à la session Orbit', - ctxSuggestedToast: 'Suggéré à la session', - ctxSuggestFailed: 'Impossible de suggérer — pas rejoint', - ctxAddToSessionHost: 'Ajouter à la session Orbit', - ctxAddedHostToast: 'Ajouté à la session', - ctxAddHostFailed: 'Impossible d\'ajouter à la session', - bulkConfirmTitle: 'Tout ajouter à la file Orbit ?', - bulkConfirmBody: 'Cela ajouterait {{count}} morceaux en une fois. C\'est beaucoup pour tes invités. Continuer ?', - bulkConfirmYes: 'Tout ajouter', - bulkConfirmNo: 'Annuler', - guestLive: 'Direct', - guestPlaying: 'En cours de lecture', - guestPaused: 'En pause', - guestLoading: 'Chargement…', - guestSuggestions: 'Suggestions', - guestUpNext: 'À suivre', - guestUpNextEmpty: 'Rien en file. Ouvre le menu contextuel d\'un morceau et choisis « Ajouter à la session Orbit ».', - guestPendingTitle: 'En attente de l\'hôte', - guestPendingHint: 'Suggéré — apparaîtra dans la file quand l\'hôte l\'acceptera.', - approvalTitle: 'Approbations en attente', - approvalFrom: 'Suggéré par {{user}}', - approvalAccept: 'Accepter', - approvalDecline: 'Refuser', - guestUpNextMore: '+ {{count}} autres dans la file de l\'hôte', - guestSubmitter: 'par {{user}}', - queueAddedByHost: 'Ajouté par l\'hôte', - queueAddedByYou: 'Ajouté par toi', - queueAddedByUser: 'Ajouté par {{user}}', - guestEmpty: 'Aucune suggestion. Ouvre le menu contextuel d\'un morceau et choisis « Ajouter à la session Orbit ».', - guestFooter: 'L\'hôte contrôle la lecture — tu ne peux pas modifier la liste.', - exitKickedTitle: 'Tu as été banni de la session', - exitRemovedTitle: 'Tu as été retiré de la session', - exitEndedTitle: 'L\'hôte a terminé la session', - exitHostTimeoutTitle: 'L\'hôte ne répond plus', - exitHostTimeoutBody: '{{host}} n\'a pas envoyé de mise à jour depuis un moment, donc « {{name}} » a été fermée de ton côté. Tu peux rejoindre à tout moment avec le lien.', - exitKickedBody: '{{host}} t\'a banni de « {{name}} ». Tu ne peux pas rejoindre.', - exitRemovedBody: '{{host}} t\'a retiré de « {{name}} ». Tu peux rejoindre via le lien à tout moment.', - exitEndedBody: '« {{name}} » est terminée. J\'espère que tu t\'es bien amusé.', - exitOk: 'OK', - }, - tray: { - playPause: 'Lecture / Pause', - nextTrack: 'Piste suivante', - previousTrack: 'Piste précédente', - showHide: 'Afficher / Masquer', - exitPsysonic: 'Quitter Psysonic', - nothingPlaying: 'Aucune lecture', - }, - licenses: { - title: 'Licences Open Source', - intro: 'Psysonic est construit sur des logiciels open source. La liste ci-dessous montre chaque dépendance livrée avec l\'application, avec sa version, sa licence et le texte de licence complet.', - highlights: 'Dépendances principales', - searchPlaceholder: 'Rechercher par nom, version ou licence…', - noResults: 'Aucun résultat.', - loading: 'Chargement des licences…', - loadError: 'Impossible de charger les données de licence.', - noLicenseText: 'Aucun texte de licence groupé pour cette dépendance.', - viewSource: 'Voir la source', - totalLine: '{{total}} dépendances — {{cargo}} cargo, {{npm}} npm', - generatedAt: 'Dernière génération {{date}}', - }, -}; diff --git a/src/locales/fr/albumDetail.ts b/src/locales/fr/albumDetail.ts new file mode 100644 index 00000000..551c1808 --- /dev/null +++ b/src/locales/fr/albumDetail.ts @@ -0,0 +1,47 @@ +export const albumDetail = { + back: 'Retour', + orbitDoubleClickHint: 'Double-clic pour ajouter ce morceau à la file Orbit', + playAll: 'Tout lire', + shareAlbum: 'Partager l\'album', + enqueue: 'Mettre en file', + enqueueTooltip: 'Ajouter l\'album entier à la file d\'attente', + artistBio: 'Biographie', + download: 'Télécharger (ZIP)', + downloading: 'Chargement…', + cacheOffline: 'Rendre disponible hors ligne', + offlineCached: 'Disponible hors ligne', + offlineDownloading: 'Mise en cache… ({{n}}/{{total}})', + removeOffline: 'Supprimer le cache hors ligne', + offlineStorageFull: 'Stockage hors ligne plein (limite : {{mb}} Mo). Supprimez un album de votre bibliothèque hors ligne ou augmentez la limite dans les paramètres.', + offlineStorageGoToSettings: 'Paramètres', + offlineStorageGoToLibrary: 'Bibliothèque hors ligne', + favoriteAdd: 'Ajouter aux favoris', + favoriteRemove: 'Retirer des favoris', + favorite: 'Favori', + noBio: 'Aucune biographie disponible.', + moreByArtist: 'Plus de {{artist}}', + tracksCount: '{{n}} pistes', + goToArtist: 'Aller à {{artist}}', + moreLabelAlbums: 'Plus d\'albums sur {{label}}', + trackTitle: 'Titre', + trackAlbum: 'Album', + trackArtist: 'Artiste', + trackGenre: 'Genre', + trackFormat: 'Format', + trackFavorite: 'Favori', + trackRating: 'Note', + trackDuration: 'Durée', + trackTotal: 'Total', + columns: 'Colonnes', + resetColumns: 'Réinitialiser', + notFound: 'Album introuvable.', + bioModal: 'Biographie de l\'artiste', + bioClose: 'Fermer', + ratingLabel: 'Note', + enlargeCover: 'Agrandir', + filterSongs: 'Filtrer…', + sortNatural: 'Naturel', + sortByTitle: 'A–Z (Titre)', + sortByArtist: 'A–Z (Artiste)', + sortByAlbum: 'A–Z (Album)', +}; diff --git a/src/locales/fr/albums.ts b/src/locales/fr/albums.ts new file mode 100644 index 00000000..e843ea4b --- /dev/null +++ b/src/locales/fr/albums.ts @@ -0,0 +1,32 @@ +export const albums = { + title: 'Tous les albums', + sortByName: 'A–Z (Album)', + sortByArtist: 'A–Z (Artiste)', + sortNewest: 'Plus récents', + sortRandom: 'Aléatoire', + yearFrom: 'De', + yearTo: 'À', + yearFilterClear: 'Effacer le filtre année', + yearFilterLabel: 'Année', + compilationLabel: 'Compilations', + compilationOnly: 'Uniquement compilations', + compilationHide: 'Masquer compilations', + compilationTooltipAll: 'Tous les albums · clic : uniquement compilations', + compilationTooltipOnly: 'Uniquement compilations · clic : masquer compilations', + compilationTooltipHide: 'Compilations masquées · clic : tout afficher', + select: 'Sélection multiple', + startSelect: 'Activer la sélection multiple', + cancelSelect: 'Annuler', + selectionCount: '{{count}} sélectionnés', + downloadZips: 'Télécharger les ZIPs', + addOffline: 'Ajouter hors ligne', + enqueueSelected_one: 'Mettre en file ({{count}})', + enqueueSelected_other: 'Mettre en file ({{count}})', + enqueueQueued_one: '{{count}} album ajouté à la file', + enqueueQueued_other: '{{count}} albums ajoutés à la file', + downloadingZip: 'Téléchargement {{current}}/{{total}} : {{name}}', + downloadZipDone: '{{count}} ZIP(s) téléchargé(s)', + downloadZipFailed: 'Échec du téléchargement de {{name}}', + offlineQueuing: 'Mise en file d\'attente de {{count}} album(s) hors ligne…', + offlineFailed: 'Échec de l\'ajout de {{name}} hors ligne', +}; diff --git a/src/locales/fr/artistDetail.ts b/src/locales/fr/artistDetail.ts new file mode 100644 index 00000000..96935946 --- /dev/null +++ b/src/locales/fr/artistDetail.ts @@ -0,0 +1,41 @@ +export const artistDetail = { + back: 'Retour', + albums: 'Albums', + album: 'Album', + playAll: 'Tout lire', + shareArtist: 'Partager l\'artiste', + shuffle: 'Aléatoire', + radio: 'Radio', + loading: 'Chargement…', + noRadio: 'Aucun morceau similaire trouvé pour cet artiste.', + notFound: 'Artiste introuvable.', + albumsBy: 'Albums de {{name}}', + topTracks: 'Morceaux populaires', + noAlbums: 'Aucun album trouvé.', + trackTitle: 'Titre', + trackAlbum: 'Album', + trackDuration: 'Durée', + favoriteAdd: 'Ajouter aux favoris', + favoriteRemove: 'Retirer des favoris', + favorite: 'Favori', + albumCount_one: '{{count}} album', + albumCount_other: '{{count}} albums', + openedInBrowser: 'Ouvert dans le navigateur', + featuredOn: 'Également sur', + similarArtists: 'Artistes similaires', + cacheOffline: 'Enregistrer la discographie hors ligne', + offlineCached: 'Discographie en cache', + offlineDownloading: 'En cache… ({{done}}/{{total}} albums)', + uploadImage: "Téléverser l'image de l'artiste", + uploadImageError: "Échec du téléversement de l'image", + releaseTypes: { + album: 'Album', + ep: 'EP', + single: 'Single', + compilation: 'Compilation', + live: 'Live', + soundtrack: 'Bande originale', + remix: 'Remix', + other: 'Autre', + }, +}; diff --git a/src/locales/fr/artists.ts b/src/locales/fr/artists.ts new file mode 100644 index 00000000..847502af --- /dev/null +++ b/src/locales/fr/artists.ts @@ -0,0 +1,18 @@ +export const artists = { + title: 'Artistes', + search: 'Rechercher…', + all: 'Tous', + gridView: 'Vue en grille', + listView: 'Vue en liste', + imagesOn: 'Images d\'artistes activées — peut augmenter la charge réseau et système', + imagesOff: 'Images d\'artistes désactivées — affichage des initiales uniquement', + loadMore: 'Charger plus', + notFound: 'Aucun artiste trouvé.', + albumCount_one: '{{count}} album', + albumCount_other: '{{count}} albums', + selectionCount: '{{count}} sélectionnés', + select: 'Sélection multiple', + startSelect: 'Activer la sélection multiple', + cancelSelect: 'Annuler', + addToPlaylist: 'Ajouter à la playlist', +}; diff --git a/src/locales/fr/changelog.ts b/src/locales/fr/changelog.ts new file mode 100644 index 00000000..4bac12a4 --- /dev/null +++ b/src/locales/fr/changelog.ts @@ -0,0 +1,5 @@ +export const changelog = { + modalTitle: 'Quoi de neuf', + dontShowAgain: 'Ne plus afficher', + close: 'Compris', +}; diff --git a/src/locales/fr/common.ts b/src/locales/fr/common.ts new file mode 100644 index 00000000..6cdd830b --- /dev/null +++ b/src/locales/fr/common.ts @@ -0,0 +1,56 @@ +export const common = { + albums: 'Albums', + album: 'Album', + loading: 'Chargement…', + loadingMore: 'Chargement…', + loadingPlaylists: 'Chargement des listes…', + noAlbums: 'Aucun album trouvé.', + downloading: 'Téléchargement…', + downloadZip: 'Télécharger (ZIP)', + back: 'Retour', + cancel: 'Annuler', + save: 'Enregistrer', + delete: 'Supprimer', + use: 'Utiliser', + add: 'Ajouter', + new: 'Nouveau', + active: 'Actif', + download: 'Télécharger', + chooseDownloadFolder: 'Choisir le dossier de téléchargement', + noFolderSelected: 'Aucun dossier sélectionné', + rememberDownloadFolder: 'Mémoriser ce dossier', + filterGenre: 'Filtre genre', + filterSearchGenres: 'Rechercher des genres…', + filterNoGenres: 'Aucun genre trouvé', + filterClear: 'Effacer', + favorites: 'Favoris', + favoritesTooltipOff: 'Afficher uniquement les favoris', + favoritesTooltipOn: 'Tout afficher', + play: 'Lire', + bulkSelected: '{{count}} sélectionné(s)', + clearSelection: 'Effacer la sélection', + bulkAddToPlaylist: 'Ajouter à la playlist', + bulkRemoveFromPlaylist: 'Retirer de la playlist', + bulkClear: 'Désélectionner', + updaterAvailable: 'Mise à jour disponible', + updaterVersion: 'v{{version}} est disponible', + updaterWebsite: 'Site Web', + updaterModalTitle: 'Nouvelle version disponible', + updaterChangelog: 'Nouveautés', + updaterDownloadBtn: 'Télécharger maintenant', + updaterSkipBtn: 'Ignorer cette version', + updaterRemindBtn: 'Me rappeler plus tard', + updaterDone: 'Téléchargement terminé', + updaterShowFolder: 'Afficher dans le dossier', + updaterInstallHint: 'Fermez Psysonic et lancez le programme d\'installation manuellement.', + updaterAurHint: 'Installer la mise à jour via AUR :', + updaterErrorMsg: 'Échec du téléchargement', + updaterRetryBtn: 'Réessayer', + durationHoursMinutes: '{{hours}} h {{minutes}} min', + durationMinutesOnly: '{{minutes}} min', + updaterOpenGitHub: 'Ouvrir sur GitHub', + filters: 'Filtres', + more: 'plus', + yearRange: 'Plage d\'années', + clearAll: 'Tout effacer', +}; diff --git a/src/locales/fr/composerDetail.ts b/src/locales/fr/composerDetail.ts new file mode 100644 index 00000000..04260f7e --- /dev/null +++ b/src/locales/fr/composerDetail.ts @@ -0,0 +1,11 @@ +export const composerDetail = { + back: 'Retour', + notFound: 'Compositeur introuvable.', + about: 'À propos de ce compositeur', + works: 'Œuvres', + noWorks: 'Aucune œuvre trouvée.', + workCount_one: '{{count}} œuvre', + workCount_other: '{{count}} œuvres', + shareComposer: 'Partager le compositeur', + unknownComposer: 'Compositeur', +}; diff --git a/src/locales/fr/composers.ts b/src/locales/fr/composers.ts new file mode 100644 index 00000000..9fbb5a4f --- /dev/null +++ b/src/locales/fr/composers.ts @@ -0,0 +1,10 @@ +export const composers = { + title: 'Compositeurs', + search: 'Rechercher…', + notFound: 'Aucun compositeur trouvé.', + unsupported: 'La navigation par compositeur nécessite Navidrome 0.55 ou plus récent.', + loadFailed: 'Impossible de charger les compositeurs.', + retry: 'Réessayer', + involvedIn_one: 'Présent sur {{count}} album', + involvedIn_other: 'Présent sur {{count}} albums', +}; diff --git a/src/locales/fr/connection.ts b/src/locales/fr/connection.ts new file mode 100644 index 00000000..1463ddc9 --- /dev/null +++ b/src/locales/fr/connection.ts @@ -0,0 +1,28 @@ +export const connection = { + connected: 'Connecté', + connectedTo: 'Connecté à {{server}}', + disconnected: 'Déconnecté', + disconnectedFrom: 'Impossible d\'atteindre {{server}} — cliquez pour vérifier les paramètres', + checking: 'Connexion…', + extern: 'Externe', + offlineTitle: 'Pas de connexion au serveur', + offlineSubtitle: 'Impossible d\'atteindre {{server}}. Vérifiez votre réseau ou le serveur.', + offlineModeBanner: 'Mode hors ligne — lecture depuis le cache local', + offlineNoCacheBanner: 'Pas de connexion au serveur — {{server}} inaccessible', + offlineLibraryTitle: 'Bibliothèque hors ligne', + offlineLibraryEmpty: 'Aucun album en cache. Connectez-vous, ouvrez un album et cliquez sur "Rendre disponible hors ligne".', + offlineAlbumCount: '{{n}} album', + offlineAlbumCount_plural: '{{n}} albums', + offlineFilterAll: 'Tout', + offlineFilterAlbums: 'Albums', + offlineFilterPlaylists: 'Playlists', + offlineFilterArtists: 'Discographies', + retry: 'Réessayer', + serverSettings: 'Paramètres serveur', + switchServerTitle: 'Changer de serveur', + switchServerHint: 'Cliquez pour choisir un autre serveur enregistré.', + manageServers: 'Gérer les serveurs…', + switchFailed: 'Impossible de changer — serveur injoignable.', + lastfmConnected: 'Last.fm connecté en tant que @{{user}}', + lastfmSessionInvalid: 'Session invalide — cliquez pour vous reconnecter', +}; diff --git a/src/locales/fr/contextMenu.ts b/src/locales/fr/contextMenu.ts new file mode 100644 index 00000000..250e0edf --- /dev/null +++ b/src/locales/fr/contextMenu.ts @@ -0,0 +1,33 @@ +export const contextMenu = { + playNow: 'Lire maintenant', + playNext: 'Lire ensuite', + addToQueue: 'Ajouter à la file', + enqueueAlbum: 'Mettre l\'album en file', + enqueueAlbums_one: 'Mettre {{count}} album en file', + enqueueAlbums_other: 'Mettre {{count}} albums en file', + startRadio: 'Démarrer la radio', + instantMix: 'Mix instantané', + instantMixFailed: 'Impossible de créer le mix instantané — erreur serveur ou plugin.', + cliMixNeedsTrack: 'Aucune lecture en cours — lancez d’abord la lecture, puis relancez la commande de mix.', + lfmLove: 'Aimer sur Last.fm', + lfmUnlove: 'Ne plus aimer sur Last.fm', + favorite: 'Favori', + favoriteArtist: 'Artiste favori', + favoriteAlbum: 'Album favori', + unfavorite: 'Retirer des favoris', + unfavoriteArtist: 'Retirer l\'artiste des favoris', + unfavoriteAlbum: 'Retirer l\'album des favoris', + removeFromQueue: 'Retirer de la file', + removeFromPlaylist: 'Retirer de la playlist', + openAlbum: 'Ouvrir l\'album', + goToArtist: 'Aller à l\'artiste', + download: 'Télécharger (ZIP)', + addToPlaylist: 'Ajouter à la playlist', + selectedPlaylists: '{{count}} playlists sélectionnées', + selectedAlbums: '{{count}} albums sélectionnés', + selectedArtists: '{{count}} artistes sélectionnés', + songInfo: 'Infos du morceau', + shareLink: 'Copier le lien de partage', + shareCopied: 'Lien de partage copié dans le presse-papiers.', + shareCopyFailed: 'Impossible de copier dans le presse-papiers.', +}; diff --git a/src/locales/fr/deviceSync.ts b/src/locales/fr/deviceSync.ts new file mode 100644 index 00000000..4915add0 --- /dev/null +++ b/src/locales/fr/deviceSync.ts @@ -0,0 +1,73 @@ +export const deviceSync = { + title: 'Sync appareil', + targetFolder: 'Dossier cible', + noFolderChosen: 'Aucun dossier sélectionné', + selectDrive: 'Sélectionner un lecteur…', + refreshDrives: 'Actualiser les lecteurs', + noDrivesDetected: 'Aucun lecteur amovible détecté', + browseManual: 'Parcourir manuellement…', + free: 'libre', + notMountedVolume: 'La cible n\u0027est pas sur un volume monté. Le lecteur a peut-être été déconnecté.', + chooseFolder: 'Choisir…', + filenameTemplate: 'Modèle de nom de fichier', + targetDevice: 'Appareil cible', + templateHint: 'Variables : {artist}, {album}, {title}, {track_number}, {disc_number}, {year}', + cleanupButton: 'Supprimer les fichiers absents', + cleanupNothingToDelete: 'Rien à supprimer — l\'appareil est déjà synchronisé.', + confirmCleanup: 'Supprimer {{count}} fichier(s) de l\'appareil qui ne font pas partie de la sélection actuelle. Continuer ?', + cleanupComplete: '{{count}} fichier(s) supprimé(s) de l\'appareil.', + selectedSources: 'Sources sélectionnées', + noSourcesSelected: 'Aucune source sélectionnée. Cliquez sur des éléments dans le navigateur pour les ajouter.', + clearAll: 'Tout effacer', + tabPlaylists: 'Listes de lecture', + tabAlbums: 'Albums', + tabArtists: 'Artistes', + searchPlaceholder: 'Rechercher…', + syncButton: 'Synchroniser vers l\'appareil', + actionTransfer: 'Transférer vers l\'appareil', + actionDelete: 'Supprimer de l\'appareil', + actionApplyAll: 'Appliquer toutes les modifications', + templatePreview: 'Aperçu', + templatePresetStandard: 'Standard', + templatePresetMultiDisc: 'Multi-Disc', + templatePresetAltFolder: 'Dossier alt.', + tokenSlashHint: '/ = séparateur de dossier', + cancel: 'Annuler', + noTargetDir: 'Veuillez d\'abord choisir un dossier cible.', + noSources: 'Veuillez sélectionner au moins une source.', + noTracks: 'Aucune piste trouvée dans les sources sélectionnées.', + fetchError: 'Échec du chargement des pistes depuis le serveur.', + syncComplete: 'Synchronisation terminée.', + dismiss: 'Fermer', + cancelSync: 'Annuler', + syncCancelled: 'Synchronisation annulée ({{done}} / {{total}} transférés).', + colName: 'Nom', + colType: 'Type', + colStatus: 'Statut', + onDevice: 'Gestionnaire d\'appareil', + addSources: 'Ajouter…', + syncResult: '{{done}} transféré(s), {{skipped}} déjà à jour ({{total}} au total)', + deleteFromDevice: 'Marquer pour suppression ({{count}})', + confirmDelete: 'Supprimer {{count}} élément(s) du périphérique : {{names}} ?', + deleteComplete: '{{count}} élément(s) supprimé(s) du périphérique.', + manifestImported: '{{count}} source(s) importée(s) depuis le manifeste du périphérique.', + statusSynced: 'Synchronisé', + statusPending: 'En attente', + statusDeletion: 'Suppression', + markForDeletion: 'Marquer pour suppression', + removeSource: 'Supprimer', + undoDeletion: 'Annuler la suppression', + syncInBackground: 'Sync démarré en arrière-plan — vous pouvez naviguer ailleurs.', + syncInProgress: '{{done}} / {{total}} pistes…', + syncSummary: 'Résumé de la synchronisation', + calculating: 'Calcul de la charge utile…', + filesToAdd: 'Fichiers à ajouter :', + filesToDelete: 'Fichiers à supprimer :', + netChange: 'Variation nette :', + availableSpace: 'Espace disque disponible :', + spaceWarning: 'Attention : L\'appareil cible ne dispose pas d\'assez d\'espace signalé.', + proceed: 'Procéder à la synchronisation', + notEnoughSpace: 'Espace disque physique insuffisant détecté !', + liveSearch: 'Live', + randomAlbumsLabel: 'Albums aléatoires', +}; diff --git a/src/locales/fr/entityRating.ts b/src/locales/fr/entityRating.ts new file mode 100644 index 00000000..1cbfb405 --- /dev/null +++ b/src/locales/fr/entityRating.ts @@ -0,0 +1,9 @@ +export const entityRating = { + albumShort: 'Note de l’album', + artistShort: 'Note de l’artiste', + albumAriaLabel: 'Note de l’album', + artistAriaLabel: 'Note de l’artiste', + selectedArtistsRatingAriaLabel: 'Note sur {{count}} artistes sélectionnés', + selectedAlbumsRatingAriaLabel: 'Note sur {{count}} albums sélectionnés', + saveFailed: 'Impossible d’enregistrer la note.', +}; diff --git a/src/locales/fr/favorites.ts b/src/locales/fr/favorites.ts new file mode 100644 index 00000000..8b1d03a2 --- /dev/null +++ b/src/locales/fr/favorites.ts @@ -0,0 +1,19 @@ +export const favorites = { + title: 'Favoris', + empty: 'Vous n\'avez pas encore de favoris.', + artists: 'Artistes', + albums: 'Albums', + songs: 'Morceaux', + enqueueAll: 'Tout ajouter à la file', + playAll: 'Tout lire', + removeSong: 'Retirer des favoris', + stations: 'Stations de radio', + showingFiltered: 'Affichage de {{filtered}} sur {{total}} ({{artist}})', + showingCount: 'Affichage de {{filtered}} sur {{total}}', + clearArtistFilter: 'Effacer le filtre artiste', + noFilterResults: 'Aucun résultat avec les filtres sélectionnés.', + allArtists: 'Tous les artistes', + topArtists: 'Artistes favoris principaux', + topArtistsSongCount_one: '{{count}} morceau', + topArtistsSongCount_other: '{{count}} morceaux', +}; diff --git a/src/locales/fr/folderBrowser.ts b/src/locales/fr/folderBrowser.ts new file mode 100644 index 00000000..f211277a --- /dev/null +++ b/src/locales/fr/folderBrowser.ts @@ -0,0 +1,4 @@ +export const folderBrowser = { + empty: 'Dossier vide', + error: 'Échec du chargement', +}; diff --git a/src/locales/fr/genres.ts b/src/locales/fr/genres.ts new file mode 100644 index 00000000..b5e37d9a --- /dev/null +++ b/src/locales/fr/genres.ts @@ -0,0 +1,12 @@ +export const genres = { + title: 'Genres', + genreCount: 'genres', + albumCount_one: '{{count}} album', + albumCount_other: '{{count}} albums', + loading: 'Chargement des genres…', + empty: 'Aucun genre trouvé.', + albumsLoading: 'Chargement des albums…', + albumsEmpty: 'Aucun album trouvé pour ce genre.', + loadMore: 'Charger plus', + back: 'Retour', +}; diff --git a/src/locales/fr/help.ts b/src/locales/fr/help.ts new file mode 100644 index 00000000..8962b8ec --- /dev/null +++ b/src/locales/fr/help.ts @@ -0,0 +1,105 @@ +export const help = { + title: 'Aide', + searchPlaceholder: 'Rechercher dans l\'aide…', + noResults: 'Aucun sujet correspondant. Essayez un autre terme.', + s1: 'Démarrage', + q1: 'Quels serveurs sont compatibles ?', + a1: 'Psysonic est conçu en priorité pour Navidrome et est entièrement compatible Subsonic — Gonic, Airsonic, LMS et autres serveurs Subsonic-API fonctionnent aussi. Certaines fonctionnalités avancées (notes, listes intelligentes, partage Magic String, gestion des utilisateurs) nécessitent Navidrome.', + q2: 'Comment ajouter un serveur ?', + a2: 'Paramètres → Serveurs → Ajouter un serveur. Saisissez l\'URL (ex. http://192.168.1.100:4533), le nom d\'utilisateur et le mot de passe. Psysonic teste la connexion avant d\'enregistrer — rien n\'est sauvegardé en cas d\'échec. Vous pouvez ajouter autant de serveurs que vous voulez et basculer entre eux dans l\'en-tête ; un seul est actif à la fois.', + q3: 'Visite rapide de l\'interface ?', + a3: 'Barre latérale (gauche) pour la navigation, Mainstage / pages au centre, barre du lecteur en bas, panneau File d\'attente à droite (icône en haut à droite, à côté de l\'indicateur Now Playing). La barre de recherche en haut couvre toute la bibliothèque ; « Now Playing » montre ce que les autres utilisateurs du même serveur Navidrome écoutent.', + s2: 'Lecture & File d\'attente', + q4: 'Comment utiliser la file d\'attente ?', + a4: 'Ouvrez le panneau File d\'attente depuis l\'en-tête en haut à droite. Glissez les lignes pour réordonner, faites-les glisser à l\'extérieur pour les supprimer, ou utilisez la barre d\'outils pour mélanger, enregistrer la file en liste de lecture ou sauter à une piste. Faites glisser une ligne hors du panneau pour la déposer ailleurs comme transfert.', + q5: 'Gapless vs Crossfade — quelle différence ?', + a5: 'Gapless pré-bufferise la piste suivante pour éliminer tout silence (idéal pour les albums live et les mixes DJ). Crossfade fait un fondu entre la piste actuelle et la suivante sur 1 à 10 s (idéal pour les mixes aléatoires). Les deux sont mutuellement exclusifs — activer l\'un désactive l\'autre. Configuration dans Paramètres → Audio.', + q6: 'Qu\'est-ce que la File infinie ?', + a6: 'Quand la file se termine et que la répétition est désactivée, Psysonic ajoute discrètement des pistes similaires/aléatoires de votre bibliothèque pour que la lecture ne s\'arrête jamais. Les pistes auto-ajoutées apparaissent sous le séparateur « — Ajouté automatiquement —». Activable/désactivable via l\'icône infini dans l\'en-tête de la file ; restreignable à un genre dans Paramètres → File d\'attente.', + q7: 'Sélection multiple et plage Maj-clic ?', + a7: 'Activez « Sélectionner » sur Albums / Nouveautés / Albums aléatoires / Listes de lecture. Cliquez un élément pour le basculer, puis maintenez Maj et cliquez un autre élément — tout ce qui se trouve entre les deux dans l\'ordre visible est sélectionné. Les Maj-clics étendent depuis l\'ancre la plus récemment cliquée. La barre d\'outils en haut propose des actions groupées (file, téléchargement, suppression, etc.).', + q8: 'Raccourcis clavier et hotkeys globaux ?', + a8: 'Touches par défaut : Espace = Lecture / Pause, Échap = fermer le mode plein écran / les modales, F1 = aide-mémoire des raccourcis. Paramètres → Entrée permet de réassigner chaque action interne (y compris des accords comme Ctrl+Maj+P) et de définir des raccourcis globaux qui fonctionnent même en arrière-plan. Les touches multimédia (Lecture/Pause, Suivant, Précédent) fonctionnent partout.', + s3: 'Outils audio', + q9: 'Modes Replay Gain ?', + a9: 'Paramètres → Audio → Replay Gain. Le mode Piste normalise chaque morceau au niveau cible. Le mode Album préserve la dynamique relative au sein d\'un album. Le mode Auto choisit Piste ou Album selon que la file vient d\'un album unique. Les pistes sans tags Replay Gain retombent sur un préampli configurable.', + q10: 'Qu\'est-ce que la normalisation intelligente (LUFS) ?', + a10: 'Une alternative moderne au Replay Gain dans Paramètres → Audio. Psysonic analyse chaque piste en LUFS / EBU R128 et stocke le résultat, pour un volume cohérent dans toute la bibliothèque — y compris les pistes sans tags Replay Gain. L\'analyse à froid tourne en arrière-plan et utilise 35–40 % du CPU pendant ~1 minute, puis 0. Définissez votre cible (par défaut −10 LUFS) une fois.', + q11: 'EQ et AutoEQ ?', + a11: 'Un égaliseur paramétrique 10 bandes dans Paramètres → Audio → Égaliseur, avec bandes manuelles et préréglages. AutoEQ à côté récupère un profil de correction mesuré pour votre modèle de casque depuis la base AutoEQ et l\'applique automatiquement aux bandes — choisissez votre casque, l\'égaliseur s\'aligne sur la bonne courbe.', + q12: 'Comment changer le périphérique de sortie audio ?', + a12: 'Paramètres → Audio → Périphérique de sortie. Psysonic liste toutes les sorties disponibles et bascule instantanément lors du choix. Le bouton Actualiser détecte les périphériques branchés après le démarrage. Sur Linux, les noms ALSA comme « sysdefault » sont auto-nettoyés pour la lisibilité.', + q13: 'Qu\'est-ce que le Hot Cache ?', + a13: 'Le Hot Cache précharge la piste actuelle plus les suivantes en RAM et sur disque pour que la lecture démarre sans buffering — particulièrement utile sur les serveurs lents/distants. L\'éviction se déclenche quand la limite de taille est atteinte. Configurez la taille et le délai de debounce (pour éviter les pré-fetchs à chaque saut rapide) dans Paramètres → Audio.', + s4: 'Bibliothèque & Découverte', + q14: 'Notes et Skip-to-1★ ?', + a14: 'Psysonic prend en charge les notes 1 à 5 étoiles via OpenSubsonic (Navidrome ≥ 0.53). Notez les pistes dans les listes, dans le menu contextuel ou dans la barre du lecteur sous le nom de l\'artiste ; les albums sur leur page ; les artistes sur la page artiste. Skip-to-1★ (Paramètres → Bibliothèque → Notes) attribue automatiquement 1 étoile après un nombre configurable de sauts consécutifs. Le même panneau permet de définir une note minimale pour les Mixes générés.', + q15: 'Comment naviguer — Dossiers, Genres, Pistes ?', + a15: 'Le navigateur de dossiers (barre latérale) parcourt l\'arborescence du serveur en colonnes Miller — clic sur un dossier pour entrer, clic sur une piste ou l\'icône lecture d\'un dossier pour jouer/ajouter. Genres utilise un nuage de tags dimensionné par le nombre de pistes ; clic sur un genre pour l\'ouvrir. Pistes est un hub plat avec liste virtuelle triable par colonnes et recherche en direct.', + q16: 'Recherche et recherche avancée ?', + a16: 'La barre de recherche d\'en-tête lance une recherche live en tapant à travers artistes, albums et pistes. Ouvrez la recherche avancée (barre latérale) pour une vue plus riche : filtres par année, genre, note, format, canaux, taux d\'échantillonnage, BPM, ambiance — combinables. Clic droit sur un résultat ouvre le même menu contextuel qu\'ailleurs.', + q17: 'Les Mixes (Aléatoire / Genre / Super Genre / Lucky) ?', + a17: 'Le Mix aléatoire crée une liste de pistes aléatoires de votre bibliothèque ; le filtre par mots-clés exclut audiobooks, comédie, etc. par sous-chaînes de genre/titre/album. Super Genre Mix regroupe votre bibliothèque par grands styles (Rock, Metal, Électronique, Jazz, Classique…) et bâtit un mix focalisé. Lucky Mix utilise votre historique d\'écoute, les notes et les pistes similaires AudioMuse-AI pour assembler une liste instantanée d\'un clic.', + q18: 'Page Statistiques ?', + a18: 'Statistiques (barre latérale) montre les top artistes, top albums, top pistes, répartition par genre, temps d\'écoute dans le temps, et un périmètre par bibliothèque si vous avez plusieurs dossiers configurés. Plusieurs vues sont exportables en image partageable.', + q19: 'Comment télécharger un album en ZIP ?', + a19: 'Page album → « Télécharger (ZIP) ». Le serveur compresse l\'album d\'abord — pour les albums volumineux ou sans perte (FLAC / WAV) la barre de progression n\'apparaît qu\'une fois le zip terminé et le transfert démarré. C\'est normal.', + s5: 'Paroles', + q20: 'D\'où viennent les paroles ?', + a20: 'Trois sources configurables dans Paramètres → Paroles : votre serveur Navidrome (paroles intégrées / OpenSubsonic), LRCLIB (paroles synchronisées communautaires) et NetEase Cloud Music (vaste catalogue asiatique + international). Chaque source est activable/désactivable et priorisable par glisser-déposer.', + q21: 'Comment voir les paroles pendant la lecture ?', + a21: 'Cliquez sur l\'icône micro de la barre du lecteur pour ouvrir l\'onglet Paroles dans le panneau de file. Les paroles synchronisées défilent automatiquement et supportent le clic-pour-aller-à ; les paroles en texte brut défilent en bloc statique. Activez le lecteur plein écran via la pochette pour une vue immersive avec fond mesh.', + s6: 'Partage & Social', + q22: 'Que sont les Magic Strings ?', + a22: 'Les Magic Strings sont de courts jetons à copier-coller qui partagent des choses entre utilisateurs Psysonic sans serveur tiers. Les chaînes d\'invitation de serveur permettent à un ami de s\'enregistrer sur votre Navidrome en un collage ; les Magic Strings d\'album / artiste / file ouvrent le même album / artiste / file chez le destinataire. Générez-les depuis le menu Partager, collez-les dans la barre de recherche pour les consommer.', + q23: 'Qu\'est-ce qu\'Orbit ?', + a23: 'Orbit, c\'est l\'écoute synchronisée à plusieurs : un hôte joue une piste, tous les invités l\'entendent en sync, et les invités peuvent suggérer des morceaux que l\'hôte peut accepter dans la file. Démarrez une session depuis le bouton Orbit dans l\'en-tête, partagez le lien d\'invitation, les autres rejoignent depuis n\'importe quelle installation Psysonic. L\'hôte contrôle la lecture (saut, recherche, file) — les invités ont une vue temps réel et une boîte à suggestions. Les sessions sont éphémères et se terminent à la fermeture par l\'hôte.', + q24: 'Qu\'est-ce que la liste déroulante Now Playing ?', + a24: 'L\'icône de diffusion en haut à droite affiche ce que les autres utilisateurs du serveur Navidrome écoutent en ce moment, rafraîchi toutes les 10 secondes. Votre propre entrée disparaît dès la pause. Par serveur — les utilisateurs sur un autre serveur actif n\'apparaissent pas.', + s7: 'Personnalisation', + q25: 'Thèmes et planificateur de thème ?', + a25: 'Paramètres → Apparence → Thème offre 60+ thèmes en 8 groupes (Psysonic, Lecteurs multimédias, Systèmes d\'exploitation, Jeux, Films, Séries, Réseaux sociaux, Open Source Classics — Catppuccin / Nord / Gruvbox / Nightfox / Dracula). Auto-Switch Theme permet de définir un thème de jour et un thème de nuit avec heures de bascule pour un changement automatique.', + q26: 'Puis-je personnaliser barre latérale, accueil et page artiste ?', + a26: 'Oui — Paramètres → Personnalisation. Le customiseur de barre latérale permet de réordonner les éléments par glisser et de masquer ceux que vous n\'utilisez pas. Le customiseur d\'accueil bascule chaque rangée Mainstage (Hero, Récent, Découvrir, Récemment écoutés, Favoris…). Le customiseur de page artiste réordonne les sections (Top morceaux, Albums, Singles, Compilations, Artistes similaires, etc.) et masque celles que vous ignorez.', + q27: 'Qu\'est-ce que le Mini Player ?', + a27: 'Une petite fenêtre flottante avec pochette, contrôles de transport et file compacte. Ouvrez-la depuis l\'icône mini-player de la barre du lecteur ou avec son raccourci. La fenêtre mémorise sa position et sa taille entre les sessions. Sous Windows, la mini-webview est précréée au démarrage pour une ouverture instantanée ; Linux / macOS doivent activer l\'option dans Paramètres → Apparence → Précharger le mini-player.', + q28: 'Qu\'est-ce que la barre de lecture flottante ?', + a28: 'Un style optionnel de barre du lecteur (Paramètres → Apparence) qui se détache du bord inférieur avec fond thématique, bordure d\'accentuation, pochette arrondie et section volume centrée. Utile sur les écrans hauts ou avec des thèmes compacts.', + q29: 'Aperçu de piste au survol ?', + a29: 'Survolez une ligne de piste, cliquez sur le petit bouton Aperçu sur la pochette, ou déclenchez l\'aperçu depuis le menu contextuel — Psysonic diffuse les ~15 premières secondes via le même moteur audio Rust afin que la normalisation de loudness s\'applique. Pratique pour parcourir un album inconnu.', + q30: 'Minuteur de mise en veille ?', + a30: 'Cliquez sur l\'icône lune de la barre du lecteur pour ouvrir le minuteur. Choisissez une durée (ou « fin de la piste actuelle ») et Psysonic fait un fondu et met en pause à la fin. Le bouton affiche un anneau circulaire et un compte à rebours pendant que le minuteur tourne.', + q31: 'Échelle UI, police, style de seekbar ?', + a31: 'Paramètres → Apparence — Échelle de l\'interface (80–125 % sans toucher à la taille système), Police (10 polices UI dont IBM Plex Mono, Fira Code, Geist, Golos Text…), Style de seekbar (Forme d\'onde analysée / pseudowave déterministe / Ligne & Point / Barre / Barre épaisse / Segmenté / Néon / Onde pulsée / Traînée de particules / Remplissage liquide / Bande rétro).', + s8: 'Utilisateur avancé', + q32: 'Contrôles du lecteur en ligne de commande ?', + a32: 'Le binaire Psysonic sert aussi de télécommande. Exemples : psysonic --player play / pause / next / prev, --player volume 75, --player seek 15, --player shuffle, --player repeat off|all|one, --player rating 1-5. Changer de serveur, périphérique audio, bibliothèque ; déclencher un Instant Mix ; rechercher artistes / albums / pistes. Liste complète : psysonic --player --help. Complétions shell pour bash et zsh via psysonic completions.', + q33: 'Listes intelligentes (Navidrome) ?', + a33: 'Les listes intelligentes sont des listes dynamiques côté Navidrome définies par des règles (genre = Rock ET année > 2020, etc.). La page Listes de lecture de Psysonic permet de les créer, modifier et supprimer avec un éditeur de règles visuel — Psysonic utilise l\'API native de Navidrome. Elles se comportent comme des listes normales dans le reste de l\'app et se mettent à jour automatiquement.', + q34: 'Sauvegarder et restaurer les paramètres ?', + a34: 'Paramètres → Stockage → Sauvegarder & Restaurer exporte les profils de serveur, thèmes, raccourcis et autres réglages dans un seul fichier JSON. Importez-le sur une autre machine ou après une réinstallation pour tout restaurer d\'un coup. Les mots de passe des serveurs sont inclus — gardez le fichier privé.', + q35: 'Où voir toutes les licences open source ?', + a35: 'Paramètres → Système → Licences open source. La liste complète des dépendances (crates Cargo et paquets npm) est livrée avec les textes de licence inclus. Cliquez sur une entrée pour voir le texte complet ; le bloc en surbrillance en haut met en avant les bibliothèques connues (Tauri, React, rodio, symphonia, etc.).', + s9: 'Hors ligne & Sync', + q36: 'Mode hors ligne — mettre en cache albums et listes ?', + a36: 'Ouvrez un album ou une liste et cliquez sur l\'icône de téléchargement dans l\'en-tête — Psysonic met chaque piste en cache localement pour une lecture sans appel réseau. La page Bibliothèque hors ligne (barre latérale) liste tout ce qui est en cache, montre les téléchargements en cours, et permet de supprimer via l\'icône poubelle (qui apparaît une fois le téléchargement terminé).', + q37: 'Limite de stockage hors ligne ?', + a37: 'Paramètres → Bibliothèque → Hors ligne permet de définir une taille maximale de cache. Quand la limite est atteinte, le bouton de téléchargement de la page album affiche un avertissement. Libérez de l\'espace en supprimant des albums ou listes depuis la page Bibliothèque hors ligne.', + q38: 'Device Sync — copier la musique sur USB / SD ?', + a38: 'Device Sync (barre latérale) copie albums, listes ou artistes entiers vers un disque externe pour l\'écoute hors ligne sur d\'autres appareils. Choisissez un dossier cible, sélectionnez les sources dans les onglets de navigation, cliquez « Transférer vers le périphérique ». Psysonic écrit un manifeste (psysonic-sync.json) pour savoir quels fichiers sont déjà là, même si vous rouvrez Device Sync sur un autre OS avec un autre modèle de nom. Les modèles supportent les jetons {artist} / {album} / {title} / {track_number} / {disc_number} / {year} avec / comme séparateur de dossier.', + s10: 'Intégrations & Dépannage', + q39: 'Scrobbling Last.fm ?', + a39: 'Paramètres → Intégrations → Last.fm. Connectez votre compte une fois et Psysonic scrobble directement vers Last.fm — pas besoin de configurer Navidrome. Un scrobble est envoyé après 50 % d\'écoute. Les pings « now playing » partent au début.', + q40: 'Discord Rich Presence ?', + a40: 'Paramètres → Intégrations → Discord affiche la piste en cours sur votre profil Discord. Choisissez entre l\'icône de l\'app, la pochette de votre serveur (via getAlbumInfo2 — serveur publiquement joignable nécessaire) ou les pochettes Apple Music. Personnalisez les chaînes affichées (détails, état, info-bulle) avec des templates de jetons.', + q41: 'Dates de tournée Bandsintown ?', + a41: 'Activation dans Paramètres → Intégrations → Now Playing Info. L\'onglet Now Playing sur la page éponyme affiche alors les dates de tournée à venir pour l\'artiste en cours via l\'API widget Bandsintown. Désactivé par défaut — aucune requête tant que vous n\'activez pas.', + q42: 'Internet Radio — lecture de flux en direct ?', + a42: 'Internet Radio (barre latérale) lit n\'importe quel flux en direct stocké sur votre serveur Navidrome (ajoutez les stations via l\'admin Navidrome). La lecture passe par le moteur HTML5 du navigateur — la plupart des réglages EQ / Replay Gain / Loudness ne s\'appliquent pas à la radio, mais les métadonnées ICY (titre courant) s\'affichent. Supporte MP3, AAC, OGG Vorbis et la plupart des flux HLS ; le support codec dépend de la plateforme.', + q43: 'Le test de connexion échoue — que faire ?', + a43: 'Vérifiez l\'URL avec le port (ex. http://192.168.1.100:4533). Sur le réseau local, http:// fonctionne souvent là où https:// ne marche pas (pas de certificat). Assurez-vous qu\'aucun pare-feu ne bloque le port et que nom d\'utilisateur et mot de passe sont corrects. Avec un reverse-proxy, essayez d\'abord l\'URL directe pour isoler la cause.', + q44: 'Les pochettes et images d\'artiste se chargent lentement.', + a44: 'Les images sont récupérées du serveur à la première vue puis mises en cache localement pour 30 jours. Si le stockage du serveur est lent, la première visite d\'une page peut prendre un instant ; les visites suivantes sont instantanées. Le Hot Cache aide aussi pour les pistes mais le cache d\'images est indépendant.', + q45: 'Problèmes Linux — écran noir ou pas de son ?', + a45: 'L\'écran noir est généralement un souci de pilote GPU / EGL dans WebKitGTK — lancez avec GDK_BACKEND=x11 WEBKIT_DISABLE_COMPOSITING_MODE=1 WEBKIT_DISABLE_DMABUF_RENDERER=1 (les installeurs AUR / .deb / .rpm le font automatiquement). Pour le son, vérifiez que PipeWire ou PulseAudio tourne. Les coupures audio après mise en veille sont désormais gérées automatiquement par le hook de récupération post-sleep.', +}; diff --git a/src/locales/fr/hero.ts b/src/locales/fr/hero.ts new file mode 100644 index 00000000..ab9ca027 --- /dev/null +++ b/src/locales/fr/hero.ts @@ -0,0 +1,6 @@ +export const hero = { + eyebrow: 'Album en vedette', + playAlbum: 'Lire l\'album', + enqueue: 'Mettre en file', + enqueueTooltip: 'Ajouter l\'album entier à la file d\'attente', +}; diff --git a/src/locales/fr/home.ts b/src/locales/fr/home.ts new file mode 100644 index 00000000..dbf09eca --- /dev/null +++ b/src/locales/fr/home.ts @@ -0,0 +1,19 @@ +export const home = { + hero: 'En vedette', + starred: 'Favoris personnels', + recent: 'Ajoutés récemment', + mostPlayed: 'Les plus écoutés', + recentlyPlayed: 'Récemment écoutés', + losslessAlbums: 'Albums lossless', + discover: 'Découvrir', + discoverSongs: 'Découvrir des titres', + loadMore: 'Charger plus', + discoverMore: 'Découvrir plus', + discoverArtists: 'Découvrir des artistes', + discoverArtistsMore: 'Tous les artistes', + becauseYouLike: 'Parce que tu as écouté…', + becauseYouLikeFor: 'Parce que tu as écouté {{artist}}', + similarTo: 'Similaire à {{artist}}', + becauseYouLikeTracks_one: '{{count}} titre', + becauseYouLikeTracks_other: '{{count}} titres' +}; diff --git a/src/locales/fr/index.ts b/src/locales/fr/index.ts new file mode 100644 index 00000000..d56e50ba --- /dev/null +++ b/src/locales/fr/index.ts @@ -0,0 +1,91 @@ +import { sidebar } from './sidebar'; +import { home } from './home'; +import { hero } from './hero'; +import { search } from './search'; +import { nowPlaying } from './nowPlaying'; +import { contextMenu } from './contextMenu'; +import { sharePaste } from './sharePaste'; +import { albumDetail } from './albumDetail'; +import { entityRating } from './entityRating'; +import { artistDetail } from './artistDetail'; +import { favorites } from './favorites'; +import { randomLanding } from './randomLanding'; +import { randomAlbums } from './randomAlbums'; +import { genres } from './genres'; +import { randomMix } from './randomMix'; +import { luckyMix } from './luckyMix'; +import { albums } from './albums'; +import { tracks } from './tracks'; +import { artists } from './artists'; +import { composers } from './composers'; +import { composerDetail } from './composerDetail'; +import { login } from './login'; +import { connection } from './connection'; +import { common } from './common'; +import { settings } from './settings'; +import { changelog } from './changelog'; +import { whatsNew } from './whatsNew'; +import { help } from './help'; +import { queue } from './queue'; +import { miniPlayer } from './miniPlayer'; +import { statistics } from './statistics'; +import { player } from './player'; +import { nowPlayingInfo } from './nowPlayingInfo'; +import { songInfo } from './songInfo'; +import { playlists } from './playlists'; +import { smartPlaylists } from './smartPlaylists'; +import { mostPlayed } from './mostPlayed'; +import { losslessAlbums } from './losslessAlbums'; +import { radio } from './radio'; +import { folderBrowser } from './folderBrowser'; +import { deviceSync } from './deviceSync'; +import { orbit } from './orbit'; +import { tray } from './tray'; +import { licenses } from './licenses'; + +export const frTranslation = { + sidebar, + home, + hero, + search, + nowPlaying, + contextMenu, + sharePaste, + albumDetail, + entityRating, + artistDetail, + favorites, + randomLanding, + randomAlbums, + genres, + randomMix, + luckyMix, + albums, + tracks, + artists, + composers, + composerDetail, + login, + connection, + common, + settings, + changelog, + whatsNew, + help, + queue, + miniPlayer, + statistics, + player, + nowPlayingInfo, + songInfo, + playlists, + smartPlaylists, + mostPlayed, + losslessAlbums, + radio, + folderBrowser, + deviceSync, + orbit, + tray, + licenses, +}; diff --git a/src/locales/fr/licenses.ts b/src/locales/fr/licenses.ts new file mode 100644 index 00000000..08599a84 --- /dev/null +++ b/src/locales/fr/licenses.ts @@ -0,0 +1,13 @@ +export const licenses = { + title: 'Licences Open Source', + intro: 'Psysonic est construit sur des logiciels open source. La liste ci-dessous montre chaque dépendance livrée avec l\'application, avec sa version, sa licence et le texte de licence complet.', + highlights: 'Dépendances principales', + searchPlaceholder: 'Rechercher par nom, version ou licence…', + noResults: 'Aucun résultat.', + loading: 'Chargement des licences…', + loadError: 'Impossible de charger les données de licence.', + noLicenseText: 'Aucun texte de licence groupé pour cette dépendance.', + viewSource: 'Voir la source', + totalLine: '{{total}} dépendances — {{cargo}} cargo, {{npm}} npm', + generatedAt: 'Dernière génération {{date}}', +}; diff --git a/src/locales/fr/login.ts b/src/locales/fr/login.ts new file mode 100644 index 00000000..05815b24 --- /dev/null +++ b/src/locales/fr/login.ts @@ -0,0 +1,22 @@ +export const login = { + subtitle: 'Votre lecteur de bureau Navidrome', + serverName: 'Nom du serveur (facultatif)', + serverNamePlaceholder: 'Mon Navidrome', + serverUrl: 'URL du serveur', + serverUrlPlaceholder: '192.168.1.100:4533 ou https://music.exemple.com', + username: 'Nom d\'utilisateur', + usernamePlaceholder: 'admin', + password: 'Mot de passe', + showPassword: 'Afficher le mot de passe', + hidePassword: 'Masquer le mot de passe', + connect: 'Se connecter', + connecting: 'Connexion…', + connected: 'Connecté !', + error: 'Connexion échouée — vérifiez vos informations.', + urlRequired: 'Veuillez saisir une URL de serveur.', + savedServers: 'Serveurs enregistrés', + addNew: 'Ou ajouter un nouveau serveur', + orMagicString: 'Ou chaîne magique', + magicStringPlaceholder: 'Collez une chaîne de partage (psysonic1-…)', + magicStringInvalid: 'Chaîne magique invalide ou illisible.', +}; diff --git a/src/locales/fr/losslessAlbums.ts b/src/locales/fr/losslessAlbums.ts new file mode 100644 index 00000000..d7a58a4c --- /dev/null +++ b/src/locales/fr/losslessAlbums.ts @@ -0,0 +1,5 @@ +export const losslessAlbums = { + empty: 'Aucun album lossless dans cette bibliothèque pour l\'instant.', + unsupported: 'Ce serveur n\'expose pas les métadonnées nécessaires pour trouver des albums lossless.', + slowFetchHint: 'Chargement plus lent que les autres pages d\'albums — Psysonic parcourt tout le catalogue par qualité.', +}; diff --git a/src/locales/fr/luckyMix.ts b/src/locales/fr/luckyMix.ts new file mode 100644 index 00000000..fbf3feb4 --- /dev/null +++ b/src/locales/fr/luckyMix.ts @@ -0,0 +1,6 @@ +export const luckyMix = { + done: 'Mix Chance prêt : {{count}} titres', + failed: 'Impossible de créer le Mix Chance. Réessayez.', + unavailable: 'Mix Chance n\'est pas disponible pour ce serveur.', + cancelTooltip: 'Annuler la création du Mix Chance', +}; diff --git a/src/locales/fr/miniPlayer.ts b/src/locales/fr/miniPlayer.ts new file mode 100644 index 00000000..e45aeb66 --- /dev/null +++ b/src/locales/fr/miniPlayer.ts @@ -0,0 +1,9 @@ +export const miniPlayer = { + showQueue: 'Afficher la file', + hideQueue: 'Masquer la file', + pinOnTop: 'Toujours visible', + pinOff: 'Désépingler', + openMainWindow: 'Ouvrir la fenêtre principale', + close: 'Fermer', + emptyQueue: 'La file est vide', +}; diff --git a/src/locales/fr/mostPlayed.ts b/src/locales/fr/mostPlayed.ts new file mode 100644 index 00000000..96f6ce97 --- /dev/null +++ b/src/locales/fr/mostPlayed.ts @@ -0,0 +1,13 @@ +export const mostPlayed = { + title: 'Les plus joués', + topArtists: 'Artistes populaires', + topAlbums: 'Albums populaires', + plays: '{{n}} écoutes', + sortMost: 'Plus joués en premier', + sortLeast: 'Moins joués en premier', + loadMore: 'Charger plus d\'albums', + noData: 'Aucune donnée d\'écoute. Commencez à écouter !', + noArtists: 'Tous les artistes filtrés.', + filterCompilations: 'Masquer les artistes de compilations (Various Artists, Soundtracks, etc.)', + filterCompilationsShort: 'Masquer les compilations', +}; diff --git a/src/locales/fr/nowPlaying.ts b/src/locales/fr/nowPlaying.ts new file mode 100644 index 00000000..b1a54dc6 --- /dev/null +++ b/src/locales/fr/nowPlaying.ts @@ -0,0 +1,47 @@ +export const nowPlaying = { + tooltip: 'Qui écoute ?', + title: 'Qui écoute ?', + loading: 'Chargement…', + nobody: 'Personne n\'écoute en ce moment.', + minutesAgo: 'il y a {{n}} min', + nothingPlaying: 'Rien en cours. Lancez un morceau !', + aboutArtist: "À propos de l'artiste", + fromAlbum: 'De cet album', + viewAlbum: "Voir l'album", + goToArtist: "Aller à l'artiste", + readMore: 'Lire la suite', + showLess: 'Réduire', + genreInfo: 'Genre', + trackInfo: 'Infos piste', + topSongs: 'Le plus joué de cet artiste', + topSongsCredit: 'Top titres de {{name}}', + trackPosition: 'Piste {{pos}}', + playsCount_one: '{{count}} écoute', + playsCount_other: '{{count}} écoutes', + releasedYearsAgo_one: 'il y a {{count}} an', + releasedYearsAgo_other: 'il y a {{count}} ans', + discography: 'Discographie', + lastfmStats: 'Statistiques Last.fm', + thisTrack: 'Ce titre', + thisArtist: 'Cet artiste', + listeners: 'auditeurs', + scrobbles: 'scrobbles', + yourScrobbles: 'par vous', + listenersN: '{{n}} auditeurs', + scrobblesN: '{{n}} scrobbles', + playsByYouN: 'écouté {{n}}× par vous', + openTrackOnLastfm: 'Titre sur Last.fm', + openArtistOnLastfm: 'Artiste sur Last.fm', + rgTrackTooltip: 'ReplayGain (piste)', + rgAlbumTooltip: 'ReplayGain (album)', + rgAutoTooltip: 'ReplayGain (auto)', + showMoreTracks: 'Afficher {{count}} de plus', + showLessTracks: 'Réduire', + hideCard: 'Masquer la carte', + layoutMenu: 'Disposition', + visibleCards: 'Cartes visibles', + hiddenCards: 'Cartes masquées', + noHiddenCards: 'Aucune carte masquée', + resetLayout: 'Réinitialiser la disposition', + emptyColumn: 'Déposez des cartes ici', +}; diff --git a/src/locales/fr/nowPlayingInfo.ts b/src/locales/fr/nowPlayingInfo.ts new file mode 100644 index 00000000..f6633db2 --- /dev/null +++ b/src/locales/fr/nowPlayingInfo.ts @@ -0,0 +1,24 @@ +export const nowPlayingInfo = { + tab: 'Info', + empty: 'Lancez une lecture pour voir les infos', + artist: 'Artiste', + songInfo: 'Infos du morceau', + onTour: 'En tournée', + noTourEvents: 'Aucun concert à venir', + tourLoading: 'Chargement…', + poweredByBandsintown: 'Données de tournée via Bandsintown', + bioReadMore: 'En lire plus', + bioReadLess: 'Réduire', + showMoreTours_one: 'Afficher {{count}} de plus', + showMoreTours_other: 'Afficher {{count}} de plus', + showLessTours: 'Réduire', + enableBandsintownPrompt: 'Afficher les prochaines dates de tournée ?', + enableBandsintownPromptDesc: 'Optionnel. Charge les concerts de l\'artiste via l\'API publique Bandsintown.', + enableBandsintownPrivacy: 'Lors de l\'activation, le nom de l\'artiste en cours de lecture est envoyé à l\'API Bandsintown pour récupérer les dates de tournée. Aucun compte ni données personnelles ne quittent votre appareil.', + enableBandsintownAction: 'Activer', + role: { + artist: 'Artiste', + albumArtist: 'Artiste de l\'album', + composer: 'Compositeur', + }, +}; diff --git a/src/locales/fr/orbit.ts b/src/locales/fr/orbit.ts new file mode 100644 index 00000000..7caa47f7 --- /dev/null +++ b/src/locales/fr/orbit.ts @@ -0,0 +1,200 @@ +export const orbit = { + triggerLabel: 'Orbit', + triggerTooltip: 'Démarrer ou rejoindre une session d\'écoute partagée', + launchCreate: 'Créer une session', + launchJoin: 'Rejoindre une session', + launchHelp: 'Comment ça marche ?', + launchHelpSoon: 'Bientôt disponible', + joinModalTitle: 'Rejoindre une session Orbit', + joinModalSub: 'Colle le lien d\'invitation que ton hôte t\'a envoyé.', + joinModalLinkLabel: 'Lien d\'invitation', + joinModalLinkPlaceholder: 'psysonic2-…', + joinModalLinkHelper: 'Fonctionne avec tout lien Orbit valide. Doit pointer vers le serveur auquel tu es actuellement connecté.', + joinModalPasteTooltip: 'Coller depuis le presse-papiers', + joinModalSubmit: 'Rejoindre', + joinModalBusy: 'Connexion…', + joinErrEmpty: 'Veuillez coller un lien d\'invitation.', + joinErrInvalid: 'Cela ne ressemble pas à un lien d\'invitation Orbit.', + closeAria: 'Fermer', + heroTitlePrefix: 'Écoute ensemble avec', + heroTitleBrand: 'Orbit', + heroSub: 'Démarre une session — les autres utilisateurs de {{server}} écouteront en même temps et pourront suggérer des morceaux.', + fallbackServer: 'ce serveur', + tipLan: 'Tu es actuellement connecté via une adresse de réseau local. Les invités hors de ton réseau ne peuvent pas rejoindre — bascule vers une adresse publique dans les paramètres avant de démarrer.', + tipRemote: 'Pour que des invités hors de ton réseau domestique puissent rejoindre, l\'adresse de ton serveur doit être publiquement accessible. Si ton serveur est interne, bascule avant de démarrer.', + labelName: 'Nom de la session', + namePlaceholder: 'Velvet Orbit', + reshuffleTooltip: 'Nouvelle suggestion', + reshuffleAria: 'Suggérer un nouveau nom', + helperName: 'Comment la session apparaîtra à tes invités — garde-le ou saisis le tien.', + labelMax: 'Invités max.', + helperMax: 'Tu ne comptes pas — ceci limite uniquement les invités entrants.', + labelLink: 'Lien d\'invitation', + tooltipCopied: 'Copié', + tooltipCopy: 'Copier', + ariaCopyLink: 'Copier le lien d\'invitation', + helperLink: 'Envoie ce lien à tes invités. Ils peuvent le coller n\'importe où dans Psysonic avec Ctrl+V.', + labelClearQueue: 'Vider ma file d\'attente d\'abord', + helperClearQueue: 'Démarre la session avec une file d\'attente vide. Désactivé : les titres déjà en file restent et sont partagés avec les invités.', + btnCancel: 'Annuler', + btnStarting: 'Démarrage…', + btnStart: 'Démarrer Orbit', + btnCopyAndStart: 'Copier le lien & démarrer', + errNameRequired: 'Veuillez donner un nom à ta session.', + errStartFailed: 'Impossible de démarrer.', + hostLabel: 'Hôte : {{name}}', + participantsTooltip: 'Participants', + settingsTooltip: 'Paramètres de session', + shareTooltip: 'Partager le lien d\'invitation', + shuffleLabel: 'Prochain mélange dans', + catchUpLabel: 'rattraper', + catchUpTooltip: 'Sauter à la position actuelle de l\'hôte', + hostAway: 'Hôte hors ligne', + hostOnline: 'Hôte en ligne', + endTooltip: 'Terminer la session', + leaveTooltip: 'Quitter la session', + helpTooltip: 'Fonctionnement d\'Orbit', + diag: { + openTooltip: 'Diagnostic — journal d\'événements copiable', + title: 'Diagnostic Orbit', + role: 'Rôle', + hostTrack: 'ID de piste de l\'hôte', + hostPos: 'Position de l\'hôte', + guestTrack: 'Mon ID de piste', + guestPos: 'Ma position', + drift: 'Décalage', + stateAge: 'Âge de l\'état', + eventLog: 'Journal d\'événements ({{count}})', + copyLabel: 'Copier', + copyTooltip: 'Copier le journal dans le presse-papiers', + clearLabel: 'Effacer', + clearTooltip: 'Vider le tampon', + empty: 'Aucun événement — ils apparaissent dès qu\'Orbit synchronise.', + hint: 'Ouvre ceci avant de reproduire le problème, puis clique Copier et colle dans le rapport.', + copied: '{{count}} lignes copiées', + copyFailed: 'Impossible de copier dans le presse-papiers', + cleared: 'Tampon vidé', + }, + helpTitle: 'Fonctionnement d\'Orbit', + helpIntro: 'Orbit transforme Psysonic en salle d\'écoute partagée. Un hôte choisit la musique ; les invités écoutent en synchro et peuvent suggérer des morceaux.', + helpHostOnly: '(hôte)', + helpSec1Title: 'Qu\'est-ce qu\'Orbit ?', + helpSec1Body: 'Un mode « écouter ensemble » — l\'hôte dirige la lecture, les invités écoutent. Tout passe par des playlists sur ton propre serveur Navidrome ; aucune infrastructure externe.', + helpSec2Title: 'Hôte et invités', + helpSec2Body: 'L\'hôte contrôle la lecture (play / pause / skip / seek) et décide quand la session se termine. Les invités suivent la lecture, peuvent suggérer des morceaux et quitter ou rejoindre à tout moment. Seul l\'hôte peut exclure ou bannir un participant.', + helpSec2WarnHead: 'Important : comptes séparés.', + helpSec2WarnBody: 'Chaque participant a besoin de son propre compte Navidrome. Si l\'hôte et l\'invité utilisent le même utilisateur, leurs soumissions entrent en conflit et l\'hôte ne voit jamais les suggestions de l\'invité.', + helpSec3Title: 'Démarrer et inviter', + helpSec3Body: 'Clique sur le bouton « Orbit » → Créer une session → le modal affiche un lien d\'invitation prêt à copier et permet optionnellement de vider ta file actuelle. Partage le lien comme tu veux. Pendant qu\'une session est active, le bouton de partage dans la barre en haut copie le lien à tout moment.', + helpSec4Title: 'Rejoindre', + helpSec4Body: 'Colle le lien d\'invitation n\'importe où dans Psysonic avec Ctrl+V / Cmd+V — l\'invite apparaît automatiquement. Alternative : « Orbit » → Rejoindre une session → colle dans le champ. Si le lien pointe vers un serveur où tu as un compte, Psysonic bascule automatiquement. Si tu as plusieurs comptes sur ce serveur, un sélecteur demande lequel utiliser.', + helpSec5Title: 'Suggérer des morceaux', + helpSec5Body: 'Dans n\'importe quelle liste : double-clic sur une ligne, ou clic droit → « Ajouter à la session Orbit ». Un simple clic affiche un indice au lieu de jeter tout l\'album dans la file partagée — c\'est intentionnel. Les actions groupées explicites comme « Tout lire » ou « Lire l\'album » demandent d\'abord confirmation puis ajoutent (ne remplacent jamais).', + helpSec6Title: 'La file d\'attente partagée', + helpSec6Body: 'La file affiche les morceaux à venir de l\'hôte — visible par tous. Les ajouts groupés sont toujours ajoutés à la fin, pour ne pas perdre les suggestions des invités. Le mélange automatique réorganise la file périodiquement (configurable : 1 / 5 / 10 / 15 / 30 min). Si ta lecture dévie, le bouton « Rattraper » dans la barre te ramène à la position en direct de l\'hôte.', + helpSec7Title: 'Approbations', + helpSec7Body: 'Par défaut, les suggestions des invités nécessitent une approbation manuelle — elles apparaissent dans une bande « Approbations » en haut du panneau avec des boutons accepter / refuser. L\'approbation automatique peut être activée dans les paramètres.', + helpSec8Title: 'Participants et paramètres', + helpSec8Body: 'Ouvre l\'icône des paramètres dans la barre pour la cadence de mélange, l\'approbation automatique et le raccourci « Mélanger maintenant ». Clique sur le nombre de participants pour voir qui est connecté — exclure (peut rejoindre via le lien) ou bannir (exclu pour la session). Les invités voient la liste en lecture seule.', + helpSec9Title: 'Terminer la session', + helpSec9Body: 'X de l\'hôte → dialogue de confirmation → la session se ferme pour tout le monde, les playlists serveur sont nettoyées automatiquement. X de l\'invité → l\'invité part, la session continue. Si l\'hôte reste silencieux 5 minutes, l\'invité part automatiquement avec un avis ; les reconnexions courtes dans ce laps sont invisibles.', + participantsInviteLabel: 'Lien d\'invitation', + participantsCountLabel: '{{count}} en session', + participantsHost: 'hôte', + participantsEmpty: 'Pas encore d\'invités', + participantsKickTooltip: 'Retirer de la session', + participantsKickAria: 'Retirer {{user}}', + participantsRemoveTooltip: 'Retirer de la session', + participantsRemoveAria: 'Retirer {{user}} de cette session', + participantsBanTooltip: 'Bannir définitivement', + participantsBanAria: 'Bannir définitivement {{user}}', + participantsMuteTooltip: 'Bloquer les suggestions', + participantsUnmuteTooltip: 'Autoriser les suggestions', + participantsMuteAria: 'Bloquer les suggestions de {{user}}', + participantsUnmuteAria: 'Autoriser à nouveau les suggestions de {{user}}', + confirmRemoveTitle: 'Retirer de la session ?', + confirmRemoveBody: '{{user}} sera retiré de la session mais peut rejoindre via ton lien d\'invitation.', + confirmRemoveConfirm: 'Retirer', + confirmBanTitle: 'Bannir définitivement ?', + confirmBanBody: '{{user}} sera retiré et empêché de rejoindre cette session. Irréversible pour la durée de la session.', + confirmBanConfirm: 'Bannir', + confirmCancel: 'Annuler', + confirmJoinTitle: 'Rejoindre la session Orbit ?', + confirmJoinBody: '{{host}} t\'a invité à « {{name}} ». Rejoindre la session ?', + confirmJoinConfirm: 'Rejoindre', + confirmLeaveTitle: 'Quitter la session ?', + confirmLeaveBody: 'Quitter « {{name}} » ? Tu peux rejoindre à tout moment via le lien d\'invitation de {{host}}.', + confirmLeaveConfirm: 'Quitter', + confirmEndTitle: 'Terminer la session pour tout le monde ?', + confirmEndBody: '« {{name}} » se fermera pour tous les participants. Les playlists de session sont nettoyées automatiquement.', + confirmEndConfirm: 'Terminer la session', + invalidLinkTitle: 'Le lien d\'invitation n\'est plus valide', + invalidLinkBody: 'Cette session Orbit n\'existe plus ou est déjà terminée. Demande à l\'hôte un nouveau lien.', + settingsTitle: 'Paramètres de session', + settingAutoApprove: 'Approuver automatiquement les suggestions', + settingAutoApproveHint: 'Les suggestions arrivent instantanément dans ta file. Désactivé : elles restent dans la liste de session pour révision.', + settingAutoShuffle: 'Mélange automatique', + settingAutoShuffleHint: 'Mélange Fisher-Yates périodique de la file à venir. Désactivé : l\'ordre ne change que lorsque tu le réorganises.', + settingShuffleInterval: 'Remélanger toutes les', + settingShuffleIntervalHint: 'Fréquence de remélange de la file pendant la session.', + suggestBlockedMuted: 'L\'hôte t\'a coupé le micro pour cette session — suggestions désactivées.', + settingShuffleIntervalValue_one: '{{count}} min', + settingShuffleIntervalValue_other: '{{count}} min', + settingShuffleNow: 'Mélanger maintenant', + toastSuggested: '{{user}} a suggéré « {{title}} »', + toastSuggestedMany: '{{count}} nouvelles suggestions dans la file', + toastShuffled: 'File mélangée', + toastJoined: 'Session rejointe', + toastLoginFirst: 'Connecte-toi avant de rejoindre une session', + toastSwitchServer: 'Bascule d\'abord vers {{url}}, puis colle à nouveau', + toastNoAccountForServer: 'Tu n\'as pas accès à {{url}}. Demande à l\'hôte une invitation.', + toastSwitchFailed: 'Impossible de basculer vers {{url}}', + accountPickerTitle: 'Quel compte ?', + accountPickerSub: 'Tu as plusieurs comptes pour {{url}}. Choisis celui avec lequel rejoindre la session.', + toastJoinFail: 'Impossible de rejoindre la session', + joinErrNotFound: 'Session introuvable', + joinErrEnded: 'La session est terminée', + joinErrFull: 'La session est pleine', + joinErrKicked: 'Tu ne peux pas rejoindre cette session', + joinErrNoUser: 'Aucun serveur actif', + joinErrServerError: 'Impossible de rejoindre', + ctxAddToSession: 'Ajouter à la session Orbit', + ctxSuggestedToast: 'Suggéré à la session', + ctxSuggestFailed: 'Impossible de suggérer — pas rejoint', + ctxAddToSessionHost: 'Ajouter à la session Orbit', + ctxAddedHostToast: 'Ajouté à la session', + ctxAddHostFailed: 'Impossible d\'ajouter à la session', + bulkConfirmTitle: 'Tout ajouter à la file Orbit ?', + bulkConfirmBody: 'Cela ajouterait {{count}} morceaux en une fois. C\'est beaucoup pour tes invités. Continuer ?', + bulkConfirmYes: 'Tout ajouter', + bulkConfirmNo: 'Annuler', + guestLive: 'Direct', + guestPlaying: 'En cours de lecture', + guestPaused: 'En pause', + guestLoading: 'Chargement…', + guestSuggestions: 'Suggestions', + guestUpNext: 'À suivre', + guestUpNextEmpty: 'Rien en file. Ouvre le menu contextuel d\'un morceau et choisis « Ajouter à la session Orbit ».', + guestPendingTitle: 'En attente de l\'hôte', + guestPendingHint: 'Suggéré — apparaîtra dans la file quand l\'hôte l\'acceptera.', + approvalTitle: 'Approbations en attente', + approvalFrom: 'Suggéré par {{user}}', + approvalAccept: 'Accepter', + approvalDecline: 'Refuser', + guestUpNextMore: '+ {{count}} autres dans la file de l\'hôte', + guestSubmitter: 'par {{user}}', + queueAddedByHost: 'Ajouté par l\'hôte', + queueAddedByYou: 'Ajouté par toi', + queueAddedByUser: 'Ajouté par {{user}}', + guestEmpty: 'Aucune suggestion. Ouvre le menu contextuel d\'un morceau et choisis « Ajouter à la session Orbit ».', + guestFooter: 'L\'hôte contrôle la lecture — tu ne peux pas modifier la liste.', + exitKickedTitle: 'Tu as été banni de la session', + exitRemovedTitle: 'Tu as été retiré de la session', + exitEndedTitle: 'L\'hôte a terminé la session', + exitHostTimeoutTitle: 'L\'hôte ne répond plus', + exitHostTimeoutBody: '{{host}} n\'a pas envoyé de mise à jour depuis un moment, donc « {{name}} » a été fermée de ton côté. Tu peux rejoindre à tout moment avec le lien.', + exitKickedBody: '{{host}} t\'a banni de « {{name}} ». Tu ne peux pas rejoindre.', + exitRemovedBody: '{{host}} t\'a retiré de « {{name}} ». Tu peux rejoindre via le lien à tout moment.', + exitEndedBody: '« {{name}} » est terminée. J\'espère que tu t\'es bien amusé.', + exitOk: 'OK', +}; diff --git a/src/locales/fr/player.ts b/src/locales/fr/player.ts new file mode 100644 index 00000000..6e7e5b3d --- /dev/null +++ b/src/locales/fr/player.ts @@ -0,0 +1,56 @@ +export const player = { + regionLabel: 'Lecteur de musique', + openFullscreen: 'Ouvrir le lecteur plein écran', + fullscreen: 'Lecteur plein écran', + closeFullscreen: 'Fermer le plein écran', + closeTooltip: 'Fermer (Échap)', + noTitle: 'Sans titre', + stop: 'Arrêter', + prev: 'Piste précédente', + play: 'Lecture', + pause: 'Pause', + previewActive: 'Aperçu en cours', + previewLabel: 'Aperçu', + delayModalTitle: 'Minuteur', + delayPauseSection: 'Pause après', + delayStartSection: 'Démarrage après', + delayPreviewPause: 'Pause à', + delayPreviewStart: 'Démarrage à', + delaySchedulePause: 'Programmer la pause', + delayScheduleStart: 'Programmer le démarrage', + delayCancelPause: 'Annuler le minuteur de pause', + delayCancelStart: 'Annuler le minuteur de démarrage', + delayInactivePause: 'Disponible uniquement pendant la lecture.', + delayInactiveStart: 'Disponible en pause avec une piste ou une radio chargée.', + delayCustomMinutes: 'Délai personnalisé (minutes)', + delayCustomPlaceholder: 'ex. 2,5', + closeDelayModal: 'Fermer', + delayIn: 'dans', + delayFmtSec: '{{n}} s', + delayFmtMin: '{{n}} min', + delayFmtHr: '{{n}} h', + delayCancel: 'Annuler', + delayApply: 'Appliquer', + next: 'Piste suivante', + repeat: 'Répéter', + repeatOff: 'Désactivé', + repeatAll: 'Tout', + repeatOne: 'Un', + progress: 'Progression', + volume: 'Volume', + toggleQueue: 'Afficher/masquer la file', + collapseQueueResize: 'Réduire la file, redimensionner', + moreOptions: 'Plus d’options', + equalizer: 'Égaliseur', + miniPlayer: 'Mini-lecteur', + lyrics: 'Paroles', + fsLyricsToggle: 'Paroles en plein écran', + lyricsLoading: 'Chargement des paroles…', + lyricsNotFound: 'Aucune parole trouvée pour ce titre', + lyricsSourceServer: 'Source : Serveur', + lyricsSourceLrclib: 'Source : LRCLIB', + lyricsSourceNetease: 'Source : Netease', + lyricsSourceLyricsplus: 'Source : YouLyPlus', + showDuration: 'Afficher la durée', + showRemainingTime: 'Afficher le temps restant', +}; diff --git a/src/locales/fr/playlists.ts b/src/locales/fr/playlists.ts new file mode 100644 index 00000000..32da819c --- /dev/null +++ b/src/locales/fr/playlists.ts @@ -0,0 +1,101 @@ +export const playlists = { + title: 'Playlists', + newPlaylist: 'Nouvelle playlist', + unnamed: 'Playlist sans nom', + createName: 'Nom de la playlist…', + create: 'Créer', + cancel: 'Annuler', + empty: 'Aucune playlist pour l\'instant.', + emptyPlaylist: 'Cette playlist est vide.', + addFirstSong: 'Ajouter votre premier titre', + notFound: 'Playlist introuvable.', + songs: '{{n}} titres', + playAll: 'Tout lire', + shuffle: 'Aléatoire', + addToQueue: 'Ajouter à la file', + back: 'Retour aux playlists', + deletePlaylist: 'Supprimer', + confirmDelete: 'Cliquer à nouveau pour confirmer', + removeSong: 'Retirer de la playlist', + addSongs: 'Ajouter des titres', + searchPlaceholder: 'Rechercher dans la bibliothèque…', + noResults: 'Aucun résultat.', + suggestions: 'Titres suggérés', + noSuggestions: 'Aucune suggestion disponible.', + titleBadge: 'Playlist', + refreshSuggestions: 'Nouvelles suggestions', + addSong: 'Ajouter à la playlist', + preview: 'Aperçu (30 s)', + previewStop: 'Arrêter l\'aperçu', + playNextSuggestion: 'Lire ensuite', + suggestionsHint: "Double-cliquez sur une ligne pour l'ajouter à la playlist", + addSelected: 'Ajouter la sélection', + cacheOffline: 'Mettre la playlist hors ligne', + offlineCached: 'Playlist en cache', + removeOffline: 'Retirer du cache hors ligne', + offlineDownloading: 'En cache… ({{done}}/{{total}} albums)', + publicLabel: 'Publique', + privateLabel: 'Privée', + editMeta: 'Modifier la playlist', + editNamePlaceholder: 'Nom de la playlist…', + editCommentPlaceholder: 'Ajouter une description…', + editPublic: 'Playlist publique', + editSave: 'Enregistrer', + editCancel: 'Annuler', + changeCover: 'Changer la pochette', + changeCoverLabel: 'Changer la photo', + removeCover: 'Supprimer la photo', + coverUpdated: 'Pochette mise à jour', + metaSaved: 'Playlist mise à jour', + downloadZip: 'Télécharger (ZIP)', + // Toast notifications for multi-select + addSuccess: '{{count}} morceaux ajoutés à {{playlist}}', + addPartial: '{{added}} ajoutés, {{skipped}} ignorés (doublons)', + addAllSkipped: 'Tous ignorés ({{count}} doublons)', + addedAsDuplicates: '{{count}} morceaux ajoutés à {{playlist}} (en doublons)', + duplicateConfirmTitle: 'Déjà dans la playlist', + duplicateConfirmMessage: 'Les {{count}} morceaux sont déjà dans « {{playlist}} ». Les ajouter quand même en doublons ?', + duplicateConfirmAction: 'Ajouter quand même', + addError: 'Erreur lors de l\'ajout des morceaux', + createAndAddSuccess: 'Playlist "{{playlist}}" créée avec {{count}} morceaux', + createError: 'Erreur lors de la création de la playlist', + deleteSuccess: '{{count}} playlists supprimées', + deleteFailed: 'Erreur lors de la suppression de {{name}}', + deleteSelected: 'Supprimer la sélection', + deleteSelectedPartial: 'Seulement {{n}} des {{total}} playlists sélectionnées peuvent être supprimées (les autres appartiennent à quelqu\'un d\'autre).', + mergeSuccess: '{{count}} morceaux fusionnés dans {{playlist}}', + mergeNoNewSongs: 'Aucun nouveau morceau à ajouter', + mergeError: 'Erreur lors de la fusion des playlists', + mergeInto: 'Fusionner dans', + selectionCount: '{{count}} sélectionnés', + select: 'Sélectionner', + startSelect: 'Activer la sélection', + cancelSelect: 'Annuler', + loadingAlbums: 'Résolution de {{count}} albums…', + loadingArtists: 'Résolution de {{count}} artistes…', + myPlaylists: 'Mes Playlists', + noOtherPlaylists: 'Aucune autre playlist disponible', + addToPlaylistSuccess: '{{count}} morceaux ajoutés à {{playlist}}', + addToPlaylistNoNew: 'Aucun nouveau morceau pour {{playlist}}', + addToPlaylistError: 'Erreur lors de l\'ajout à la playlist', + removeSuccess: 'Morceau retiré de la playlist', + removeError: 'Erreur lors du retrait de la playlist', + importCSV: 'Importer CSV', + importCSVTooltip: 'Importer depuis CSV Spotify', + csvImportReport: 'Rapport d\'Import CSV', + csvImportTotal: 'Total', + csvImportAdded: 'Ajoutés', + csvImportDuplicates: 'Doublons', + csvImportNotFound: 'Non Trouvés', + csvImportNetworkErrors: 'Erreurs Réseau', + csvImportDuplicatesTitle: 'Titres en Doublon (Déjà dans la Playlist):', + csvImportNotFoundTitle: 'Titres Non Trouvés:', + csvImportNetworkErrorsTitle: 'Erreurs Réseau (peut réessayer l\'import):', + csvImportDownloadReport: 'Télécharger le Rapport', + csvImportClose: 'Fermer', + csvImportNoValidTracks: 'Aucun titre valide trouvé dans le fichier CSV', + csvImportFailed: 'Échec de l\'import CSV', + csvImportToast: '{{added}} ajoutés, {{notFound}} non trouvés, {{duplicates}} doublons', + csvImportDownloadSuccess: 'Rapport téléchargé avec succès', + csvImportDownloadError: 'Échec du téléchargement du rapport', +}; diff --git a/src/locales/fr/queue.ts b/src/locales/fr/queue.ts new file mode 100644 index 00000000..be36e752 --- /dev/null +++ b/src/locales/fr/queue.ts @@ -0,0 +1,45 @@ +export const queue = { + title: 'File d\'attente', + savePlaylist: 'Enregistrer la liste', + updatePlaylist: 'Mettre à jour la liste', + filterPlaylists: 'Filtrer les listes…', + playlistName: 'Nom de la liste', + cancel: 'Annuler', + save: 'Enregistrer', + loadPlaylist: 'Charger une liste', + loading: 'Chargement…', + noPlaylists: 'Aucune liste trouvée.', + load: 'Remplacer la file et lire', + appendToQueue: 'Ajouter à la file', + delete: 'Supprimer', + deleteConfirm: 'Supprimer la liste « {{name}} » ?', + clear: 'Vider', + shuffle: 'Mélanger la file', + gapless: 'Sans blanc', + crossfade: 'Fondu', + infiniteQueue: 'File infinie', + autoAdded: '— Ajouté automatiquement —', + radioAdded: '— Radio —', + hide: 'Masquer', + hideNowPlaying: 'Masquer les infos de lecture', + showNowPlaying: 'Afficher les infos de lecture', + close: 'Fermer', + nextTracks: 'Pistes suivantes', + shareQueue: 'Copier le lien de la file d’attente', + shareQueueEmpty: 'La file d’attente est vide — rien à partager.', + emptyQueue: 'La file d\'attente est vide.', + trackSingular: 'piste', + trackPlural: 'pistes', + showRemaining: 'Afficher le temps restant', + showTotal: 'Afficher la durée totale', + showEta: 'Afficher l\'heure de fin estimée', + replayGain: 'ReplayGain', + rgTrack: 'T {{db}} dB', + rgAlbum: 'A {{db}} dB', + rgPeak: 'Pic {{pk}}', + sourceOffline: 'Lecture depuis la bibliothèque hors ligne', + sourceHot: 'Lecture depuis le cache', + sourceStream: 'Lecture depuis le flux réseau', + clearCachedLoudnessWaveform: 'Clear cached loudness and waveform, then re-analyze this track', + recalculatingLoudnessWaveform: 'Recalculating loudness and waveform for this track…', +}; diff --git a/src/locales/fr/radio.ts b/src/locales/fr/radio.ts new file mode 100644 index 00000000..3c6c68dc --- /dev/null +++ b/src/locales/fr/radio.ts @@ -0,0 +1,35 @@ +export const radio = { + title: 'Radio Internet', + empty: 'Aucune station radio configurée.', + addStation: 'Ajouter une station', + editStation: 'Modifier', + deleteStation: 'Supprimer la station', + confirmDelete: 'Cliquer à nouveau pour confirmer', + stationName: 'Nom de la station…', + streamUrl: 'URL du flux…', + homepageUrl: 'URL de la page d\'accueil (optionnel)', + save: 'Enregistrer', + cancel: 'Annuler', + live: 'LIVE', + liveStream: 'Radio Internet', + openHomepage: 'Ouvrir la page d\'accueil', + changeCoverLabel: 'Changer la pochette', + removeCover: 'Supprimer la pochette', + browseDirectory: 'Parcourir l\'annuaire', + directoryPlaceholder: 'Rechercher des stations…', + noResults: 'Aucune station trouvée.', + stationAdded: 'Station ajoutée', + filterAll: 'Toutes', + filterFavorites: 'Favoris', + sortManual: 'Manuel', + sortAZ: 'A → Z', + sortZA: 'Z → A', + sortNewest: 'Plus récentes', + favorite: 'Ajouter aux favoris', + unfavorite: 'Retirer des favoris', + noFavorites: 'Aucune station favorite.', + listenerCount_one: '{{count}} auditeur', + listenerCount_other: '{{count}} auditeurs', + recentlyPlayed: 'Récemment joués', + upNext: 'À suivre', +}; diff --git a/src/locales/fr/randomAlbums.ts b/src/locales/fr/randomAlbums.ts new file mode 100644 index 00000000..a88b6e81 --- /dev/null +++ b/src/locales/fr/randomAlbums.ts @@ -0,0 +1,4 @@ +export const randomAlbums = { + title: 'Albums aléatoires', + refresh: 'Actualiser', +}; diff --git a/src/locales/fr/randomLanding.ts b/src/locales/fr/randomLanding.ts new file mode 100644 index 00000000..6ab98dde --- /dev/null +++ b/src/locales/fr/randomLanding.ts @@ -0,0 +1,9 @@ +export const randomLanding = { + title: 'Créer un mix', + mixByTracks: 'Mix par pistes', + mixByTracksDesc: 'Sélection aléatoire de titres depuis toute votre médiathèque', + mixByAlbums: 'Mix par albums', + mixByAlbumsDesc: 'Albums aléatoires pour vos prochaines découvertes', + mixByLucky: 'Mix Chance', + mixByLuckyDesc: 'Instant Mix intelligent basé sur artistes, albums et notes élevées', +}; diff --git a/src/locales/fr/randomMix.ts b/src/locales/fr/randomMix.ts new file mode 100644 index 00000000..550a2b3f --- /dev/null +++ b/src/locales/fr/randomMix.ts @@ -0,0 +1,39 @@ +export const randomMix = { + title: 'Mix aléatoire', + remix: 'Remixer', + remixTooltip: 'Charger de nouveaux morceaux aléatoires', + remixGenre: 'Remixer {{genre}}', + remixTooltipGenre: 'Charger de nouveaux morceaux {{genre}}', + playAll: 'Tout lire', + trackTitle: 'Titre', + trackArtist: 'Artiste', + trackAlbum: 'Album', + trackFavorite: 'Favori', + trackDuration: 'Durée', + favoriteAdd: 'Ajouter aux favoris', + favoriteRemove: 'Retirer des favoris', + play: 'Lire', + trackGenre: 'Genre', + mixSettingsHeader: 'Réglages du mix', + exclusionsHeader: 'Exclusions', + filterPanelInexactSizeNote: 'La taille du mix est une cible — les grandes requêtes peuvent renvoyer moins de morceaux uniques si le pool aléatoire du serveur s\'épuise.', + mixSize: 'Taille de liste', + excludeAudiobooks: 'Exclure les livres audio et pièces radiophoniques', + excludeAudiobooksDesc: 'Correspond aux mots-clés dans le genre, le titre, l\'album et l\'artiste — ex. Hörbuch, Audiobook, Spoken Word, …', + genreBlocked: 'Mot-clé bloqué', + genreAddedToBlacklist: 'Ajouté à la liste de filtres', + genreAlreadyBlocked: 'Déjà bloqué', + artistBlocked: 'Artiste bloqué', + artistAddedToBlacklist: 'Artiste ajouté à la liste de filtres', + artistClickHint: 'Cliquer pour bloquer cet artiste', + blacklistToggle: 'Filtre par mot-clé', + genreMixTitle: 'Mix par genre', + genreMixDesc: 'Top 20 genres par nombre de morceaux — cliquer pour un mix aléatoire', + genreMixAll: 'Tous les morceaux', + genreMixLoadMore: 'Charger 10 de plus', + genreMixNoGenres: 'Aucun genre trouvé sur le serveur.', + shuffleGenres: 'Afficher d\'autres genres', + filterPanelTitle: 'Filtres', + filterPanelDesc: 'Cliquez sur un tag de genre ou un nom d\'artiste dans la liste pour l\'exclure des futurs mix.', + genreClickHint: 'Cliquez sur un tag de genre pour l\'ajouter\ncomme mot-clé de filtre.\nCorrespond au genre, titre, album et artiste.', +}; diff --git a/src/locales/fr/search.ts b/src/locales/fr/search.ts new file mode 100644 index 00000000..fa87d444 --- /dev/null +++ b/src/locales/fr/search.ts @@ -0,0 +1,29 @@ +export const search = { + placeholder: 'Rechercher un artiste, album ou morceau…', + noResults: 'Aucun résultat pour « {{query}} »', + artists: 'Artistes', + albums: 'Albums', + songs: 'Morceaux', + clearLabel: 'Effacer la recherche', + addedToQueueToast: '« {{title}} » ajouté à la file', + title: 'Recherche', + resultsFor: 'Résultats pour « {{query}} »', + album: 'Album', + advanced: 'Recherche avancée', + advancedSearchTerm: 'Terme de recherche', + advancedSearchPlaceholder: 'Titre, album, artiste…', + advancedGenre: 'Genre', + advancedAllGenres: 'Tous les genres', + advancedYear: 'Année', + advancedYearFrom: 'de', + advancedYearTo: 'à', + advancedAll: 'Tous', + advancedSearch: 'Rechercher', + advancedEmpty: 'Entrez un terme de recherche ou sélectionnez un filtre.', + advancedNoResults: 'Aucun résultat trouvé.', + advancedGenreNote: 'Les morceaux sont sélectionnés aléatoirement dans ce genre.', + recentSearches: 'Recherches récentes', + browse: 'Parcourir', + emptyHint: 'Que veux-tu écouter ?', + genres: 'Genres', +}; diff --git a/src/locales/fr/settings.ts b/src/locales/fr/settings.ts new file mode 100644 index 00000000..479766d7 --- /dev/null +++ b/src/locales/fr/settings.ts @@ -0,0 +1,440 @@ +export const settings = { + title: 'Paramètres', + language: 'Langue', + languageEn: 'English', + languageDe: 'Deutsch', + languageEs: 'Español', + languageFr: 'Français', + languageNl: 'Nederlands', + languageNb: 'Norsk', + languageRu: 'Русский', + languageZh: '中文', + languageRo: 'Română', + font: 'Police', + fontHintOpenDyslexic: 'Adapté à la dyslexie · sans prise en charge du chinois', + theme: 'Thème', + appearance: 'Apparence', + servers: 'Serveurs', + serverName: 'Nom du serveur', + serverUrl: 'URL du serveur', + serverUrlPlaceholder: '192.168.1.100:4533 ou https://music.exemple.com', + serverUsername: 'Nom d\'utilisateur', + serverPassword: 'Mot de passe', + addServer: 'Ajouter un serveur', + addServerTitle: 'Ajouter un nouveau serveur', + useServer: 'Utiliser', + deleteServer: 'Supprimer', + noServers: 'Aucun serveur enregistré.', + serverActive: 'Actif', + confirmDeleteServer: 'Supprimer le serveur « {{name}} » ?', + serverConnecting: 'Connexion…', + serverConnected: 'Connecté !', + serverFailed: 'Connexion échouée.', + testBtn: 'Tester la connexion', + testingBtn: 'Test en cours…', + serverCompatible: 'Conçu pour Navidrome. Les autres serveurs compatibles Subsonic (Gonic, Airsonic, …) peuvent fonctionner avec des fonctionnalités réduites, car Psysonic utilise de nombreux endpoints d’API spécifiques à Navidrome.', + userMgmtTitle: 'Gestion des utilisateurs', + userMgmtDesc: 'Gérer les utilisateurs sur ce serveur. Nécessite des privilèges administrateur.', + userMgmtNoAdmin: 'Vous devez être administrateur pour gérer les utilisateurs sur ce serveur.', + userMgmtLoadError: 'Impossible de charger les utilisateurs.', + userMgmtLoadFriendly: 'Le serveur n\'a pas répondu — généralement ponctuel.', + userMgmtRetry: 'Réessayer', + userMgmtEmpty: 'Aucun utilisateur trouvé.', + userMgmtYouBadge: 'Vous', + userMgmtAdminBadge: 'Admin', + userMgmtAddUser: 'Ajouter un utilisateur', + userMgmtAddUserTitle: 'Nouvel utilisateur', + userMgmtEditUserTitle: 'Modifier l’utilisateur', + userMgmtUsername: 'Nom d’utilisateur', + userMgmtName: 'Nom affiché', + userMgmtEmail: 'E-mail', + userMgmtPassword: 'Mot de passe', + userMgmtPasswordEditHint: 'Saisir un nouveau mot de passe pour le modifier.', + userMgmtRoleAdmin: 'Admin', + userMgmtLibraries: 'Bibliothèques', + userMgmtLibrariesAdminHint: 'Les utilisateurs admin ont automatiquement accès à toutes les bibliothèques.', + userMgmtLibrariesEmpty: 'Aucune bibliothèque disponible sur ce serveur.', + userMgmtLibrariesValidation: 'Sélectionnez au moins une bibliothèque.', + userMgmtLibrariesUpdateError: 'Utilisateur enregistré, mais l\u2019attribution des bibliothèques a échoué', + userMgmtNoLibraries: 'Aucune bibliothèque attribuée', + userMgmtNeverSeen: 'Jamais', + userMgmtSave: 'Enregistrer', + userMgmtCancel: 'Annuler', + userMgmtDelete: 'Supprimer', + userMgmtEdit: 'Modifier', + userMgmtConfirmDelete: 'Supprimer l’utilisateur « {{username}} » ? Action irréversible.', + userMgmtCreateError: 'Impossible de créer l’utilisateur.', + userMgmtUpdateError: 'Impossible de mettre à jour l’utilisateur.', + userMgmtDeleteError: 'Impossible de supprimer l’utilisateur.', + userMgmtCreated: 'Utilisateur créé.', + userMgmtUpdated: 'Utilisateur mis à jour.', + userMgmtDeleted: 'Utilisateur supprimé.', + userMgmtValidationMissing: 'Nom d’utilisateur, nom affiché et mot de passe sont requis.', + userMgmtValidationMissingIdentity: 'Le nom d’utilisateur et le nom affiché sont requis.', + userMgmtMagicStringGenerate: 'Générer la chaîne magique', + userMgmtSaveAndMagicString: 'Enregistrer et obtenir la chaîne magique', + userMgmtMagicStringPasswordNavHint: + 'Navidrome enregistrera ce mot de passe pour l’utilisateur. S’il diffère de l’actuel, le mot de passe de connexion sur le serveur sera mis à jour.', + userMgmtMagicStringPlaintextWarning: + 'Partagez la chaîne magique avec prudence : elle contient un mot de passe non chiffré (l’encodage n’est pas du chiffrement). Quiconque possède la chaîne complète peut se connecter en tant que cet utilisateur.', + userMgmtMagicStringCopied: 'Chaîne magique copiée dans le presse-papiers.', + userMgmtMagicStringCopyFailed: 'Impossible de copier dans le presse-papiers.', + userMgmtMagicStringLoginFailed: 'Échec de la vérification du mot de passe — identifiants non confirmés.', + userMgmtMagicStringModalTitle: 'Générer la chaîne magique', + userMgmtMagicStringModalDesc: 'Saisissez le mot de passe Subsonic de « {{username}} ». Il est inclus dans la chaîne magique copiée.', + userMgmtMagicStringModalConfirm: 'Copier la chaîne', + audiomuseTitle: 'AudioMuse-AI (Navidrome)', + audiomuseDesc: + 'Activez si ce serveur utilise le plugin Navidrome AudioMuse-AI. Active le mix instantané depuis un morceau et affiche les artistes similaires côté serveur au lieu de Last.fm sur les pages artiste.', + audiomuseIssueHint: + 'Le mix instantané a échoué récemment — vérifiez le plugin Navidrome et l’API AudioMuse. Les artistes similaires utilisent Last.fm si le serveur ne renvoie rien.', + connected: 'Connecté', + failed: 'Échec', + eqTitle: 'Égaliseur', + eqEnabled: 'Activer l\'égaliseur', + eqPreset: 'Préréglage', + eqPresetCustom: 'Personnalisé', + eqPresetBuiltin: 'Préréglages intégrés', + eqPresetCustomGroup: 'Mes préréglages', + eqSavePreset: 'Enregistrer comme préréglage', + eqPresetName: 'Nom du préréglage…', + eqDeletePreset: 'Supprimer le préréglage', + eqResetBands: 'Réinitialiser à plat', + eqPreGain: 'Pré-amplification', + eqResetPreGain: 'Réinitialiser la pré-amplification', + eqAutoEqTitle: 'Recherche AutoEQ', + eqAutoEqPlaceholder: 'Rechercher un casque / IEM…', + eqAutoEqSearching: 'Recherche…', + eqAutoEqNoResults: 'Aucun résultat', + eqAutoEqError: 'Échec de la recherche', + eqAutoEqRateLimit: 'Limite GitHub atteinte — réessayez dans une minute', + eqAutoEqFetchError: 'Impossible de charger le profil EQ', + lfmTitle: 'Last.fm', + lfmConnect: 'Connecter avec Last.fm', + lfmConnecting: 'En attente d\'autorisation…', + lfmConfirm: 'J\'ai autorisé l\'application', + lfmConnected: 'Connecté en tant que', + lfmDisconnect: 'Déconnecter', + lfmConnectDesc: 'Connectez votre compte Last.fm pour activer le scrobbling et les mises à jour « En cours de lecture » depuis Psysonic — aucune configuration Navidrome requise.', + lfmOpenBrowser: 'Une fenêtre de navigateur s\'ouvrira. Autorisez Psysonic sur Last.fm, puis cliquez sur le bouton ci-dessous.', + lfmScrobbles: '{{n}} scrobbles', + lfmMemberSince: 'Membre depuis {{year}}', + scrobbleEnabled: 'Scrobbling activé', + scrobbleDesc: 'Envoyer les morceaux à Last.fm après 50% d\'écoute', + behavior: 'Comportement de l\'application', + cacheTitle: 'Taille max. du stockage', + cacheDesc: 'Pochettes et images d\'artistes. Quand le cache est plein, les entrées les plus anciennes sont supprimées automatiquement. Les albums hors ligne ne sont pas supprimés automatiquement, mais le seront lors d\'un nettoyage manuel.', + cacheUsedImages: 'Images :', + cacheUsedOffline: 'Pistes hors ligne :', + cacheUsedHot: 'Espace disque :', + hotCacheTrackCount: 'Pistes en cache :', + cacheMaxLabel: 'Taille max.', + cacheClearBtn: 'Vider le cache', + cacheClearWarning: 'Cela supprimera aussi tous les albums hors ligne de la bibliothèque.', + cacheClearConfirm: 'Tout supprimer', + cacheClearCancel: 'Annuler', + offlineDirTitle: 'Bibliothèque hors ligne (intégrée)', + offlineDirDesc: 'Emplacement de stockage des titres rendus disponibles hors ligne dans Psysonic.', + offlineDirDefault: 'Par défaut (données d\'application)', + offlineDirChange: 'Changer le dossier', + offlineDirClear: 'Réinitialiser', + offlineDirHint: 'Les nouveaux téléchargements utiliseront cet emplacement. Les téléchargements existants restent à leur emplacement d\'origine.', + hotCacheTitle: 'Cache de lecture à chaud', + hotCacheDisclaimer: 'Précharge les titres à venir dans la file et conserve les précédents. Si activé : espace disque et réseau.', + hotCacheDirDefault: 'Par défaut (données d\'application)', + hotCacheDirChange: 'Changer le dossier', + hotCacheDirClear: 'Réinitialiser', + hotCacheDirHint: 'Changer de dossier réinitialise l’index dans l’app ; les fichiers déjà écrits restent à l’ancien emplacement.', + hotCacheEnabled: 'Activer le cache de lecture à chaud', + hotCacheMaxMb: 'Taille maximale du cache', + hotCacheDebounce: 'Délai après changement de file', + hotCacheDebounceImmediate: 'Immédiat', + hotCacheDebounceSeconds: '{{n}} s', + hotCacheClearBtn: 'Vider le cache à chaud', + audioOutputDevice: 'Périphérique de sortie audio', + audioOutputDeviceDesc: 'Choisissez le périphérique audio utilisé par Psysonic. Les changements sont immédiats et relancent la piste en cours.', + audioOutputDeviceDefault: 'Défaut système', + audioOutputDeviceRefresh: 'Actualiser la liste', + audioOutputDeviceOsDefaultNow: 'sortie système actuelle', + audioOutputDeviceListError: 'Impossible de charger la liste des périphériques audio.', + audioOutputDeviceNotInCurrentList: 'absent de la liste actuelle', + audioOutputDeviceMacNotice: 'Sur macOS, la lecture suit actuellement toujours la sortie audio du système pour des raisons techniques. Changez la cible via Réglages Système → Son ou l\'icône haut-parleur de la barre de menus. Contexte : CoreAudio déclenche une demande d\'autorisation du microphone à l\'ouverture d\'un flux non par défaut — nous l\'évitons en utilisant toujours la sortie système par défaut.', + hiResTitle: 'Lecture haute résolution native', + hiResEnabled: 'Activer la lecture haute résolution native', + hiResDesc: "Force une sortie à 44,1 kHz par défaut pour une stabilité maximale. N'activer que si le matériel et le réseau prennent en charge les hautes fréquences d'échantillonnage (88,2 kHz+).", + showArtistImages: 'Afficher les images d\'artistes', + showArtistImagesDesc: 'Charge et affiche les images d\'artistes dans la vue d\'ensemble. Désactivé par défaut pour réduire les E/S disque serveur et la charge réseau sur les grandes bibliothèques.', + showOrbitTrigger: 'Afficher « Orbit » dans l\'en-tête', + showOrbitTriggerDesc: 'Le bouton d\'en-tête pour démarrer ou rejoindre une session d\'écoute partagée. Masque-le si tu n\'utilises pas Orbit — tu peux le réactiver ici.', + showTrayIcon: 'Afficher l\'icône dans la barre système', + showTrayIconDesc: 'Affiche l\'icône Psysonic dans la zone de notification / barre des menus.', + minimizeToTray: 'Réduire dans la barre système', + minimizeToTrayDesc: 'Lors de la fermeture, Psysonic continue de fonctionner dans la barre système au lieu de se fermer.', + preloadMiniPlayer: 'Précharger le mini-lecteur', + preloadMiniPlayerDesc: 'Construit la fenêtre du mini-lecteur en arrière-plan au démarrage de l\'application afin qu\'elle affiche son contenu instantanément à la première ouverture. Utilise un peu plus de mémoire.', + linuxWebkitSmoothScroll: 'Molette fluide (Linux)', + linuxWebkitSmoothScrollDesc: 'Activé : inertie. Désactivé : pas à la ligne, style GTK.', + discordRichPresence: 'Discord Rich Presence', + discordRichPresenceDesc: 'Affiche le titre en cours de lecture sur votre profil Discord. Discord doit être ouvert.', + discordCoverSource: 'Source de pochette', + discordCoverSourceDesc: 'D\'où récupérer la pochette pour votre profil Discord.', + discordCoverNone: 'Aucune (icône de l\'app uniquement)', + discordCoverServer: 'Serveur (via infos album)', + discordCoverApple: 'Apple Music', + discordOptions: 'Options Discord avancées', + discordTemplates: 'Modèles de texte personnalisés', + discordTemplatesDesc: 'Personnalisez les informations affichées sur votre profil Discord. Variables : {title}, {artist}, {album}', + discordTemplateDetails: 'Ligne principale (details)', + discordTemplateState: 'Ligne secondaire (state)', + discordTemplateLargeText: 'Info-bulle album (largeText)', + nowPlayingEnabled: 'Afficher dans la fenêtre live', + nowPlayingEnabledDesc: 'Diffuse le titre en cours de lecture vers la vue des auditeurs en direct du serveur. Désactiver pour ne pas envoyer de données de lecture.', + enableBandsintown: 'Dates de tournée Bandsintown', + enableBandsintownDesc: 'Affiche les concerts à venir de l\'artiste actuel dans l\'onglet Info. Les données proviennent de l\'API publique Bandsintown.', + lyricsServerFirst: 'Préférer les paroles du serveur', + lyricsServerFirstDesc: 'Consulter d\'abord les paroles fournies par le serveur (tags intégrés, fichiers sidecar) avant LRCLIB. Désactiver pour utiliser LRCLIB en priorité.', + enableNeteaselyrics: 'Paroles Netease Cloud Music', + enableNeteaselyricsDesc: 'Utiliser Netease Cloud Music en dernier recours lorsque le serveur et LRCLIB ne retournent rien. Meilleure couverture pour la musique asiatique et internationale.', + lyricsSourcesTitle: 'Sources de paroles', + lyricsSourcesDesc: 'Choisissez quelles sources interroger et dans quel ordre. Glissez pour réordonner. Les sources désactivées sont ignorées.', + lyricsSourceServer: 'Serveur', + lyricsSourceLrclib: 'LRCLIB', + lyricsSourceNetease: 'Netease Cloud Music', + lyricsModeStandard: 'Standard', + lyricsModeStandardDesc: 'Trois sources avec ordre librement configurable : tags du serveur, LRCLIB, Netease.', + lyricsModeLyricsplus: 'YouLyPlus (Karaoké)', + lyricsModeLyricsplusDesc: 'Synchronisation mot à mot depuis Apple Music, Spotify, Musixmatch et QQ (backend communautaire). Retombe silencieusement sur les sources standard si rien n\'est trouvé.', + lyricsStaticOnly: 'Afficher les paroles en texte statique uniquement', + lyricsStaticOnlyDesc: 'Affiche les paroles synchronisées sans défilement automatique ni surlignage des mots.', + downloadsTitle: 'Export ZIP & Archivage', + downloadsFolderDesc: 'Dossier de destination pour les albums téléchargés en tant que fichier ZIP sur votre ordinateur.', + downloadsDefault: 'Dossier de téléchargement par défaut', + pickFolder: 'Sélectionner', + pickFolderTitle: 'Sélectionner le dossier de téléchargement', + clearFolder: 'Effacer le dossier', + logout: 'Se déconnecter', + aboutTitle: 'À propos de Psysonic', + aboutDesc: 'Un lecteur de musique de bureau moderne conçu pour Navidrome. Utilise l\'API Subsonic ainsi que des extensions spécifiques à Navidrome. Basé sur Tauri v2 avec un moteur audio Rust natif — léger et rapide, mais riche en fonctionnalités : barre waveform, paroles synchronisées, intégration Last.fm, égaliseur 10 bandes, crossfade, lecture sans blanc, Replay Gain, navigation par genre et une grande bibliothèque de thèmes.', + aboutLicense: 'Licence', + aboutLicenseText: 'GNU GPL v3 — libre d\'utilisation, de modification et de distribution sous la même licence.', + aboutRepo: 'Code source sur GitHub', + aboutVersion: 'Version', + aboutBuiltWith: 'Construit avec Tauri · React · TypeScript · Rust/rodio', + aboutReleaseNotesLabel: 'Notes de version', + aboutReleaseNotesLink: 'Ouvrir les nouveautés de cette version', + aboutContributorsLabel: 'Contributeurs', + showChangelogOnUpdate: "Afficher 'Quoi de neuf' lors des mises à jour", + showChangelogOnUpdateDesc: "Affiche une bannière discrète du changelog au-dessus de Now Playing après une mise à jour. Un clic ouvre les notes de version, le X la masque.", + randomMixTitle: 'Liste noire du mix aléatoire', + luckyMixMenuTitle: 'Afficher Mix Chance dans le menu', + luckyMixMenuDesc: 'Active Mix Chance dans "Créer un mix" et comme entrée séparée quand la navigation est scindée. Visible uniquement si AudioMuse est actif sur le serveur courant.', + randomMixBlacklistTitle: 'Mots-clés de filtre personnalisés', + randomMixBlacklistDesc: 'Les morceaux sont exclus si un mot-clé correspond à leur genre, titre, album ou artiste (actif quand la case ci-dessus est cochée).', + randomMixBlacklistPlaceholder: 'Ajouter un mot-clé…', + randomMixBlacklistAdd: 'Ajouter', + randomMixBlacklistEmpty: 'Aucun mot-clé personnalisé ajouté.', + randomMixHardcodedTitle: 'Mots-clés intégrés (actifs quand la case est cochée)', + tabAudio: 'Audio', + tabStorage: 'Hors ligne & Cache', + tabAppearance: 'Apparence', + tabLibrary: 'Bibliothèque', + tabServers: 'Serveurs', + tabLyrics: 'Paroles', + tabPersonalisation: 'Personnalisation', + tabIntegrations: 'Intégrations', + inputKeybindingsTitle: 'Raccourcis clavier', + aboutContributorsCount_one: '{{count}} contribution', + aboutContributorsCount_other: '{{count}} contributions', + searchPlaceholder: 'Rechercher dans les paramètres…', + searchNoResults: 'Aucun réglage ne correspond à votre recherche.', + aboutMaintainersLabel: 'Mainteneurs', + integrationsPrivacyTitle: 'Avis de confidentialité', + integrationsPrivacyBody: 'Toutes les intégrations de cet onglet sont facultatives et, une fois activées, envoient des données à des services externes ou à votre serveur Navidrome. Last.fm reçoit votre historique d\'écoute, Discord affiche le morceau en cours dans votre profil, Bandsintown est interrogé par artiste pour récupérer les dates de tournée, et le partage « En cours de lecture » publie votre morceau actuel auprès des autres utilisateurs de votre serveur Navidrome. Si vous ne voulez rien de tout cela, laissez simplement la section correspondante désactivée.', + homeCustomizerTitle: 'Page d\'accueil', + queueToolbarTitle: 'Barre d\'outils de file d\'attente', + queueToolbarReset: 'Réinitialiser', + queueToolbarSeparator: 'Séparateur', + sidebarTitle: 'Barre latérale', + sidebarReset: 'Réinitialiser', + artistLayoutTitle: 'Sections de la page artiste', + artistLayoutDesc: 'Glissez pour réorganiser, basculez pour masquer des sections individuelles de la page artiste. Les sections sans données sont ignorées automatiquement.', + artistLayoutReset: 'Réinitialiser', + artistLayoutBio: 'Biographie de l\'artiste', + artistLayoutTopTracks: 'Titres populaires', + artistLayoutSimilar: 'Artistes similaires', + artistLayoutAlbums: 'Albums', + artistLayoutFeatured: 'Apparaît aussi sur', + sidebarDrag: 'Glisser pour réorganiser', + sidebarFixed: 'Toujours visible', + randomNavSplitTitle: 'Diviser la navigation Mix', + randomNavSplitDesc: 'Afficher "Mix Aléatoire", "Albums Aléatoires" et "Mix Chance" comme entrées séparées dans la barre latérale plutôt que le hub "Créer un Mix".', + tabInput: 'Entrée', + tabUsers: 'Utilisateurs', + shortcutsReset: 'Réinitialiser', + shortcutListening: 'Appuyez sur une touche…', + shortcutUnbound: '—', + shortcutClear: 'Effacer', + globalShortcutsTitle: 'Raccourcis globaux', + globalShortcutsNote: 'Fonctionnent à l\'échelle du système, même quand Psysonic est en arrière-plan. Nécessite Ctrl, Alt ou Super comme modificateur.', + shortcutPlayPause: 'Lecture / Pause', + shortcutNext: 'Piste suivante', + shortcutPrev: 'Piste précédente', + shortcutVolumeUp: 'Volume +', + shortcutVolumeDown: 'Volume -', + shortcutSeekForward: 'Avancer de 10s', + shortcutSeekBackward: 'Reculer de 10s', + shortcutToggleQueue: 'Afficher/masquer la file', + shortcutOpenFolderBrowser: 'Ouvrir {{folderBrowser}}', + shortcutFullscreenPlayer: 'Lecteur plein écran', + shortcutNativeFullscreen: 'Plein écran natif', + shortcutOpenMiniPlayer: 'Ouvrir le mini-lecteur', + shortcutStartSearch: 'Lancer une recherche', + shortcutStartAdvancedSearch: 'Lancer une recherche avancée', + shortcutToggleSidebar: 'Afficher / masquer la barre latérale', + shortcutMuteSound: 'Couper le son', + shortcutToggleEqualizer: 'Ouvrir / basculer l\'égaliseur', + shortcutToggleRepeat: 'Basculer la répétition', + shortcutOpenNowPlaying: 'Ouvrir « En cours »', + shortcutShowLyrics: 'Afficher les paroles', + shortcutFavoriteCurrentTrack: 'Ajouter la piste actuelle aux favoris', + shortcutOpenHelp: 'Aide', + tabSystem: 'Système', + loggingTitle: 'Journalisation', + loggingModeDesc: 'Contrôle le niveau de verbosité des journaux backend dans le terminal.', + loggingModeOff: 'Désactivé', + loggingModeNormal: 'Normal', + loggingModeDebug: 'Débogage', + loggingExport: 'Exporter les journaux', + loggingExportSuccess: 'Journaux exportés ({{count}} lignes).', + loggingExportError: 'Impossible d\'exporter les journaux.', + ratingsSectionTitle: 'Notes', + ratingsSkipStarTitle: 'Passer pour 1 étoile', + ratingsSkipStarDesc: + "Après plusieurs sauts d’affilée, le morceau passe à 1 étoile. Uniquement s’il n’était pas encore noté.", + ratingsSkipStarThresholdLabel: 'Sauts', + ratingsMixFilterTitle: 'Filtrage par note', + ratingsMixFilterDesc: + "Filtrer le contenu peu noté dans {{mix}} et {{albums}}. Cliquer de nouveau sur l’étoile choisie désactive le seuil.", + ratingsMixMinSong: 'Morceaux', + ratingsMixMinAlbum: 'Albums', + ratingsMixMinArtist: 'Artistes', + ratingsMixMinThresholdAria: 'Étoiles minimum : {{label}}', + backupTitle: 'Sauvegarde & Restauration', + backupExport: 'Exporter les paramètres', + backupExportDesc: 'Enregistre tous les paramètres, profils serveur, configuration Last.fm, thème, EQ et raccourcis dans un fichier .psybkp. Les mots de passe sont stockés en clair — conservez le fichier en sécurité.', + backupImport: 'Importer les paramètres', + backupImportDesc: 'Restaure les paramètres depuis un fichier .psybkp. L\'application sera rechargée après l\'import.', + backupImportConfirm: 'Tous les paramètres actuels seront écrasés. Continuer ?', + backupSuccess: 'Sauvegarde enregistrée', + backupImportSuccess: 'Paramètres restaurés — rechargement…', + backupImportError: 'Fichier de sauvegarde invalide ou corrompu.', + playbackTitle: 'Lecture', + replayGain: 'Replay Gain', + replayGainDesc: 'Normaliser le volume des pistes avec les métadonnées ReplayGain', + replayGainMode: 'Mode', + replayGainAuto: 'Auto', + replayGainAutoDesc: 'Utilise le gain d\'album quand les pistes voisines de la file proviennent du même album, sinon le gain de piste.', + replayGainTrack: 'Piste', + replayGainAlbum: 'Album', + replayGainPreGain: 'Pré-Gain (fichiers taggés)', + replayGainPreGainDesc: 'Boost universel ajouté à chaque calcul ReplayGain. Utile si votre bibliothèque semble globalement trop discrète.', + replayGainFallback: 'Repli (sans tags / radio)', + replayGainFallbackDesc: 'Appliqué aux pistes (et flux radio) sans tags ReplayGain, pour que le contenu non taggé ne sorte pas plus fort que le reste.', + normalization: 'Normalisation', + normalizationDesc: 'Égalise la sonie perçue entre pistes, albums et radio.', + normalizationOff: 'Désactivé', + normalizationReplayGain: 'ReplayGain', + normalizationLufs: 'LUFS', + loudnessTargetLufs: 'LUFS cible', + loudnessTargetLufsDesc: 'Sonie de référence sur laquelle toutes les pistes sont calées. Valeur plus basse = sortie plus forte. Les services de streaming tournent autour de -14 LUFS.', + loudnessPreAnalysisAttenuation: 'Atténuation avant mesure', + loudnessPreAnalysisAttenuationDesc: + 'Réduit le volume tant que la loudness du morceau n’est pas enregistrée. En streaming, des estimations grossières suivent, pas une mesure complète. 0 dB = rien ; plus négatif = plus discret. À droite, le dB effectif pour la cible actuelle.', + loudnessPreAnalysisAttenuationRef: 'Effectif {{eff}} dB avec cible {{tgt}} LUFS.', + loudnessPreAnalysisAttenuationReset: 'Valeur par défaut', + loudnessFirstPlayNote: + 'À la première lecture d’un nouveau morceau, le volume peut brièvement varier pendant la mesure. La fois suivante, la mesure mise en cache prend le relais et tout reste stable. Les pistes à venir dans la file sont en général pré-analysées pendant la lecture précédente, ce cas est donc rare en pratique.', + crossfade: 'Fondu enchaîné', + crossfadeDesc: 'Fondu entre les pistes', + crossfadeSecs: '{{n}} s', + notWithGapless: 'Non disponible quand la lecture sans blanc est active', + notWithCrossfade: 'Non disponible quand le fondu enchaîné est actif', + gapless: 'Lecture sans blanc', + gaplessDesc: 'Préparer la piste suivante pour éliminer les silences entre les morceaux', + preservePlayNextOrder: "Préserver l'ordre « Lire ensuite »", + preservePlayNextOrderDesc: 'Les nouveaux éléments « Lire ensuite » s\'ajoutent à la fin de la file existante au lieu de la doubler.', + trackPreviewsTitle: 'Aperçus de pistes', + trackPreviewsToggle: 'Activer les aperçus de pistes', + trackPreviewsDesc: 'Affiche les boutons Lecture et Aperçu dans les listes pour un court extrait au milieu du morceau.', + trackPreviewStart: 'Position de départ', + trackPreviewStartDesc: 'À quel point du morceau l\'aperçu commence (% de la durée).', + trackPreviewDuration: 'Durée', + trackPreviewDurationDesc: 'Combien de temps chaque aperçu joue avant de s\'arrêter.', + trackPreviewDurationSecs: '{{n}} s', + trackPreviewLocationsTitle: 'Où afficher les aperçus', + trackPreviewLocationsDesc: 'Choisissez dans quelles listes afficher les boutons d\'aperçu.', + trackPreviewLocation_suggestions: 'Dans les suggestions de playlist', + trackPreviewLocation_albums: 'Dans les listes d\'albums', + trackPreviewLocation_playlists: 'Dans les playlists', + trackPreviewLocation_favorites: 'Dans les favoris', + trackPreviewLocation_artist: 'Dans les meilleurs morceaux de l\'artiste', + trackPreviewLocation_randomMix: 'Dans Random Mix', + preloadMode: 'Précharger la piste suivante', + preloadModeDesc: 'Quand commencer à mettre en mémoire tampon la piste suivante', + nextTrackBufferingTitle: 'Mise en mémoire tampon', + preloadHotCacheMutualExclusive: "Preload et Hot Cache remplissent le même rôle — un seul peut être actif à la fois. Activer l'un désactive automatiquement l'autre.", + preloadOff: 'Désactivé', + preloadBalanced: 'Équilibré (30 s avant la fin)', + preloadEarly: 'Tôt (après 5 s de lecture)', + preloadCustom: 'Personnalisé', + preloadCustomSeconds: 'Secondes avant la fin : {{n}}', + infiniteQueue: 'File infinie', + infiniteQueueDesc: 'Ajouter automatiquement des morceaux aléatoires quand la file est épuisée', + experimental: 'Expérimental', + fsPlayerSection: 'Lecteur plein écran', + fsShowArtistPortrait: "Afficher la photo de l'artiste", + fsShowArtistPortraitDesc: "Afficher la photo de l'artiste (ou la pochette) sur le côté droit du lecteur plein écran.", + fsPortraitDim: "Assombrissement de la photo", + fsLyricsStyle: "Style des paroles", + fsLyricsStyleRail: "Rail", + fsLyricsStyleRailDesc: "Rail glissant classique de 5 lignes.", + fsLyricsStyleApple: "Défilement", + fsLyricsStyleAppleDesc: "Liste déroulante plein écran.", + sidebarLyricsStyle: "Style de défilement des paroles", + sidebarLyricsStyleClassic: "Classique", + sidebarLyricsStyleClassicDesc: "La ligne active est centrée.", + sidebarLyricsStyleApple: "Apple Music-like", + sidebarLyricsStyleAppleDesc: "La ligne active reste en haut avec une animation fluide.", + seekbarStyle: 'Style de la barre de lecture', + seekbarStyleDesc: 'Choisir l\'apparence de la barre de progression', + seekbarTruewave: 'Forme d\'onde réelle', + seekbarPseudowave: 'Forme d\'onde pseudo', + seekbarLinedot: 'Ligne & point', + seekbarBar: 'Barre', + seekbarThick: 'Barre épaisse', + seekbarSegmented: 'Segmentée', + seekbarNeon: 'Néon', + seekbarPulsewave: 'Onde pulsée', + seekbarParticletrail: 'Traînée de particules', + seekbarLiquidfill: 'Tube liquide', + seekbarRetrotape: 'Bande rétro', + themeSchedulerTitle: 'Planificateur de thème', + themeSchedulerEnable: 'Activer le planificateur de thème', + themeSchedulerEnableSub: 'Bascule automatiquement entre deux thèmes selon l\'heure', + themeSchedulerDayTheme: 'Thème de jour', + themeSchedulerDayStart: 'Début du jour', + themeSchedulerNightTheme: 'Thème de nuit', + themeSchedulerNightStart: 'Début de la nuit', + themeSchedulerActiveHint: 'Le planificateur de thème est actif - les thèmes changent automatiquement.', + visualOptionsTitle: 'Options Visuelles', + coverArtBackground: "Fond d'Art de Poche", + coverArtBackgroundSub: "Afficher la pochette floutée comme fond dans les en-têtes d'albums et de playlists", + playlistCoverPhoto: 'Photo de Couverture de Playlist', + playlistCoverPhotoSub: 'Afficher la grille de photos de couverture dans la vue détaillée des playlists', + showBitrate: 'Afficher le Débit', + showBitrateSub: 'Afficher le débit audio dans les listes de pistes', + floatingPlayerBar: 'Barre de Lecteur Flottante', + floatingPlayerBarSub: 'Garder la barre du lecteur flottante au-dessus du contenu', + uiScaleTitle: "Mise à l'échelle de l'interface", + uiScaleLabel: 'Zoom', +}; diff --git a/src/locales/fr/sharePaste.ts b/src/locales/fr/sharePaste.ts new file mode 100644 index 00000000..0321cc02 --- /dev/null +++ b/src/locales/fr/sharePaste.ts @@ -0,0 +1,18 @@ +export const sharePaste = { + notLoggedIn: 'Connectez-vous et ajoutez le serveur avant de coller un lien de partage.', + noMatchingServer: 'Aucun serveur enregistré ne correspond à ce lien. Ajoutez un serveur avec cette adresse : {{url}}', + trackUnavailable: 'Ce morceau est introuvable sur le serveur.', + albumUnavailable: 'Cet album est introuvable sur le serveur.', + artistUnavailable: 'Cet artiste est introuvable sur le serveur.', + composerUnavailable: 'Ce compositeur est introuvable sur le serveur.', + openedTrack: 'Lecture du morceau partagé.', + openedAlbum: 'Ouverture de l’album partagé.', + openedArtist: 'Ouverture de l’artiste partagé.', + openedComposer: 'Ouverture du compositeur partagé.', + openedQueue_one: 'Lecture de {{count}} morceau depuis le lien de partage.', + openedQueue_other: 'Lecture de {{count}} morceaux depuis le lien de partage.', + openedQueuePartial: + '{{played}} sur {{total}} morceaux du lien : {{skipped}} introuvable(s) sur ce serveur.', + queueAllUnavailable: 'Aucun morceau de ce lien n’a été trouvé sur le serveur.', + genericError: 'Impossible d’ouvrir le lien de partage.', +}; diff --git a/src/locales/fr/sidebar.ts b/src/locales/fr/sidebar.ts new file mode 100644 index 00000000..75b84073 --- /dev/null +++ b/src/locales/fr/sidebar.ts @@ -0,0 +1,37 @@ +export const sidebar = { + library: 'Bibliothèque', + mainstage: 'Scène principale', + newReleases: 'Nouveautés', + allAlbums: 'Tous les albums', + randomAlbums: 'Albums aléatoires', + randomPicker: 'Créer un mix', + artists: 'Artistes', + composers: 'Compositeurs', + randomMix: 'Mix aléatoire', + favorites: 'Favoris', + nowPlaying: 'En cours', + system: 'Système', + statistics: 'Statistiques', + settings: 'Paramètres', + help: 'Aide', + expand: 'Développer la barre latérale', + collapse: 'Réduire la barre latérale', + downloadingTracks: '{{n}} pistes en cache…', + syncingTracks: 'Synchro {{done}}/{{total}}…', + cancelDownload: 'Annuler le téléchargement', + offlineLibrary: 'Bibliothèque hors ligne', + genres: 'Genres', + tracks: 'Titres', + playlists: 'Playlists', + mostPlayed: 'Les plus joués', + losslessAlbums: 'Lossless', + radio: 'Radio Internet', + folderBrowser: 'Explorateur de dossiers', + deviceSync: 'Sync appareil', + libraryScope: 'Portée de la bibliothèque', + allLibraries: 'Toutes les bibliothèques', + expandPlaylists: 'Développer les playlists', + collapsePlaylists: 'Réduire les playlists', + more: 'Plus', + feelingLucky: 'Mix Chance', +}; diff --git a/src/locales/fr/smartPlaylists.ts b/src/locales/fr/smartPlaylists.ts new file mode 100644 index 00000000..19edbb77 --- /dev/null +++ b/src/locales/fr/smartPlaylists.ts @@ -0,0 +1,41 @@ +export const smartPlaylists = { + sectionBasic: '1. Base', + sectionGenres: '2. Genres', + sectionYearsAndFilters: '3. Années et filtres', + genreMode: 'Mode des genres', + genreModeInclude: 'Inclure les genres', + genreModeExclude: 'Exclure les genres', + genreSearchPlaceholder: 'Filtrer les genres...', + availableGenres: 'Disponibles', + selectedGenres: 'Sélectionnés', + yearMode: 'Mode des années', + yearModeInclude: 'Inclure la plage', + yearModeExclude: 'Exclure la plage', + name: 'Nom (sans préfixe)', + limit: 'Limite', + limitHint: 'Nombre de morceaux à inclure dans la playlist (1-{{max}}, généralement 50).', + artistContains: 'Artiste contient…', + albumContains: 'Album contient…', + titleContains: 'Titre contient…', + minRating: 'Note minimale', + minRatingAria: 'Note minimale pour playlist intelligente', + minRatingHint: '0 désactive le seuil minimum; 1-5 conserve les morceaux avec une note supérieure à la valeur choisie.', + fromYear: 'Depuis l\'année', + toYear: 'Jusqu\'à l\'année', + excludeUnrated: 'Exclure les morceaux non notés', + compilationOnly: 'Compilations uniquement', + create: 'Nouvelle Smart Playlist', + save: 'Enregistrer la Smart Playlist', + created: '{{name}} créée', + updated: '{{name}} mise à jour', + createFailed: 'Impossible de créer la smart playlist.', + updateFailed: 'Impossible de mettre à jour la smart playlist.', + navidromeOnly: 'Les smart playlists ne peuvent être créées que sur des serveurs Navidrome.', + loadFailed: 'Impossible de charger les smart playlists depuis Navidrome.', + sortRandom: 'Tri : aléatoire', + sortTitleAsc: 'Tri : titre A-Z', + sortTitleDesc: 'Tri : titre Z-A', + sortYearDesc: 'Tri : année décroissante', + sortYearAsc: 'Tri : année croissante', + sortPlayCountDesc: 'Tri : nombre d\'écoutes décroissant', +}; diff --git a/src/locales/fr/songInfo.ts b/src/locales/fr/songInfo.ts new file mode 100644 index 00000000..81ead9d1 --- /dev/null +++ b/src/locales/fr/songInfo.ts @@ -0,0 +1,23 @@ +export const songInfo = { + title: 'Infos du morceau', + songTitle: 'Titre', + artist: 'Artiste', + album: 'Album', + albumArtist: 'Artiste de l\'album', + year: 'Année', + genre: 'Genre', + duration: 'Durée', + track: 'Piste', + format: 'Format', + bitrate: 'Débit', + sampleRate: 'Fréquence d\'échantillonnage', + bitDepth: 'Profondeur de bits', + channels: 'Canaux', + fileSize: 'Taille du fichier', + path: 'Emplacement', + replayGainTrack: 'RG Gain de piste', + replayGainAlbum: 'RG Gain d\'album', + replayGainPeak: 'RG Crête de piste', + mono: 'Mono', + stereo: 'Stéréo', +}; diff --git a/src/locales/fr/statistics.ts b/src/locales/fr/statistics.ts new file mode 100644 index 00000000..f733b02d --- /dev/null +++ b/src/locales/fr/statistics.ts @@ -0,0 +1,47 @@ +export const statistics = { + title: 'Statistiques', + recentlyPlayed: 'Écoutés récemment', + mostPlayed: 'Albums les plus écoutés', + highestRated: 'Albums les mieux notés', + genreDistribution: 'Répartition par genre (Top 20)', + loadMore: 'Charger plus', + statArtists: 'Artistes', + statArtistsTooltip: 'Artistes d\'album uniquement — les artistes apparaissant seulement sur des pistes (featuring, invité, etc.) sans album propre ne sont pas comptés.', + statAlbums: 'Albums', + statSongs: 'Morceaux', + statGenres: 'Genres', + statPlaytime: 'Durée totale', + genreInsights: 'Aperçu des genres', + formatDistribution: 'Distribution des formats', + formatSample: 'Échantillon de {{n}} pistes', + computing: 'Calcul en cours…', + genreSongs: '{{count}} morceaux', + genreAlbums: '{{count}} albums', + recentlyAdded: 'Ajoutés récemment', + decadeDistribution: 'Albums par décennie', + decadeAlbums_one: '{{count}} album', + decadeAlbums_other: '{{count}} albums', + decadeUnknown: 'Inconnu', + lfmTitle: 'Stats Last.fm', + lfmTopArtists: 'Artistes favoris', + lfmTopAlbums: 'Albums favoris', + lfmTopTracks: 'Morceaux favoris', + lfmPlays: '{{count}} écoutes', + lfmPeriodOverall: 'Tout le temps', + lfmPeriod7day: '7 jours', + lfmPeriod1month: '1 mois', + lfmPeriod3month: '3 mois', + lfmPeriod6month: '6 mois', + lfmPeriod12month: '12 mois', + lfmNotConnected: 'Connectez Last.fm dans les Paramètres pour voir vos stats.', + lfmRecentTracks: 'Scrobbles récents', + lfmNowPlaying: 'En cours de lecture', + lfmJustNow: 'à l\'instant', + lfmMinutesAgo: 'il y a {{n}} min', + lfmHoursAgo: 'il y a {{n}}h', + lfmDaysAgo: 'il y a {{n}}j', + topRatedSongs: 'Morceaux les mieux notés', + topRatedArtists: 'Artistes les mieux notés', + noRatedSongs: 'Aucun morceau noté. Notez des morceaux dans la vue album ou playlist.', + noRatedArtists: 'Aucun artiste noté.', +}; diff --git a/src/locales/fr/tracks.ts b/src/locales/fr/tracks.ts new file mode 100644 index 00000000..f706422e --- /dev/null +++ b/src/locales/fr/tracks.ts @@ -0,0 +1,15 @@ +export const tracks = { + title: 'Titres', + subtitle: 'Parcourir. Chercher. Découvrir.', + heroEyebrow: 'Titre du moment', + heroReroll: 'En choisir un autre', + playSong: 'Lire', + enqueueSong: 'Ajouter à la file', + railRandom: 'Sélection aléatoire', + railHighlyRated: 'Mieux notés', + browseTitle: 'Parcourir tous les titres', + browseUnsupported: 'Ce serveur ne liste pas toute la bibliothèque d\'un coup. Utilisez la recherche ci-dessus pour trouver des titres précis.', + searchPlaceholder: 'Chercher un titre par titre, artiste ou album…', + count_one: '{{count}} titre', + count_other: '{{count}} titres', +}; diff --git a/src/locales/fr/tray.ts b/src/locales/fr/tray.ts new file mode 100644 index 00000000..81d238dd --- /dev/null +++ b/src/locales/fr/tray.ts @@ -0,0 +1,8 @@ +export const tray = { + playPause: 'Lecture / Pause', + nextTrack: 'Piste suivante', + previousTrack: 'Piste précédente', + showHide: 'Afficher / Masquer', + exitPsysonic: 'Quitter Psysonic', + nothingPlaying: 'Aucune lecture', +}; diff --git a/src/locales/fr/whatsNew.ts b/src/locales/fr/whatsNew.ts new file mode 100644 index 00000000..7279b028 --- /dev/null +++ b/src/locales/fr/whatsNew.ts @@ -0,0 +1,8 @@ +export const whatsNew = { + title: 'Quoi de neuf', + empty: 'Aucune entrée de changelog pour cette version.', + bannerTitle: 'Changelog', + bannerCollapsed: 'Nouveau dans v{{version}}', + dismiss: 'Ignorer', + close: 'Fermer', +}; diff --git a/src/locales/nb.ts b/src/locales/nb.ts deleted file mode 100644 index 91fa438a..00000000 --- a/src/locales/nb.ts +++ /dev/null @@ -1,1823 +0,0 @@ -export const nbTranslation = { - sidebar: { - library: 'Bibliotek', - mainstage: 'Hovedscene', - newReleases: 'Nye utgivelser', - allAlbums: 'Alle album', - randomAlbums: 'Tilfeldige album', - randomPicker: 'Lag en miks', - artists: 'Artister', - composers: 'Komponister', - randomMix: 'Tilfeldig miks', - favorites: 'Favoritter', - nowPlaying: 'Spilles nå', - system: 'System', - statistics: 'Statistikk', - settings: 'Innstillinger', - help: 'Hjelp', - expand: 'Utvid sidefelt', - collapse: 'Skjul sidefelt', - downloadingTracks: 'Bufre {{n}} spor…', - syncingTracks: 'Synkroniserer {{done}}/{{total}}…', - cancelDownload: 'Avbryt nedlasting', - offlineLibrary: 'Frakoblet bibliotek', - genres: 'Sjangere', - tracks: 'Spor', - playlists: 'Spillelister', - mostPlayed: 'Mest spilt', - losslessAlbums: 'Lossless', - radio: 'Internettradio', - folderBrowser: 'Mappeleser', - deviceSync: 'Enhetssynk', - libraryScope: 'Biblioteksomfang', - allLibraries: 'Alle biblioteker', - expandPlaylists: 'Utvid spillelister', - collapsePlaylists: 'Skjul spillelister', - more: 'Mer', - feelingLucky: 'Lykkemiks', - }, - home: { - hero: 'Utvalgt', - starred: 'Personlige favoritter', - recent: 'Nylig lagt til', - mostPlayed: 'Mest spilt', - recentlyPlayed: 'Nylig spilt', - losslessAlbums: 'Lossless-album', - discover: 'Oppdag', - discoverSongs: 'Oppdag spor', - loadMore: 'Last inn flere', - discoverMore: 'Oppdag flere', - discoverArtists: 'Oppdag artister', - discoverArtistsMore: 'Alle artister', - becauseYouLike: 'Fordi du har hørt…', - becauseYouLikeFor: 'Fordi du har hørt på {{artist}}', - similarTo: 'Likt {{artist}}', - becauseYouLikeTracks_one: '{{count}} spor', - becauseYouLikeTracks_other: '{{count}} spor' - }, - hero: { - eyebrow: 'Utvalgt album', - playAlbum: 'Spill av album', - enqueue: 'Legg til i kø', - enqueueTooltip: 'Legg til hele albumet i køen', - }, - search: { - placeholder: 'Søk etter artist, album eller sang…', - noResults: 'Ingen resultater funnet for "{{query}}"', - artists: 'Artister', - albums: 'Album', - songs: 'Sanger', - clearLabel: 'Fjern søk', - addedToQueueToast: '«{{title}}» lagt til i køen', - title: 'Søk', - resultsFor: 'Resultater for "{{query}}"', - album: 'Album', - advanced: 'Avansert søk', - advancedSearchTerm: 'Søkeord', - advancedSearchPlaceholder: 'Tittel, album, artist…', - advancedGenre: 'Sjanger', - advancedAllGenres: 'Alle sjangre', - advancedYear: 'År', - advancedYearFrom: 'fra', - advancedYearTo: 'til', - advancedAll: 'Alle', - advancedSearch: 'Søk', - advancedEmpty: 'Skriv inn et søkeord eller velg ett filter for å begynne.', - advancedNoResults: 'Ingen resultater funnet.', - advancedGenreNote: 'Sanger er tilfeldig valgt fra denne sjangeren.', - recentSearches: 'Siste søk', - browse: 'Utforsk', - emptyHint: 'Hva vil du høre?', - genres: 'Sjangre', - }, - nowPlaying: { - tooltip: 'Hvem lytter?', - title: 'Hvem lytter?', - loading: 'Laster…', - nobody: 'Ingen lyttere for øyeblikket.', - minutesAgo: '{{n}}m siden', - nothingPlaying: 'Ingenting spiller akkurat å. Start et spor!', - aboutArtist: 'Om artisten', - fromAlbum: 'Fra dette albumet', - viewAlbum: 'Se album', - goToArtist: 'Gå til artist', - readMore: 'Les mer', - showLess: 'Vis mindre', - genreInfo: 'Sjanger', - trackInfo: 'Sporinfo', - topSongs: 'Mest spilt av denne artisten', - topSongsCredit: 'Toppspor fra {{name}}', - trackPosition: 'Spor {{pos}}', - playsCount_one: '{{count}} avspilling', - playsCount_other: '{{count}} avspillinger', - releasedYearsAgo_one: 'for {{count}} år siden', - releasedYearsAgo_other: 'for {{count}} år siden', - discography: 'Diskografi', - lastfmStats: 'Last.fm-statistikk', - thisTrack: 'Dette sporet', - thisArtist: 'Denne artisten', - listeners: 'lyttere', - scrobbles: 'scrobbles', - yourScrobbles: 'av deg', - listenersN: '{{n}} lyttere', - scrobblesN: '{{n}} scrobbles', - playsByYouN: 'spilt {{n}}× av deg', - openTrackOnLastfm: 'Spor på Last.fm', - openArtistOnLastfm: 'Artist på Last.fm', - rgTrackTooltip: 'ReplayGain (spor)', - rgAlbumTooltip: 'ReplayGain (album)', - rgAutoTooltip: 'ReplayGain (auto)', - showMoreTracks: 'Vis {{count}} til', - showLessTracks: 'Vis mindre', - hideCard: 'Skjul kort', - layoutMenu: 'Oppsett', - visibleCards: 'Synlige kort', - hiddenCards: 'Skjulte kort', - noHiddenCards: 'Ingen skjulte kort', - resetLayout: 'Tilbakestill oppsett', - emptyColumn: 'Slipp kort her', - }, - contextMenu: { - playNow: 'Spill nå', - playNext: 'Spill neste', - addToQueue: 'Legg til i kø', - enqueueAlbum: 'Legg albumet i kø', - enqueueAlbums_one: 'Legg {{count}} album i kø', - enqueueAlbums_other: 'Legg {{count}} album i kø', - startRadio: 'Start radio', - instantMix: 'Instant Mix', - instantMixFailed: 'Kunne ikke lage Instant Mix — server- eller pluginfeil.', - cliMixNeedsTrack: 'Ingenting spilles — start avspilling først, og kjør mix-kommandoen på nytt.', - lfmLove: 'Lik på Last.fm', - lfmUnlove: 'Fjern fra likte på Last.fm', - favorite: 'Favoritt', - favoriteArtist: 'Favorittartist', - favoriteAlbum: 'Favorittalbum', - unfavorite: 'Fjern fra favoritter', - unfavoriteArtist: 'Fjern artist fra favoritter', - unfavoriteAlbum: 'Fjern album fra favoritter', - removeFromQueue: 'Fjern fra kø', - removeFromPlaylist: 'Fjern fra spilleliste', - openAlbum: 'Åpne album', - goToArtist: 'Gå til artist', - download: 'Last ned (ZIP)', - addToPlaylist: 'Legg til i spilleliste', - selectedPlaylists: '{{count}} spillelister valgt', - selectedAlbums: '{{count}} album valgt', - selectedArtists: '{{count}} artister valgt', - songInfo: 'Sanginfo', - shareLink: 'Kopiér delingslenke', - shareCopied: 'Delingslenke kopiert til utklippstavlen.', - shareCopyFailed: 'Kunne ikke kopiere til utklippstavlen.', - }, - sharePaste: { - notLoggedIn: 'Logg inn og legg til serveren før du limer inn en delingslenke.', - noMatchingServer: 'Ingen lagret server samsvarer med denne lenken. Legg til en server med denne adressen: {{url}}', - trackUnavailable: 'Fant ikke dette sporet på serveren.', - albumUnavailable: 'Fant ikke dette albumet på serveren.', - artistUnavailable: 'Fant ikke denne artisten på serveren.', - composerUnavailable: 'Fant ikke denne komponisten på serveren.', - openedTrack: 'Spiller delt spor.', - openedAlbum: 'Åpner delt album.', - openedArtist: 'Åpner delt artist.', - openedComposer: 'Åpner delt komponist.', - openedQueue_one: 'Spiller {{count}} spor fra delingslenken.', - openedQueue_other: 'Spiller {{count}} spor fra delingslenken.', - openedQueuePartial: - 'Spiller {{played}} av {{total}} spor fra lenken ({{skipped}} ble ikke funnet på denne serveren).', - queueAllUnavailable: 'Ingen av sporene fra denne lenken ble funnet på serveren.', - genericError: 'Klarte ikke å åpne delingslenken.', - }, - albumDetail: { - back: 'Tilbake', - orbitDoubleClickHint: 'Dobbeltklikk for å legge dette sporet til Orbit-køen', - playAll: 'Spill alt', - shareAlbum: 'Del album', - enqueue: 'Legg i kø', - enqueueTooltip: 'Legg hele albumet i kø', - artistBio: 'Artistbiografi', - download: 'Last ned (ZIP)', - downloading: 'Laster…', - cacheOffline: 'Gjør tilgjengelig som frakoblet', - offlineCached: 'Tilgjengelig frakoblet', - offlineDownloading: 'Bufrer… ({{n}}/{{total}})', - removeOffline: 'Fjern frakoblet hurtigbuffer', - offlineStorageFull: 'Frakoblet lagring er full (lagringsgrense: {{mb}} MB). Frigjør plass, ved å slette et album fra ditt frakoblede bibliotek, eller øk lagringsgrensen i Innstillinger.', - offlineStorageGoToLibrary: 'Frakoblet bibliotek', - offlineStorageGoToSettings: 'Innstillinger', - favoriteAdd: 'Legg til i favoritter', - favoriteRemove: 'Fjern fra favoritter', - favorite: 'Favoritt', - noBio: 'Ingen biografi er tilgjengelig.', - moreByArtist: 'Mer av {{artist}}', - tracksCount: '{{n}} spor', - goToArtist: 'Gå til {{artist}}', - moreLabelAlbums: 'Flere album på {{label}}', - trackTitle: 'Tittel', - trackAlbum: 'Album', - trackArtist: 'Artist', - trackGenre: 'Sjanger', - trackFormat: 'Format', - trackFavorite: 'Favoritt', - trackRating: 'Vurdering', - trackDuration: 'Varighet', - trackTotal: 'Totalt', - columns: 'Kolonner', - resetColumns: 'Tilbakestill', - notFound: 'Album ble ikke funnet.', - bioModal: 'Artistbiografi', - bioClose: 'Lukk', - ratingLabel: 'Vurdering', - enlargeCover: 'Forstørr', - filterSongs: 'Filtrer sanger…', - sortNatural: 'Naturlig', - sortByTitle: 'A–Å (Tittel)', - sortByArtist: 'A–Å (Artist)', - sortByAlbum: 'A–Å (Album)', - }, - entityRating: { - albumShort: 'Albumvurdering', - artistShort: 'Artistvurdering', - albumAriaLabel: 'Albumvurdering', - artistAriaLabel: 'Artistvurdering', - selectedArtistsRatingAriaLabel: 'Stjernevurdering for {{count}} valgte artister', - selectedAlbumsRatingAriaLabel: 'Stjernevurdering for {{count}} valgte album', - saveFailed: 'Kunne ikke lagre vurderingen.', - }, - artistDetail: { - back: 'Tilbake', - albums: 'Album', - album: 'Album', - playAll: 'Spill alt', - shareArtist: 'Del artist', - shuffle: 'Tilfeldig rekkefølge', - radio: 'Radio', - loading: 'Laster…', - noRadio: 'Ingen lignende spor funnet for denne artisten.', - notFound: 'Artisten ble ikke funnet.', - albumsBy: 'Album fra {{name}}', - topTracks: 'Toppspor', - noAlbums: 'Ingen album funnet.', - trackTitle: 'Tittel', - trackAlbum: 'Album', - trackDuration: 'Varighet', - favoriteAdd: 'Legg til i favoritter', - favoriteRemove: 'Fjern fra favoritter', - favorite: 'Favoritt', - albumCount_one: '{{count}} album', - albumCount_other: '{{count}} album', - openedInBrowser: 'Åpnet i nettleser', - featuredOn: 'Også en del av', - similarArtists: 'Lignende artister', - cacheOffline: 'Lagre diskografi som frakoblet', - offlineCached: 'Diskografi bufret', - offlineDownloading: 'Bufrer… ({{done}}/{{total}} album)', - uploadImage: 'Last opp artistbilde', - uploadImageError: 'Kunne ikke laste opp bildet', - releaseTypes: { - album: 'Album', - ep: 'EP', - single: 'Single', - compilation: 'Samling', - live: 'Live', - soundtrack: 'Filmmusikk', - remix: 'Remiks', - other: 'Annet', - }, - }, - favorites: { - title: 'Favoritter', - empty: "Du har ikke lagret noen favoritter ennå.", - artists: 'Artister', - albums: 'Album', - songs: 'Sanger', - enqueueAll: 'Legg alle i kø', - playAll: 'Spill alle', - removeSong: 'Fjern fra favoritter', - stations: 'Radiostasjoner', - showingFiltered: 'Viser {{filtered}} av {{total}} ({{artist}})', - showingCount: 'Viser {{filtered}} av {{total}}', - clearArtistFilter: 'Tøm artistfilter', - noFilterResults: 'Ingen resultater med valgte filtre.', - allArtists: 'Alle artister', - topArtists: 'Toppartister etter favoritter', - topArtistsSongCount_one: '{{count}} sang', - topArtistsSongCount_other: '{{count}} sanger', - }, - randomLanding: { - title: 'Lag en miks', - mixByTracks: 'Miks etter spor', - mixByTracksDesc: 'Tilfeldig utvalg av spor fra hele biblioteket ditt', - mixByAlbums: 'Miks etter album', - mixByAlbumsDesc: 'Tilfeldige album for nye oppdagelser', - mixByLucky: 'Lykkemiks', - mixByLuckyDesc: 'Smart Instant Mix fra toppartister, album og gode vurderinger', - }, - randomAlbums: { - title: 'Tilfeldige album', - refresh: 'Oppdater', - }, - genres: { - title: 'Sjangre', - genreCount: 'Sjangre', - albumCount_one: '{{count}} album', - albumCount_other: '{{count}} album', - loading: 'Laster sjangre…', - empty: 'Ingen sjangre funnet.', - albumsLoading: 'Laster album…', - albumsEmpty: 'Ingen album funnet for denne sjangeren.', - loadMore: 'Last mer', - back: 'Tilbake', - }, - randomMix: { - title: 'Tilfeldig miks', - remix: 'Remiks', - remixTooltip: 'Last inn nye tilfeldige sanger', - remixGenre: 'Remiks {{genre}}', - remixTooltipGenre: 'Last inn nye {{genre}}-sanger', - playAll: 'Spill alt', - trackTitle: 'Tittel', - trackArtist: 'Artist', - trackAlbum: 'Album', - trackFavorite: 'Favoritt', - trackDuration: 'Varighet', - favoriteAdd: 'Legg til i favoritter', - favoriteRemove: 'Fjern fra favoritter', - play: 'Spill', - trackGenre: 'Sjanger', - mixSettingsHeader: 'Miks-innstillinger', - exclusionsHeader: 'Ekskluderinger', - filterPanelInexactSizeNote: 'Miks-størrelsen er et mål — store forespørsler kan returnere færre unike spor hvis serverens tilfeldige pool tar slutt.', - mixSize: 'Listestørrelse', - excludeAudiobooks: 'Ekskluder lydbøker og hørespill', - excludeAudiobooksDesc: 'Samsvarer nøkkelord mot sjanger, tittel, album og artist - f.eks. Hørespill, Lydbok, Spoken Word, …', - genreBlocked: 'Nøkkelord blokkert', - genreAddedToBlacklist: 'Lagt til i filterliste', - genreAlreadyBlocked: 'Allerede blokkert', - artistBlocked: 'Artisten er blokkert', - artistAddedToBlacklist: 'Artist er lagt til i filterliste', - artistClickHint: 'Klikk for å blokkere denne artisten', - blacklistToggle: 'Nøkkelordfilter', - genreMixTitle: 'Sjangermiks', - genreMixDesc: 'Topp 20 sjangre etter antall sanger - klikk for å laste en tilfeldig miks', - genreMixAll: 'Alle sanger', - genreMixLoadMore: 'Last 10 til', - genreMixNoGenres: 'Ingen sjangre funnet på tjeneren.', - shuffleGenres: 'Vis andre sjangre', - filterPanelTitle: 'Filtre', - filterPanelDesc: 'Klikk på en sjanger-tag eller på artistnavnet i sporlisten nedenfor, for å blokkere den fra fremtidige mikser.', - genreClickHint: 'Klikk på en sjanger-tag for å legge den til\nsom et filternøkkelord.\nSamsvarer med sjanger, tittel, album og artist.', - }, - luckyMix: { - done: 'Lykkemiks klar: {{count}} spor', - failed: 'Kunne ikke lage Lykkemiksen. Prøv igjen.', - unavailable: 'Lykkemiks er ikke tilgjengelig for denne serveren.', - cancelTooltip: 'Avbryt Lykkemiks-bygging', - }, - albums: { - title: 'Alle album', - sortByName: 'A–Å (Album)', - sortByArtist: 'A–Å (Artist)', - sortNewest: 'Vis nyeste først', - sortRandom: 'Tilfeldig', - yearFrom: 'Fra', - yearTo: 'Til', - yearFilterClear: 'Tøm år filteret', - yearFilterLabel: 'År', - compilationLabel: 'Samleplater', - compilationOnly: 'Kun samleplater', - compilationHide: 'Skjul samleplater', - compilationTooltipAll: 'Alle album · klikk: kun samleplater', - compilationTooltipOnly: 'Kun samleplater · klikk: skjul samleplater', - compilationTooltipHide: 'Samleplater skjult · klikk: vis alle', - select: 'Multivalg', - startSelect: 'Aktiver multivalg', - cancelSelect: 'Avbryt', - selectionCount: '{{count}} valgt', - downloadZips: 'Last ned ZIPs', - addOffline: 'Legg til offline', - enqueueSelected_one: 'Legg i kø ({{count}})', - enqueueSelected_other: 'Legg i kø ({{count}})', - enqueueQueued_one: '{{count}} album lagt til i køen', - enqueueQueued_other: '{{count}} album lagt til i køen', - downloadingZip: 'Laster ned {{current}}/{{total}}: {{name}}', - downloadZipDone: '{{count}} ZIP(s) lastet ned', - downloadZipFailed: 'Kunne ikke laste ned {{name}}', - offlineQueuing: 'Legger {{count}} album i kø for offline…', - offlineFailed: 'Kunne ikke legge til {{name}} offline', - }, - tracks: { - title: 'Spor', - subtitle: 'Bla. Søk. Oppdag.', - heroEyebrow: 'Sporet akkurat nå', - heroReroll: 'Velg et annet', - playSong: 'Spill av', - enqueueSong: 'Legg til i kø', - railRandom: 'Tilfeldig valg', - railHighlyRated: 'Høyt vurdert', - browseTitle: 'Bla gjennom alle spor', - browseUnsupported: 'Denne tjeneren lister ikke hele biblioteket på én gang. Bruk søket ovenfor for å finne bestemte spor.', - searchPlaceholder: 'Finn et spor etter tittel, artist eller album…', - count_one: '{{count}} spor', - count_other: '{{count}} spor', - }, - artists: { - title: 'Artister', - search: 'Søk…', - all: 'Alle', - gridView: 'Rutenettvisning', - listView: 'Listevisning', - imagesOn: 'Artistbilder på - kan øke belastningen på nettverket og applikasjonen', - imagesOff: 'Artistbilder av - viser kun initialer', - loadMore: 'Last flere', - notFound: 'Ingen artister funnet.', - albumCount_one: '{{count}} album', - albumCount_other: '{{count}} album', - selectionCount: '{{count}} valgt', - select: 'Multivalg', - startSelect: 'Aktiver multivalg', - cancelSelect: 'Avbryt', - addToPlaylist: 'Legg til i spilleliste', - }, - composers: { - title: 'Komponister', - search: 'Søk…', - notFound: 'Ingen komponister funnet.', - unsupported: 'Bla etter komponist krever Navidrome 0.55 eller nyere.', - loadFailed: 'Kunne ikke laste komponister.', - retry: 'Prøv igjen', - involvedIn_one: 'Bidratt på {{count}} album', - involvedIn_other: 'Bidratt på {{count}} album', - }, - composerDetail: { - back: 'Tilbake', - notFound: 'Komponist ikke funnet.', - about: 'Om denne komponisten', - works: 'Verker', - noWorks: 'Ingen verker funnet.', - workCount_one: '{{count}} verk', - workCount_other: '{{count}} verker', - shareComposer: 'Del komponist', - unknownComposer: 'Komponist', - }, - login: { - subtitle: 'Din Navidrome-mediaspiller', - serverName: 'Tjenernavn (valgfritt)', - serverNamePlaceholder: 'Mitt mediabibliotek', - serverUrl: 'Tjener-URL', - serverUrlPlaceholder: '192.168.1.100:4533 eller https://musikk.eksempel.com', - username: 'Brukernavn', - usernamePlaceholder: 'admin', - password: 'Passord', - showPassword: 'Vis passord', - hidePassword: 'Skjul passord', - connect: 'Koble til', - connecting: 'Kobler til…', - connected: 'Tilkoblet!', - error: 'Tilkoblingen mislyktes – vennligst sjekk instillingene.', - urlRequired: 'Vennligst skriv inn en tjeneer-URL.', - savedServers: 'Lagrede servere', - addNew: 'Eller legg til en ny tjener', - orMagicString: 'Eller magic string', - magicStringPlaceholder: 'Lim inn en delingsstreng (psysonic1-…)', - magicStringInvalid: 'Ugyldig eller uleselig magic string.', - }, - connection: { - connected: 'Tilkoblet', - connectedTo: 'Tilkoblet til {{server}}', - disconnected: 'Frakoblet', - disconnectedFrom: 'Kan ikke nå {{server}} - klikk for å sjekke innstillinger', - checking: 'Kobler til…', - extern: 'Ekstern', - offlineTitle: 'Ingen tjenertilkobling', - offlineSubtitle: 'Kan ikke nå {{server}}. Sjekk nettverket eller tjeneren din.', - offlineModeBanner: 'Frakoblet modus - spiller fra lokal hurtigbuffer', - offlineNoCacheBanner: 'Ingen servertilkobling — kan ikke nå {{server}}', - offlineLibraryTitle: 'Frakoblet bibliotek', - offlineLibraryEmpty: 'Ingen album bufret ennå. Kobl deg til nettverket, åpne et album og klikk "Gjør tilgjengelig frakoblet".', - offlineAlbumCount: '{{n}} album', - offlineAlbumCount_plural: '{{n}} album', - offlineFilterAll: 'Alle', - offlineFilterAlbums: 'Album', - offlineFilterPlaylists: 'Spillelister', - offlineFilterArtists: 'Diskografier', - retry: 'Prøv igjen', - serverSettings: 'Serverinnstillinger', - switchServerTitle: 'Bytt server', - switchServerHint: 'Klikk for å velge en annen lagret server.', - manageServers: 'Administrer servere…', - switchFailed: 'Klarte ikke å bytte — serveren er utilgjengelig.', - lastfmConnected: 'Last.fm tilkoblet som bruker @{{user}}', - lastfmSessionInvalid: 'Sesjonen er ugyldig - klikk her for å koble til på nytt', - }, - common: { - albums: 'Album', - album: 'Album', - loading: 'Laster…', - loadingMore: 'Laster…', - loadingPlaylists: 'Laster spillelister…', - noAlbums: 'Ingen album funnet.', - downloading: 'Laster ned…', - downloadZip: 'Last ned (ZIP)', - back: 'Tilbake', - cancel: 'Avbryt', - save: 'Lagre', - delete: 'Slett', - use: 'Bruk', - add: 'Legg til', - new: 'Ny', - active: 'Aktiv', - download: 'Last ned', - chooseDownloadFolder: 'Velg nedlastingsmappe', - noFolderSelected: 'Ingen mappe valgt', - rememberDownloadFolder: 'Husk denne mappen', - filterGenre: 'Sjangerfilter', - filterSearchGenres: 'Søk i sjangre…', - filterNoGenres: 'Ingen sjangre samsvarer', - filterClear: 'Tøm', - favorites: 'Favoritter', - favoritesTooltipOff: 'Vis bare favoritter', - favoritesTooltipOn: 'Vis alle', - play: 'Spill', - bulkSelected: '{{count}} valgt', - clearSelection: 'Fjern utvalg', - bulkAddToPlaylist: 'Legg til i spilleliste', - bulkRemoveFromPlaylist: 'Fjern fra spilleliste', - bulkClear: 'Tøm utvalg', - updaterAvailable: 'Ny versjon er tilgjengelig', - updaterVersion: 'v{{version}} er tilgjengelig', - updaterWebsite: 'Nettsted', - updaterModalTitle: 'Ny versjon tilgjengelig', - updaterChangelog: 'Hva er nytt', - updaterDownloadBtn: 'Last ned nå', - updaterSkipBtn: 'Hopp over denne versjonen', - updaterRemindBtn: 'Påminn meg senere', - updaterDone: 'Nedlasting fullført', - updaterShowFolder: 'Vis i mappe', - updaterInstallHint: 'Lukk Psysonic og kjør installasjonsprogrammet manuelt.', - updaterAurHint: 'Installer oppdateringen via AUR:', - updaterErrorMsg: 'Nedlasting mislyktes', - updaterRetryBtn: 'Prøv igjen', - durationHoursMinutes: '{{hours}} t {{minutes}} min', - durationMinutesOnly: '{{minutes}} min', - updaterOpenGitHub: 'Åpne på GitHub', - filters: 'Filter', - more: 'mer', - yearRange: 'Årsspenn', - clearAll: 'Tøm alt', - }, - settings: { - title: 'Innstillinger', - language: 'Språk', - languageEn: 'English', - languageDe: 'Deutsch', - languageEs: 'Español', - languageFr: 'Français', - languageNl: 'Nederlands', - languageNb: 'Norsk', - languageRu: 'Русский', - languageZh: '中文', - languageRo: 'Română', - font: 'Skrifttype', - fontHintOpenDyslexic: 'Dyslexivennlig · ingen kinesisk støtte', - theme: 'Tema', - appearance: 'Utseende', - servers: 'Tjenere', - serverName: 'Tjenernavn', - serverUrl: 'Tjener-URL', - serverUrlPlaceholder: '192.168.1.100:4533 eller https://musikk.eksempel.com', - serverUsername: 'Brukernavn', - serverPassword: 'Passord', - addServer: 'Legg til tjener', - addServerTitle: 'Legg til ny tjener', - useServer: 'Bruk', - deleteServer: 'Slett', - noServers: 'Ingen tjenere lagret.', - serverActive: 'Aktiv', - confirmDeleteServer: 'Slett tjener "{{name}}"?', - serverConnecting: 'Kobler til…', - serverConnected: 'Tilkoblet!', - serverFailed: 'Tilkobling mislyktes.', - testBtn: 'Test tilkobling', - testingBtn: 'Tester…', - serverCompatible: 'Laget for Navidrome. Andre Subsonic-kompatible servere (Gonic, Airsonic, …) kan fungere med begrenset funksjonalitet, fordi Psysonic bruker mange Navidrome-spesifikke API-endepunkter.', - userMgmtTitle: 'Brukeradministrasjon', - userMgmtDesc: 'Administrer brukere på denne serveren. Krever admin-rettigheter.', - userMgmtNoAdmin: 'Du trenger admin-rettigheter for å administrere brukere på denne serveren.', - userMgmtLoadError: 'Kunne ikke laste brukere.', - userMgmtLoadFriendly: 'Serveren svarte ikke — som regel en engangsfeil.', - userMgmtRetry: 'Prøv igjen', - userMgmtEmpty: 'Ingen brukere funnet.', - userMgmtYouBadge: 'Deg', - userMgmtAdminBadge: 'Admin', - userMgmtAddUser: 'Legg til bruker', - userMgmtAddUserTitle: 'Ny bruker', - userMgmtEditUserTitle: 'Rediger bruker', - userMgmtUsername: 'Brukernavn', - userMgmtName: 'Visningsnavn', - userMgmtEmail: 'E-post', - userMgmtPassword: 'Passord', - userMgmtPasswordEditHint: 'Skriv inn et nytt passord for å oppdatere det.', - userMgmtRoleAdmin: 'Admin', - userMgmtLibraries: 'Biblioteker', - userMgmtLibrariesAdminHint: 'Administratorbrukere har automatisk tilgang til alle biblioteker.', - userMgmtLibrariesEmpty: 'Ingen biblioteker tilgjengelig på denne serveren.', - userMgmtLibrariesValidation: 'Velg minst ett bibliotek.', - userMgmtLibrariesUpdateError: 'Brukeren ble lagret, men bibliotekstilordning mislyktes', - userMgmtNoLibraries: 'Ingen biblioteker tilordnet', - userMgmtNeverSeen: 'Aldri', - userMgmtSave: 'Lagre', - userMgmtCancel: 'Avbryt', - userMgmtDelete: 'Slett', - userMgmtEdit: 'Rediger', - userMgmtConfirmDelete: 'Slett brukeren «{{username}}»? Dette kan ikke angres.', - userMgmtCreateError: 'Kunne ikke opprette bruker.', - userMgmtUpdateError: 'Kunne ikke oppdatere bruker.', - userMgmtDeleteError: 'Kunne ikke slette bruker.', - userMgmtCreated: 'Bruker opprettet.', - userMgmtUpdated: 'Bruker oppdatert.', - userMgmtDeleted: 'Bruker slettet.', - userMgmtValidationMissing: 'Brukernavn, visningsnavn og passord er påkrevd.', - userMgmtValidationMissingIdentity: 'Brukernavn og visningsnavn er påkrevd.', - userMgmtMagicStringGenerate: 'Generer magic string', - userMgmtSaveAndMagicString: 'Lagre og hent magic string', - userMgmtMagicStringPasswordNavHint: - 'Navidrome lagrer dette passordet for brukeren. Hvis det avviker fra det nåværende, oppdateres innloggingspassordet på serveren.', - userMgmtMagicStringPlaintextWarning: - 'Del magic string med varsomhet: den inneholder passordet i klartekst (koding er ikke kryptering). Den som har hele strengen, kan logge inn som denne brukeren.', - userMgmtMagicStringCopied: 'Magic string er kopiert til utklippstavlen.', - userMgmtMagicStringCopyFailed: 'Klarte ikke å kopiere til utklippstavlen.', - userMgmtMagicStringLoginFailed: 'Passordsjekk mislyktes — påloggingsdetaljene kunne ikke verifiseres.', - userMgmtMagicStringModalTitle: 'Generer magic string', - userMgmtMagicStringModalDesc: 'Skriv inn Subsonic-passordet for «{{username}}». Det tas med i den kopierte magic string-en.', - userMgmtMagicStringModalConfirm: 'Kopier streng', - audiomuseTitle: 'AudioMuse-AI (Navidrome)', - audiomuseDesc: - 'Slå på hvis denne serveren bruker AudioMuse-AI Navidrome-plugin. Aktiverer Instant Mix fra spor og henter lignende artister fra serveren i stedet for Last.fm på artistsider.', - audiomuseIssueHint: - 'Instant Mix feilet nylig — sjekk Navidrome-plugin og AudioMuse API. Lignende artister hentes fra Last.fm hvis serveren ikke returnerer noe.', - connected: 'Tilkoblet', - failed: 'Mislyktes', - eqTitle: 'Jevnstiller', - eqEnabled: 'Aktiver jevnstiller', - eqPreset: 'Forhåndsinnstilling', - eqPresetCustom: 'Egendefinert', - eqPresetBuiltin: 'Innebygde forhåndsinnstillinger', - eqPresetCustomGroup: 'Mine forhåndsinnstillinger', - eqSavePreset: 'Lagre som forhåndsinnstilling', - eqPresetName: 'Navn på forhåndsinnstilling…', - eqDeletePreset: 'Slett forhåndsinnstilling', - eqResetBands: 'Tilbakestill til standard', - eqPreGain: 'Forforsterkning', - eqResetPreGain: 'Tilbakestill forforsterkning', - eqAutoEqTitle: 'AutoEQ hodetelefonoppslag', - eqAutoEqPlaceholder: 'Søk etter hodetelefon- / IEM-modell…', - eqAutoEqSearching: 'Søker…', - eqAutoEqNoResults: 'Ingen resultater funnet', - eqAutoEqError: 'Søk mislyktes', - eqAutoEqRateLimit: 'GitHub-hastighetsgrense nådd - prøv igjen om ett minutt', - eqAutoEqFetchError: 'Kunne ikke hente EQ-profil', - lfmTitle: 'Last.fm', - lfmConnect: 'Koble til med Last.fm', - lfmConnecting: 'Venter på autorisasjon…', - lfmConfirm: 'Jeg har autorisert appen', - lfmConnected: 'Tilkoblet som', - lfmDisconnect: 'Koble fra', - lfmConnectDesc: 'Koble til din Last.fm-konto for å aktivere scrobbling og få "Nå spiller"-oppdateringer direkte fra Psysonic - ingen Navidrome-konfigurasjon kreves.', - lfmOpenBrowser: 'Et nettleservindu vil åpne seg. Autoriser Psysonic via Last.fm, og klikk deretter på knappen nedenfor.', - lfmScrobbles: '{{n}} scrobbles', - lfmMemberSince: 'Medlem siden {{year}}', - scrobbleEnabled: 'Scrobbling er aktivert', - scrobbleDesc: 'Send sanger til Last.fm etter 50 % avspilling', - behavior: 'App-oppførsel', - cacheTitle: 'Maks. lagringsstørrelse', - cacheDesc: 'Plateomslag og artistbilder. Når den er full, fjernes de eldste oppføringene automatisk. Frakoblede album fjernes ikke automatisk, men slettes når hurtigbufferen tømmes manuelt.', - cacheUsed: 'Brukt: {{images}} bilder · {{offline}} frakoblede spor', - cacheUsedImages: 'Bilder:', - cacheUsedOffline: 'Frakoblede spor:', - cacheUsedHot: 'Plass brukt:', - hotCacheTrackCount: 'Spor i buffer:', - cacheMaxLabel: 'Maks størrelse', - cacheClearBtn: 'Tøm hurtigbuffer', - cacheClearWarning: 'Dette vil også fjerne alle frakoblede album fra biblioteket.', - cacheClearConfirm: 'Tøm alt', - cacheClearCancel: 'Avbryt', - offlineDirTitle: 'Frakoblet bibliotek (In-App)', - offlineDirDesc: 'Lagringsplassering for spor som du gjør tilgjengelige som frakoblet i Psysonic.', - offlineDirDefault: 'Standard (App-data)', - offlineDirChange: 'Endre katalog', - offlineDirClear: 'Tilbakestill til standard', - offlineDirHint: 'Nye nedlastinger vil bruke denne plasseringen. Eksisterende nedlastinger forblir på sin opprinnelige lokasjon.', - hotCacheTitle: 'Varm avspillingsbuffer', - hotCacheDisclaimer: 'Forhåndshenter neste spor i køen og beholder tidligere. Når aktivert: diskplass og nettverk.', - hotCacheDirDefault: 'Standard (App-data)', - hotCacheDirChange: 'Endre mappe', - hotCacheDirClear: 'Tilbakestill til standard', - hotCacheDirHint: 'Bytte mappe nullstiller indeksen i appen; gamle filer blir liggende til du sletter dem.', - hotCacheEnabled: 'Aktiver varm avspillingsbuffer', - hotCacheMaxMb: 'Maks bufferstørrelse', - hotCacheDebounce: 'Utsettelse ved køendring', - hotCacheDebounceImmediate: 'Umiddelbart', - hotCacheDebounceSeconds: '{{n}} sek', - hotCacheClearBtn: 'Tøm varm buffer', - audioOutputDevice: 'Lydutgangsenhet', - audioOutputDeviceDesc: 'Velg hvilken lydenhet Psysonic spiller gjennom. Endringer trer i kraft umiddelbart og starter gjeldende spor på nytt.', - audioOutputDeviceDefault: 'Systemstandard', - audioOutputDeviceRefresh: 'Oppdater enhetsliste', - audioOutputDeviceOsDefaultNow: 'gjeldende systemutgang', - audioOutputDeviceListError: 'Kunne ikke laste listen over lydenheter.', - audioOutputDeviceNotInCurrentList: 'ikke i gjeldende liste', - audioOutputDeviceMacNotice: 'På macOS følger avspillingen av tekniske årsaker alltid systemets lydutgang. Endre målet via Systeminnstillinger → Lyd eller høyttalerikonet i menylinjen. Bakgrunn: CoreAudio utløser en mikrofontillatelsesdialog når en ikke-standard strøm åpnes — vi unngår det ved alltid å bruke systemets standardutgang.', - hiResTitle: 'Innebygd hi-res-avspilling', - hiResEnabled: 'Aktiver innebygd hi-res-avspilling', - hiResDesc: "Begrenser utdata til 44,1 kHz som standard for maksimal stabilitet. Aktiver kun hvis maskinvare og nettverk støtter høye samplingsrater (88,2 kHz+) pålitelig.", - showArtistImages: 'Vis artistbilder', - showArtistImagesDesc: 'Last inn og vis artistbilder i artistoversikten. Denne er deaktivert som standard, for å redusere disk-I/O og nettverksbelastningen på store biblioteker.', - showOrbitTrigger: 'Vis «Orbit» i toppen', - showOrbitTriggerDesc: 'Knappen i toppen for å starte eller bli med i en delt lytteøkt. Skjul den hvis du ikke bruker Orbit — du kan slå den på igjen her.', - minimizeToTray: 'Minimer til oppgavelinjen', - minimizeToTrayDesc: 'Når vinduet lukkes, vil Psysonic bli kjørende i oppgavelinjen fremfor å bli avsluttet.', - preloadMiniPlayer: 'Forhåndslast miniavspiller', - preloadMiniPlayerDesc: 'Bygger miniavspiller-vinduet i bakgrunnen ved appstart slik at det viser innhold umiddelbart ved første åpning. Bruker litt mer minne.', - linuxWebkitSmoothScroll: 'Mykt musehjul (Linux)', - linuxWebkitSmoothScrollDesc: 'På: treg rull med etterslep. Av: trinnvis som i GTK.', - discordRichPresence: 'Discord Rich Presence', - discordRichPresenceDesc: 'Vis sporet som spilles i din Discord-profil. Krever at Discord kjører.', - discordCoverSource: 'Coverkilde', - discordCoverSourceDesc: 'Hvor albumcoveret for Discord-profilen din hentes fra.', - discordCoverNone: 'Ingen (kun app-ikon)', - discordCoverServer: 'Server (via albuminfo)', - discordCoverApple: 'Apple Music', - discordOptions: 'Avanserte Discord-alternativer', - discordTemplates: 'Egendefinerte tekstmaler', - discordTemplatesDesc: 'Tilpass hvilken informasjon som vises på Discord-profilen din. Variabler: {title}, {artist}, {album}', - discordTemplateDetails: 'Primær linje (details)', - discordTemplateState: 'Sekundær linje (state)', - discordTemplateLargeText: 'Album-verktøytips (largeText)', - nowPlayingEnabled: 'Vis i "Nå spiller"', - nowPlayingEnabledDesc: 'Send sporet som spilles av til tjenerens live-lyttervisning. Deaktiver for å stoppe sending av avspillingsdata.', - enableBandsintown: 'Bandsintown-turnédatoer', - enableBandsintownDesc: 'Vis kommende konserter for gjeldende artist i Info-fanen. Data hentes fra det offentlige Bandsintown-API-et.', - lyricsServerFirst: 'Foretrekk server-sangtekst', - lyricsServerFirstDesc: 'Sjekk tjenerlevererte sangtekster (innebygde tagger, sidecar-filer) før LRCLIB. Deaktiver for å bruke LRCLIB først.', - enableNeteaselyrics: 'Netease Cloud Music sangtekster', - enableNeteaselyricsDesc: 'Bruk Netease Cloud Music som siste utvei når server og LRCLIB ikke finner noe. Best dekning for asiatisk og internasjonal musikk.', - lyricsSourcesTitle: 'Sangtekstkilder', - lyricsSourcesDesc: 'Velg hvilke kilder som skal brukes og i hvilken rekkefølge. Dra for å sortere. Deaktiverte kilder hoppes over.', - lyricsSourceServer: 'Tjener', - lyricsSourceLrclib: 'LRCLIB', - lyricsSourceNetease: 'Netease Cloud Music', - lyricsModeStandard: 'Standard', - lyricsModeStandardDesc: 'Tre kilder med fritt valgbar rekkefølge: server-tagger, LRCLIB, Netease.', - lyricsModeLyricsplus: 'YouLyPlus (Karaoke)', - lyricsModeLyricsplusDesc: 'Ord-for-ord-synkronisering fra Apple Music, Spotify, Musixmatch og QQ (fellesskapsbackend). Faller stille tilbake på standardkildene når ingenting finnes.', - lyricsStaticOnly: 'Vis sangtekst som statisk tekst', - lyricsStaticOnlyDesc: 'Viser synkroniserte tekster uten auto-scroll og uten ord-utheving.', - downloadsTitle: 'ZIP Eksport & Arkivering', - downloadsFolderDesc: 'Målmappe for album du laster ned som en ZIP-fil til datamaskinen din.', - downloadsDefault: 'Standard nedlastingsmappe', - pickFolder: 'Velg', - pickFolderTitle: 'Velg nedlastingsmappe', - clearFolder: 'Tøm nedlastingsmappe', - logout: 'Logg ut', - aboutTitle: 'Om Psysonic', - aboutDesc: 'En moderne musikkspiller laget for Navidrome. Bruker Subsonic-API-en pluss Navidrome-spesifikke utvidelser. Bygget på Tauri v2 med en innebygd Rust-lydmotor — lett og rask, men fullpakket med funksjoner: bølgeform-søkelinje, synkroniserte sangtekster, Last.fm-integrasjon, 10-bånds jevnstiller, crossfade, gapless-avspilling, Replay Gain, sjangerlesing og et stort bibliotek med temaer.', - aboutLicense: 'Lisens', - aboutLicenseText: 'GNU GPL v3 - gratis å bruke, endre og distribuere under samme lisens.', - aboutRepo: 'Kildekode på GitHub', - aboutVersion: 'Versjon', - aboutBuiltWith: 'Bygget med Tauri · React · TypeScript · Rust/rodio', - aboutReleaseNotesLabel: 'Versjonsnotater', - aboutReleaseNotesLink: 'Åpne nyhetene for denne versjonen', - aboutContributorsLabel: 'Bidragsytere', - showChangelogOnUpdate: "Vis 'Hva er nytt' ved oppdatering til ny versjon", - showChangelogOnUpdateDesc: "Viser et diskret changelog-banner over Now Playing etter en oppdatering. Klikk åpner versjonsnotatene; X skjuler det.", - randomMixTitle: 'Svarteliste for tilfeldig miks', - luckyMixMenuTitle: 'Vis Lykkemiks i menyen', - luckyMixMenuDesc: 'Aktiverer Lykkemiks i "Lag en miks" og som eget menypunkt når delt navigasjon er aktiv. Vises bare når AudioMuse er aktiv på gjeldende server.', - randomMixBlacklistTitle: 'Egendefinerte filternøkkelord', - randomMixBlacklistDesc: 'Sanger ekskluderes når et nøkkelord samsvarer med sjanger, tittel, album eller artist (aktiv når avkrysningsboksen ovenfor er på).', - randomMixBlacklistPlaceholder: 'Legg til nøkkelord…', - randomMixBlacklistAdd: 'Legg til', - randomMixBlacklistEmpty: 'Ingen egendefinerte nøkkelord lagt til ennå.', - randomMixHardcodedTitle: 'Innebygde nøkkelord (aktiv når avkrysningsboksen er på)', - tabPlayback: 'Avspilling', - tabLibrary: 'Bibliotek', - tabServers: 'Servere', - tabLyrics: 'Sangtekster', - tabPersonalisation: 'Personalisering', - tabIntegrations: 'Integrasjoner', - tabAppearance: 'Utseende', - tabStorage: 'Frakoblet & Cache', - inputKeybindingsTitle: 'Tastatursnarveier', - aboutContributorsCount_one: '{{count}} bidrag', - aboutContributorsCount_other: '{{count}} bidrag', - searchPlaceholder: 'Søk i innstillinger…', - searchNoResults: 'Ingen innstillinger samsvarer med søket ditt.', - aboutMaintainersLabel: 'Ansvarlige', - integrationsPrivacyTitle: 'Personvern-merknad', - integrationsPrivacyBody: 'Alle integrasjoner på denne fanen er frivillige og sender, når aktivert, data til eksterne tjenester eller til Navidrome-serveren din. Last.fm mottar lyttehistorikken din, Discord viser gjeldende spor i profilen din, Bandsintown spørres per artist for turnédatoer, og "Spilles nå"-delingen publiserer gjeldende spor til andre brukere av Navidrome-serveren din. Hvis du ikke ønsker noe av dette, la den aktuelle seksjonen stå deaktivert.', - homeCustomizerTitle: 'Hjemmeside', - queueToolbarTitle: 'Kø-verktøylinje', - queueToolbarReset: 'Tilbakestill til standard', - queueToolbarSeparator: 'Skilje', - sidebarTitle: 'Sidefelt', - sidebarReset: 'Tilbakestill til standard', - artistLayoutTitle: 'Artistsidens seksjoner', - artistLayoutDesc: 'Dra for å omorganisere, veksle for å skjule individuelle seksjoner av artistsiden. Seksjoner uten data hoppes over automatisk.', - artistLayoutReset: 'Tilbakestill til standard', - artistLayoutBio: 'Artistbiografi', - artistLayoutTopTracks: 'Toppspor', - artistLayoutSimilar: 'Lignende artister', - artistLayoutAlbums: 'Album', - artistLayoutFeatured: 'Også med på', - sidebarDrag: 'Dra for å endre rekkefølge', - sidebarFixed: 'Alltid synlig', - randomNavSplitTitle: 'Del Mix-navigasjon', - randomNavSplitDesc: 'Vis "Tilfeldig miks", "Tilfeldige album" og "Lykkemiks" som separate sidefeltsoppføringer i stedet for "Lag en miks"-huben.', - tabShortcuts: 'Snarveier', - tabUsers: 'Brukere', - tabSystem: 'System', - loggingTitle: 'Loggføring', - loggingModeDesc: 'Styrer hvor detaljert backend-loggene i terminalen er.', - loggingModeOff: 'Av', - loggingModeNormal: 'Normal', - loggingModeDebug: 'Debug', - loggingExport: 'Eksporter logger', - loggingExportSuccess: 'Logger eksportert ({{count}} linjer).', - loggingExportError: 'Kunne ikke eksportere logger.', - ratingsSectionTitle: 'Vurderinger', - ratingsSkipStarTitle: 'Hopp for 1 stjerne', - ratingsSkipStarDesc: - 'Etter flere hopp på rad: sett sporet til 1 stjerne. Bare for spor som ikke var vurdert før.', - ratingsSkipStarThresholdLabel: 'Hopp', - ratingsMixFilterTitle: 'Filtrering etter vurdering', - ratingsMixFilterDesc: - 'Filtrer innhold med lav vurdering i {{mix}} og {{albums}}. Klikk på den valgte stjerna igjen for å slå av terskelen.', - ratingsMixMinSong: 'Spor', - ratingsMixMinAlbum: 'Album', - ratingsMixMinArtist: 'Artister', - ratingsMixMinThresholdAria: 'Minimum stjerner: {{label}}', - backupTitle: 'Sikkerhetskopiering og gjenoppretting', - backupExport: 'Eksporter innstillinger', - backupExportDesc: 'Lagrer alle innstillinger, tjenerprofiler, Last.fm-konfigurasjon, tema, jevnstiller og tastebindinger til en .psybkp-fil. Passordet lagres i klartekst – hold filen sikker.', - backupImport: 'Importer innstillinger', - backupImportDesc: 'Gjenoppretter innstillinger fra en .psybkp-fil. Applikasjonen starter på nytt etter import.', - backupImportConfirm: 'Dette vil overskrive alle gjeldende innstillinger. Vil du fortsette?', - backupSuccess: 'Sikkerhetskopiering lagret', - backupImportSuccess: 'Innstillinger gjenopprettet – laster inn data på nytt…', - backupImportError: 'Ugyldig eller ødelagt fil for sikkerhetskopi.', - shortcutsReset: 'Tilbakestill til standardinnstillinger', - shortcutListening: 'Trykk på en tast…', - shortcutUnbound: '-', - globalShortcutsTitle: 'Globale snarveier', - globalShortcutsNote: 'Arbeid systemomfattende selv når Psysonic er i bakgrunnen. Krever Ctrl, Alt eller Super som modifikator.', - shortcutClear: 'Fjern', - shortcutPlayPause: 'Spill av / Pause', - shortcutNext: 'Neste spor', - shortcutPrev: 'Forrige spor', - shortcutVolumeUp: 'Volum opp', - shortcutVolumeDown: 'Volum ned', - shortcutSeekForward: 'Søk fremover 10 sekunder', - shortcutSeekBackward: 'Søk bakover 10 sekunder', - shortcutToggleQueue: 'Veksle kø', - shortcutOpenFolderBrowser: 'Åpne {{folderBrowser}}', - shortcutFullscreenPlayer: 'Fullskjermsspiller', - shortcutNativeFullscreen: 'Naturlig fullskjerm', - shortcutOpenMiniPlayer: 'Åpne minispiller', - shortcutStartSearch: 'Start et søk', - shortcutStartAdvancedSearch: 'Start et avansert søk', - shortcutToggleSidebar: 'Veksle sidefelt', - shortcutMuteSound: 'Demp lyd', - shortcutToggleEqualizer: 'Åpne / veksle Equalizer', - shortcutToggleRepeat: 'Veksle gjenta', - shortcutOpenNowPlaying: 'Åpne "Spilles nå"', - shortcutShowLyrics: 'Vis sangtekst', - shortcutFavoriteCurrentTrack: 'Legg gjeldende spor til favoritter', - shortcutOpenHelp: 'Hjelp', - playbackTitle: 'Avspilling', - replayGain: 'Replay Gain', - replayGainDesc: 'Normaliser sporvolumet ved hjelp av ReplayGain-metadata', - replayGainMode: 'Modus', - replayGainAuto: 'Auto', - replayGainAutoDesc: 'Bruker albumforsterkning når nabospor i køen er fra samme album, ellers sporforsterkning.', - replayGainTrack: 'Spor', - replayGainAlbum: 'Album', - replayGainPreGain: 'Pre-Gain (taggede filer)', - replayGainPreGainDesc: 'Universelt løft som legges på hver ReplayGain-beregning. Nyttig hvis biblioteket ditt totalt sett virker for stille.', - replayGainFallback: 'Reserveverdi (uten tagger / radio)', - replayGainFallbackDesc: 'Brukes for spor (og radiostrømmer) uten ReplayGain-tagger, slik at utagget innhold ikke spretter høyere enn resten.', - normalization: 'Normalisering', - normalizationDesc: 'Jevn ut opplevd loudness mellom spor, album og radio.', - normalizationOff: 'Av', - normalizationReplayGain: 'ReplayGain', - normalizationLufs: 'LUFS', - loudnessTargetLufs: 'Mål-LUFS', - loudnessTargetLufsDesc: 'Referanse-loudness alle spor matches mot. Lavere tall = høyere utgang. Strømmetjenester ligger vanligvis rundt -14 LUFS.', - loudnessPreAnalysisAttenuation: 'Demping før måling', - loudnessPreAnalysisAttenuationDesc: - 'Ekstra demping til loudness for sporet er lagret. Streaming bruker deretter grove anslag, ikke full måling. 0 dB = av; lavere = roligere. Til høyre vises effektiv dB for valgt mål.', - loudnessPreAnalysisAttenuationRef: 'Effektivt {{eff}} dB med mål {{tgt}} LUFS.', - loudnessPreAnalysisAttenuationReset: 'Standard', - loudnessFirstPlayNote: - 'Første avspilling av et helt nytt spor kan drive litt i volum mens målingen skjer. Neste gang brukes den lagrede målingen, og alt blir stabilt. Kommende spor i køen blir vanligvis pre-analysert mens det forrige spilles, så dette skjer sjelden i praksis.', - crossfade: 'Crossfade', - crossfadeDesc: 'Tone mellom spor', - crossfadeSecs: '{{n}}s', - notWithGapless: 'Ikke tilgjengelig mens Gapless er aktiv', - notWithCrossfade: 'Ikke tilgjengelig mens Crossfade er aktiv', - gapless: 'Gapless avspilling', - gaplessDesc: 'Forhåndsbuffer neste spor for å eliminere mellomrom mellom sanger', - preservePlayNextOrder: 'Behold "Spill neste"-rekkefølge', - preservePlayNextOrderDesc: 'Nye "Spill neste"-elementer havner bak de eksisterende i stedet for å snike seg foran.', - trackPreviewsTitle: 'Sporforhåndsvisning', - trackPreviewsToggle: 'Aktiver sporforhåndsvisning', - trackPreviewsDesc: 'Vis innebygde Spill- og Forhåndsvisning-knapper i sporlister for en kort smakebit fra midten av sangen.', - trackPreviewStart: 'Startposisjon', - trackPreviewStartDesc: 'Hvor langt inn i sporet forhåndsvisningen starter (% av lengden).', - trackPreviewDuration: 'Varighet', - trackPreviewDurationDesc: 'Hvor lenge hver forhåndsvisning spiller før den stopper.', - trackPreviewDurationSecs: '{{n}} s', - trackPreviewLocationsTitle: 'Hvor forhåndsvisninger vises', - trackPreviewLocationsDesc: 'Velg hvilke lister som viser forhåndsvisningsknapper.', - trackPreviewLocation_suggestions: 'I spillelisteforslag', - trackPreviewLocation_albums: 'I albumsporlister', - trackPreviewLocation_playlists: 'I spillelister', - trackPreviewLocation_favorites: 'I favoritter', - trackPreviewLocation_artist: 'I artistens toppspor', - trackPreviewLocation_randomMix: 'I Random Mix', - infiniteQueue: 'Uendelig kø', - infiniteQueueDesc: 'Legg automatisk til tilfeldige spor når køen går tom', - experimental: 'Eksperimentell', - preloadMode: 'Forhåndslast neste spor', - preloadModeDesc: 'Når buffering av neste spor i køen skal starte', - nextTrackBufferingTitle: 'Bufring', - preloadHotCacheMutualExclusive: 'Forhåndslasting og Hot Cache tjener samme formål – bare én kan være aktiv om gangen. Å aktivere den ene deaktiverer automatisk den andre.', - preloadOff: 'Av', - preloadBalanced: 'Balansert (30 s før slutt)', - preloadEarly: 'Tidlig (etter 5 s avspilling)', - preloadCustom: 'Egendefinert', - preloadCustomSeconds: 'Sekunder før slutt: {{n}}', - fsPlayerSection: 'Fullskjermspiller', - fsShowArtistPortrait: 'Vis artistbilde', - fsShowArtistPortraitDesc: 'Vis artistbilde (eller albumomslag) på høyre side av fullskjermspilleren.', - fsPortraitDim: 'Mørklegging av bilde', - fsLyricsStyle: 'Tekststil', - fsLyricsStyleRail: 'Skinner', - fsLyricsStyleRailDesc: 'Klassisk 5-linjes glidende skinner.', - fsLyricsStyleApple: 'Rulling', - fsLyricsStyleAppleDesc: 'Fullskjerm rulleliste.', - sidebarLyricsStyle: 'Rullestil for tekst', - sidebarLyricsStyleClassic: 'Klassisk', - sidebarLyricsStyleClassicDesc: 'Aktiv linje sentreres.', - sidebarLyricsStyleApple: 'Apple Music-like', - sidebarLyricsStyleAppleDesc: 'Aktiv linje forankres øverst med jevn animasjon.', - seekbarStyle: 'Søkefelt-stil', - seekbarStyleDesc: 'Velg utseendet på avspillingssøkefeltet', - seekbarTruewave: 'Ekte bølgeform', - seekbarPseudowave: 'Pseudo-bølgeform', - seekbarLinedot: 'Linje & punkt', - seekbarBar: 'Linje', - seekbarThick: 'Tykk linje', - seekbarSegmented: 'Segmentert', - seekbarNeon: 'Neon', - seekbarPulsewave: 'Pulsbølge', - seekbarParticletrail: 'Partikkelspor', - seekbarLiquidfill: 'Væskerør', - seekbarRetrotape: 'Retrotape', - themeSchedulerTitle: 'Tidsplanlagt tema', - themeSchedulerEnable: 'Aktiver temaplanlegger', - themeSchedulerEnableSub: 'Bytter automatisk mellom to temaer basert på tidspunkt', - themeSchedulerDayTheme: 'Dagtema', - themeSchedulerDayStart: 'Dag starter kl.', - themeSchedulerNightTheme: 'Natttema', - themeSchedulerNightStart: 'Natt starter kl.', - themeSchedulerActiveHint: 'Temaplanlegger er aktiv - temaer byttes automatisk.', - visualOptionsTitle: 'Visuelle Alternativer', - coverArtBackground: 'Cover-bakgrunn', - coverArtBackgroundSub: 'Vis uskarpt cover som bakgrunn i album/playlist-overskrifter', - playlistCoverPhoto: 'Playlist-coverfoto', - playlistCoverPhotoSub: 'Vis coverfoto-rutenett i playlist-detailedvisning', - showBitrate: 'Vis Bitrate', - showBitrateSub: 'Vis audio-bitrate i sporlister', - floatingPlayerBar: 'Flytende Spillerlinje', - floatingPlayerBarSub: 'Hold spillerlinjen flytende over innholdet', - uiScaleTitle: 'Grensesnittskala', - uiScaleLabel: 'Zoom', - }, - changelog: { - modalTitle: "Nyheter", - dontShowAgain: "Ikke vis igjen", - close: 'Forstått', - }, - whatsNew: { - title: 'Nyheter', - empty: 'Ingen endringslogg for denne versjonen ennå.', - bannerTitle: 'Changelog', - bannerCollapsed: 'Nyheter i v{{version}}', - dismiss: 'Skjul', - close: 'Lukk', - }, - help: { - title: 'Hjelp', - searchPlaceholder: 'Søk i hjelpen…', - noResults: 'Ingen treff. Prøv et annet søkeord.', - s1: 'Komme i gang', - q1: 'Hvilke servere er kompatible?', - a1: 'Psysonic er primært bygget for Navidrome og er fullt Subsonic-kompatibel — Gonic, Airsonic, LMS og andre Subsonic-API-servere fungerer også. Noen avanserte funksjoner (vurderinger, smarte spillelister, Magic-String-deling, brukerhåndtering) krever Navidrome.', - q2: 'Hvordan legger jeg til en server?', - a2: 'Innstillinger → Servere → Legg til server. Skriv inn URL (f.eks. http://192.168.1.100:4533), brukernavn og passord. Psysonic tester tilkoblingen før lagring — ingenting lagres ved feil. Du kan legge til så mange servere du vil og bytte mellom dem i toppen; bare én er aktiv om gangen.', - q3: 'Rask UI-omvisning?', - a3: 'Sidefelt (venstre) for navigasjon, Mainstage / sider i midten, spillerbaren nederst, kø-panelet til høyre (åpnes via ikonet øverst til høyre ved siden av Now-Playing-indikatoren). Søkefeltet øverst søker i hele biblioteket; «Now Playing» viser hva andre brukere på samme Navidrome-server hører på akkurat nå.', - s2: 'Avspilling & Kø', - q4: 'Hvordan bruker jeg køen?', - a4: 'Åpne kø-panelet fra toppen til høyre. Dra rader for å omorganisere, dra dem utenfor for å fjerne, eller bruk verktøylinjen for å blande, lagre køen som spilleliste eller hoppe til en låt. Dra rader ut av panelet for å slippe dem et annet sted som overføring.', - q5: 'Gapless vs Crossfade — hva er forskjellen?', - a5: 'Gapless forhåndslager neste låt slik at det er null stillhet mellom låtene (ideelt for liveplater og DJ-mikser). Crossfade toner gjeldende låt ut mens neste tones inn over 1–10 s (ideelt for blandede mikser). De er gjensidig utelukkende — å aktivere én deaktiverer den andre. Konfigureres i Innstillinger → Lyd.', - q6: 'Hva er Infinite Queue?', - a6: 'Når køen tar slutt og Gjenta er av, legger Psysonic stille til lignende/tilfeldige låter fra biblioteket ditt slik at avspillingen aldri stopper. Auto-lagte låter vises under et «— Lagt til automatisk —»-skille. Slå på/av via uendelighetssymbolet i kø-toppen; begrens auto-tilføyelser til en sjanger i Innstillinger → Kø.', - q7: 'Multi-utvalg og Shift-klikk-rekkevidde?', - a7: 'Aktiver «Velg» på Album / Nye utgivelser / Random Albums / Spillelister. Klikk et element for å veksle, hold deretter Shift og klikk et annet element — alt mellom dem i synlig rekkefølge blir valgt. Shift-klikk utvider fra det sist klikkede ankerpunktet. Verktøylinjen over rutenettet tilbyr handlinger for flere (kø, nedlasting, sletting, osv.).', - q8: 'Tastatursnarveier og globale hurtigtaster?', - a8: 'Standard i-app-taster: Mellomrom = Spill / Pause, Esc = lukk fullskjerm / modaler, F1 = snarveisreferanse. Innstillinger → Inndata lar deg tilbakestille hver i-app-handling (inkludert akkorder som Ctrl+Shift+P) og sette systemomfattende globale snarveier som virker selv når Psysonic er i bakgrunnen. Mediataster (Spill/Pause, Neste, Forrige) virker på alle plattformer.', - s3: 'Lydverktøy', - q9: 'Replay Gain-modi?', - a9: 'Innstillinger → Lyd → Replay Gain. Spor-modus normaliserer hver låt til et målnivå. Album-modus bevarer lydstyrkekurven innen et album. Auto-modus velger Spor eller Album basert på om køen kommer fra ett enkelt album. Spor uten Replay Gain-tagger faller tilbake til en konfigurerbar forforsterker.', - q10: 'Hva er Smart Loudness Normalization (LUFS)?', - a10: 'Et moderne alternativ til Replay Gain i Innstillinger → Lyd. Psysonic analyserer hver låt til LUFS / EBU R128 og lagrer resultatet, så lyden er konsistent på tvers av hele biblioteket — også låter uten Replay Gain-tagger. Cold-cache-analyse kjører i bakgrunnen og bruker 35–40 % CPU i ~1 minutt, deretter 0. Sett målnivået (standard −10 LUFS) én gang.', - q11: 'EQ og AutoEQ?', - a11: 'En 10-bånds parametrisk EQ i Innstillinger → Lyd → Equalizer med manuelle bånd og forhåndsinnstillinger. AutoEQ ved siden av henter en målt korreksjonsprofil for hodetelefonmodellen din fra AutoEQ-databasen og bruker den automatisk på båndene — velg hodetelefonene dine, EQ-en låser på riktig kurve.', - q12: 'Hvordan bytter jeg lydutgangsenhet?', - a12: 'Innstillinger → Lyd → Utgangsenhet. Psysonic lister alle tilgjengelige utganger og bytter umiddelbart når du velger. Oppdater-knappen finner enheter som ble koblet til etter oppstart. Linux ALSA-navn som «sysdefault» blir auto-renset for lesbarhet.', - q13: 'Hva er Hot Cache?', - a13: 'Hot Cache forhåndslaster gjeldende låt pluss de neste i RAM og på disk slik at avspillingen starter uten buffer-forsinkelse — særlig nyttig på trege / fjerne servere. Eviksjon utløses når størrelsesgrensen nås. Konfigurer størrelse og debounce-forsinkelse (slik at raske skip ikke overhenter) i Innstillinger → Lyd.', - s4: 'Bibliotek & Oppdagelse', - q14: 'Hvordan fungerer vurderinger og Skip-to-1★?', - a14: 'Psysonic støtter 1–5-stjerners vurderinger via OpenSubsonic (Navidrome ≥ 0.53). Vurder låter i sporlister, i høyreklikkmenyen eller i spillerbaren under artistnavnet; album på albumsiden; artister på artistsiden. Skip-to-1★ (Innstillinger → Bibliotek → Vurderinger) gir automatisk 1 stjerne etter et konfigurerbart antall sammenhengende skip. Samme panel lar deg sette en minimum vurdering for genererte mikser.', - q15: 'Hvordan blar jeg — Mapper, Sjangre, Spor?', - a15: 'Mappebrowseren (sidefelt) går gjennom serverens musikkmappe i Miller-kolonneoppsett — klikk en mappe for å gå inn, klikk en låt eller spillikonet på en mappe for å spille / legge til. Sjangre bruker en tag-sky-visning skalert etter antall spor; klikk en sjanger for å åpne. Spor er en flat bibliotekshub med kolonnesorterbar virtuell liste og live søk.', - q16: 'Søk og avansert søk?', - a16: 'Søkefeltet i toppen kjører rask live-søk på artister, album og spor mens du skriver. Åpne Avansert søk (sidefelt) for en rikere visning: filtrer etter år, sjanger, vurdering, format, kanaler, samplingsfrekvens, BPM, stemning, og kombiner kriterier. Høyreklikk på et resultat for samme kontekstmeny som ellers.', - q17: 'Hva er Mixene (Random / Sjanger / Super Genre / Lucky)?', - a17: 'Random Mix bygger en spilleliste av tilfeldige låter fra biblioteket; Nøkkelordfilteret ekskluderer lydbøker, komedie etc. ved hjelp av sjanger / tittel / album-undertekster. Super Genre Mix grupperer biblioteket i brede stiler (Rock, Metal, Elektronisk, Jazz, Klassisk …) og bygger en fokusert miks. Lucky Mix bruker lyttehistorikk, vurderinger og AudioMuse-AI-lignende spor for å sette sammen en spilleliste med ett klikk.', - q18: 'Statistikkside?', - a18: 'Statistikk (sidefelt) viser topp artister, topp album, topp spor, sjangerfordeling, lyttetid over tid, og per-bibliotek-omfang når du har flere musikkmapper konfigurert. Flere visninger kan eksporteres som delbart kortbilde.', - q19: 'Hvordan laster jeg ned et album som ZIP?', - a19: 'Albumside → «Last ned (ZIP)». Serveren komprimerer albumet først — for store eller tapsfrie album (FLAC / WAV) vises fremdriftsfeltet først når zipping er fullført og overføringen begynner. Dette er normalt.', - s5: 'Lyrikk', - q20: 'Hvor kommer lyrikken fra?', - a20: 'Tre kilder, konfigurerbare i Innstillinger → Lyrikk: Navidrome-serveren (innebygd / OpenSubsonic-lyrikk), LRCLIB (felles synkroniserte tekster) og NetEase Cloud Music (stort asiatisk + internasjonalt katalog). Hver kilde kan aktiveres / deaktiveres og prioriteres ved drag.', - q21: 'Hvordan ser jeg lyrikk under avspilling?', - a21: 'Klikk på mikrofonikonet i spillerbaren for å åpne Lyrikk-fanen i kø-panelet. Synkronisert lyrikk auto-skroller og støtter klikk-for-å-hoppe; klartekst skroller som en statisk blokk. Veksle Fullskjermspilleren via spillerbarens cover for en oppslukende lyrikk-visning med mesh-blob-bakgrunn.', - s6: 'Deling & Sosialt', - q22: 'Hva er Magic Strings?', - a22: 'Magic Strings er korte kopier-lim-tokens som deler ting mellom Psysonic-brukere uten noen tredjeparts server. Server-Invite-strenger lar en venn onboarde til Navidrome-serveren din med ett lim; Album- / Artist- / Kø Magic Strings åpner samme album / artist / kø hos mottaker. Generer fra del-menyen, lim dem inn i søkefeltet for å bruke.', - q23: 'Hva er Orbit?', - a23: 'Orbit er synkronisert lytte-sammen: en vert spiller en låt, hver gjest hører den synkront, og gjester kan foreslå låter verten kan godta i køen. Start en økt fra Orbit-knappen i toppen, del invitasjonslenken, og andre kan bli med fra hvilken som helst Psysonic-installasjon. Verten eier avspillingen (skip, søk, kø) — gjester får sanntidsvisning og en forslagsboks. Økter er flyktige og avsluttes når verten lukker dem.', - q24: 'Hva er Now Playing-rullegardinen?', - a24: 'Kringkastingsikonet øverst til høyre viser hva andre brukere på Navidrome-serveren din hører på akkurat nå, oppdatert hvert 10. sekund. Din egen oppføring forsvinner i det øyeblikket du pauser. Per-server, så brukere på en annen aktiv server vises ikke.', - s7: 'Personalisering', - q25: 'Temaer og temaplanlegger?', - a25: 'Innstillinger → Utseende → Tema velger fra 60+ temaer i 8 grupper (Psysonic, Mediaplayer, Operativsystemer, Spill, Filmer, Serier, Sosiale medier, Open Source Classics — Catppuccin / Nord / Gruvbox / Nightfox / Dracula). Auto-Switch Theme lar deg sette et dag-tema + natt-tema med starttider slik at Psysonic bytter automatisk.', - q26: 'Kan jeg tilpasse Sidefeltet, Hjem og Artistside?', - a26: 'Ja — Innstillinger → Personalisering. Sidefelt-tilpasseren lar deg dra nav-elementer i ønsket rekkefølge og skjule de du ikke bruker. Hjem-tilpasseren slår av/på hver Mainstage-rad (Hero, Recent, Discover, Recently Played, Starred …). Artistside-tilpasseren omorganiserer seksjonene (Topplåter, Album, Singler, Compilations, Lignende artister, etc.) og lar deg skjule de du aldri ser på.', - q27: 'Hva er Mini Player?', - a27: 'Et lite flytende vindu med cover, transport-kontroller og en kompakt kø. Åpnes fra mini-player-ikonet i spillerbaren eller med tastatursnarveien. Vinduet husker posisjon og størrelse mellom økter. På Windows opprettes mini-webview-en på forhånd ved oppstart slik at åpningen er umiddelbar; Linux / macOS aktiverer dette via Innstillinger → Utseende → Forhåndslast mini-spiller.', - q28: 'Hva er Floating Player Bar?', - a28: 'En valgfri spillerbar-stil (Innstillinger → Utseende) som løsriver seg fra bunnkanten med tema-bakgrunn, accent-kant, avrundet albumcover og en sentrert volum-seksjon. Nyttig på høye skjermer eller kompakte temaer.', - q29: 'Spor-forhåndsvisning ved hover?', - a29: 'Hover over en sporrad, klikk den lille forhåndsvisning-knappen på coveret, eller utløs forhåndsvisning fra høyreklikkmenyen — Psysonic strømmer de første ~15 s gjennom samme Rust-lyd-engine slik at lydstyrkenormalisering gjelder. Nyttig for å bla gjennom et album du ikke har hørt før.', - q30: 'Sleep timer?', - a30: 'Klikk på måneikonet i spillerbaren for å åpne sleep timer. Velg en varighet (eller «slutten av nåværende låt») og Psysonic toner ut og pauser ved slutten. Knappen viser en sirkulær ring og en innebygd nedtelling mens timeren går.', - q31: 'UI-skala, font, seekbar-stil?', - a31: 'Innstillinger → Utseende — Grensesnitt-skala (80–125 % uten å påvirke systemets fontstørrelse), Font (10 UI-fonter inkludert IBM Plex Mono, Fira Code, Geist, Golos Text…), Seekbar-stil (Bølgeform analysert / pseudobølge deterministisk / Linje & Punkt / Bjelke / Tykk Bjelke / Segmentert / Neon-Glow / Pulsbølge / Partikkelspor / Flytende Fyll / Retro Tape).', - s8: 'Power User', - q32: 'CLI player-kontroller?', - a32: 'Psysonic-binæren fungerer også som fjernkontroll. Eksempler: psysonic --player play / pause / next / prev, --player volume 75, --player seek 15, --player shuffle, --player repeat off|all|one, --player rating 1-5. Bytt servere, lydenheter, biblioteker; utløs Instant Mix; søk artister / album / spor. Komplett liste med psysonic --player --help. Shell-fullføring for bash og zsh via psysonic completions.', - q33: 'Smarte spillelister (Navidrome)?', - a33: 'Smarte spillelister er Navidrome-side dynamiske spillelister definert av regler (sjanger = Rock OG år > 2020, etc.). Spillelister-siden i Psysonic lar deg opprette, redigere og slette dem med en visuell regelredigerer — Psysonic snakker med Navidromes native API for det. De oppfører seg som vanlige spillelister i resten av appen og oppdateres automatisk når biblioteket endres.', - q34: 'Sikkerhetskopiere og gjenopprette innstillinger?', - a34: 'Innstillinger → Lagring → Sikkerhetskopi & Gjenoppretting eksporterer serverprofiler, temaer, snarveier og andre innstillinger til en enkelt JSON-fil. Importer den på en annen maskin eller etter en reinstallasjon for å gjenopprette alt. Server-passord er inkludert — hold filen privat.', - q35: 'Hvor ser jeg alle åpen kildekode-lisenser?', - a35: 'Innstillinger → System → Open Source Licenses. Den fullstendige avhengighetslisten (cargo crates og npm-pakker) leveres med innebygde lisenstekster. Klikk på en oppføring for full tekst; det kuraterte fremhevingsblokket øverst viser de brukerkjente bibliotekene (Tauri, React, rodio, symphonia, etc.).', - s9: 'Offline & Sync', - q36: 'Offline-modus — cache album og spillelister?', - a36: 'Åpne et album eller en spilleliste og klikk på nedlastingsikonet i headeren — Psysonic cacher hver låt lokalt slik at den spilles av fra disk uten nettverkskall. Offline Library-siden (sidefelt) viser alt som er cachet, viser fremdrift under nedlasting, og lar deg fjerne med søppelbøtte-ikonet (som vises etter at en nedlasting er fullført).', - q37: 'Offline-lagringsgrense?', - a37: 'Innstillinger → Bibliotek → Offline lar deg sette en maksimal cache-størrelse. Når grensen nås, viser albumsidens nedlastingsknapp et advarselsbanner. Frigjør plass ved å fjerne album eller spillelister fra Offline Library-siden.', - q38: 'Device Sync — kopiere musikk til USB / SD?', - a38: 'Device Sync (sidefelt) kopierer album, spillelister eller hele artister til en ekstern stasjon for offline lytting på andre enheter. Velg en målmappe, velg kilder fra browserfanene, klikk «Overfør til enhet». Psysonic skriver et manifest (psysonic-sync.json) slik at det vet hvilke filer som allerede er der, selv hvis du åpner Device Sync på et annet OS med en annen filnavn-mal. Maler støtter {artist} / {album} / {title} / {track_number} / {disc_number} / {year}-tokens med / som mappe-skille.', - s10: 'Integrasjoner & Feilsøking', - q39: 'Last.fm-scrobbling?', - a39: 'Innstillinger → Integrasjoner → Last.fm. Koble til kontoen din én gang og Psysonic scrobbler direkte til Last.fm — ingen Navidrome-konfigurasjon trengs. En scrobble sendes etter at du har hørt 50 % av en låt. Now-playing-pings sendes ved start.', - q40: 'Discord Rich Presence?', - a40: 'Innstillinger → Integrasjoner → Discord viser gjeldende låt på Discord-profilen din. Velg mellom app-ikonet, serverens cover-art (via getAlbumInfo2 — krever en offentlig nåbar server), eller Apple Music-cover. Tilpass visningsstrenger (detaljer, tilstand, verktøytips) med token-maler.', - q41: 'Bandsintown-turnedato?', - a41: 'Opt-in under Innstillinger → Integrasjoner → Now-Playing Info. Now Playing-fanen på Now Playing-siden viser deretter kommende turnedater for artisten som spiller via Bandsintown widget API. Av som standard — ingen forespørsler gjøres før du aktiverer.', - q42: 'Internet Radio — spille livestrømmer?', - a42: 'Internet Radio (sidefelt) spiller enhver livestrøm lagret på Navidrome-serveren din (legg til stasjoner via Navidrome admin UI). Avspilling kjører gjennom nettleserens HTML5-lyd-engine — de fleste EQ / Replay Gain / Loudness-innstillinger gjelder ikke for radio, men ICY-metadata (gjeldende låtnavn) vises. Støtter MP3, AAC, OGG Vorbis og de fleste HLS-strømmer; codec-støtte avhenger av plattformen.', - q43: 'Tilkoblingstesten feiler — hva nå?', - a43: 'Dobbeltsjekk URL-en inkludert porten (f.eks. http://192.168.1.100:4533). På et lokalt nettverk virker http:// ofte der https:// ikke gjør (intet sertifikat). Sørg for at ingen brannmur blokkerer porten og at brukernavn og passord er korrekte. Hvis serveren er bak en omvendt proxy, prøv først direkte URL for å isolere årsaken.', - q44: 'Cover-art og artistbilder lastes sakte.', - a44: 'Bilder hentes fra serveren ved første visning og caches deretter lokalt i 30 dager. Hvis serverens lagring er treg, kan første besøk på en side ta et øyeblikk; påfølgende besøk er umiddelbare. Hot Cache hjelper også for spor, men bildecachen er uavhengig.', - q45: 'Linux-problemer — svart skjerm eller ingen lyd?', - a45: 'Svart skjerm er vanligvis et GPU- / EGL-driverproblem i WebKitGTK — start med GDK_BACKEND=x11 WEBKIT_DISABLE_COMPOSITING_MODE=1 WEBKIT_DISABLE_DMABUF_RENDERER=1 (AUR / .deb / .rpm-installerne setter disse automatisk). For lyd, sørg for at PipeWire eller PulseAudio kjører. Lydutfall etter dvale / oppvåkning håndteres nå automatisk av post-sleep recovery hook.', - }, - queue: { - title: 'Kø', - savePlaylist: 'Lagre spilleliste', - updatePlaylist: 'Oppdater spilleliste', - filterPlaylists: 'Filtrer spillelister…', - playlistName: 'Spillelistenavn', - cancel: 'Avbryt', - save: 'Lagre', - loadPlaylist: 'Last inn spilleliste', - loading: 'Laster…', - noPlaylists: 'Ingen spillelister funnet.', - load: 'Erstatt kø og spill av', - appendToQueue: 'Legg til i kø', - delete: 'Slett', - deleteConfirm: 'Slett spillelisten "{{name}}"?', - clear: 'Fjern', - shuffle: 'Bland kø', - gapless: 'Uten mellomrom', - crossfade: 'Crossfade', - infiniteQueue: 'Uendelig kø', - autoAdded: '- Lagt til automatisk -', - radioAdded: '- Radio -', - hide: 'Skjul', - hideNowPlaying: 'Skjul avspillingsinfo', - showNowPlaying: 'Vis avspillingsinfo', - close: 'Lukk', - nextTracks: 'Neste spor', - shareQueue: 'Kopiér lenke til kø', - shareQueueEmpty: 'Køen er tom — ingenting å dele.', - emptyQueue: 'Køen er tom.', - trackSingular: 'spor', - trackPlural: 'spor', - showRemaining: 'Vis gjenværende tid', - showTotal: 'Vis total tid', - showEta: 'Vis estimert sluttid', - replayGain: 'ReplayGain', - rgTrack: 'T {{db}} dB', - rgAlbum: 'A {{db}} dB', - rgPeak: 'Topp {{pk}}', - sourceOffline: 'Spiller fra offlinebibliotek', - sourceHot: 'Spiller fra cache', - sourceStream: 'Spiller fra nettverksstrøm', - clearCachedLoudnessWaveform: 'Clear cached loudness and waveform, then re-analyze this track', - recalculatingLoudnessWaveform: 'Recalculating loudness and waveform for this track…', - }, - miniPlayer: { - showQueue: 'Vis kø', - hideQueue: 'Skjul kø', - pinOnTop: 'Hold øverst', - pinOff: 'Løsne', - openMainWindow: 'Åpne hovedvindu', - close: 'Lukk', - emptyQueue: 'Køen er tom', - }, - statistics: { - title: 'Statistikk', - recentlyPlayed: 'Nylig spilt', - mostPlayed: 'Mest spilte album', - highestRated: 'Høyest rangerte album', - genreDistribution: 'Sjangerfordeling (Topp 20)', - loadMore: 'Last inn mer', - statArtists: 'Artister', - statArtistsTooltip: 'Kun albumartister — artister som bare opptrer som sporartist (featuring, gjest, osv.) uten eget album telles ikke med.', - statAlbums: 'Album', - statSongs: 'Sanger', - statGenres: 'Sjangere', - statPlaytime: 'Total spilletid', - genreInsights: 'Sjangerinnsikt', - formatDistribution: 'Formatdistribusjon', - formatSample: 'Utvalg av {{n}} spor', - computing: 'Utregner…', - genreSongs: '{{count}} Sanger', - genreAlbums: '{{count}} Album', - recentlyAdded: 'Nylig lagt til', - decadeDistribution: 'Album etter tiår', - decadeAlbums_one: '{{count}} Album', - decadeAlbums_other: '{{count}} Album', - decadeUnknown: 'Ukjent', - lfmTitle: 'Last.fm Statistikk', - lfmTopArtists: 'Toppartister', - lfmTopAlbums: 'Toppalbum', - lfmTopTracks: 'Toppspor', - lfmPlays: '{{count}} avspillinger', - lfmPeriodOverall: 'Alltid', - lfmPeriod7day: '7 dager', - lfmPeriod1month: '1 måned', - lfmPeriod3month: '3 måneder', - lfmPeriod6month: '6 måneder', - lfmPeriod12month: '12 måneder', - lfmNotConnected: 'Koble til Last.fm i Innstillinger for å se statistikken din.', - lfmRecentTracks: 'Siste Scrobble-innslag', - lfmNowPlaying: 'Spilles nå', - lfmJustNow: 'akkurat nå', - lfmMinutesAgo: 'For {{n}}m siden', - lfmHoursAgo: 'For {{n}}t siden', - lfmDaysAgo: 'For {{n}}d siden', - topRatedSongs: 'Høyest vurderte spor', - topRatedArtists: 'Høyest vurderte artister', - noRatedSongs: 'Ingen vurderte spor ennå. Vurder spor i album- eller spillelistevisning.', - noRatedArtists: 'Ingen vurderte artister ennå.', - }, - player: { - regionLabel: 'Musikkspiller', - openFullscreen: 'Åpne fullskjermsspiller', - fullscreen: 'Fullskjermsspiller', - closeFullscreen: 'Lukk fullskjerm', - closeTooltip: 'Lukk (Esc)', - noTitle: 'Ingen tittel', - stop: 'Stopp', - prev: 'Forrige spor', - play: 'Spill av', - pause: 'Pause', - previewActive: 'Forhåndsvisning spilles av', - previewLabel: 'Forhåndsvisning', - delayModalTitle: 'Tidsur', - delayPauseSection: 'Pause etter', - delayStartSection: 'Start etter', - delayPreviewPause: 'Pause kl.', - delayPreviewStart: 'Start kl.', - delaySchedulePause: 'Planlegg pause', - delayScheduleStart: 'Planlegg start', - delayCancelPause: 'Avbryt pause-timer', - delayCancelStart: 'Avbryt start-timer', - delayInactivePause: 'Kun tilgjengelig under avspilling.', - delayInactiveStart: 'Kun i pause med spor eller radio lastet.', - delayCustomMinutes: 'Egen forsinkelse (minutter)', - delayCustomPlaceholder: 'f.eks. 2,5', - closeDelayModal: 'Lukk', - delayIn: 'om', - delayFmtSec: '{{n}} s', - delayFmtMin: '{{n}} min', - delayFmtHr: '{{n}} t', - delayCancel: 'Avbryt', - delayApply: 'Bruk', - next: 'Neste spor', - repeat: 'Gjenta', - repeatOff: 'Av', - repeatAll: 'Alle', - repeatOne: 'Én', - progress: 'Sangfremdrift', - volume: 'Volum', - toggleQueue: 'Veksle kø', - collapseQueueResize: 'Skjul kø, endre bredde', - moreOptions: 'Flere alternativer', - equalizer: 'Equalizer', - miniPlayer: 'Minispiller', - lyrics: 'Sangtekst', - fsLyricsToggle: 'Sangtekst i fullskjerm', - lyricsLoading: 'Laster sangtekst…', - lyricsNotFound: 'Ingen sangtekst funnet for dette sporet', - lyricsSourceServer: 'Kilde: Server', - lyricsSourceLrclib: 'Kilde: LRCLIB', - lyricsSourceNetease: 'Kilde: Netease', - lyricsSourceLyricsplus: 'Kilde: YouLyPlus', - showDuration: 'Vis varighet', - showRemainingTime: 'Vis gjenværende tid', - }, - nowPlayingInfo: { - tab: 'Info', - empty: 'Spill noe for å se info', - artist: 'Artist', - songInfo: 'Sporinfo', - onTour: 'På turné', - noTourEvents: 'Ingen kommende konserter', - tourLoading: 'Laster…', - poweredByBandsintown: 'Turnédata via Bandsintown', - bioReadMore: 'Vis mer', - bioReadLess: 'Vis mindre', - showMoreTours_one: 'Vis {{count}} til', - showMoreTours_other: 'Vis {{count}} til', - showLessTours: 'Vis mindre', - enableBandsintownPrompt: 'Vis kommende turnédatoer?', - enableBandsintownPromptDesc: 'Valgfritt. Henter konserter for gjeldende artist via det offentlige Bandsintown-API-et.', - enableBandsintownPrivacy: 'Ved aktivering sendes navnet på artisten som spilles av til Bandsintown-API-et for å hente turnédatoer. Ingen konto- eller personopplysninger forlater enheten din.', - enableBandsintownAction: 'Aktiver', - role: { - artist: 'Artist', - albumArtist: 'Albumartist', - composer: 'Komponist', - }, - }, - songInfo: { - title: 'Sanginfo', - songTitle: 'Tittel', - artist: 'Artist', - album: 'Album', - albumArtist: 'Albumartist', - year: 'År', - genre: 'Sjanger', - duration: 'Varighet', - track: 'Spor', - format: 'Format', - bitrate: 'Bitrate', - sampleRate: 'Samplingfrekvens', - bitDepth: 'Bitdybde', - channels: 'Kanaler', - fileSize: 'Filstørrelse', - path: 'Sti', - replayGainTrack: 'RG-sporforsterkning', - replayGainAlbum: 'RG-albumforsterkning', - replayGainPeak: 'RG-sportopp', - mono: 'Mono', - stereo: 'Stereo', - }, - playlists: { - title: 'Spillelister', - newPlaylist: 'Ny spilleliste', - unnamed: 'Navnløs spilleliste', - createName: 'Spillelistenavn…', - create: 'Opprett', - cancel: 'Avbryt', - empty: 'Ingen spillelister ennå.', - emptyPlaylist: 'Denne spillelisten er tom.', - addFirstSong: 'Legg til din første sang', - notFound: 'Spillelisten ble ikke funnet.', - songs: '{{n}} sanger', - playAll: 'Spill alle', - shuffle: 'Bland', - addToQueue: 'Legg til i kø', - back: 'Tilbake til spillelister', - deletePlaylist: 'Slett', - confirmDelete: 'Klikk igjen for å bekrefte', - removeSong: 'Fjern fra spilleliste', - addSongs: 'Legg til sanger', - searchPlaceholder: 'Søk i biblioteket ditt…', - noResults: 'Ingen resultater.', - suggestions: 'Foreslåtte sanger', - noSuggestions: 'Ingen forslag tilgjengelig.', - titleBadge: 'Spilleliste', - refreshSuggestions: 'Nye forslag', - addSong: 'Legg til i spilleliste', - preview: 'Forhåndsvisning (30 s)', - previewStop: 'Stopp forhåndsvisning', - playNextSuggestion: 'Spill som neste', - suggestionsHint: 'Dobbeltklikk på en rad for å legge den til i spillelisten', - addSelected: 'Legg til valgte', - cacheOffline: 'Bufre spilleliste offline', - offlineCached: 'Spilleliste bufret', - removeOffline: 'Fjern fra offline-buffer', - offlineDownloading: 'Bufre… ({{done}}/{{total}} album)', - publicLabel: 'Offentlig', - privateLabel: 'Privat', - editMeta: 'Rediger spilleliste', - editNamePlaceholder: 'Spillelistenavn…', - editCommentPlaceholder: 'Legg til en beskrivelse…', - editPublic: 'Offentlig spilleliste', - editSave: 'Lagre', - editCancel: 'Avbryt', - changeCover: 'Endre omslagsbilde', - changeCoverLabel: 'Endre bilde', - removeCover: 'Fjern bilde', - coverUpdated: 'Omslag oppdatert', - metaSaved: 'Spillelisten er oppdatert', - downloadZip: 'Last ned (ZIP)', - // Toast notifications for multi-select - addSuccess: '{{count}} sanger lagt til i {{playlist}}', - addPartial: '{{added}} lagt til, {{skipped}} hoppet over (duplikater)', - addAllSkipped: 'Alle hoppet over ({{count}} duplikater)', - addedAsDuplicates: '{{count}} sanger lagt til i {{playlist}} (som duplikater)', - duplicateConfirmTitle: 'Allerede i spillelisten', - duplicateConfirmMessage: 'Alle {{count}} sanger finnes allerede i "{{playlist}}". Legg dem til likevel som duplikater?', - duplicateConfirmAction: 'Legg til likevel', - addError: 'Feil ved å legge til sanger', - createAndAddSuccess: 'Spilleliste "{{playlist}}" opprettet med {{count}} sanger', - createError: 'Feil ved oppretting av spilleliste', - deleteSuccess: '{{count}} spillelister slettet', - deleteFailed: 'Feil ved sletting av {{name}}', - deleteSelected: 'Slett valgte', - deleteSelectedPartial: 'Bare {{n}} av {{total}} valgte spillelister kan slettes (de andre tilhører noen andre).', - mergeSuccess: '{{count}} sanger slått sammen i {{playlist}}', - mergeNoNewSongs: 'Ingen nye sanger å legge til', - mergeError: 'Feil ved sammenslåing av spillelister', - mergeInto: 'Slå sammen i', - selectionCount: '{{count}} valgt', - select: 'Velg', - startSelect: 'Aktiver valg', - cancelSelect: 'Avbryt', - loadingAlbums: 'Løser {{count}} album…', - loadingArtists: 'Løser {{count}} artister…', - myPlaylists: 'Mine spillelister', - noOtherPlaylists: 'Ingen andre spillelister tilgjengelig', - addToPlaylistSuccess: '{{count}} sanger lagt til i {{playlist}}', - addToPlaylistNoNew: 'Ingen nye sanger for {{playlist}}', - addToPlaylistError: 'Feil ved å legge til i spilleliste', - removeSuccess: 'Sang fjernet fra spilleliste', - removeError: 'Feil ved fjerning fra spilleliste', - importCSV: 'Importer CSV', - importCSVTooltip: 'Importer fra Spotify CSV', - csvImportReport: 'CSV-importrapport', - csvImportTotal: 'Totalt', - csvImportAdded: 'Lagt til', - csvImportDuplicates: 'Duplikater', - csvImportNotFound: 'Ikke funnet', - csvImportNetworkErrors: 'Nettverksfeil', - csvImportDuplicatesTitle: 'Duplikater (allerede i spillelisten):', - csvImportNotFoundTitle: 'Ikke funnet spor:', - csvImportNetworkErrorsTitle: 'Nettverksfeil (kan prøve import på nytt):', - csvImportDownloadReport: 'Last ned rapport', - csvImportClose: 'Lukk', - csvImportNoValidTracks: 'Ingen gyldige spor funnet i CSV-filen', - csvImportFailed: 'Kunne ikke importere CSV-fil', - csvImportToast: '{{added}} lagt til, {{notFound}} ikke funnet, {{duplicates}} duplikater', - csvImportDownloadSuccess: 'Rapport lastet ned', - csvImportDownloadError: 'Kunne ikke laste ned rapport', - }, - mostPlayed: { - title: 'Mest spilt', - topArtists: 'Toppkunstnere', - topAlbums: 'Toppalbum', - plays: '{{n}} avspillinger', - sortMost: 'Mest spilt først', - sortLeast: 'Minst spilt først', - loadMore: 'Last inn flere album', - noData: 'Ingen avspillingsdata ennå. Begynn å høre!', - noArtists: 'Alle artister filtrert bort.', - filterCompilations: 'Skjul kompilasjonsartister (Various Artists, Soundtracks, etc.)', - filterCompilationsShort: 'Skjul kompilasjoner', - }, - losslessAlbums: { - empty: 'Ingen lossless-album i dette biblioteket ennå.', - unsupported: 'Denne serveren eksponerer ikke metadata som trengs for å finne lossless-album.', - slowFetchHint: 'Lastes saktere enn andre albumsider — Psysonic går gjennom hele sangkatalogen etter kvalitet.', - }, - smartPlaylists: { - sectionBasic: '1. Grunnleggende', - sectionGenres: '2. Sjanger', - sectionYearsAndFilters: '3. År og filtre', - genreMode: 'Sjanger-modus', - genreModeInclude: 'Inkluder sjangre', - genreModeExclude: 'Ekskluder sjangre', - genreSearchPlaceholder: 'Filtrer sjangre...', - availableGenres: 'Tilgjengelige', - selectedGenres: 'Valgte', - yearMode: 'År-modus', - yearModeInclude: 'Inkluder område', - yearModeExclude: 'Ekskluder område', - name: 'Navn (uten prefiks)', - limit: 'Grense', - limitHint: 'Hvor mange spor som skal inkluderes i spillelisten (1-{{max}}, vanligvis 50).', - artistContains: 'Artist inneholder…', - albumContains: 'Album inneholder…', - titleContains: 'Tittel inneholder…', - minRating: 'Minimumsvurdering', - minRatingAria: 'Minimumsvurdering for smart-spilleliste', - minRatingHint: '0 deaktiverer minimumsterskelen; 1-5 beholder spor med vurdering over valgt verdi.', - fromYear: 'Fra år', - toYear: 'Til år', - excludeUnrated: 'Ekskluder spor uten vurdering', - compilationOnly: 'Kun samlinger', - create: 'Ny Smart-spilleliste', - save: 'Lagre Smart-spilleliste', - created: '{{name}} opprettet', - updated: '{{name}} oppdatert', - createFailed: 'Kunne ikke opprette smart-spilleliste.', - updateFailed: 'Kunne ikke oppdatere smart-spilleliste.', - navidromeOnly: 'Smart-spillelister kan bare opprettes på Navidrome-servere.', - loadFailed: 'Kunne ikke laste smart-spillelister fra Navidrome.', - sortRandom: 'Sortering: tilfeldig', - sortTitleAsc: 'Sortering: tittel A-Å', - sortTitleDesc: 'Sortering: tittel Å-A', - sortYearDesc: 'Sortering: år synkende', - sortYearAsc: 'Sortering: år stigende', - sortPlayCountDesc: 'Sortering: avspillinger synkende', - }, - radio: { - title: 'Internettradio', - empty: 'Ingen radiostasjoner konfigurert.', - addStation: 'Legg til radio stasjon', - editStation: 'Rediger', - deleteStation: 'Slett stasjon', - confirmDelete: 'Klikk igjen for å bekrefte', - stationName: 'Stasjonsnavn…', - streamUrl: 'Strøm-URL…', - homepageUrl: 'Hjemmeside-URL (valgfritt)', - save: 'Lagre', - cancel: 'Avbryt', - live: 'LIVE', - liveStream: 'Internettradio', - openHomepage: 'Åpne hjemmesiden', - changeCoverLabel: 'Endre omslag', - removeCover: 'Fjern omslag', - browseDirectory: 'Søk i katalogen', - directoryPlaceholder: 'Søk i stasjoner…', - noResults: 'Ingen stasjoner funnet.', - stationAdded: 'Stasjon lagt til', - filterAll: 'Alle', - filterFavorites: 'Favoritter', - sortManual: 'Manuell', - sortAZ: 'A → Å', - sortZA: 'Å → A', - sortNewest: 'Nyeste', - favorite: 'Legg til i favoritter', - unfavorite: 'Fjern fra favoritter', - noFavorites: 'Ingen favorittstasjoner.', - listenerCount_one: '{{count}} lytter', - listenerCount_other: '{{count}} lyttere', - recentlyPlayed: 'Nylig spilt', - upNext: 'Neste ut', - }, - folderBrowser: { - empty: 'Tom mappe', - error: 'Kunne ikke laste', - }, - deviceSync: { - title: 'Enhetssynk', - targetFolder: 'Målmappe', - noFolderChosen: 'Ingen mappe valgt', - selectDrive: 'Velg en stasjon…', - refreshDrives: 'Oppdater stasjoner', - noDrivesDetected: 'Ingen flyttbare stasjoner oppdaget', - browseManual: 'Bla manuelt…', - free: 'ledig', - notMountedVolume: 'Målet er ikke på en montert stasjon. Enheten kan ha blitt koblet fra.', - chooseFolder: 'Velg…', - filenameTemplate: 'Filnavnmal', - targetDevice: 'Målenhet', - templateHint: 'Variabler: {artist}, {album}, {title}, {track_number}, {disc_number}, {year}', - cleanupButton: 'Fjern filer som ikke er i utvalget', - cleanupNothingToDelete: 'Ingenting å fjerne — enheten er allerede synkronisert.', - confirmCleanup: 'Slette {{count}} fil(er) fra enheten som ikke er i det gjeldende utvalget. Fortsette?', - cleanupComplete: '{{count}} fil(er) fjernet fra enheten.', - selectedSources: 'Valgte kilder', - noSourcesSelected: 'Ingen kilder valgt. Klikk på elementer i nettleseren for å legge dem til.', - clearAll: 'Fjern alle', - tabPlaylists: 'Spillelister', - tabAlbums: 'Album', - tabArtists: 'Artister', - searchPlaceholder: 'Søk…', - syncButton: 'Synkroniser til enhet', - actionTransfer: 'Overfør til enhet', - actionDelete: 'Slett fra enhet', - actionApplyAll: 'Bruk alle endringer', - templatePreview: 'Forhåndsvisning', - templatePresetStandard: 'Standard', - templatePresetMultiDisc: 'Multi-Disc', - templatePresetAltFolder: 'Alt. mappe', - tokenSlashHint: '/ = mappeskiller', - cancel: 'Avbryt', - noTargetDir: 'Velg en målmappe først.', - noSources: 'Velg minst én kilde.', - noTracks: 'Ingen spor funnet i de valgte kildene.', - fetchError: 'Kunne ikke hente spor fra serveren.', - syncComplete: 'Synkronisering fullført.', - dismiss: 'Lukk', - cancelSync: 'Avbryt', - syncCancelled: 'Synkronisering avbrutt ({{done}} / {{total}} overført).', - colName: 'Navn', - colType: 'Type', - colStatus: 'Status', - onDevice: 'Enhetsbehandling', - addSources: 'Legg til…', - syncResult: '{{done}} overført, {{skipped}} allerede oppdatert ({{total}} totalt)', - deleteFromDevice: 'Merk for sletting ({{count}})', - confirmDelete: 'Slette {{count}} element(er) fra enheten: {{names}}?', - deleteComplete: '{{count}} element(er) fjernet fra enheten.', - manifestImported: '{{count}} kilde(r) importert fra enhetsmanifest.', - statusSynced: 'Synkronisert', - statusPending: 'Venter', - statusDeletion: 'Sletting', - markForDeletion: 'Merk for sletting', - removeSource: 'Fjern', - undoDeletion: 'Angre sletting', - syncInBackground: 'Synkronisering startet i bakgrunnen — du kan navigere bort.', - syncInProgress: '{{done}} / {{total}} spor…', - syncSummary: 'Synkroniseringssammendrag', - calculating: 'Beregner nødvendig nyttelast…', - filesToAdd: 'Filer som skal legges til:', - filesToDelete: 'Filer som skal slettes:', - netChange: 'Nettoendring:', - availableSpace: 'Tilgjengelig diskplass:', - spaceWarning: 'Advarsel: Målenheten har ikke nok rapportert plass.', - proceed: 'Fortsett med synkronisering', - notEnoughSpace: 'Ikke nok fysisk diskplass oppdaget!', - liveSearch: 'Live', - randomAlbumsLabel: 'Tilfeldige album', - }, - orbit: { - triggerLabel: 'Orbit', - triggerTooltip: 'Start eller bli med i en delt lytteøkt', - launchCreate: 'Opprett en økt', - launchJoin: 'Bli med i en økt', - launchHelp: 'Hvordan fungerer dette?', - launchHelpSoon: 'Kommer snart', - joinModalTitle: 'Bli med i en Orbit-økt', - joinModalSub: 'Lim inn invitasjonslenken verten sendte deg.', - joinModalLinkLabel: 'Invitasjonslenke', - joinModalLinkPlaceholder: 'psysonic2-…', - joinModalLinkHelper: 'Fungerer med enhver gyldig Orbit-lenke. Må peke til serveren du er innlogget på.', - joinModalPasteTooltip: 'Lim inn fra utklippstavlen', - joinModalSubmit: 'Bli med', - joinModalBusy: 'Blir med…', - joinErrEmpty: 'Lim inn en invitasjonslenke.', - joinErrInvalid: 'Dette ser ikke ut som en Orbit-invitasjonslenke.', - closeAria: 'Lukk', - heroTitlePrefix: 'Lytt sammen med', - heroTitleBrand: 'Orbit', - heroSub: 'Start en økt — andre brukere på {{server}} lytter med og kan foreslå spor.', - fallbackServer: 'denne serveren', - tipLan: 'Du er for øyeblikket koblet til via en hjemmenettverksadresse. Gjester utenfor nettverket kan ikke bli med — bytt til en offentlig serveradresse i innstillingene før du starter.', - tipRemote: 'For at gjester utenfor hjemmenettverket skal kunne bli med, må serveradressen være offentlig tilgjengelig. Hvis serveren din bare er intern, bytt før du starter.', - labelName: 'Øktnavn', - namePlaceholder: 'Velvet Orbit', - reshuffleTooltip: 'Nytt forslag', - reshuffleAria: 'Foreslå et nytt navn', - helperName: 'Slik vises økten for gjestene — behold den eller skriv din egen.', - labelMax: 'Maks gjester', - helperMax: 'Du telles ikke — dette begrenser bare innkommende gjester.', - labelLink: 'Invitasjonslenke', - tooltipCopied: 'Kopiert', - tooltipCopy: 'Kopier', - ariaCopyLink: 'Kopier invitasjonslenke', - helperLink: 'Send denne lenken til gjestene dine. De kan lime den inn hvor som helst i Psysonic med Ctrl+V.', - labelClearQueue: 'Tøm min kø først', - helperClearQueue: 'Start økten med en tom kø. Av: eksisterende spor beholdes og deles med gjester.', - btnCancel: 'Avbryt', - btnStarting: 'Starter…', - btnStart: 'Start Orbit', - btnCopyAndStart: 'Kopier lenke & start', - errNameRequired: 'Gi økten din et navn.', - errStartFailed: 'Kunne ikke starte.', - hostLabel: 'Vert: {{name}}', - participantsTooltip: 'Deltakere', - settingsTooltip: 'Øktinnstillinger', - shareTooltip: 'Del invitasjonslenke', - shuffleLabel: 'Kø stokkes på nytt om', - catchUpLabel: 'ta igjen', - catchUpTooltip: 'Hopp til vertens nåværende posisjon', - hostAway: 'Vert offline', - hostOnline: 'Vert online', - endTooltip: 'Avslutt økt', - leaveTooltip: 'Forlat økt', - helpTooltip: 'Hvordan Orbit fungerer', - diag: { - openTooltip: 'Diagnose — kopierbar hendelseslogg', - title: 'Orbit-diagnose', - role: 'Rolle', - hostTrack: 'Vertens spor-ID', - hostPos: 'Vertens posisjon', - guestTrack: 'Min spor-ID', - guestPos: 'Min posisjon', - drift: 'Avvik', - stateAge: 'Tilstandens alder', - eventLog: 'Hendelseslogg ({{count}})', - copyLabel: 'Kopier', - copyTooltip: 'Kopier loggen til utklippstavlen', - clearLabel: 'Tøm', - clearTooltip: 'Tøm bufferen', - empty: 'Ingen hendelser ennå — de dukker opp når Orbit synkroniserer.', - hint: 'Åpne dette før du reproduserer problemet, klikk Kopier og lim inn i feilrapporten.', - copied: '{{count}} linjer kopiert', - copyFailed: 'Kunne ikke kopiere til utklippstavlen', - cleared: 'Buffer tømt', - }, - helpTitle: 'Hvordan Orbit fungerer', - helpIntro: 'Orbit gjør Psysonic til et delt lytterom. En vert velger musikken; gjester lytter synkronisert og kan foreslå spor.', - helpHostOnly: '(vert)', - helpSec1Title: 'Hva er Orbit?', - helpSec1Body: 'En "lytte sammen"-modus — verten driver avspillingen, gjester blir med. Alt går via spillelister på din egen Navidrome-server; ingen ekstern infrastruktur.', - helpSec2Title: 'Vert og gjester', - helpSec2Body: 'Verten kontrollerer avspillingen (spill / pause / hopp / søk) og bestemmer når økten avsluttes. Gjester følger vertens avspilling, kan foreslå spor og forlate eller bli med igjen når som helst. Bare verten kan utvise eller permanent utestenge en deltaker.', - helpSec2WarnHead: 'Viktig: separate kontoer.', - helpSec2WarnBody: 'Hver deltaker trenger sin egen Navidrome-konto. Hvis vert og gjest logger inn med samme bruker kolliderer innsendingene, og verten ser aldri gjestens forslag.', - helpSec3Title: 'Starte og invitere', - helpSec3Body: 'Klikk på "Orbit"-knappen → Opprett en økt → startmodalen viser en klar-til-kopiering invitasjonslenke og lar deg eventuelt tømme gjeldende kø. Del lenken som du vil. Mens en økt kjører, kopierer delknappen i øktlinjen øverst lenken når som helst.', - helpSec4Title: 'Bli med', - helpSec4Body: 'Lim inn invitasjonslenken hvor som helst i Psysonic med Ctrl+V / Cmd+V — bli-med-spørsmålet dukker opp automatisk. Alternativt: "Orbit" → Bli med i en økt → lim inn i feltet. Hvis lenken peker til en server du har konto på, bytter Psysonic for deg. Ved flere kontoer på den serveren spør en liten velger hvilken som skal brukes.', - helpSec5Title: 'Foreslå spor', - helpSec5Body: 'I enhver sporliste: dobbeltklikk en rad, eller høyreklikk → "Legg til i Orbit-økt". Et enkelt klikk viser et hint i stedet for å dumpe hele albumet i den delte køen — det er bevisst. Eksplisitte bulk-handlinger som "Spill alt" eller "Spill album" ber først om bekreftelse og legger deretter til (erstatter aldri).', - helpSec6Title: 'Den delte køen', - helpSec6Body: 'Køen viser vertens kommende spor — synlig for alle. Innkommende bulk-tillegg legges alltid til bakerst, så gjesteforslag går ikke tapt. Auto-stokking omorganiserer køen periodisk (konfigurerbar: 1 / 5 / 10 / 15 / 30 min). Hvis avspillingen din avviker fra verten, bringer "Ta igjen"-knappen i øktlinjen deg tilbake til vertens liveposisjon.', - helpSec7Title: 'Godkjenninger', - helpSec7Body: 'Som standard trenger gjesteforslag manuell godkjenning — de vises i en "Godkjenninger"-stripe øverst i køpanelet med godta / avvis-knapper. Auto-godkjenning kan slås på i øktinnstillingene slik at alt lander direkte.', - helpSec8Title: 'Deltakere og innstillinger', - helpSec8Body: 'Åpne innstillingsikonet i øktlinjen for stokkingsfrekvens, auto-godkjenning og "Stokk nå"-snarveien. Klikk på deltakerantallet for å se hvem som er koblet til — utvis (kan bli med igjen via lenken) eller utesteng (utelåst for økten). Gjester ser også deltakerlisten, men bare-lesing.', - helpSec9Title: 'Avslutte økten', - helpSec9Body: 'Vert X → bekreftelsesdialog → økten lukkes for alle og serverspillelistene ryddes opp automatisk. Gjest X → gjesten forlater, økten fortsetter. Hvis verten er stille i 5 minutter, forlater gjesten automatisk med en melding; korte gjentilkoblinger innenfor tiden er usynlige.', - participantsInviteLabel: 'Invitasjonslenke', - participantsCountLabel: '{{count}} i økten', - participantsHost: 'vert', - participantsEmpty: 'Ingen gjester ennå', - participantsKickTooltip: 'Fjern fra økten', - participantsKickAria: 'Fjern {{user}}', - participantsRemoveTooltip: 'Fjern fra økten', - participantsRemoveAria: 'Fjern {{user}} fra denne økten', - participantsBanTooltip: 'Uteste permanent', - participantsBanAria: 'Uteste {{user}} permanent', - participantsMuteTooltip: 'Blokker forslag', - participantsUnmuteTooltip: 'Tillat forslag', - participantsMuteAria: 'Blokker forslag fra {{user}}', - participantsUnmuteAria: 'Tillat forslag fra {{user}} igjen', - confirmRemoveTitle: 'Fjerne fra økten?', - confirmRemoveBody: '{{user}} fjernes fra økten, men kan bli med igjen via invitasjonslenken din.', - confirmRemoveConfirm: 'Fjern', - confirmBanTitle: 'Uteste permanent?', - confirmBanBody: '{{user}} fjernes og hindres i å bli med i denne økten igjen. Kan ikke angres i løpet av økten.', - confirmBanConfirm: 'Uteste', - confirmCancel: 'Avbryt', - confirmJoinTitle: 'Bli med i Orbit-økt?', - confirmJoinBody: '{{host}} inviterte deg til "{{name}}". Bli med i økten?', - confirmJoinConfirm: 'Bli med', - confirmLeaveTitle: 'Forlate økten?', - confirmLeaveBody: 'Forlate "{{name}}"? Du kan bli med igjen når som helst via {{host}}s invitasjonslenke.', - confirmLeaveConfirm: 'Forlat', - confirmEndTitle: 'Avslutte økten for alle?', - confirmEndBody: '"{{name}}" lukkes for alle deltakere. Øktens spillelister ryddes opp automatisk.', - confirmEndConfirm: 'Avslutt økt', - invalidLinkTitle: 'Invitasjonslenken er ikke lenger gyldig', - invalidLinkBody: 'Denne Orbit-økten finnes ikke lenger eller er allerede avsluttet. Be verten om en ny invitasjonslenke.', - settingsTitle: 'Øktinnstillinger', - settingAutoApprove: 'Godkjenn forslag automatisk', - settingAutoApproveHint: 'Gjesteforslag lander umiddelbart i køen din. Av: de blir værende i øktlisten for senere gjennomgang.', - settingAutoShuffle: 'Automatisk stokking', - settingAutoShuffleHint: 'Periodisk Fisher-Yates-stokking av kommende kø. Av: rekkefølgen endres bare når du omorganiserer den.', - settingShuffleInterval: 'Stokk på nytt hver', - settingShuffleIntervalHint: 'Hvor ofte kommende kø stokkes på nytt mens økten kjører.', - suggestBlockedMuted: 'Verten har blokkert deg for denne økten — forslag er av.', - settingShuffleIntervalValue_one: '{{count}} min', - settingShuffleIntervalValue_other: '{{count}} min', - settingShuffleNow: 'Stokk nå', - toastSuggested: '{{user}} foreslo "{{title}}"', - toastSuggestedMany: '{{count}} nye forslag i køen', - toastShuffled: 'Kø stokket', - toastJoined: 'Ble med i økt', - toastLoginFirst: 'Logg inn før du blir med i en økt', - toastSwitchServer: 'Bytt til {{url}} først, og lim inn igjen', - toastNoAccountForServer: 'Du har ikke tilgang til {{url}}. Be verten om en invitasjon.', - toastSwitchFailed: 'Kunne ikke bytte til {{url}}', - accountPickerTitle: 'Hvilken konto?', - accountPickerSub: 'Du har mer enn én konto for {{url}}. Velg den du vil bli med i økten med.', - toastJoinFail: 'Kunne ikke bli med i økten', - joinErrNotFound: 'Økt ikke funnet', - joinErrEnded: 'Økten er avsluttet', - joinErrFull: 'Økten er full', - joinErrKicked: 'Du kan ikke bli med i denne økten igjen', - joinErrNoUser: 'Ingen aktiv server', - joinErrServerError: 'Kunne ikke bli med', - ctxAddToSession: 'Legg til i Orbit-økt', - ctxSuggestedToast: 'Foreslått til økten', - ctxSuggestFailed: 'Kunne ikke foreslå — ikke blitt med', - ctxAddToSessionHost: 'Legg til i Orbit-økt', - ctxAddedHostToast: 'Lagt til i økten', - ctxAddHostFailed: 'Kunne ikke legge til i økten', - bulkConfirmTitle: 'Legg alt til i Orbit-køen?', - bulkConfirmBody: 'Dette vil slippe {{count}} spor i den delte køen på én gang. Det er mye for gjestene dine. Fortsette?', - bulkConfirmYes: 'Legg til alle', - bulkConfirmNo: 'Avbryt', - guestLive: 'Live', - guestPlaying: 'Spiller nå', - guestPaused: 'Pauset', - guestLoading: 'Laster…', - guestSuggestions: 'Forslag', - guestUpNext: 'Neste', - guestUpNextEmpty: 'Ingenting i kø. Åpne et spors kontekstmeny og velg "Legg til i Orbit-økt" for å foreslå ett.', - guestPendingTitle: 'Venter på vert', - guestPendingHint: 'Foreslått — dukker opp i køen når verten tar det.', - approvalTitle: 'Venter på godkjenning', - approvalFrom: 'Foreslått av {{user}}', - approvalAccept: 'Godta', - approvalDecline: 'Avvis', - guestUpNextMore: '+ {{count}} flere i vertens kø', - guestSubmitter: 'av {{user}}', - queueAddedByHost: 'Lagt til av verten', - queueAddedByYou: 'Lagt til av deg', - queueAddedByUser: 'Lagt til av {{user}}', - guestEmpty: 'Ingen forslag ennå. Åpne et spors kontekstmeny og velg "Legg til i Orbit-økt".', - guestFooter: 'Verten kontrollerer avspillingen — du kan ikke endre listen.', - exitKickedTitle: 'Du ble utestengt fra økten', - exitRemovedTitle: 'Du ble fjernet fra økten', - exitEndedTitle: 'Verten avsluttet økten', - exitHostTimeoutTitle: 'Vert ikke tilgjengelig', - exitHostTimeoutBody: '{{host}} har ikke sendt en oppdatering på en stund, så "{{name}}" ble lukket på din side. Du kan bli med igjen når som helst med invitasjonslenken.', - exitKickedBody: '{{host}} utestengte deg fra "{{name}}". Du kan ikke bli med igjen.', - exitRemovedBody: '{{host}} fjernet deg fra "{{name}}". Du kan bli med igjen når som helst via invitasjonslenken.', - exitEndedBody: '"{{name}}" er avsluttet. Håper du hadde det gøy.', - exitOk: 'OK', - }, - tray: { - playPause: 'Spill / Pause', - nextTrack: 'Neste spor', - previousTrack: 'Forrige spor', - showHide: 'Vis / Skjul', - exitPsysonic: 'Avslutt Psysonic', - nothingPlaying: 'Ingenting spilles', - }, - licenses: { - title: 'Åpen kildekode-lisenser', - intro: 'Psysonic er bygget på åpen kildekode-programvare. Listen nedenfor viser hver avhengighet som leveres med appen, med versjon, lisens og full lisenstekst.', - highlights: 'Sentrale avhengigheter', - searchPlaceholder: 'Søk etter navn, versjon eller lisens…', - noResults: 'Ingen treff.', - loading: 'Laster lisenser…', - loadError: 'Kunne ikke laste inn lisensdata.', - noLicenseText: 'Ingen lisenstekst inkludert for denne avhengigheten.', - viewSource: 'Vis kilde', - totalLine: '{{total}} avhengigheter — {{cargo}} cargo, {{npm}} npm', - generatedAt: 'Sist generert {{date}}', - }, -}; diff --git a/src/locales/nb/albumDetail.ts b/src/locales/nb/albumDetail.ts new file mode 100644 index 00000000..05ced5c7 --- /dev/null +++ b/src/locales/nb/albumDetail.ts @@ -0,0 +1,47 @@ +export const albumDetail = { + back: 'Tilbake', + orbitDoubleClickHint: 'Dobbeltklikk for å legge dette sporet til Orbit-køen', + playAll: 'Spill alt', + shareAlbum: 'Del album', + enqueue: 'Legg i kø', + enqueueTooltip: 'Legg hele albumet i kø', + artistBio: 'Artistbiografi', + download: 'Last ned (ZIP)', + downloading: 'Laster…', + cacheOffline: 'Gjør tilgjengelig som frakoblet', + offlineCached: 'Tilgjengelig frakoblet', + offlineDownloading: 'Bufrer… ({{n}}/{{total}})', + removeOffline: 'Fjern frakoblet hurtigbuffer', + offlineStorageFull: 'Frakoblet lagring er full (lagringsgrense: {{mb}} MB). Frigjør plass, ved å slette et album fra ditt frakoblede bibliotek, eller øk lagringsgrensen i Innstillinger.', + offlineStorageGoToLibrary: 'Frakoblet bibliotek', + offlineStorageGoToSettings: 'Innstillinger', + favoriteAdd: 'Legg til i favoritter', + favoriteRemove: 'Fjern fra favoritter', + favorite: 'Favoritt', + noBio: 'Ingen biografi er tilgjengelig.', + moreByArtist: 'Mer av {{artist}}', + tracksCount: '{{n}} spor', + goToArtist: 'Gå til {{artist}}', + moreLabelAlbums: 'Flere album på {{label}}', + trackTitle: 'Tittel', + trackAlbum: 'Album', + trackArtist: 'Artist', + trackGenre: 'Sjanger', + trackFormat: 'Format', + trackFavorite: 'Favoritt', + trackRating: 'Vurdering', + trackDuration: 'Varighet', + trackTotal: 'Totalt', + columns: 'Kolonner', + resetColumns: 'Tilbakestill', + notFound: 'Album ble ikke funnet.', + bioModal: 'Artistbiografi', + bioClose: 'Lukk', + ratingLabel: 'Vurdering', + enlargeCover: 'Forstørr', + filterSongs: 'Filtrer sanger…', + sortNatural: 'Naturlig', + sortByTitle: 'A–Å (Tittel)', + sortByArtist: 'A–Å (Artist)', + sortByAlbum: 'A–Å (Album)', +}; diff --git a/src/locales/nb/albums.ts b/src/locales/nb/albums.ts new file mode 100644 index 00000000..b00ae5a1 --- /dev/null +++ b/src/locales/nb/albums.ts @@ -0,0 +1,32 @@ +export const albums = { + title: 'Alle album', + sortByName: 'A–Å (Album)', + sortByArtist: 'A–Å (Artist)', + sortNewest: 'Vis nyeste først', + sortRandom: 'Tilfeldig', + yearFrom: 'Fra', + yearTo: 'Til', + yearFilterClear: 'Tøm år filteret', + yearFilterLabel: 'År', + compilationLabel: 'Samleplater', + compilationOnly: 'Kun samleplater', + compilationHide: 'Skjul samleplater', + compilationTooltipAll: 'Alle album · klikk: kun samleplater', + compilationTooltipOnly: 'Kun samleplater · klikk: skjul samleplater', + compilationTooltipHide: 'Samleplater skjult · klikk: vis alle', + select: 'Multivalg', + startSelect: 'Aktiver multivalg', + cancelSelect: 'Avbryt', + selectionCount: '{{count}} valgt', + downloadZips: 'Last ned ZIPs', + addOffline: 'Legg til offline', + enqueueSelected_one: 'Legg i kø ({{count}})', + enqueueSelected_other: 'Legg i kø ({{count}})', + enqueueQueued_one: '{{count}} album lagt til i køen', + enqueueQueued_other: '{{count}} album lagt til i køen', + downloadingZip: 'Laster ned {{current}}/{{total}}: {{name}}', + downloadZipDone: '{{count}} ZIP(s) lastet ned', + downloadZipFailed: 'Kunne ikke laste ned {{name}}', + offlineQueuing: 'Legger {{count}} album i kø for offline…', + offlineFailed: 'Kunne ikke legge til {{name}} offline', +}; diff --git a/src/locales/nb/artistDetail.ts b/src/locales/nb/artistDetail.ts new file mode 100644 index 00000000..763fd943 --- /dev/null +++ b/src/locales/nb/artistDetail.ts @@ -0,0 +1,41 @@ +export const artistDetail = { + back: 'Tilbake', + albums: 'Album', + album: 'Album', + playAll: 'Spill alt', + shareArtist: 'Del artist', + shuffle: 'Tilfeldig rekkefølge', + radio: 'Radio', + loading: 'Laster…', + noRadio: 'Ingen lignende spor funnet for denne artisten.', + notFound: 'Artisten ble ikke funnet.', + albumsBy: 'Album fra {{name}}', + topTracks: 'Toppspor', + noAlbums: 'Ingen album funnet.', + trackTitle: 'Tittel', + trackAlbum: 'Album', + trackDuration: 'Varighet', + favoriteAdd: 'Legg til i favoritter', + favoriteRemove: 'Fjern fra favoritter', + favorite: 'Favoritt', + albumCount_one: '{{count}} album', + albumCount_other: '{{count}} album', + openedInBrowser: 'Åpnet i nettleser', + featuredOn: 'Også en del av', + similarArtists: 'Lignende artister', + cacheOffline: 'Lagre diskografi som frakoblet', + offlineCached: 'Diskografi bufret', + offlineDownloading: 'Bufrer… ({{done}}/{{total}} album)', + uploadImage: 'Last opp artistbilde', + uploadImageError: 'Kunne ikke laste opp bildet', + releaseTypes: { + album: 'Album', + ep: 'EP', + single: 'Single', + compilation: 'Samling', + live: 'Live', + soundtrack: 'Filmmusikk', + remix: 'Remiks', + other: 'Annet', + }, +}; diff --git a/src/locales/nb/artists.ts b/src/locales/nb/artists.ts new file mode 100644 index 00000000..5706f1d9 --- /dev/null +++ b/src/locales/nb/artists.ts @@ -0,0 +1,18 @@ +export const artists = { + title: 'Artister', + search: 'Søk…', + all: 'Alle', + gridView: 'Rutenettvisning', + listView: 'Listevisning', + imagesOn: 'Artistbilder på - kan øke belastningen på nettverket og applikasjonen', + imagesOff: 'Artistbilder av - viser kun initialer', + loadMore: 'Last flere', + notFound: 'Ingen artister funnet.', + albumCount_one: '{{count}} album', + albumCount_other: '{{count}} album', + selectionCount: '{{count}} valgt', + select: 'Multivalg', + startSelect: 'Aktiver multivalg', + cancelSelect: 'Avbryt', + addToPlaylist: 'Legg til i spilleliste', +}; diff --git a/src/locales/nb/changelog.ts b/src/locales/nb/changelog.ts new file mode 100644 index 00000000..6f72349f --- /dev/null +++ b/src/locales/nb/changelog.ts @@ -0,0 +1,5 @@ +export const changelog = { + modalTitle: "Nyheter", + dontShowAgain: "Ikke vis igjen", + close: 'Forstått', +}; diff --git a/src/locales/nb/common.ts b/src/locales/nb/common.ts new file mode 100644 index 00000000..695f0ef2 --- /dev/null +++ b/src/locales/nb/common.ts @@ -0,0 +1,56 @@ +export const common = { + albums: 'Album', + album: 'Album', + loading: 'Laster…', + loadingMore: 'Laster…', + loadingPlaylists: 'Laster spillelister…', + noAlbums: 'Ingen album funnet.', + downloading: 'Laster ned…', + downloadZip: 'Last ned (ZIP)', + back: 'Tilbake', + cancel: 'Avbryt', + save: 'Lagre', + delete: 'Slett', + use: 'Bruk', + add: 'Legg til', + new: 'Ny', + active: 'Aktiv', + download: 'Last ned', + chooseDownloadFolder: 'Velg nedlastingsmappe', + noFolderSelected: 'Ingen mappe valgt', + rememberDownloadFolder: 'Husk denne mappen', + filterGenre: 'Sjangerfilter', + filterSearchGenres: 'Søk i sjangre…', + filterNoGenres: 'Ingen sjangre samsvarer', + filterClear: 'Tøm', + favorites: 'Favoritter', + favoritesTooltipOff: 'Vis bare favoritter', + favoritesTooltipOn: 'Vis alle', + play: 'Spill', + bulkSelected: '{{count}} valgt', + clearSelection: 'Fjern utvalg', + bulkAddToPlaylist: 'Legg til i spilleliste', + bulkRemoveFromPlaylist: 'Fjern fra spilleliste', + bulkClear: 'Tøm utvalg', + updaterAvailable: 'Ny versjon er tilgjengelig', + updaterVersion: 'v{{version}} er tilgjengelig', + updaterWebsite: 'Nettsted', + updaterModalTitle: 'Ny versjon tilgjengelig', + updaterChangelog: 'Hva er nytt', + updaterDownloadBtn: 'Last ned nå', + updaterSkipBtn: 'Hopp over denne versjonen', + updaterRemindBtn: 'Påminn meg senere', + updaterDone: 'Nedlasting fullført', + updaterShowFolder: 'Vis i mappe', + updaterInstallHint: 'Lukk Psysonic og kjør installasjonsprogrammet manuelt.', + updaterAurHint: 'Installer oppdateringen via AUR:', + updaterErrorMsg: 'Nedlasting mislyktes', + updaterRetryBtn: 'Prøv igjen', + durationHoursMinutes: '{{hours}} t {{minutes}} min', + durationMinutesOnly: '{{minutes}} min', + updaterOpenGitHub: 'Åpne på GitHub', + filters: 'Filter', + more: 'mer', + yearRange: 'Årsspenn', + clearAll: 'Tøm alt', +}; diff --git a/src/locales/nb/composerDetail.ts b/src/locales/nb/composerDetail.ts new file mode 100644 index 00000000..da52138b --- /dev/null +++ b/src/locales/nb/composerDetail.ts @@ -0,0 +1,11 @@ +export const composerDetail = { + back: 'Tilbake', + notFound: 'Komponist ikke funnet.', + about: 'Om denne komponisten', + works: 'Verker', + noWorks: 'Ingen verker funnet.', + workCount_one: '{{count}} verk', + workCount_other: '{{count}} verker', + shareComposer: 'Del komponist', + unknownComposer: 'Komponist', +}; diff --git a/src/locales/nb/composers.ts b/src/locales/nb/composers.ts new file mode 100644 index 00000000..1c133c18 --- /dev/null +++ b/src/locales/nb/composers.ts @@ -0,0 +1,10 @@ +export const composers = { + title: 'Komponister', + search: 'Søk…', + notFound: 'Ingen komponister funnet.', + unsupported: 'Bla etter komponist krever Navidrome 0.55 eller nyere.', + loadFailed: 'Kunne ikke laste komponister.', + retry: 'Prøv igjen', + involvedIn_one: 'Bidratt på {{count}} album', + involvedIn_other: 'Bidratt på {{count}} album', +}; diff --git a/src/locales/nb/connection.ts b/src/locales/nb/connection.ts new file mode 100644 index 00000000..7890fe8f --- /dev/null +++ b/src/locales/nb/connection.ts @@ -0,0 +1,28 @@ +export const connection = { + connected: 'Tilkoblet', + connectedTo: 'Tilkoblet til {{server}}', + disconnected: 'Frakoblet', + disconnectedFrom: 'Kan ikke nå {{server}} - klikk for å sjekke innstillinger', + checking: 'Kobler til…', + extern: 'Ekstern', + offlineTitle: 'Ingen tjenertilkobling', + offlineSubtitle: 'Kan ikke nå {{server}}. Sjekk nettverket eller tjeneren din.', + offlineModeBanner: 'Frakoblet modus - spiller fra lokal hurtigbuffer', + offlineNoCacheBanner: 'Ingen servertilkobling — kan ikke nå {{server}}', + offlineLibraryTitle: 'Frakoblet bibliotek', + offlineLibraryEmpty: 'Ingen album bufret ennå. Kobl deg til nettverket, åpne et album og klikk "Gjør tilgjengelig frakoblet".', + offlineAlbumCount: '{{n}} album', + offlineAlbumCount_plural: '{{n}} album', + offlineFilterAll: 'Alle', + offlineFilterAlbums: 'Album', + offlineFilterPlaylists: 'Spillelister', + offlineFilterArtists: 'Diskografier', + retry: 'Prøv igjen', + serverSettings: 'Serverinnstillinger', + switchServerTitle: 'Bytt server', + switchServerHint: 'Klikk for å velge en annen lagret server.', + manageServers: 'Administrer servere…', + switchFailed: 'Klarte ikke å bytte — serveren er utilgjengelig.', + lastfmConnected: 'Last.fm tilkoblet som bruker @{{user}}', + lastfmSessionInvalid: 'Sesjonen er ugyldig - klikk her for å koble til på nytt', +}; diff --git a/src/locales/nb/contextMenu.ts b/src/locales/nb/contextMenu.ts new file mode 100644 index 00000000..b4ba24ea --- /dev/null +++ b/src/locales/nb/contextMenu.ts @@ -0,0 +1,33 @@ +export const contextMenu = { + playNow: 'Spill nå', + playNext: 'Spill neste', + addToQueue: 'Legg til i kø', + enqueueAlbum: 'Legg albumet i kø', + enqueueAlbums_one: 'Legg {{count}} album i kø', + enqueueAlbums_other: 'Legg {{count}} album i kø', + startRadio: 'Start radio', + instantMix: 'Instant Mix', + instantMixFailed: 'Kunne ikke lage Instant Mix — server- eller pluginfeil.', + cliMixNeedsTrack: 'Ingenting spilles — start avspilling først, og kjør mix-kommandoen på nytt.', + lfmLove: 'Lik på Last.fm', + lfmUnlove: 'Fjern fra likte på Last.fm', + favorite: 'Favoritt', + favoriteArtist: 'Favorittartist', + favoriteAlbum: 'Favorittalbum', + unfavorite: 'Fjern fra favoritter', + unfavoriteArtist: 'Fjern artist fra favoritter', + unfavoriteAlbum: 'Fjern album fra favoritter', + removeFromQueue: 'Fjern fra kø', + removeFromPlaylist: 'Fjern fra spilleliste', + openAlbum: 'Åpne album', + goToArtist: 'Gå til artist', + download: 'Last ned (ZIP)', + addToPlaylist: 'Legg til i spilleliste', + selectedPlaylists: '{{count}} spillelister valgt', + selectedAlbums: '{{count}} album valgt', + selectedArtists: '{{count}} artister valgt', + songInfo: 'Sanginfo', + shareLink: 'Kopiér delingslenke', + shareCopied: 'Delingslenke kopiert til utklippstavlen.', + shareCopyFailed: 'Kunne ikke kopiere til utklippstavlen.', +}; diff --git a/src/locales/nb/deviceSync.ts b/src/locales/nb/deviceSync.ts new file mode 100644 index 00000000..491c52f1 --- /dev/null +++ b/src/locales/nb/deviceSync.ts @@ -0,0 +1,73 @@ +export const deviceSync = { + title: 'Enhetssynk', + targetFolder: 'Målmappe', + noFolderChosen: 'Ingen mappe valgt', + selectDrive: 'Velg en stasjon…', + refreshDrives: 'Oppdater stasjoner', + noDrivesDetected: 'Ingen flyttbare stasjoner oppdaget', + browseManual: 'Bla manuelt…', + free: 'ledig', + notMountedVolume: 'Målet er ikke på en montert stasjon. Enheten kan ha blitt koblet fra.', + chooseFolder: 'Velg…', + filenameTemplate: 'Filnavnmal', + targetDevice: 'Målenhet', + templateHint: 'Variabler: {artist}, {album}, {title}, {track_number}, {disc_number}, {year}', + cleanupButton: 'Fjern filer som ikke er i utvalget', + cleanupNothingToDelete: 'Ingenting å fjerne — enheten er allerede synkronisert.', + confirmCleanup: 'Slette {{count}} fil(er) fra enheten som ikke er i det gjeldende utvalget. Fortsette?', + cleanupComplete: '{{count}} fil(er) fjernet fra enheten.', + selectedSources: 'Valgte kilder', + noSourcesSelected: 'Ingen kilder valgt. Klikk på elementer i nettleseren for å legge dem til.', + clearAll: 'Fjern alle', + tabPlaylists: 'Spillelister', + tabAlbums: 'Album', + tabArtists: 'Artister', + searchPlaceholder: 'Søk…', + syncButton: 'Synkroniser til enhet', + actionTransfer: 'Overfør til enhet', + actionDelete: 'Slett fra enhet', + actionApplyAll: 'Bruk alle endringer', + templatePreview: 'Forhåndsvisning', + templatePresetStandard: 'Standard', + templatePresetMultiDisc: 'Multi-Disc', + templatePresetAltFolder: 'Alt. mappe', + tokenSlashHint: '/ = mappeskiller', + cancel: 'Avbryt', + noTargetDir: 'Velg en målmappe først.', + noSources: 'Velg minst én kilde.', + noTracks: 'Ingen spor funnet i de valgte kildene.', + fetchError: 'Kunne ikke hente spor fra serveren.', + syncComplete: 'Synkronisering fullført.', + dismiss: 'Lukk', + cancelSync: 'Avbryt', + syncCancelled: 'Synkronisering avbrutt ({{done}} / {{total}} overført).', + colName: 'Navn', + colType: 'Type', + colStatus: 'Status', + onDevice: 'Enhetsbehandling', + addSources: 'Legg til…', + syncResult: '{{done}} overført, {{skipped}} allerede oppdatert ({{total}} totalt)', + deleteFromDevice: 'Merk for sletting ({{count}})', + confirmDelete: 'Slette {{count}} element(er) fra enheten: {{names}}?', + deleteComplete: '{{count}} element(er) fjernet fra enheten.', + manifestImported: '{{count}} kilde(r) importert fra enhetsmanifest.', + statusSynced: 'Synkronisert', + statusPending: 'Venter', + statusDeletion: 'Sletting', + markForDeletion: 'Merk for sletting', + removeSource: 'Fjern', + undoDeletion: 'Angre sletting', + syncInBackground: 'Synkronisering startet i bakgrunnen — du kan navigere bort.', + syncInProgress: '{{done}} / {{total}} spor…', + syncSummary: 'Synkroniseringssammendrag', + calculating: 'Beregner nødvendig nyttelast…', + filesToAdd: 'Filer som skal legges til:', + filesToDelete: 'Filer som skal slettes:', + netChange: 'Nettoendring:', + availableSpace: 'Tilgjengelig diskplass:', + spaceWarning: 'Advarsel: Målenheten har ikke nok rapportert plass.', + proceed: 'Fortsett med synkronisering', + notEnoughSpace: 'Ikke nok fysisk diskplass oppdaget!', + liveSearch: 'Live', + randomAlbumsLabel: 'Tilfeldige album', +}; diff --git a/src/locales/nb/entityRating.ts b/src/locales/nb/entityRating.ts new file mode 100644 index 00000000..fbea8fe5 --- /dev/null +++ b/src/locales/nb/entityRating.ts @@ -0,0 +1,9 @@ +export const entityRating = { + albumShort: 'Albumvurdering', + artistShort: 'Artistvurdering', + albumAriaLabel: 'Albumvurdering', + artistAriaLabel: 'Artistvurdering', + selectedArtistsRatingAriaLabel: 'Stjernevurdering for {{count}} valgte artister', + selectedAlbumsRatingAriaLabel: 'Stjernevurdering for {{count}} valgte album', + saveFailed: 'Kunne ikke lagre vurderingen.', +}; diff --git a/src/locales/nb/favorites.ts b/src/locales/nb/favorites.ts new file mode 100644 index 00000000..6cc4bdd9 --- /dev/null +++ b/src/locales/nb/favorites.ts @@ -0,0 +1,19 @@ +export const favorites = { + title: 'Favoritter', + empty: "Du har ikke lagret noen favoritter ennå.", + artists: 'Artister', + albums: 'Album', + songs: 'Sanger', + enqueueAll: 'Legg alle i kø', + playAll: 'Spill alle', + removeSong: 'Fjern fra favoritter', + stations: 'Radiostasjoner', + showingFiltered: 'Viser {{filtered}} av {{total}} ({{artist}})', + showingCount: 'Viser {{filtered}} av {{total}}', + clearArtistFilter: 'Tøm artistfilter', + noFilterResults: 'Ingen resultater med valgte filtre.', + allArtists: 'Alle artister', + topArtists: 'Toppartister etter favoritter', + topArtistsSongCount_one: '{{count}} sang', + topArtistsSongCount_other: '{{count}} sanger', +}; diff --git a/src/locales/nb/folderBrowser.ts b/src/locales/nb/folderBrowser.ts new file mode 100644 index 00000000..ccf9c5e9 --- /dev/null +++ b/src/locales/nb/folderBrowser.ts @@ -0,0 +1,4 @@ +export const folderBrowser = { + empty: 'Tom mappe', + error: 'Kunne ikke laste', +}; diff --git a/src/locales/nb/genres.ts b/src/locales/nb/genres.ts new file mode 100644 index 00000000..52c1938d --- /dev/null +++ b/src/locales/nb/genres.ts @@ -0,0 +1,12 @@ +export const genres = { + title: 'Sjangre', + genreCount: 'Sjangre', + albumCount_one: '{{count}} album', + albumCount_other: '{{count}} album', + loading: 'Laster sjangre…', + empty: 'Ingen sjangre funnet.', + albumsLoading: 'Laster album…', + albumsEmpty: 'Ingen album funnet for denne sjangeren.', + loadMore: 'Last mer', + back: 'Tilbake', +}; diff --git a/src/locales/nb/help.ts b/src/locales/nb/help.ts new file mode 100644 index 00000000..494a84f9 --- /dev/null +++ b/src/locales/nb/help.ts @@ -0,0 +1,105 @@ +export const help = { + title: 'Hjelp', + searchPlaceholder: 'Søk i hjelpen…', + noResults: 'Ingen treff. Prøv et annet søkeord.', + s1: 'Komme i gang', + q1: 'Hvilke servere er kompatible?', + a1: 'Psysonic er primært bygget for Navidrome og er fullt Subsonic-kompatibel — Gonic, Airsonic, LMS og andre Subsonic-API-servere fungerer også. Noen avanserte funksjoner (vurderinger, smarte spillelister, Magic-String-deling, brukerhåndtering) krever Navidrome.', + q2: 'Hvordan legger jeg til en server?', + a2: 'Innstillinger → Servere → Legg til server. Skriv inn URL (f.eks. http://192.168.1.100:4533), brukernavn og passord. Psysonic tester tilkoblingen før lagring — ingenting lagres ved feil. Du kan legge til så mange servere du vil og bytte mellom dem i toppen; bare én er aktiv om gangen.', + q3: 'Rask UI-omvisning?', + a3: 'Sidefelt (venstre) for navigasjon, Mainstage / sider i midten, spillerbaren nederst, kø-panelet til høyre (åpnes via ikonet øverst til høyre ved siden av Now-Playing-indikatoren). Søkefeltet øverst søker i hele biblioteket; «Now Playing» viser hva andre brukere på samme Navidrome-server hører på akkurat nå.', + s2: 'Avspilling & Kø', + q4: 'Hvordan bruker jeg køen?', + a4: 'Åpne kø-panelet fra toppen til høyre. Dra rader for å omorganisere, dra dem utenfor for å fjerne, eller bruk verktøylinjen for å blande, lagre køen som spilleliste eller hoppe til en låt. Dra rader ut av panelet for å slippe dem et annet sted som overføring.', + q5: 'Gapless vs Crossfade — hva er forskjellen?', + a5: 'Gapless forhåndslager neste låt slik at det er null stillhet mellom låtene (ideelt for liveplater og DJ-mikser). Crossfade toner gjeldende låt ut mens neste tones inn over 1–10 s (ideelt for blandede mikser). De er gjensidig utelukkende — å aktivere én deaktiverer den andre. Konfigureres i Innstillinger → Lyd.', + q6: 'Hva er Infinite Queue?', + a6: 'Når køen tar slutt og Gjenta er av, legger Psysonic stille til lignende/tilfeldige låter fra biblioteket ditt slik at avspillingen aldri stopper. Auto-lagte låter vises under et «— Lagt til automatisk —»-skille. Slå på/av via uendelighetssymbolet i kø-toppen; begrens auto-tilføyelser til en sjanger i Innstillinger → Kø.', + q7: 'Multi-utvalg og Shift-klikk-rekkevidde?', + a7: 'Aktiver «Velg» på Album / Nye utgivelser / Random Albums / Spillelister. Klikk et element for å veksle, hold deretter Shift og klikk et annet element — alt mellom dem i synlig rekkefølge blir valgt. Shift-klikk utvider fra det sist klikkede ankerpunktet. Verktøylinjen over rutenettet tilbyr handlinger for flere (kø, nedlasting, sletting, osv.).', + q8: 'Tastatursnarveier og globale hurtigtaster?', + a8: 'Standard i-app-taster: Mellomrom = Spill / Pause, Esc = lukk fullskjerm / modaler, F1 = snarveisreferanse. Innstillinger → Inndata lar deg tilbakestille hver i-app-handling (inkludert akkorder som Ctrl+Shift+P) og sette systemomfattende globale snarveier som virker selv når Psysonic er i bakgrunnen. Mediataster (Spill/Pause, Neste, Forrige) virker på alle plattformer.', + s3: 'Lydverktøy', + q9: 'Replay Gain-modi?', + a9: 'Innstillinger → Lyd → Replay Gain. Spor-modus normaliserer hver låt til et målnivå. Album-modus bevarer lydstyrkekurven innen et album. Auto-modus velger Spor eller Album basert på om køen kommer fra ett enkelt album. Spor uten Replay Gain-tagger faller tilbake til en konfigurerbar forforsterker.', + q10: 'Hva er Smart Loudness Normalization (LUFS)?', + a10: 'Et moderne alternativ til Replay Gain i Innstillinger → Lyd. Psysonic analyserer hver låt til LUFS / EBU R128 og lagrer resultatet, så lyden er konsistent på tvers av hele biblioteket — også låter uten Replay Gain-tagger. Cold-cache-analyse kjører i bakgrunnen og bruker 35–40 % CPU i ~1 minutt, deretter 0. Sett målnivået (standard −10 LUFS) én gang.', + q11: 'EQ og AutoEQ?', + a11: 'En 10-bånds parametrisk EQ i Innstillinger → Lyd → Equalizer med manuelle bånd og forhåndsinnstillinger. AutoEQ ved siden av henter en målt korreksjonsprofil for hodetelefonmodellen din fra AutoEQ-databasen og bruker den automatisk på båndene — velg hodetelefonene dine, EQ-en låser på riktig kurve.', + q12: 'Hvordan bytter jeg lydutgangsenhet?', + a12: 'Innstillinger → Lyd → Utgangsenhet. Psysonic lister alle tilgjengelige utganger og bytter umiddelbart når du velger. Oppdater-knappen finner enheter som ble koblet til etter oppstart. Linux ALSA-navn som «sysdefault» blir auto-renset for lesbarhet.', + q13: 'Hva er Hot Cache?', + a13: 'Hot Cache forhåndslaster gjeldende låt pluss de neste i RAM og på disk slik at avspillingen starter uten buffer-forsinkelse — særlig nyttig på trege / fjerne servere. Eviksjon utløses når størrelsesgrensen nås. Konfigurer størrelse og debounce-forsinkelse (slik at raske skip ikke overhenter) i Innstillinger → Lyd.', + s4: 'Bibliotek & Oppdagelse', + q14: 'Hvordan fungerer vurderinger og Skip-to-1★?', + a14: 'Psysonic støtter 1–5-stjerners vurderinger via OpenSubsonic (Navidrome ≥ 0.53). Vurder låter i sporlister, i høyreklikkmenyen eller i spillerbaren under artistnavnet; album på albumsiden; artister på artistsiden. Skip-to-1★ (Innstillinger → Bibliotek → Vurderinger) gir automatisk 1 stjerne etter et konfigurerbart antall sammenhengende skip. Samme panel lar deg sette en minimum vurdering for genererte mikser.', + q15: 'Hvordan blar jeg — Mapper, Sjangre, Spor?', + a15: 'Mappebrowseren (sidefelt) går gjennom serverens musikkmappe i Miller-kolonneoppsett — klikk en mappe for å gå inn, klikk en låt eller spillikonet på en mappe for å spille / legge til. Sjangre bruker en tag-sky-visning skalert etter antall spor; klikk en sjanger for å åpne. Spor er en flat bibliotekshub med kolonnesorterbar virtuell liste og live søk.', + q16: 'Søk og avansert søk?', + a16: 'Søkefeltet i toppen kjører rask live-søk på artister, album og spor mens du skriver. Åpne Avansert søk (sidefelt) for en rikere visning: filtrer etter år, sjanger, vurdering, format, kanaler, samplingsfrekvens, BPM, stemning, og kombiner kriterier. Høyreklikk på et resultat for samme kontekstmeny som ellers.', + q17: 'Hva er Mixene (Random / Sjanger / Super Genre / Lucky)?', + a17: 'Random Mix bygger en spilleliste av tilfeldige låter fra biblioteket; Nøkkelordfilteret ekskluderer lydbøker, komedie etc. ved hjelp av sjanger / tittel / album-undertekster. Super Genre Mix grupperer biblioteket i brede stiler (Rock, Metal, Elektronisk, Jazz, Klassisk …) og bygger en fokusert miks. Lucky Mix bruker lyttehistorikk, vurderinger og AudioMuse-AI-lignende spor for å sette sammen en spilleliste med ett klikk.', + q18: 'Statistikkside?', + a18: 'Statistikk (sidefelt) viser topp artister, topp album, topp spor, sjangerfordeling, lyttetid over tid, og per-bibliotek-omfang når du har flere musikkmapper konfigurert. Flere visninger kan eksporteres som delbart kortbilde.', + q19: 'Hvordan laster jeg ned et album som ZIP?', + a19: 'Albumside → «Last ned (ZIP)». Serveren komprimerer albumet først — for store eller tapsfrie album (FLAC / WAV) vises fremdriftsfeltet først når zipping er fullført og overføringen begynner. Dette er normalt.', + s5: 'Lyrikk', + q20: 'Hvor kommer lyrikken fra?', + a20: 'Tre kilder, konfigurerbare i Innstillinger → Lyrikk: Navidrome-serveren (innebygd / OpenSubsonic-lyrikk), LRCLIB (felles synkroniserte tekster) og NetEase Cloud Music (stort asiatisk + internasjonalt katalog). Hver kilde kan aktiveres / deaktiveres og prioriteres ved drag.', + q21: 'Hvordan ser jeg lyrikk under avspilling?', + a21: 'Klikk på mikrofonikonet i spillerbaren for å åpne Lyrikk-fanen i kø-panelet. Synkronisert lyrikk auto-skroller og støtter klikk-for-å-hoppe; klartekst skroller som en statisk blokk. Veksle Fullskjermspilleren via spillerbarens cover for en oppslukende lyrikk-visning med mesh-blob-bakgrunn.', + s6: 'Deling & Sosialt', + q22: 'Hva er Magic Strings?', + a22: 'Magic Strings er korte kopier-lim-tokens som deler ting mellom Psysonic-brukere uten noen tredjeparts server. Server-Invite-strenger lar en venn onboarde til Navidrome-serveren din med ett lim; Album- / Artist- / Kø Magic Strings åpner samme album / artist / kø hos mottaker. Generer fra del-menyen, lim dem inn i søkefeltet for å bruke.', + q23: 'Hva er Orbit?', + a23: 'Orbit er synkronisert lytte-sammen: en vert spiller en låt, hver gjest hører den synkront, og gjester kan foreslå låter verten kan godta i køen. Start en økt fra Orbit-knappen i toppen, del invitasjonslenken, og andre kan bli med fra hvilken som helst Psysonic-installasjon. Verten eier avspillingen (skip, søk, kø) — gjester får sanntidsvisning og en forslagsboks. Økter er flyktige og avsluttes når verten lukker dem.', + q24: 'Hva er Now Playing-rullegardinen?', + a24: 'Kringkastingsikonet øverst til høyre viser hva andre brukere på Navidrome-serveren din hører på akkurat nå, oppdatert hvert 10. sekund. Din egen oppføring forsvinner i det øyeblikket du pauser. Per-server, så brukere på en annen aktiv server vises ikke.', + s7: 'Personalisering', + q25: 'Temaer og temaplanlegger?', + a25: 'Innstillinger → Utseende → Tema velger fra 60+ temaer i 8 grupper (Psysonic, Mediaplayer, Operativsystemer, Spill, Filmer, Serier, Sosiale medier, Open Source Classics — Catppuccin / Nord / Gruvbox / Nightfox / Dracula). Auto-Switch Theme lar deg sette et dag-tema + natt-tema med starttider slik at Psysonic bytter automatisk.', + q26: 'Kan jeg tilpasse Sidefeltet, Hjem og Artistside?', + a26: 'Ja — Innstillinger → Personalisering. Sidefelt-tilpasseren lar deg dra nav-elementer i ønsket rekkefølge og skjule de du ikke bruker. Hjem-tilpasseren slår av/på hver Mainstage-rad (Hero, Recent, Discover, Recently Played, Starred …). Artistside-tilpasseren omorganiserer seksjonene (Topplåter, Album, Singler, Compilations, Lignende artister, etc.) og lar deg skjule de du aldri ser på.', + q27: 'Hva er Mini Player?', + a27: 'Et lite flytende vindu med cover, transport-kontroller og en kompakt kø. Åpnes fra mini-player-ikonet i spillerbaren eller med tastatursnarveien. Vinduet husker posisjon og størrelse mellom økter. På Windows opprettes mini-webview-en på forhånd ved oppstart slik at åpningen er umiddelbar; Linux / macOS aktiverer dette via Innstillinger → Utseende → Forhåndslast mini-spiller.', + q28: 'Hva er Floating Player Bar?', + a28: 'En valgfri spillerbar-stil (Innstillinger → Utseende) som løsriver seg fra bunnkanten med tema-bakgrunn, accent-kant, avrundet albumcover og en sentrert volum-seksjon. Nyttig på høye skjermer eller kompakte temaer.', + q29: 'Spor-forhåndsvisning ved hover?', + a29: 'Hover over en sporrad, klikk den lille forhåndsvisning-knappen på coveret, eller utløs forhåndsvisning fra høyreklikkmenyen — Psysonic strømmer de første ~15 s gjennom samme Rust-lyd-engine slik at lydstyrkenormalisering gjelder. Nyttig for å bla gjennom et album du ikke har hørt før.', + q30: 'Sleep timer?', + a30: 'Klikk på måneikonet i spillerbaren for å åpne sleep timer. Velg en varighet (eller «slutten av nåværende låt») og Psysonic toner ut og pauser ved slutten. Knappen viser en sirkulær ring og en innebygd nedtelling mens timeren går.', + q31: 'UI-skala, font, seekbar-stil?', + a31: 'Innstillinger → Utseende — Grensesnitt-skala (80–125 % uten å påvirke systemets fontstørrelse), Font (10 UI-fonter inkludert IBM Plex Mono, Fira Code, Geist, Golos Text…), Seekbar-stil (Bølgeform analysert / pseudobølge deterministisk / Linje & Punkt / Bjelke / Tykk Bjelke / Segmentert / Neon-Glow / Pulsbølge / Partikkelspor / Flytende Fyll / Retro Tape).', + s8: 'Power User', + q32: 'CLI player-kontroller?', + a32: 'Psysonic-binæren fungerer også som fjernkontroll. Eksempler: psysonic --player play / pause / next / prev, --player volume 75, --player seek 15, --player shuffle, --player repeat off|all|one, --player rating 1-5. Bytt servere, lydenheter, biblioteker; utløs Instant Mix; søk artister / album / spor. Komplett liste med psysonic --player --help. Shell-fullføring for bash og zsh via psysonic completions.', + q33: 'Smarte spillelister (Navidrome)?', + a33: 'Smarte spillelister er Navidrome-side dynamiske spillelister definert av regler (sjanger = Rock OG år > 2020, etc.). Spillelister-siden i Psysonic lar deg opprette, redigere og slette dem med en visuell regelredigerer — Psysonic snakker med Navidromes native API for det. De oppfører seg som vanlige spillelister i resten av appen og oppdateres automatisk når biblioteket endres.', + q34: 'Sikkerhetskopiere og gjenopprette innstillinger?', + a34: 'Innstillinger → Lagring → Sikkerhetskopi & Gjenoppretting eksporterer serverprofiler, temaer, snarveier og andre innstillinger til en enkelt JSON-fil. Importer den på en annen maskin eller etter en reinstallasjon for å gjenopprette alt. Server-passord er inkludert — hold filen privat.', + q35: 'Hvor ser jeg alle åpen kildekode-lisenser?', + a35: 'Innstillinger → System → Open Source Licenses. Den fullstendige avhengighetslisten (cargo crates og npm-pakker) leveres med innebygde lisenstekster. Klikk på en oppføring for full tekst; det kuraterte fremhevingsblokket øverst viser de brukerkjente bibliotekene (Tauri, React, rodio, symphonia, etc.).', + s9: 'Offline & Sync', + q36: 'Offline-modus — cache album og spillelister?', + a36: 'Åpne et album eller en spilleliste og klikk på nedlastingsikonet i headeren — Psysonic cacher hver låt lokalt slik at den spilles av fra disk uten nettverkskall. Offline Library-siden (sidefelt) viser alt som er cachet, viser fremdrift under nedlasting, og lar deg fjerne med søppelbøtte-ikonet (som vises etter at en nedlasting er fullført).', + q37: 'Offline-lagringsgrense?', + a37: 'Innstillinger → Bibliotek → Offline lar deg sette en maksimal cache-størrelse. Når grensen nås, viser albumsidens nedlastingsknapp et advarselsbanner. Frigjør plass ved å fjerne album eller spillelister fra Offline Library-siden.', + q38: 'Device Sync — kopiere musikk til USB / SD?', + a38: 'Device Sync (sidefelt) kopierer album, spillelister eller hele artister til en ekstern stasjon for offline lytting på andre enheter. Velg en målmappe, velg kilder fra browserfanene, klikk «Overfør til enhet». Psysonic skriver et manifest (psysonic-sync.json) slik at det vet hvilke filer som allerede er der, selv hvis du åpner Device Sync på et annet OS med en annen filnavn-mal. Maler støtter {artist} / {album} / {title} / {track_number} / {disc_number} / {year}-tokens med / som mappe-skille.', + s10: 'Integrasjoner & Feilsøking', + q39: 'Last.fm-scrobbling?', + a39: 'Innstillinger → Integrasjoner → Last.fm. Koble til kontoen din én gang og Psysonic scrobbler direkte til Last.fm — ingen Navidrome-konfigurasjon trengs. En scrobble sendes etter at du har hørt 50 % av en låt. Now-playing-pings sendes ved start.', + q40: 'Discord Rich Presence?', + a40: 'Innstillinger → Integrasjoner → Discord viser gjeldende låt på Discord-profilen din. Velg mellom app-ikonet, serverens cover-art (via getAlbumInfo2 — krever en offentlig nåbar server), eller Apple Music-cover. Tilpass visningsstrenger (detaljer, tilstand, verktøytips) med token-maler.', + q41: 'Bandsintown-turnedato?', + a41: 'Opt-in under Innstillinger → Integrasjoner → Now-Playing Info. Now Playing-fanen på Now Playing-siden viser deretter kommende turnedater for artisten som spiller via Bandsintown widget API. Av som standard — ingen forespørsler gjøres før du aktiverer.', + q42: 'Internet Radio — spille livestrømmer?', + a42: 'Internet Radio (sidefelt) spiller enhver livestrøm lagret på Navidrome-serveren din (legg til stasjoner via Navidrome admin UI). Avspilling kjører gjennom nettleserens HTML5-lyd-engine — de fleste EQ / Replay Gain / Loudness-innstillinger gjelder ikke for radio, men ICY-metadata (gjeldende låtnavn) vises. Støtter MP3, AAC, OGG Vorbis og de fleste HLS-strømmer; codec-støtte avhenger av plattformen.', + q43: 'Tilkoblingstesten feiler — hva nå?', + a43: 'Dobbeltsjekk URL-en inkludert porten (f.eks. http://192.168.1.100:4533). På et lokalt nettverk virker http:// ofte der https:// ikke gjør (intet sertifikat). Sørg for at ingen brannmur blokkerer porten og at brukernavn og passord er korrekte. Hvis serveren er bak en omvendt proxy, prøv først direkte URL for å isolere årsaken.', + q44: 'Cover-art og artistbilder lastes sakte.', + a44: 'Bilder hentes fra serveren ved første visning og caches deretter lokalt i 30 dager. Hvis serverens lagring er treg, kan første besøk på en side ta et øyeblikk; påfølgende besøk er umiddelbare. Hot Cache hjelper også for spor, men bildecachen er uavhengig.', + q45: 'Linux-problemer — svart skjerm eller ingen lyd?', + a45: 'Svart skjerm er vanligvis et GPU- / EGL-driverproblem i WebKitGTK — start med GDK_BACKEND=x11 WEBKIT_DISABLE_COMPOSITING_MODE=1 WEBKIT_DISABLE_DMABUF_RENDERER=1 (AUR / .deb / .rpm-installerne setter disse automatisk). For lyd, sørg for at PipeWire eller PulseAudio kjører. Lydutfall etter dvale / oppvåkning håndteres nå automatisk av post-sleep recovery hook.', +}; diff --git a/src/locales/nb/hero.ts b/src/locales/nb/hero.ts new file mode 100644 index 00000000..52f42138 --- /dev/null +++ b/src/locales/nb/hero.ts @@ -0,0 +1,6 @@ +export const hero = { + eyebrow: 'Utvalgt album', + playAlbum: 'Spill av album', + enqueue: 'Legg til i kø', + enqueueTooltip: 'Legg til hele albumet i køen', +}; diff --git a/src/locales/nb/home.ts b/src/locales/nb/home.ts new file mode 100644 index 00000000..259661de --- /dev/null +++ b/src/locales/nb/home.ts @@ -0,0 +1,19 @@ +export const home = { + hero: 'Utvalgt', + starred: 'Personlige favoritter', + recent: 'Nylig lagt til', + mostPlayed: 'Mest spilt', + recentlyPlayed: 'Nylig spilt', + losslessAlbums: 'Lossless-album', + discover: 'Oppdag', + discoverSongs: 'Oppdag spor', + loadMore: 'Last inn flere', + discoverMore: 'Oppdag flere', + discoverArtists: 'Oppdag artister', + discoverArtistsMore: 'Alle artister', + becauseYouLike: 'Fordi du har hørt…', + becauseYouLikeFor: 'Fordi du har hørt på {{artist}}', + similarTo: 'Likt {{artist}}', + becauseYouLikeTracks_one: '{{count}} spor', + becauseYouLikeTracks_other: '{{count}} spor' +}; diff --git a/src/locales/nb/index.ts b/src/locales/nb/index.ts new file mode 100644 index 00000000..007c317f --- /dev/null +++ b/src/locales/nb/index.ts @@ -0,0 +1,91 @@ +import { sidebar } from './sidebar'; +import { home } from './home'; +import { hero } from './hero'; +import { search } from './search'; +import { nowPlaying } from './nowPlaying'; +import { contextMenu } from './contextMenu'; +import { sharePaste } from './sharePaste'; +import { albumDetail } from './albumDetail'; +import { entityRating } from './entityRating'; +import { artistDetail } from './artistDetail'; +import { favorites } from './favorites'; +import { randomLanding } from './randomLanding'; +import { randomAlbums } from './randomAlbums'; +import { genres } from './genres'; +import { randomMix } from './randomMix'; +import { luckyMix } from './luckyMix'; +import { albums } from './albums'; +import { tracks } from './tracks'; +import { artists } from './artists'; +import { composers } from './composers'; +import { composerDetail } from './composerDetail'; +import { login } from './login'; +import { connection } from './connection'; +import { common } from './common'; +import { settings } from './settings'; +import { changelog } from './changelog'; +import { whatsNew } from './whatsNew'; +import { help } from './help'; +import { queue } from './queue'; +import { miniPlayer } from './miniPlayer'; +import { statistics } from './statistics'; +import { player } from './player'; +import { nowPlayingInfo } from './nowPlayingInfo'; +import { songInfo } from './songInfo'; +import { playlists } from './playlists'; +import { mostPlayed } from './mostPlayed'; +import { losslessAlbums } from './losslessAlbums'; +import { smartPlaylists } from './smartPlaylists'; +import { radio } from './radio'; +import { folderBrowser } from './folderBrowser'; +import { deviceSync } from './deviceSync'; +import { orbit } from './orbit'; +import { tray } from './tray'; +import { licenses } from './licenses'; + +export const nbTranslation = { + sidebar, + home, + hero, + search, + nowPlaying, + contextMenu, + sharePaste, + albumDetail, + entityRating, + artistDetail, + favorites, + randomLanding, + randomAlbums, + genres, + randomMix, + luckyMix, + albums, + tracks, + artists, + composers, + composerDetail, + login, + connection, + common, + settings, + changelog, + whatsNew, + help, + queue, + miniPlayer, + statistics, + player, + nowPlayingInfo, + songInfo, + playlists, + mostPlayed, + losslessAlbums, + smartPlaylists, + radio, + folderBrowser, + deviceSync, + orbit, + tray, + licenses, +}; diff --git a/src/locales/nb/licenses.ts b/src/locales/nb/licenses.ts new file mode 100644 index 00000000..de8baea8 --- /dev/null +++ b/src/locales/nb/licenses.ts @@ -0,0 +1,13 @@ +export const licenses = { + title: 'Åpen kildekode-lisenser', + intro: 'Psysonic er bygget på åpen kildekode-programvare. Listen nedenfor viser hver avhengighet som leveres med appen, med versjon, lisens og full lisenstekst.', + highlights: 'Sentrale avhengigheter', + searchPlaceholder: 'Søk etter navn, versjon eller lisens…', + noResults: 'Ingen treff.', + loading: 'Laster lisenser…', + loadError: 'Kunne ikke laste inn lisensdata.', + noLicenseText: 'Ingen lisenstekst inkludert for denne avhengigheten.', + viewSource: 'Vis kilde', + totalLine: '{{total}} avhengigheter — {{cargo}} cargo, {{npm}} npm', + generatedAt: 'Sist generert {{date}}', +}; diff --git a/src/locales/nb/login.ts b/src/locales/nb/login.ts new file mode 100644 index 00000000..e061ab30 --- /dev/null +++ b/src/locales/nb/login.ts @@ -0,0 +1,22 @@ +export const login = { + subtitle: 'Din Navidrome-mediaspiller', + serverName: 'Tjenernavn (valgfritt)', + serverNamePlaceholder: 'Mitt mediabibliotek', + serverUrl: 'Tjener-URL', + serverUrlPlaceholder: '192.168.1.100:4533 eller https://musikk.eksempel.com', + username: 'Brukernavn', + usernamePlaceholder: 'admin', + password: 'Passord', + showPassword: 'Vis passord', + hidePassword: 'Skjul passord', + connect: 'Koble til', + connecting: 'Kobler til…', + connected: 'Tilkoblet!', + error: 'Tilkoblingen mislyktes – vennligst sjekk instillingene.', + urlRequired: 'Vennligst skriv inn en tjeneer-URL.', + savedServers: 'Lagrede servere', + addNew: 'Eller legg til en ny tjener', + orMagicString: 'Eller magic string', + magicStringPlaceholder: 'Lim inn en delingsstreng (psysonic1-…)', + magicStringInvalid: 'Ugyldig eller uleselig magic string.', +}; diff --git a/src/locales/nb/losslessAlbums.ts b/src/locales/nb/losslessAlbums.ts new file mode 100644 index 00000000..6342c12d --- /dev/null +++ b/src/locales/nb/losslessAlbums.ts @@ -0,0 +1,5 @@ +export const losslessAlbums = { + empty: 'Ingen lossless-album i dette biblioteket ennå.', + unsupported: 'Denne serveren eksponerer ikke metadata som trengs for å finne lossless-album.', + slowFetchHint: 'Lastes saktere enn andre albumsider — Psysonic går gjennom hele sangkatalogen etter kvalitet.', +}; diff --git a/src/locales/nb/luckyMix.ts b/src/locales/nb/luckyMix.ts new file mode 100644 index 00000000..f15922d9 --- /dev/null +++ b/src/locales/nb/luckyMix.ts @@ -0,0 +1,6 @@ +export const luckyMix = { + done: 'Lykkemiks klar: {{count}} spor', + failed: 'Kunne ikke lage Lykkemiksen. Prøv igjen.', + unavailable: 'Lykkemiks er ikke tilgjengelig for denne serveren.', + cancelTooltip: 'Avbryt Lykkemiks-bygging', +}; diff --git a/src/locales/nb/miniPlayer.ts b/src/locales/nb/miniPlayer.ts new file mode 100644 index 00000000..9dcd8a89 --- /dev/null +++ b/src/locales/nb/miniPlayer.ts @@ -0,0 +1,9 @@ +export const miniPlayer = { + showQueue: 'Vis kø', + hideQueue: 'Skjul kø', + pinOnTop: 'Hold øverst', + pinOff: 'Løsne', + openMainWindow: 'Åpne hovedvindu', + close: 'Lukk', + emptyQueue: 'Køen er tom', +}; diff --git a/src/locales/nb/mostPlayed.ts b/src/locales/nb/mostPlayed.ts new file mode 100644 index 00000000..81b82305 --- /dev/null +++ b/src/locales/nb/mostPlayed.ts @@ -0,0 +1,13 @@ +export const mostPlayed = { + title: 'Mest spilt', + topArtists: 'Toppkunstnere', + topAlbums: 'Toppalbum', + plays: '{{n}} avspillinger', + sortMost: 'Mest spilt først', + sortLeast: 'Minst spilt først', + loadMore: 'Last inn flere album', + noData: 'Ingen avspillingsdata ennå. Begynn å høre!', + noArtists: 'Alle artister filtrert bort.', + filterCompilations: 'Skjul kompilasjonsartister (Various Artists, Soundtracks, etc.)', + filterCompilationsShort: 'Skjul kompilasjoner', +}; diff --git a/src/locales/nb/nowPlaying.ts b/src/locales/nb/nowPlaying.ts new file mode 100644 index 00000000..c15db027 --- /dev/null +++ b/src/locales/nb/nowPlaying.ts @@ -0,0 +1,47 @@ +export const nowPlaying = { + tooltip: 'Hvem lytter?', + title: 'Hvem lytter?', + loading: 'Laster…', + nobody: 'Ingen lyttere for øyeblikket.', + minutesAgo: '{{n}}m siden', + nothingPlaying: 'Ingenting spiller akkurat å. Start et spor!', + aboutArtist: 'Om artisten', + fromAlbum: 'Fra dette albumet', + viewAlbum: 'Se album', + goToArtist: 'Gå til artist', + readMore: 'Les mer', + showLess: 'Vis mindre', + genreInfo: 'Sjanger', + trackInfo: 'Sporinfo', + topSongs: 'Mest spilt av denne artisten', + topSongsCredit: 'Toppspor fra {{name}}', + trackPosition: 'Spor {{pos}}', + playsCount_one: '{{count}} avspilling', + playsCount_other: '{{count}} avspillinger', + releasedYearsAgo_one: 'for {{count}} år siden', + releasedYearsAgo_other: 'for {{count}} år siden', + discography: 'Diskografi', + lastfmStats: 'Last.fm-statistikk', + thisTrack: 'Dette sporet', + thisArtist: 'Denne artisten', + listeners: 'lyttere', + scrobbles: 'scrobbles', + yourScrobbles: 'av deg', + listenersN: '{{n}} lyttere', + scrobblesN: '{{n}} scrobbles', + playsByYouN: 'spilt {{n}}× av deg', + openTrackOnLastfm: 'Spor på Last.fm', + openArtistOnLastfm: 'Artist på Last.fm', + rgTrackTooltip: 'ReplayGain (spor)', + rgAlbumTooltip: 'ReplayGain (album)', + rgAutoTooltip: 'ReplayGain (auto)', + showMoreTracks: 'Vis {{count}} til', + showLessTracks: 'Vis mindre', + hideCard: 'Skjul kort', + layoutMenu: 'Oppsett', + visibleCards: 'Synlige kort', + hiddenCards: 'Skjulte kort', + noHiddenCards: 'Ingen skjulte kort', + resetLayout: 'Tilbakestill oppsett', + emptyColumn: 'Slipp kort her', +}; diff --git a/src/locales/nb/nowPlayingInfo.ts b/src/locales/nb/nowPlayingInfo.ts new file mode 100644 index 00000000..1b9fabf3 --- /dev/null +++ b/src/locales/nb/nowPlayingInfo.ts @@ -0,0 +1,24 @@ +export const nowPlayingInfo = { + tab: 'Info', + empty: 'Spill noe for å se info', + artist: 'Artist', + songInfo: 'Sporinfo', + onTour: 'På turné', + noTourEvents: 'Ingen kommende konserter', + tourLoading: 'Laster…', + poweredByBandsintown: 'Turnédata via Bandsintown', + bioReadMore: 'Vis mer', + bioReadLess: 'Vis mindre', + showMoreTours_one: 'Vis {{count}} til', + showMoreTours_other: 'Vis {{count}} til', + showLessTours: 'Vis mindre', + enableBandsintownPrompt: 'Vis kommende turnédatoer?', + enableBandsintownPromptDesc: 'Valgfritt. Henter konserter for gjeldende artist via det offentlige Bandsintown-API-et.', + enableBandsintownPrivacy: 'Ved aktivering sendes navnet på artisten som spilles av til Bandsintown-API-et for å hente turnédatoer. Ingen konto- eller personopplysninger forlater enheten din.', + enableBandsintownAction: 'Aktiver', + role: { + artist: 'Artist', + albumArtist: 'Albumartist', + composer: 'Komponist', + }, +}; diff --git a/src/locales/nb/orbit.ts b/src/locales/nb/orbit.ts new file mode 100644 index 00000000..673e8274 --- /dev/null +++ b/src/locales/nb/orbit.ts @@ -0,0 +1,200 @@ +export const orbit = { + triggerLabel: 'Orbit', + triggerTooltip: 'Start eller bli med i en delt lytteøkt', + launchCreate: 'Opprett en økt', + launchJoin: 'Bli med i en økt', + launchHelp: 'Hvordan fungerer dette?', + launchHelpSoon: 'Kommer snart', + joinModalTitle: 'Bli med i en Orbit-økt', + joinModalSub: 'Lim inn invitasjonslenken verten sendte deg.', + joinModalLinkLabel: 'Invitasjonslenke', + joinModalLinkPlaceholder: 'psysonic2-…', + joinModalLinkHelper: 'Fungerer med enhver gyldig Orbit-lenke. Må peke til serveren du er innlogget på.', + joinModalPasteTooltip: 'Lim inn fra utklippstavlen', + joinModalSubmit: 'Bli med', + joinModalBusy: 'Blir med…', + joinErrEmpty: 'Lim inn en invitasjonslenke.', + joinErrInvalid: 'Dette ser ikke ut som en Orbit-invitasjonslenke.', + closeAria: 'Lukk', + heroTitlePrefix: 'Lytt sammen med', + heroTitleBrand: 'Orbit', + heroSub: 'Start en økt — andre brukere på {{server}} lytter med og kan foreslå spor.', + fallbackServer: 'denne serveren', + tipLan: 'Du er for øyeblikket koblet til via en hjemmenettverksadresse. Gjester utenfor nettverket kan ikke bli med — bytt til en offentlig serveradresse i innstillingene før du starter.', + tipRemote: 'For at gjester utenfor hjemmenettverket skal kunne bli med, må serveradressen være offentlig tilgjengelig. Hvis serveren din bare er intern, bytt før du starter.', + labelName: 'Øktnavn', + namePlaceholder: 'Velvet Orbit', + reshuffleTooltip: 'Nytt forslag', + reshuffleAria: 'Foreslå et nytt navn', + helperName: 'Slik vises økten for gjestene — behold den eller skriv din egen.', + labelMax: 'Maks gjester', + helperMax: 'Du telles ikke — dette begrenser bare innkommende gjester.', + labelLink: 'Invitasjonslenke', + tooltipCopied: 'Kopiert', + tooltipCopy: 'Kopier', + ariaCopyLink: 'Kopier invitasjonslenke', + helperLink: 'Send denne lenken til gjestene dine. De kan lime den inn hvor som helst i Psysonic med Ctrl+V.', + labelClearQueue: 'Tøm min kø først', + helperClearQueue: 'Start økten med en tom kø. Av: eksisterende spor beholdes og deles med gjester.', + btnCancel: 'Avbryt', + btnStarting: 'Starter…', + btnStart: 'Start Orbit', + btnCopyAndStart: 'Kopier lenke & start', + errNameRequired: 'Gi økten din et navn.', + errStartFailed: 'Kunne ikke starte.', + hostLabel: 'Vert: {{name}}', + participantsTooltip: 'Deltakere', + settingsTooltip: 'Øktinnstillinger', + shareTooltip: 'Del invitasjonslenke', + shuffleLabel: 'Kø stokkes på nytt om', + catchUpLabel: 'ta igjen', + catchUpTooltip: 'Hopp til vertens nåværende posisjon', + hostAway: 'Vert offline', + hostOnline: 'Vert online', + endTooltip: 'Avslutt økt', + leaveTooltip: 'Forlat økt', + helpTooltip: 'Hvordan Orbit fungerer', + diag: { + openTooltip: 'Diagnose — kopierbar hendelseslogg', + title: 'Orbit-diagnose', + role: 'Rolle', + hostTrack: 'Vertens spor-ID', + hostPos: 'Vertens posisjon', + guestTrack: 'Min spor-ID', + guestPos: 'Min posisjon', + drift: 'Avvik', + stateAge: 'Tilstandens alder', + eventLog: 'Hendelseslogg ({{count}})', + copyLabel: 'Kopier', + copyTooltip: 'Kopier loggen til utklippstavlen', + clearLabel: 'Tøm', + clearTooltip: 'Tøm bufferen', + empty: 'Ingen hendelser ennå — de dukker opp når Orbit synkroniserer.', + hint: 'Åpne dette før du reproduserer problemet, klikk Kopier og lim inn i feilrapporten.', + copied: '{{count}} linjer kopiert', + copyFailed: 'Kunne ikke kopiere til utklippstavlen', + cleared: 'Buffer tømt', + }, + helpTitle: 'Hvordan Orbit fungerer', + helpIntro: 'Orbit gjør Psysonic til et delt lytterom. En vert velger musikken; gjester lytter synkronisert og kan foreslå spor.', + helpHostOnly: '(vert)', + helpSec1Title: 'Hva er Orbit?', + helpSec1Body: 'En "lytte sammen"-modus — verten driver avspillingen, gjester blir med. Alt går via spillelister på din egen Navidrome-server; ingen ekstern infrastruktur.', + helpSec2Title: 'Vert og gjester', + helpSec2Body: 'Verten kontrollerer avspillingen (spill / pause / hopp / søk) og bestemmer når økten avsluttes. Gjester følger vertens avspilling, kan foreslå spor og forlate eller bli med igjen når som helst. Bare verten kan utvise eller permanent utestenge en deltaker.', + helpSec2WarnHead: 'Viktig: separate kontoer.', + helpSec2WarnBody: 'Hver deltaker trenger sin egen Navidrome-konto. Hvis vert og gjest logger inn med samme bruker kolliderer innsendingene, og verten ser aldri gjestens forslag.', + helpSec3Title: 'Starte og invitere', + helpSec3Body: 'Klikk på "Orbit"-knappen → Opprett en økt → startmodalen viser en klar-til-kopiering invitasjonslenke og lar deg eventuelt tømme gjeldende kø. Del lenken som du vil. Mens en økt kjører, kopierer delknappen i øktlinjen øverst lenken når som helst.', + helpSec4Title: 'Bli med', + helpSec4Body: 'Lim inn invitasjonslenken hvor som helst i Psysonic med Ctrl+V / Cmd+V — bli-med-spørsmålet dukker opp automatisk. Alternativt: "Orbit" → Bli med i en økt → lim inn i feltet. Hvis lenken peker til en server du har konto på, bytter Psysonic for deg. Ved flere kontoer på den serveren spør en liten velger hvilken som skal brukes.', + helpSec5Title: 'Foreslå spor', + helpSec5Body: 'I enhver sporliste: dobbeltklikk en rad, eller høyreklikk → "Legg til i Orbit-økt". Et enkelt klikk viser et hint i stedet for å dumpe hele albumet i den delte køen — det er bevisst. Eksplisitte bulk-handlinger som "Spill alt" eller "Spill album" ber først om bekreftelse og legger deretter til (erstatter aldri).', + helpSec6Title: 'Den delte køen', + helpSec6Body: 'Køen viser vertens kommende spor — synlig for alle. Innkommende bulk-tillegg legges alltid til bakerst, så gjesteforslag går ikke tapt. Auto-stokking omorganiserer køen periodisk (konfigurerbar: 1 / 5 / 10 / 15 / 30 min). Hvis avspillingen din avviker fra verten, bringer "Ta igjen"-knappen i øktlinjen deg tilbake til vertens liveposisjon.', + helpSec7Title: 'Godkjenninger', + helpSec7Body: 'Som standard trenger gjesteforslag manuell godkjenning — de vises i en "Godkjenninger"-stripe øverst i køpanelet med godta / avvis-knapper. Auto-godkjenning kan slås på i øktinnstillingene slik at alt lander direkte.', + helpSec8Title: 'Deltakere og innstillinger', + helpSec8Body: 'Åpne innstillingsikonet i øktlinjen for stokkingsfrekvens, auto-godkjenning og "Stokk nå"-snarveien. Klikk på deltakerantallet for å se hvem som er koblet til — utvis (kan bli med igjen via lenken) eller utesteng (utelåst for økten). Gjester ser også deltakerlisten, men bare-lesing.', + helpSec9Title: 'Avslutte økten', + helpSec9Body: 'Vert X → bekreftelsesdialog → økten lukkes for alle og serverspillelistene ryddes opp automatisk. Gjest X → gjesten forlater, økten fortsetter. Hvis verten er stille i 5 minutter, forlater gjesten automatisk med en melding; korte gjentilkoblinger innenfor tiden er usynlige.', + participantsInviteLabel: 'Invitasjonslenke', + participantsCountLabel: '{{count}} i økten', + participantsHost: 'vert', + participantsEmpty: 'Ingen gjester ennå', + participantsKickTooltip: 'Fjern fra økten', + participantsKickAria: 'Fjern {{user}}', + participantsRemoveTooltip: 'Fjern fra økten', + participantsRemoveAria: 'Fjern {{user}} fra denne økten', + participantsBanTooltip: 'Uteste permanent', + participantsBanAria: 'Uteste {{user}} permanent', + participantsMuteTooltip: 'Blokker forslag', + participantsUnmuteTooltip: 'Tillat forslag', + participantsMuteAria: 'Blokker forslag fra {{user}}', + participantsUnmuteAria: 'Tillat forslag fra {{user}} igjen', + confirmRemoveTitle: 'Fjerne fra økten?', + confirmRemoveBody: '{{user}} fjernes fra økten, men kan bli med igjen via invitasjonslenken din.', + confirmRemoveConfirm: 'Fjern', + confirmBanTitle: 'Uteste permanent?', + confirmBanBody: '{{user}} fjernes og hindres i å bli med i denne økten igjen. Kan ikke angres i løpet av økten.', + confirmBanConfirm: 'Uteste', + confirmCancel: 'Avbryt', + confirmJoinTitle: 'Bli med i Orbit-økt?', + confirmJoinBody: '{{host}} inviterte deg til "{{name}}". Bli med i økten?', + confirmJoinConfirm: 'Bli med', + confirmLeaveTitle: 'Forlate økten?', + confirmLeaveBody: 'Forlate "{{name}}"? Du kan bli med igjen når som helst via {{host}}s invitasjonslenke.', + confirmLeaveConfirm: 'Forlat', + confirmEndTitle: 'Avslutte økten for alle?', + confirmEndBody: '"{{name}}" lukkes for alle deltakere. Øktens spillelister ryddes opp automatisk.', + confirmEndConfirm: 'Avslutt økt', + invalidLinkTitle: 'Invitasjonslenken er ikke lenger gyldig', + invalidLinkBody: 'Denne Orbit-økten finnes ikke lenger eller er allerede avsluttet. Be verten om en ny invitasjonslenke.', + settingsTitle: 'Øktinnstillinger', + settingAutoApprove: 'Godkjenn forslag automatisk', + settingAutoApproveHint: 'Gjesteforslag lander umiddelbart i køen din. Av: de blir værende i øktlisten for senere gjennomgang.', + settingAutoShuffle: 'Automatisk stokking', + settingAutoShuffleHint: 'Periodisk Fisher-Yates-stokking av kommende kø. Av: rekkefølgen endres bare når du omorganiserer den.', + settingShuffleInterval: 'Stokk på nytt hver', + settingShuffleIntervalHint: 'Hvor ofte kommende kø stokkes på nytt mens økten kjører.', + suggestBlockedMuted: 'Verten har blokkert deg for denne økten — forslag er av.', + settingShuffleIntervalValue_one: '{{count}} min', + settingShuffleIntervalValue_other: '{{count}} min', + settingShuffleNow: 'Stokk nå', + toastSuggested: '{{user}} foreslo "{{title}}"', + toastSuggestedMany: '{{count}} nye forslag i køen', + toastShuffled: 'Kø stokket', + toastJoined: 'Ble med i økt', + toastLoginFirst: 'Logg inn før du blir med i en økt', + toastSwitchServer: 'Bytt til {{url}} først, og lim inn igjen', + toastNoAccountForServer: 'Du har ikke tilgang til {{url}}. Be verten om en invitasjon.', + toastSwitchFailed: 'Kunne ikke bytte til {{url}}', + accountPickerTitle: 'Hvilken konto?', + accountPickerSub: 'Du har mer enn én konto for {{url}}. Velg den du vil bli med i økten med.', + toastJoinFail: 'Kunne ikke bli med i økten', + joinErrNotFound: 'Økt ikke funnet', + joinErrEnded: 'Økten er avsluttet', + joinErrFull: 'Økten er full', + joinErrKicked: 'Du kan ikke bli med i denne økten igjen', + joinErrNoUser: 'Ingen aktiv server', + joinErrServerError: 'Kunne ikke bli med', + ctxAddToSession: 'Legg til i Orbit-økt', + ctxSuggestedToast: 'Foreslått til økten', + ctxSuggestFailed: 'Kunne ikke foreslå — ikke blitt med', + ctxAddToSessionHost: 'Legg til i Orbit-økt', + ctxAddedHostToast: 'Lagt til i økten', + ctxAddHostFailed: 'Kunne ikke legge til i økten', + bulkConfirmTitle: 'Legg alt til i Orbit-køen?', + bulkConfirmBody: 'Dette vil slippe {{count}} spor i den delte køen på én gang. Det er mye for gjestene dine. Fortsette?', + bulkConfirmYes: 'Legg til alle', + bulkConfirmNo: 'Avbryt', + guestLive: 'Live', + guestPlaying: 'Spiller nå', + guestPaused: 'Pauset', + guestLoading: 'Laster…', + guestSuggestions: 'Forslag', + guestUpNext: 'Neste', + guestUpNextEmpty: 'Ingenting i kø. Åpne et spors kontekstmeny og velg "Legg til i Orbit-økt" for å foreslå ett.', + guestPendingTitle: 'Venter på vert', + guestPendingHint: 'Foreslått — dukker opp i køen når verten tar det.', + approvalTitle: 'Venter på godkjenning', + approvalFrom: 'Foreslått av {{user}}', + approvalAccept: 'Godta', + approvalDecline: 'Avvis', + guestUpNextMore: '+ {{count}} flere i vertens kø', + guestSubmitter: 'av {{user}}', + queueAddedByHost: 'Lagt til av verten', + queueAddedByYou: 'Lagt til av deg', + queueAddedByUser: 'Lagt til av {{user}}', + guestEmpty: 'Ingen forslag ennå. Åpne et spors kontekstmeny og velg "Legg til i Orbit-økt".', + guestFooter: 'Verten kontrollerer avspillingen — du kan ikke endre listen.', + exitKickedTitle: 'Du ble utestengt fra økten', + exitRemovedTitle: 'Du ble fjernet fra økten', + exitEndedTitle: 'Verten avsluttet økten', + exitHostTimeoutTitle: 'Vert ikke tilgjengelig', + exitHostTimeoutBody: '{{host}} har ikke sendt en oppdatering på en stund, så "{{name}}" ble lukket på din side. Du kan bli med igjen når som helst med invitasjonslenken.', + exitKickedBody: '{{host}} utestengte deg fra "{{name}}". Du kan ikke bli med igjen.', + exitRemovedBody: '{{host}} fjernet deg fra "{{name}}". Du kan bli med igjen når som helst via invitasjonslenken.', + exitEndedBody: '"{{name}}" er avsluttet. Håper du hadde det gøy.', + exitOk: 'OK', +}; diff --git a/src/locales/nb/player.ts b/src/locales/nb/player.ts new file mode 100644 index 00000000..1c317332 --- /dev/null +++ b/src/locales/nb/player.ts @@ -0,0 +1,56 @@ +export const player = { + regionLabel: 'Musikkspiller', + openFullscreen: 'Åpne fullskjermsspiller', + fullscreen: 'Fullskjermsspiller', + closeFullscreen: 'Lukk fullskjerm', + closeTooltip: 'Lukk (Esc)', + noTitle: 'Ingen tittel', + stop: 'Stopp', + prev: 'Forrige spor', + play: 'Spill av', + pause: 'Pause', + previewActive: 'Forhåndsvisning spilles av', + previewLabel: 'Forhåndsvisning', + delayModalTitle: 'Tidsur', + delayPauseSection: 'Pause etter', + delayStartSection: 'Start etter', + delayPreviewPause: 'Pause kl.', + delayPreviewStart: 'Start kl.', + delaySchedulePause: 'Planlegg pause', + delayScheduleStart: 'Planlegg start', + delayCancelPause: 'Avbryt pause-timer', + delayCancelStart: 'Avbryt start-timer', + delayInactivePause: 'Kun tilgjengelig under avspilling.', + delayInactiveStart: 'Kun i pause med spor eller radio lastet.', + delayCustomMinutes: 'Egen forsinkelse (minutter)', + delayCustomPlaceholder: 'f.eks. 2,5', + closeDelayModal: 'Lukk', + delayIn: 'om', + delayFmtSec: '{{n}} s', + delayFmtMin: '{{n}} min', + delayFmtHr: '{{n}} t', + delayCancel: 'Avbryt', + delayApply: 'Bruk', + next: 'Neste spor', + repeat: 'Gjenta', + repeatOff: 'Av', + repeatAll: 'Alle', + repeatOne: 'Én', + progress: 'Sangfremdrift', + volume: 'Volum', + toggleQueue: 'Veksle kø', + collapseQueueResize: 'Skjul kø, endre bredde', + moreOptions: 'Flere alternativer', + equalizer: 'Equalizer', + miniPlayer: 'Minispiller', + lyrics: 'Sangtekst', + fsLyricsToggle: 'Sangtekst i fullskjerm', + lyricsLoading: 'Laster sangtekst…', + lyricsNotFound: 'Ingen sangtekst funnet for dette sporet', + lyricsSourceServer: 'Kilde: Server', + lyricsSourceLrclib: 'Kilde: LRCLIB', + lyricsSourceNetease: 'Kilde: Netease', + lyricsSourceLyricsplus: 'Kilde: YouLyPlus', + showDuration: 'Vis varighet', + showRemainingTime: 'Vis gjenværende tid', +}; diff --git a/src/locales/nb/playlists.ts b/src/locales/nb/playlists.ts new file mode 100644 index 00000000..2e59e242 --- /dev/null +++ b/src/locales/nb/playlists.ts @@ -0,0 +1,101 @@ +export const playlists = { + title: 'Spillelister', + newPlaylist: 'Ny spilleliste', + unnamed: 'Navnløs spilleliste', + createName: 'Spillelistenavn…', + create: 'Opprett', + cancel: 'Avbryt', + empty: 'Ingen spillelister ennå.', + emptyPlaylist: 'Denne spillelisten er tom.', + addFirstSong: 'Legg til din første sang', + notFound: 'Spillelisten ble ikke funnet.', + songs: '{{n}} sanger', + playAll: 'Spill alle', + shuffle: 'Bland', + addToQueue: 'Legg til i kø', + back: 'Tilbake til spillelister', + deletePlaylist: 'Slett', + confirmDelete: 'Klikk igjen for å bekrefte', + removeSong: 'Fjern fra spilleliste', + addSongs: 'Legg til sanger', + searchPlaceholder: 'Søk i biblioteket ditt…', + noResults: 'Ingen resultater.', + suggestions: 'Foreslåtte sanger', + noSuggestions: 'Ingen forslag tilgjengelig.', + titleBadge: 'Spilleliste', + refreshSuggestions: 'Nye forslag', + addSong: 'Legg til i spilleliste', + preview: 'Forhåndsvisning (30 s)', + previewStop: 'Stopp forhåndsvisning', + playNextSuggestion: 'Spill som neste', + suggestionsHint: 'Dobbeltklikk på en rad for å legge den til i spillelisten', + addSelected: 'Legg til valgte', + cacheOffline: 'Bufre spilleliste offline', + offlineCached: 'Spilleliste bufret', + removeOffline: 'Fjern fra offline-buffer', + offlineDownloading: 'Bufre… ({{done}}/{{total}} album)', + publicLabel: 'Offentlig', + privateLabel: 'Privat', + editMeta: 'Rediger spilleliste', + editNamePlaceholder: 'Spillelistenavn…', + editCommentPlaceholder: 'Legg til en beskrivelse…', + editPublic: 'Offentlig spilleliste', + editSave: 'Lagre', + editCancel: 'Avbryt', + changeCover: 'Endre omslagsbilde', + changeCoverLabel: 'Endre bilde', + removeCover: 'Fjern bilde', + coverUpdated: 'Omslag oppdatert', + metaSaved: 'Spillelisten er oppdatert', + downloadZip: 'Last ned (ZIP)', + // Toast notifications for multi-select + addSuccess: '{{count}} sanger lagt til i {{playlist}}', + addPartial: '{{added}} lagt til, {{skipped}} hoppet over (duplikater)', + addAllSkipped: 'Alle hoppet over ({{count}} duplikater)', + addedAsDuplicates: '{{count}} sanger lagt til i {{playlist}} (som duplikater)', + duplicateConfirmTitle: 'Allerede i spillelisten', + duplicateConfirmMessage: 'Alle {{count}} sanger finnes allerede i "{{playlist}}". Legg dem til likevel som duplikater?', + duplicateConfirmAction: 'Legg til likevel', + addError: 'Feil ved å legge til sanger', + createAndAddSuccess: 'Spilleliste "{{playlist}}" opprettet med {{count}} sanger', + createError: 'Feil ved oppretting av spilleliste', + deleteSuccess: '{{count}} spillelister slettet', + deleteFailed: 'Feil ved sletting av {{name}}', + deleteSelected: 'Slett valgte', + deleteSelectedPartial: 'Bare {{n}} av {{total}} valgte spillelister kan slettes (de andre tilhører noen andre).', + mergeSuccess: '{{count}} sanger slått sammen i {{playlist}}', + mergeNoNewSongs: 'Ingen nye sanger å legge til', + mergeError: 'Feil ved sammenslåing av spillelister', + mergeInto: 'Slå sammen i', + selectionCount: '{{count}} valgt', + select: 'Velg', + startSelect: 'Aktiver valg', + cancelSelect: 'Avbryt', + loadingAlbums: 'Løser {{count}} album…', + loadingArtists: 'Løser {{count}} artister…', + myPlaylists: 'Mine spillelister', + noOtherPlaylists: 'Ingen andre spillelister tilgjengelig', + addToPlaylistSuccess: '{{count}} sanger lagt til i {{playlist}}', + addToPlaylistNoNew: 'Ingen nye sanger for {{playlist}}', + addToPlaylistError: 'Feil ved å legge til i spilleliste', + removeSuccess: 'Sang fjernet fra spilleliste', + removeError: 'Feil ved fjerning fra spilleliste', + importCSV: 'Importer CSV', + importCSVTooltip: 'Importer fra Spotify CSV', + csvImportReport: 'CSV-importrapport', + csvImportTotal: 'Totalt', + csvImportAdded: 'Lagt til', + csvImportDuplicates: 'Duplikater', + csvImportNotFound: 'Ikke funnet', + csvImportNetworkErrors: 'Nettverksfeil', + csvImportDuplicatesTitle: 'Duplikater (allerede i spillelisten):', + csvImportNotFoundTitle: 'Ikke funnet spor:', + csvImportNetworkErrorsTitle: 'Nettverksfeil (kan prøve import på nytt):', + csvImportDownloadReport: 'Last ned rapport', + csvImportClose: 'Lukk', + csvImportNoValidTracks: 'Ingen gyldige spor funnet i CSV-filen', + csvImportFailed: 'Kunne ikke importere CSV-fil', + csvImportToast: '{{added}} lagt til, {{notFound}} ikke funnet, {{duplicates}} duplikater', + csvImportDownloadSuccess: 'Rapport lastet ned', + csvImportDownloadError: 'Kunne ikke laste ned rapport', +}; diff --git a/src/locales/nb/queue.ts b/src/locales/nb/queue.ts new file mode 100644 index 00000000..35a3edd7 --- /dev/null +++ b/src/locales/nb/queue.ts @@ -0,0 +1,45 @@ +export const queue = { + title: 'Kø', + savePlaylist: 'Lagre spilleliste', + updatePlaylist: 'Oppdater spilleliste', + filterPlaylists: 'Filtrer spillelister…', + playlistName: 'Spillelistenavn', + cancel: 'Avbryt', + save: 'Lagre', + loadPlaylist: 'Last inn spilleliste', + loading: 'Laster…', + noPlaylists: 'Ingen spillelister funnet.', + load: 'Erstatt kø og spill av', + appendToQueue: 'Legg til i kø', + delete: 'Slett', + deleteConfirm: 'Slett spillelisten "{{name}}"?', + clear: 'Fjern', + shuffle: 'Bland kø', + gapless: 'Uten mellomrom', + crossfade: 'Crossfade', + infiniteQueue: 'Uendelig kø', + autoAdded: '- Lagt til automatisk -', + radioAdded: '- Radio -', + hide: 'Skjul', + hideNowPlaying: 'Skjul avspillingsinfo', + showNowPlaying: 'Vis avspillingsinfo', + close: 'Lukk', + nextTracks: 'Neste spor', + shareQueue: 'Kopiér lenke til kø', + shareQueueEmpty: 'Køen er tom — ingenting å dele.', + emptyQueue: 'Køen er tom.', + trackSingular: 'spor', + trackPlural: 'spor', + showRemaining: 'Vis gjenværende tid', + showTotal: 'Vis total tid', + showEta: 'Vis estimert sluttid', + replayGain: 'ReplayGain', + rgTrack: 'T {{db}} dB', + rgAlbum: 'A {{db}} dB', + rgPeak: 'Topp {{pk}}', + sourceOffline: 'Spiller fra offlinebibliotek', + sourceHot: 'Spiller fra cache', + sourceStream: 'Spiller fra nettverksstrøm', + clearCachedLoudnessWaveform: 'Clear cached loudness and waveform, then re-analyze this track', + recalculatingLoudnessWaveform: 'Recalculating loudness and waveform for this track…', +}; diff --git a/src/locales/nb/radio.ts b/src/locales/nb/radio.ts new file mode 100644 index 00000000..6d4874be --- /dev/null +++ b/src/locales/nb/radio.ts @@ -0,0 +1,35 @@ +export const radio = { + title: 'Internettradio', + empty: 'Ingen radiostasjoner konfigurert.', + addStation: 'Legg til radio stasjon', + editStation: 'Rediger', + deleteStation: 'Slett stasjon', + confirmDelete: 'Klikk igjen for å bekrefte', + stationName: 'Stasjonsnavn…', + streamUrl: 'Strøm-URL…', + homepageUrl: 'Hjemmeside-URL (valgfritt)', + save: 'Lagre', + cancel: 'Avbryt', + live: 'LIVE', + liveStream: 'Internettradio', + openHomepage: 'Åpne hjemmesiden', + changeCoverLabel: 'Endre omslag', + removeCover: 'Fjern omslag', + browseDirectory: 'Søk i katalogen', + directoryPlaceholder: 'Søk i stasjoner…', + noResults: 'Ingen stasjoner funnet.', + stationAdded: 'Stasjon lagt til', + filterAll: 'Alle', + filterFavorites: 'Favoritter', + sortManual: 'Manuell', + sortAZ: 'A → Å', + sortZA: 'Å → A', + sortNewest: 'Nyeste', + favorite: 'Legg til i favoritter', + unfavorite: 'Fjern fra favoritter', + noFavorites: 'Ingen favorittstasjoner.', + listenerCount_one: '{{count}} lytter', + listenerCount_other: '{{count}} lyttere', + recentlyPlayed: 'Nylig spilt', + upNext: 'Neste ut', +}; diff --git a/src/locales/nb/randomAlbums.ts b/src/locales/nb/randomAlbums.ts new file mode 100644 index 00000000..36564aa0 --- /dev/null +++ b/src/locales/nb/randomAlbums.ts @@ -0,0 +1,4 @@ +export const randomAlbums = { + title: 'Tilfeldige album', + refresh: 'Oppdater', +}; diff --git a/src/locales/nb/randomLanding.ts b/src/locales/nb/randomLanding.ts new file mode 100644 index 00000000..043cd194 --- /dev/null +++ b/src/locales/nb/randomLanding.ts @@ -0,0 +1,9 @@ +export const randomLanding = { + title: 'Lag en miks', + mixByTracks: 'Miks etter spor', + mixByTracksDesc: 'Tilfeldig utvalg av spor fra hele biblioteket ditt', + mixByAlbums: 'Miks etter album', + mixByAlbumsDesc: 'Tilfeldige album for nye oppdagelser', + mixByLucky: 'Lykkemiks', + mixByLuckyDesc: 'Smart Instant Mix fra toppartister, album og gode vurderinger', +}; diff --git a/src/locales/nb/randomMix.ts b/src/locales/nb/randomMix.ts new file mode 100644 index 00000000..9342f242 --- /dev/null +++ b/src/locales/nb/randomMix.ts @@ -0,0 +1,39 @@ +export const randomMix = { + title: 'Tilfeldig miks', + remix: 'Remiks', + remixTooltip: 'Last inn nye tilfeldige sanger', + remixGenre: 'Remiks {{genre}}', + remixTooltipGenre: 'Last inn nye {{genre}}-sanger', + playAll: 'Spill alt', + trackTitle: 'Tittel', + trackArtist: 'Artist', + trackAlbum: 'Album', + trackFavorite: 'Favoritt', + trackDuration: 'Varighet', + favoriteAdd: 'Legg til i favoritter', + favoriteRemove: 'Fjern fra favoritter', + play: 'Spill', + trackGenre: 'Sjanger', + mixSettingsHeader: 'Miks-innstillinger', + exclusionsHeader: 'Ekskluderinger', + filterPanelInexactSizeNote: 'Miks-størrelsen er et mål — store forespørsler kan returnere færre unike spor hvis serverens tilfeldige pool tar slutt.', + mixSize: 'Listestørrelse', + excludeAudiobooks: 'Ekskluder lydbøker og hørespill', + excludeAudiobooksDesc: 'Samsvarer nøkkelord mot sjanger, tittel, album og artist - f.eks. Hørespill, Lydbok, Spoken Word, …', + genreBlocked: 'Nøkkelord blokkert', + genreAddedToBlacklist: 'Lagt til i filterliste', + genreAlreadyBlocked: 'Allerede blokkert', + artistBlocked: 'Artisten er blokkert', + artistAddedToBlacklist: 'Artist er lagt til i filterliste', + artistClickHint: 'Klikk for å blokkere denne artisten', + blacklistToggle: 'Nøkkelordfilter', + genreMixTitle: 'Sjangermiks', + genreMixDesc: 'Topp 20 sjangre etter antall sanger - klikk for å laste en tilfeldig miks', + genreMixAll: 'Alle sanger', + genreMixLoadMore: 'Last 10 til', + genreMixNoGenres: 'Ingen sjangre funnet på tjeneren.', + shuffleGenres: 'Vis andre sjangre', + filterPanelTitle: 'Filtre', + filterPanelDesc: 'Klikk på en sjanger-tag eller på artistnavnet i sporlisten nedenfor, for å blokkere den fra fremtidige mikser.', + genreClickHint: 'Klikk på en sjanger-tag for å legge den til\nsom et filternøkkelord.\nSamsvarer med sjanger, tittel, album og artist.', +}; diff --git a/src/locales/nb/search.ts b/src/locales/nb/search.ts new file mode 100644 index 00000000..85cfaa6d --- /dev/null +++ b/src/locales/nb/search.ts @@ -0,0 +1,29 @@ +export const search = { + placeholder: 'Søk etter artist, album eller sang…', + noResults: 'Ingen resultater funnet for "{{query}}"', + artists: 'Artister', + albums: 'Album', + songs: 'Sanger', + clearLabel: 'Fjern søk', + addedToQueueToast: '«{{title}}» lagt til i køen', + title: 'Søk', + resultsFor: 'Resultater for "{{query}}"', + album: 'Album', + advanced: 'Avansert søk', + advancedSearchTerm: 'Søkeord', + advancedSearchPlaceholder: 'Tittel, album, artist…', + advancedGenre: 'Sjanger', + advancedAllGenres: 'Alle sjangre', + advancedYear: 'År', + advancedYearFrom: 'fra', + advancedYearTo: 'til', + advancedAll: 'Alle', + advancedSearch: 'Søk', + advancedEmpty: 'Skriv inn et søkeord eller velg ett filter for å begynne.', + advancedNoResults: 'Ingen resultater funnet.', + advancedGenreNote: 'Sanger er tilfeldig valgt fra denne sjangeren.', + recentSearches: 'Siste søk', + browse: 'Utforsk', + emptyHint: 'Hva vil du høre?', + genres: 'Sjangre', +}; diff --git a/src/locales/nb/settings.ts b/src/locales/nb/settings.ts new file mode 100644 index 00000000..1e5015fe --- /dev/null +++ b/src/locales/nb/settings.ts @@ -0,0 +1,439 @@ +export const settings = { + title: 'Innstillinger', + language: 'Språk', + languageEn: 'English', + languageDe: 'Deutsch', + languageEs: 'Español', + languageFr: 'Français', + languageNl: 'Nederlands', + languageNb: 'Norsk', + languageRu: 'Русский', + languageZh: '中文', + languageRo: 'Română', + font: 'Skrifttype', + fontHintOpenDyslexic: 'Dyslexivennlig · ingen kinesisk støtte', + theme: 'Tema', + appearance: 'Utseende', + servers: 'Tjenere', + serverName: 'Tjenernavn', + serverUrl: 'Tjener-URL', + serverUrlPlaceholder: '192.168.1.100:4533 eller https://musikk.eksempel.com', + serverUsername: 'Brukernavn', + serverPassword: 'Passord', + addServer: 'Legg til tjener', + addServerTitle: 'Legg til ny tjener', + useServer: 'Bruk', + deleteServer: 'Slett', + noServers: 'Ingen tjenere lagret.', + serverActive: 'Aktiv', + confirmDeleteServer: 'Slett tjener "{{name}}"?', + serverConnecting: 'Kobler til…', + serverConnected: 'Tilkoblet!', + serverFailed: 'Tilkobling mislyktes.', + testBtn: 'Test tilkobling', + testingBtn: 'Tester…', + serverCompatible: 'Laget for Navidrome. Andre Subsonic-kompatible servere (Gonic, Airsonic, …) kan fungere med begrenset funksjonalitet, fordi Psysonic bruker mange Navidrome-spesifikke API-endepunkter.', + userMgmtTitle: 'Brukeradministrasjon', + userMgmtDesc: 'Administrer brukere på denne serveren. Krever admin-rettigheter.', + userMgmtNoAdmin: 'Du trenger admin-rettigheter for å administrere brukere på denne serveren.', + userMgmtLoadError: 'Kunne ikke laste brukere.', + userMgmtLoadFriendly: 'Serveren svarte ikke — som regel en engangsfeil.', + userMgmtRetry: 'Prøv igjen', + userMgmtEmpty: 'Ingen brukere funnet.', + userMgmtYouBadge: 'Deg', + userMgmtAdminBadge: 'Admin', + userMgmtAddUser: 'Legg til bruker', + userMgmtAddUserTitle: 'Ny bruker', + userMgmtEditUserTitle: 'Rediger bruker', + userMgmtUsername: 'Brukernavn', + userMgmtName: 'Visningsnavn', + userMgmtEmail: 'E-post', + userMgmtPassword: 'Passord', + userMgmtPasswordEditHint: 'Skriv inn et nytt passord for å oppdatere det.', + userMgmtRoleAdmin: 'Admin', + userMgmtLibraries: 'Biblioteker', + userMgmtLibrariesAdminHint: 'Administratorbrukere har automatisk tilgang til alle biblioteker.', + userMgmtLibrariesEmpty: 'Ingen biblioteker tilgjengelig på denne serveren.', + userMgmtLibrariesValidation: 'Velg minst ett bibliotek.', + userMgmtLibrariesUpdateError: 'Brukeren ble lagret, men bibliotekstilordning mislyktes', + userMgmtNoLibraries: 'Ingen biblioteker tilordnet', + userMgmtNeverSeen: 'Aldri', + userMgmtSave: 'Lagre', + userMgmtCancel: 'Avbryt', + userMgmtDelete: 'Slett', + userMgmtEdit: 'Rediger', + userMgmtConfirmDelete: 'Slett brukeren «{{username}}»? Dette kan ikke angres.', + userMgmtCreateError: 'Kunne ikke opprette bruker.', + userMgmtUpdateError: 'Kunne ikke oppdatere bruker.', + userMgmtDeleteError: 'Kunne ikke slette bruker.', + userMgmtCreated: 'Bruker opprettet.', + userMgmtUpdated: 'Bruker oppdatert.', + userMgmtDeleted: 'Bruker slettet.', + userMgmtValidationMissing: 'Brukernavn, visningsnavn og passord er påkrevd.', + userMgmtValidationMissingIdentity: 'Brukernavn og visningsnavn er påkrevd.', + userMgmtMagicStringGenerate: 'Generer magic string', + userMgmtSaveAndMagicString: 'Lagre og hent magic string', + userMgmtMagicStringPasswordNavHint: + 'Navidrome lagrer dette passordet for brukeren. Hvis det avviker fra det nåværende, oppdateres innloggingspassordet på serveren.', + userMgmtMagicStringPlaintextWarning: + 'Del magic string med varsomhet: den inneholder passordet i klartekst (koding er ikke kryptering). Den som har hele strengen, kan logge inn som denne brukeren.', + userMgmtMagicStringCopied: 'Magic string er kopiert til utklippstavlen.', + userMgmtMagicStringCopyFailed: 'Klarte ikke å kopiere til utklippstavlen.', + userMgmtMagicStringLoginFailed: 'Passordsjekk mislyktes — påloggingsdetaljene kunne ikke verifiseres.', + userMgmtMagicStringModalTitle: 'Generer magic string', + userMgmtMagicStringModalDesc: 'Skriv inn Subsonic-passordet for «{{username}}». Det tas med i den kopierte magic string-en.', + userMgmtMagicStringModalConfirm: 'Kopier streng', + audiomuseTitle: 'AudioMuse-AI (Navidrome)', + audiomuseDesc: + 'Slå på hvis denne serveren bruker AudioMuse-AI Navidrome-plugin. Aktiverer Instant Mix fra spor og henter lignende artister fra serveren i stedet for Last.fm på artistsider.', + audiomuseIssueHint: + 'Instant Mix feilet nylig — sjekk Navidrome-plugin og AudioMuse API. Lignende artister hentes fra Last.fm hvis serveren ikke returnerer noe.', + connected: 'Tilkoblet', + failed: 'Mislyktes', + eqTitle: 'Jevnstiller', + eqEnabled: 'Aktiver jevnstiller', + eqPreset: 'Forhåndsinnstilling', + eqPresetCustom: 'Egendefinert', + eqPresetBuiltin: 'Innebygde forhåndsinnstillinger', + eqPresetCustomGroup: 'Mine forhåndsinnstillinger', + eqSavePreset: 'Lagre som forhåndsinnstilling', + eqPresetName: 'Navn på forhåndsinnstilling…', + eqDeletePreset: 'Slett forhåndsinnstilling', + eqResetBands: 'Tilbakestill til standard', + eqPreGain: 'Forforsterkning', + eqResetPreGain: 'Tilbakestill forforsterkning', + eqAutoEqTitle: 'AutoEQ hodetelefonoppslag', + eqAutoEqPlaceholder: 'Søk etter hodetelefon- / IEM-modell…', + eqAutoEqSearching: 'Søker…', + eqAutoEqNoResults: 'Ingen resultater funnet', + eqAutoEqError: 'Søk mislyktes', + eqAutoEqRateLimit: 'GitHub-hastighetsgrense nådd - prøv igjen om ett minutt', + eqAutoEqFetchError: 'Kunne ikke hente EQ-profil', + lfmTitle: 'Last.fm', + lfmConnect: 'Koble til med Last.fm', + lfmConnecting: 'Venter på autorisasjon…', + lfmConfirm: 'Jeg har autorisert appen', + lfmConnected: 'Tilkoblet som', + lfmDisconnect: 'Koble fra', + lfmConnectDesc: 'Koble til din Last.fm-konto for å aktivere scrobbling og få "Nå spiller"-oppdateringer direkte fra Psysonic - ingen Navidrome-konfigurasjon kreves.', + lfmOpenBrowser: 'Et nettleservindu vil åpne seg. Autoriser Psysonic via Last.fm, og klikk deretter på knappen nedenfor.', + lfmScrobbles: '{{n}} scrobbles', + lfmMemberSince: 'Medlem siden {{year}}', + scrobbleEnabled: 'Scrobbling er aktivert', + scrobbleDesc: 'Send sanger til Last.fm etter 50 % avspilling', + behavior: 'App-oppførsel', + cacheTitle: 'Maks. lagringsstørrelse', + cacheDesc: 'Plateomslag og artistbilder. Når den er full, fjernes de eldste oppføringene automatisk. Frakoblede album fjernes ikke automatisk, men slettes når hurtigbufferen tømmes manuelt.', + cacheUsed: 'Brukt: {{images}} bilder · {{offline}} frakoblede spor', + cacheUsedImages: 'Bilder:', + cacheUsedOffline: 'Frakoblede spor:', + cacheUsedHot: 'Plass brukt:', + hotCacheTrackCount: 'Spor i buffer:', + cacheMaxLabel: 'Maks størrelse', + cacheClearBtn: 'Tøm hurtigbuffer', + cacheClearWarning: 'Dette vil også fjerne alle frakoblede album fra biblioteket.', + cacheClearConfirm: 'Tøm alt', + cacheClearCancel: 'Avbryt', + offlineDirTitle: 'Frakoblet bibliotek (In-App)', + offlineDirDesc: 'Lagringsplassering for spor som du gjør tilgjengelige som frakoblet i Psysonic.', + offlineDirDefault: 'Standard (App-data)', + offlineDirChange: 'Endre katalog', + offlineDirClear: 'Tilbakestill til standard', + offlineDirHint: 'Nye nedlastinger vil bruke denne plasseringen. Eksisterende nedlastinger forblir på sin opprinnelige lokasjon.', + hotCacheTitle: 'Varm avspillingsbuffer', + hotCacheDisclaimer: 'Forhåndshenter neste spor i køen og beholder tidligere. Når aktivert: diskplass og nettverk.', + hotCacheDirDefault: 'Standard (App-data)', + hotCacheDirChange: 'Endre mappe', + hotCacheDirClear: 'Tilbakestill til standard', + hotCacheDirHint: 'Bytte mappe nullstiller indeksen i appen; gamle filer blir liggende til du sletter dem.', + hotCacheEnabled: 'Aktiver varm avspillingsbuffer', + hotCacheMaxMb: 'Maks bufferstørrelse', + hotCacheDebounce: 'Utsettelse ved køendring', + hotCacheDebounceImmediate: 'Umiddelbart', + hotCacheDebounceSeconds: '{{n}} sek', + hotCacheClearBtn: 'Tøm varm buffer', + audioOutputDevice: 'Lydutgangsenhet', + audioOutputDeviceDesc: 'Velg hvilken lydenhet Psysonic spiller gjennom. Endringer trer i kraft umiddelbart og starter gjeldende spor på nytt.', + audioOutputDeviceDefault: 'Systemstandard', + audioOutputDeviceRefresh: 'Oppdater enhetsliste', + audioOutputDeviceOsDefaultNow: 'gjeldende systemutgang', + audioOutputDeviceListError: 'Kunne ikke laste listen over lydenheter.', + audioOutputDeviceNotInCurrentList: 'ikke i gjeldende liste', + audioOutputDeviceMacNotice: 'På macOS følger avspillingen av tekniske årsaker alltid systemets lydutgang. Endre målet via Systeminnstillinger → Lyd eller høyttalerikonet i menylinjen. Bakgrunn: CoreAudio utløser en mikrofontillatelsesdialog når en ikke-standard strøm åpnes — vi unngår det ved alltid å bruke systemets standardutgang.', + hiResTitle: 'Innebygd hi-res-avspilling', + hiResEnabled: 'Aktiver innebygd hi-res-avspilling', + hiResDesc: "Begrenser utdata til 44,1 kHz som standard for maksimal stabilitet. Aktiver kun hvis maskinvare og nettverk støtter høye samplingsrater (88,2 kHz+) pålitelig.", + showArtistImages: 'Vis artistbilder', + showArtistImagesDesc: 'Last inn og vis artistbilder i artistoversikten. Denne er deaktivert som standard, for å redusere disk-I/O og nettverksbelastningen på store biblioteker.', + showOrbitTrigger: 'Vis «Orbit» i toppen', + showOrbitTriggerDesc: 'Knappen i toppen for å starte eller bli med i en delt lytteøkt. Skjul den hvis du ikke bruker Orbit — du kan slå den på igjen her.', + minimizeToTray: 'Minimer til oppgavelinjen', + minimizeToTrayDesc: 'Når vinduet lukkes, vil Psysonic bli kjørende i oppgavelinjen fremfor å bli avsluttet.', + preloadMiniPlayer: 'Forhåndslast miniavspiller', + preloadMiniPlayerDesc: 'Bygger miniavspiller-vinduet i bakgrunnen ved appstart slik at det viser innhold umiddelbart ved første åpning. Bruker litt mer minne.', + linuxWebkitSmoothScroll: 'Mykt musehjul (Linux)', + linuxWebkitSmoothScrollDesc: 'På: treg rull med etterslep. Av: trinnvis som i GTK.', + discordRichPresence: 'Discord Rich Presence', + discordRichPresenceDesc: 'Vis sporet som spilles i din Discord-profil. Krever at Discord kjører.', + discordCoverSource: 'Coverkilde', + discordCoverSourceDesc: 'Hvor albumcoveret for Discord-profilen din hentes fra.', + discordCoverNone: 'Ingen (kun app-ikon)', + discordCoverServer: 'Server (via albuminfo)', + discordCoverApple: 'Apple Music', + discordOptions: 'Avanserte Discord-alternativer', + discordTemplates: 'Egendefinerte tekstmaler', + discordTemplatesDesc: 'Tilpass hvilken informasjon som vises på Discord-profilen din. Variabler: {title}, {artist}, {album}', + discordTemplateDetails: 'Primær linje (details)', + discordTemplateState: 'Sekundær linje (state)', + discordTemplateLargeText: 'Album-verktøytips (largeText)', + nowPlayingEnabled: 'Vis i "Nå spiller"', + nowPlayingEnabledDesc: 'Send sporet som spilles av til tjenerens live-lyttervisning. Deaktiver for å stoppe sending av avspillingsdata.', + enableBandsintown: 'Bandsintown-turnédatoer', + enableBandsintownDesc: 'Vis kommende konserter for gjeldende artist i Info-fanen. Data hentes fra det offentlige Bandsintown-API-et.', + lyricsServerFirst: 'Foretrekk server-sangtekst', + lyricsServerFirstDesc: 'Sjekk tjenerlevererte sangtekster (innebygde tagger, sidecar-filer) før LRCLIB. Deaktiver for å bruke LRCLIB først.', + enableNeteaselyrics: 'Netease Cloud Music sangtekster', + enableNeteaselyricsDesc: 'Bruk Netease Cloud Music som siste utvei når server og LRCLIB ikke finner noe. Best dekning for asiatisk og internasjonal musikk.', + lyricsSourcesTitle: 'Sangtekstkilder', + lyricsSourcesDesc: 'Velg hvilke kilder som skal brukes og i hvilken rekkefølge. Dra for å sortere. Deaktiverte kilder hoppes over.', + lyricsSourceServer: 'Tjener', + lyricsSourceLrclib: 'LRCLIB', + lyricsSourceNetease: 'Netease Cloud Music', + lyricsModeStandard: 'Standard', + lyricsModeStandardDesc: 'Tre kilder med fritt valgbar rekkefølge: server-tagger, LRCLIB, Netease.', + lyricsModeLyricsplus: 'YouLyPlus (Karaoke)', + lyricsModeLyricsplusDesc: 'Ord-for-ord-synkronisering fra Apple Music, Spotify, Musixmatch og QQ (fellesskapsbackend). Faller stille tilbake på standardkildene når ingenting finnes.', + lyricsStaticOnly: 'Vis sangtekst som statisk tekst', + lyricsStaticOnlyDesc: 'Viser synkroniserte tekster uten auto-scroll og uten ord-utheving.', + downloadsTitle: 'ZIP Eksport & Arkivering', + downloadsFolderDesc: 'Målmappe for album du laster ned som en ZIP-fil til datamaskinen din.', + downloadsDefault: 'Standard nedlastingsmappe', + pickFolder: 'Velg', + pickFolderTitle: 'Velg nedlastingsmappe', + clearFolder: 'Tøm nedlastingsmappe', + logout: 'Logg ut', + aboutTitle: 'Om Psysonic', + aboutDesc: 'En moderne musikkspiller laget for Navidrome. Bruker Subsonic-API-en pluss Navidrome-spesifikke utvidelser. Bygget på Tauri v2 med en innebygd Rust-lydmotor — lett og rask, men fullpakket med funksjoner: bølgeform-søkelinje, synkroniserte sangtekster, Last.fm-integrasjon, 10-bånds jevnstiller, crossfade, gapless-avspilling, Replay Gain, sjangerlesing og et stort bibliotek med temaer.', + aboutLicense: 'Lisens', + aboutLicenseText: 'GNU GPL v3 - gratis å bruke, endre og distribuere under samme lisens.', + aboutRepo: 'Kildekode på GitHub', + aboutVersion: 'Versjon', + aboutBuiltWith: 'Bygget med Tauri · React · TypeScript · Rust/rodio', + aboutReleaseNotesLabel: 'Versjonsnotater', + aboutReleaseNotesLink: 'Åpne nyhetene for denne versjonen', + aboutContributorsLabel: 'Bidragsytere', + showChangelogOnUpdate: "Vis 'Hva er nytt' ved oppdatering til ny versjon", + showChangelogOnUpdateDesc: "Viser et diskret changelog-banner over Now Playing etter en oppdatering. Klikk åpner versjonsnotatene; X skjuler det.", + randomMixTitle: 'Svarteliste for tilfeldig miks', + luckyMixMenuTitle: 'Vis Lykkemiks i menyen', + luckyMixMenuDesc: 'Aktiverer Lykkemiks i "Lag en miks" og som eget menypunkt når delt navigasjon er aktiv. Vises bare når AudioMuse er aktiv på gjeldende server.', + randomMixBlacklistTitle: 'Egendefinerte filternøkkelord', + randomMixBlacklistDesc: 'Sanger ekskluderes når et nøkkelord samsvarer med sjanger, tittel, album eller artist (aktiv når avkrysningsboksen ovenfor er på).', + randomMixBlacklistPlaceholder: 'Legg til nøkkelord…', + randomMixBlacklistAdd: 'Legg til', + randomMixBlacklistEmpty: 'Ingen egendefinerte nøkkelord lagt til ennå.', + randomMixHardcodedTitle: 'Innebygde nøkkelord (aktiv når avkrysningsboksen er på)', + tabPlayback: 'Avspilling', + tabLibrary: 'Bibliotek', + tabServers: 'Servere', + tabLyrics: 'Sangtekster', + tabPersonalisation: 'Personalisering', + tabIntegrations: 'Integrasjoner', + tabAppearance: 'Utseende', + tabStorage: 'Frakoblet & Cache', + inputKeybindingsTitle: 'Tastatursnarveier', + aboutContributorsCount_one: '{{count}} bidrag', + aboutContributorsCount_other: '{{count}} bidrag', + searchPlaceholder: 'Søk i innstillinger…', + searchNoResults: 'Ingen innstillinger samsvarer med søket ditt.', + aboutMaintainersLabel: 'Ansvarlige', + integrationsPrivacyTitle: 'Personvern-merknad', + integrationsPrivacyBody: 'Alle integrasjoner på denne fanen er frivillige og sender, når aktivert, data til eksterne tjenester eller til Navidrome-serveren din. Last.fm mottar lyttehistorikken din, Discord viser gjeldende spor i profilen din, Bandsintown spørres per artist for turnédatoer, og "Spilles nå"-delingen publiserer gjeldende spor til andre brukere av Navidrome-serveren din. Hvis du ikke ønsker noe av dette, la den aktuelle seksjonen stå deaktivert.', + homeCustomizerTitle: 'Hjemmeside', + queueToolbarTitle: 'Kø-verktøylinje', + queueToolbarReset: 'Tilbakestill til standard', + queueToolbarSeparator: 'Skilje', + sidebarTitle: 'Sidefelt', + sidebarReset: 'Tilbakestill til standard', + artistLayoutTitle: 'Artistsidens seksjoner', + artistLayoutDesc: 'Dra for å omorganisere, veksle for å skjule individuelle seksjoner av artistsiden. Seksjoner uten data hoppes over automatisk.', + artistLayoutReset: 'Tilbakestill til standard', + artistLayoutBio: 'Artistbiografi', + artistLayoutTopTracks: 'Toppspor', + artistLayoutSimilar: 'Lignende artister', + artistLayoutAlbums: 'Album', + artistLayoutFeatured: 'Også med på', + sidebarDrag: 'Dra for å endre rekkefølge', + sidebarFixed: 'Alltid synlig', + randomNavSplitTitle: 'Del Mix-navigasjon', + randomNavSplitDesc: 'Vis "Tilfeldig miks", "Tilfeldige album" og "Lykkemiks" som separate sidefeltsoppføringer i stedet for "Lag en miks"-huben.', + tabShortcuts: 'Snarveier', + tabUsers: 'Brukere', + tabSystem: 'System', + loggingTitle: 'Loggføring', + loggingModeDesc: 'Styrer hvor detaljert backend-loggene i terminalen er.', + loggingModeOff: 'Av', + loggingModeNormal: 'Normal', + loggingModeDebug: 'Debug', + loggingExport: 'Eksporter logger', + loggingExportSuccess: 'Logger eksportert ({{count}} linjer).', + loggingExportError: 'Kunne ikke eksportere logger.', + ratingsSectionTitle: 'Vurderinger', + ratingsSkipStarTitle: 'Hopp for 1 stjerne', + ratingsSkipStarDesc: + 'Etter flere hopp på rad: sett sporet til 1 stjerne. Bare for spor som ikke var vurdert før.', + ratingsSkipStarThresholdLabel: 'Hopp', + ratingsMixFilterTitle: 'Filtrering etter vurdering', + ratingsMixFilterDesc: + 'Filtrer innhold med lav vurdering i {{mix}} og {{albums}}. Klikk på den valgte stjerna igjen for å slå av terskelen.', + ratingsMixMinSong: 'Spor', + ratingsMixMinAlbum: 'Album', + ratingsMixMinArtist: 'Artister', + ratingsMixMinThresholdAria: 'Minimum stjerner: {{label}}', + backupTitle: 'Sikkerhetskopiering og gjenoppretting', + backupExport: 'Eksporter innstillinger', + backupExportDesc: 'Lagrer alle innstillinger, tjenerprofiler, Last.fm-konfigurasjon, tema, jevnstiller og tastebindinger til en .psybkp-fil. Passordet lagres i klartekst – hold filen sikker.', + backupImport: 'Importer innstillinger', + backupImportDesc: 'Gjenoppretter innstillinger fra en .psybkp-fil. Applikasjonen starter på nytt etter import.', + backupImportConfirm: 'Dette vil overskrive alle gjeldende innstillinger. Vil du fortsette?', + backupSuccess: 'Sikkerhetskopiering lagret', + backupImportSuccess: 'Innstillinger gjenopprettet – laster inn data på nytt…', + backupImportError: 'Ugyldig eller ødelagt fil for sikkerhetskopi.', + shortcutsReset: 'Tilbakestill til standardinnstillinger', + shortcutListening: 'Trykk på en tast…', + shortcutUnbound: '-', + globalShortcutsTitle: 'Globale snarveier', + globalShortcutsNote: 'Arbeid systemomfattende selv når Psysonic er i bakgrunnen. Krever Ctrl, Alt eller Super som modifikator.', + shortcutClear: 'Fjern', + shortcutPlayPause: 'Spill av / Pause', + shortcutNext: 'Neste spor', + shortcutPrev: 'Forrige spor', + shortcutVolumeUp: 'Volum opp', + shortcutVolumeDown: 'Volum ned', + shortcutSeekForward: 'Søk fremover 10 sekunder', + shortcutSeekBackward: 'Søk bakover 10 sekunder', + shortcutToggleQueue: 'Veksle kø', + shortcutOpenFolderBrowser: 'Åpne {{folderBrowser}}', + shortcutFullscreenPlayer: 'Fullskjermsspiller', + shortcutNativeFullscreen: 'Naturlig fullskjerm', + shortcutOpenMiniPlayer: 'Åpne minispiller', + shortcutStartSearch: 'Start et søk', + shortcutStartAdvancedSearch: 'Start et avansert søk', + shortcutToggleSidebar: 'Veksle sidefelt', + shortcutMuteSound: 'Demp lyd', + shortcutToggleEqualizer: 'Åpne / veksle Equalizer', + shortcutToggleRepeat: 'Veksle gjenta', + shortcutOpenNowPlaying: 'Åpne "Spilles nå"', + shortcutShowLyrics: 'Vis sangtekst', + shortcutFavoriteCurrentTrack: 'Legg gjeldende spor til favoritter', + shortcutOpenHelp: 'Hjelp', + playbackTitle: 'Avspilling', + replayGain: 'Replay Gain', + replayGainDesc: 'Normaliser sporvolumet ved hjelp av ReplayGain-metadata', + replayGainMode: 'Modus', + replayGainAuto: 'Auto', + replayGainAutoDesc: 'Bruker albumforsterkning når nabospor i køen er fra samme album, ellers sporforsterkning.', + replayGainTrack: 'Spor', + replayGainAlbum: 'Album', + replayGainPreGain: 'Pre-Gain (taggede filer)', + replayGainPreGainDesc: 'Universelt løft som legges på hver ReplayGain-beregning. Nyttig hvis biblioteket ditt totalt sett virker for stille.', + replayGainFallback: 'Reserveverdi (uten tagger / radio)', + replayGainFallbackDesc: 'Brukes for spor (og radiostrømmer) uten ReplayGain-tagger, slik at utagget innhold ikke spretter høyere enn resten.', + normalization: 'Normalisering', + normalizationDesc: 'Jevn ut opplevd loudness mellom spor, album og radio.', + normalizationOff: 'Av', + normalizationReplayGain: 'ReplayGain', + normalizationLufs: 'LUFS', + loudnessTargetLufs: 'Mål-LUFS', + loudnessTargetLufsDesc: 'Referanse-loudness alle spor matches mot. Lavere tall = høyere utgang. Strømmetjenester ligger vanligvis rundt -14 LUFS.', + loudnessPreAnalysisAttenuation: 'Demping før måling', + loudnessPreAnalysisAttenuationDesc: + 'Ekstra demping til loudness for sporet er lagret. Streaming bruker deretter grove anslag, ikke full måling. 0 dB = av; lavere = roligere. Til høyre vises effektiv dB for valgt mål.', + loudnessPreAnalysisAttenuationRef: 'Effektivt {{eff}} dB med mål {{tgt}} LUFS.', + loudnessPreAnalysisAttenuationReset: 'Standard', + loudnessFirstPlayNote: + 'Første avspilling av et helt nytt spor kan drive litt i volum mens målingen skjer. Neste gang brukes den lagrede målingen, og alt blir stabilt. Kommende spor i køen blir vanligvis pre-analysert mens det forrige spilles, så dette skjer sjelden i praksis.', + crossfade: 'Crossfade', + crossfadeDesc: 'Tone mellom spor', + crossfadeSecs: '{{n}}s', + notWithGapless: 'Ikke tilgjengelig mens Gapless er aktiv', + notWithCrossfade: 'Ikke tilgjengelig mens Crossfade er aktiv', + gapless: 'Gapless avspilling', + gaplessDesc: 'Forhåndsbuffer neste spor for å eliminere mellomrom mellom sanger', + preservePlayNextOrder: 'Behold "Spill neste"-rekkefølge', + preservePlayNextOrderDesc: 'Nye "Spill neste"-elementer havner bak de eksisterende i stedet for å snike seg foran.', + trackPreviewsTitle: 'Sporforhåndsvisning', + trackPreviewsToggle: 'Aktiver sporforhåndsvisning', + trackPreviewsDesc: 'Vis innebygde Spill- og Forhåndsvisning-knapper i sporlister for en kort smakebit fra midten av sangen.', + trackPreviewStart: 'Startposisjon', + trackPreviewStartDesc: 'Hvor langt inn i sporet forhåndsvisningen starter (% av lengden).', + trackPreviewDuration: 'Varighet', + trackPreviewDurationDesc: 'Hvor lenge hver forhåndsvisning spiller før den stopper.', + trackPreviewDurationSecs: '{{n}} s', + trackPreviewLocationsTitle: 'Hvor forhåndsvisninger vises', + trackPreviewLocationsDesc: 'Velg hvilke lister som viser forhåndsvisningsknapper.', + trackPreviewLocation_suggestions: 'I spillelisteforslag', + trackPreviewLocation_albums: 'I albumsporlister', + trackPreviewLocation_playlists: 'I spillelister', + trackPreviewLocation_favorites: 'I favoritter', + trackPreviewLocation_artist: 'I artistens toppspor', + trackPreviewLocation_randomMix: 'I Random Mix', + infiniteQueue: 'Uendelig kø', + infiniteQueueDesc: 'Legg automatisk til tilfeldige spor når køen går tom', + experimental: 'Eksperimentell', + preloadMode: 'Forhåndslast neste spor', + preloadModeDesc: 'Når buffering av neste spor i køen skal starte', + nextTrackBufferingTitle: 'Bufring', + preloadHotCacheMutualExclusive: 'Forhåndslasting og Hot Cache tjener samme formål – bare én kan være aktiv om gangen. Å aktivere den ene deaktiverer automatisk den andre.', + preloadOff: 'Av', + preloadBalanced: 'Balansert (30 s før slutt)', + preloadEarly: 'Tidlig (etter 5 s avspilling)', + preloadCustom: 'Egendefinert', + preloadCustomSeconds: 'Sekunder før slutt: {{n}}', + fsPlayerSection: 'Fullskjermspiller', + fsShowArtistPortrait: 'Vis artistbilde', + fsShowArtistPortraitDesc: 'Vis artistbilde (eller albumomslag) på høyre side av fullskjermspilleren.', + fsPortraitDim: 'Mørklegging av bilde', + fsLyricsStyle: 'Tekststil', + fsLyricsStyleRail: 'Skinner', + fsLyricsStyleRailDesc: 'Klassisk 5-linjes glidende skinner.', + fsLyricsStyleApple: 'Rulling', + fsLyricsStyleAppleDesc: 'Fullskjerm rulleliste.', + sidebarLyricsStyle: 'Rullestil for tekst', + sidebarLyricsStyleClassic: 'Klassisk', + sidebarLyricsStyleClassicDesc: 'Aktiv linje sentreres.', + sidebarLyricsStyleApple: 'Apple Music-like', + sidebarLyricsStyleAppleDesc: 'Aktiv linje forankres øverst med jevn animasjon.', + seekbarStyle: 'Søkefelt-stil', + seekbarStyleDesc: 'Velg utseendet på avspillingssøkefeltet', + seekbarTruewave: 'Ekte bølgeform', + seekbarPseudowave: 'Pseudo-bølgeform', + seekbarLinedot: 'Linje & punkt', + seekbarBar: 'Linje', + seekbarThick: 'Tykk linje', + seekbarSegmented: 'Segmentert', + seekbarNeon: 'Neon', + seekbarPulsewave: 'Pulsbølge', + seekbarParticletrail: 'Partikkelspor', + seekbarLiquidfill: 'Væskerør', + seekbarRetrotape: 'Retrotape', + themeSchedulerTitle: 'Tidsplanlagt tema', + themeSchedulerEnable: 'Aktiver temaplanlegger', + themeSchedulerEnableSub: 'Bytter automatisk mellom to temaer basert på tidspunkt', + themeSchedulerDayTheme: 'Dagtema', + themeSchedulerDayStart: 'Dag starter kl.', + themeSchedulerNightTheme: 'Natttema', + themeSchedulerNightStart: 'Natt starter kl.', + themeSchedulerActiveHint: 'Temaplanlegger er aktiv - temaer byttes automatisk.', + visualOptionsTitle: 'Visuelle Alternativer', + coverArtBackground: 'Cover-bakgrunn', + coverArtBackgroundSub: 'Vis uskarpt cover som bakgrunn i album/playlist-overskrifter', + playlistCoverPhoto: 'Playlist-coverfoto', + playlistCoverPhotoSub: 'Vis coverfoto-rutenett i playlist-detailedvisning', + showBitrate: 'Vis Bitrate', + showBitrateSub: 'Vis audio-bitrate i sporlister', + floatingPlayerBar: 'Flytende Spillerlinje', + floatingPlayerBarSub: 'Hold spillerlinjen flytende over innholdet', + uiScaleTitle: 'Grensesnittskala', + uiScaleLabel: 'Zoom', +}; diff --git a/src/locales/nb/sharePaste.ts b/src/locales/nb/sharePaste.ts new file mode 100644 index 00000000..94a7414f --- /dev/null +++ b/src/locales/nb/sharePaste.ts @@ -0,0 +1,18 @@ +export const sharePaste = { + notLoggedIn: 'Logg inn og legg til serveren før du limer inn en delingslenke.', + noMatchingServer: 'Ingen lagret server samsvarer med denne lenken. Legg til en server med denne adressen: {{url}}', + trackUnavailable: 'Fant ikke dette sporet på serveren.', + albumUnavailable: 'Fant ikke dette albumet på serveren.', + artistUnavailable: 'Fant ikke denne artisten på serveren.', + composerUnavailable: 'Fant ikke denne komponisten på serveren.', + openedTrack: 'Spiller delt spor.', + openedAlbum: 'Åpner delt album.', + openedArtist: 'Åpner delt artist.', + openedComposer: 'Åpner delt komponist.', + openedQueue_one: 'Spiller {{count}} spor fra delingslenken.', + openedQueue_other: 'Spiller {{count}} spor fra delingslenken.', + openedQueuePartial: + 'Spiller {{played}} av {{total}} spor fra lenken ({{skipped}} ble ikke funnet på denne serveren).', + queueAllUnavailable: 'Ingen av sporene fra denne lenken ble funnet på serveren.', + genericError: 'Klarte ikke å åpne delingslenken.', +}; diff --git a/src/locales/nb/sidebar.ts b/src/locales/nb/sidebar.ts new file mode 100644 index 00000000..669bad6e --- /dev/null +++ b/src/locales/nb/sidebar.ts @@ -0,0 +1,37 @@ +export const sidebar = { + library: 'Bibliotek', + mainstage: 'Hovedscene', + newReleases: 'Nye utgivelser', + allAlbums: 'Alle album', + randomAlbums: 'Tilfeldige album', + randomPicker: 'Lag en miks', + artists: 'Artister', + composers: 'Komponister', + randomMix: 'Tilfeldig miks', + favorites: 'Favoritter', + nowPlaying: 'Spilles nå', + system: 'System', + statistics: 'Statistikk', + settings: 'Innstillinger', + help: 'Hjelp', + expand: 'Utvid sidefelt', + collapse: 'Skjul sidefelt', + downloadingTracks: 'Bufre {{n}} spor…', + syncingTracks: 'Synkroniserer {{done}}/{{total}}…', + cancelDownload: 'Avbryt nedlasting', + offlineLibrary: 'Frakoblet bibliotek', + genres: 'Sjangere', + tracks: 'Spor', + playlists: 'Spillelister', + mostPlayed: 'Mest spilt', + losslessAlbums: 'Lossless', + radio: 'Internettradio', + folderBrowser: 'Mappeleser', + deviceSync: 'Enhetssynk', + libraryScope: 'Biblioteksomfang', + allLibraries: 'Alle biblioteker', + expandPlaylists: 'Utvid spillelister', + collapsePlaylists: 'Skjul spillelister', + more: 'Mer', + feelingLucky: 'Lykkemiks', +}; diff --git a/src/locales/nb/smartPlaylists.ts b/src/locales/nb/smartPlaylists.ts new file mode 100644 index 00000000..bb6781d3 --- /dev/null +++ b/src/locales/nb/smartPlaylists.ts @@ -0,0 +1,41 @@ +export const smartPlaylists = { + sectionBasic: '1. Grunnleggende', + sectionGenres: '2. Sjanger', + sectionYearsAndFilters: '3. År og filtre', + genreMode: 'Sjanger-modus', + genreModeInclude: 'Inkluder sjangre', + genreModeExclude: 'Ekskluder sjangre', + genreSearchPlaceholder: 'Filtrer sjangre...', + availableGenres: 'Tilgjengelige', + selectedGenres: 'Valgte', + yearMode: 'År-modus', + yearModeInclude: 'Inkluder område', + yearModeExclude: 'Ekskluder område', + name: 'Navn (uten prefiks)', + limit: 'Grense', + limitHint: 'Hvor mange spor som skal inkluderes i spillelisten (1-{{max}}, vanligvis 50).', + artistContains: 'Artist inneholder…', + albumContains: 'Album inneholder…', + titleContains: 'Tittel inneholder…', + minRating: 'Minimumsvurdering', + minRatingAria: 'Minimumsvurdering for smart-spilleliste', + minRatingHint: '0 deaktiverer minimumsterskelen; 1-5 beholder spor med vurdering over valgt verdi.', + fromYear: 'Fra år', + toYear: 'Til år', + excludeUnrated: 'Ekskluder spor uten vurdering', + compilationOnly: 'Kun samlinger', + create: 'Ny Smart-spilleliste', + save: 'Lagre Smart-spilleliste', + created: '{{name}} opprettet', + updated: '{{name}} oppdatert', + createFailed: 'Kunne ikke opprette smart-spilleliste.', + updateFailed: 'Kunne ikke oppdatere smart-spilleliste.', + navidromeOnly: 'Smart-spillelister kan bare opprettes på Navidrome-servere.', + loadFailed: 'Kunne ikke laste smart-spillelister fra Navidrome.', + sortRandom: 'Sortering: tilfeldig', + sortTitleAsc: 'Sortering: tittel A-Å', + sortTitleDesc: 'Sortering: tittel Å-A', + sortYearDesc: 'Sortering: år synkende', + sortYearAsc: 'Sortering: år stigende', + sortPlayCountDesc: 'Sortering: avspillinger synkende', +}; diff --git a/src/locales/nb/songInfo.ts b/src/locales/nb/songInfo.ts new file mode 100644 index 00000000..774beecc --- /dev/null +++ b/src/locales/nb/songInfo.ts @@ -0,0 +1,23 @@ +export const songInfo = { + title: 'Sanginfo', + songTitle: 'Tittel', + artist: 'Artist', + album: 'Album', + albumArtist: 'Albumartist', + year: 'År', + genre: 'Sjanger', + duration: 'Varighet', + track: 'Spor', + format: 'Format', + bitrate: 'Bitrate', + sampleRate: 'Samplingfrekvens', + bitDepth: 'Bitdybde', + channels: 'Kanaler', + fileSize: 'Filstørrelse', + path: 'Sti', + replayGainTrack: 'RG-sporforsterkning', + replayGainAlbum: 'RG-albumforsterkning', + replayGainPeak: 'RG-sportopp', + mono: 'Mono', + stereo: 'Stereo', +}; diff --git a/src/locales/nb/statistics.ts b/src/locales/nb/statistics.ts new file mode 100644 index 00000000..a032dcd9 --- /dev/null +++ b/src/locales/nb/statistics.ts @@ -0,0 +1,47 @@ +export const statistics = { + title: 'Statistikk', + recentlyPlayed: 'Nylig spilt', + mostPlayed: 'Mest spilte album', + highestRated: 'Høyest rangerte album', + genreDistribution: 'Sjangerfordeling (Topp 20)', + loadMore: 'Last inn mer', + statArtists: 'Artister', + statArtistsTooltip: 'Kun albumartister — artister som bare opptrer som sporartist (featuring, gjest, osv.) uten eget album telles ikke med.', + statAlbums: 'Album', + statSongs: 'Sanger', + statGenres: 'Sjangere', + statPlaytime: 'Total spilletid', + genreInsights: 'Sjangerinnsikt', + formatDistribution: 'Formatdistribusjon', + formatSample: 'Utvalg av {{n}} spor', + computing: 'Utregner…', + genreSongs: '{{count}} Sanger', + genreAlbums: '{{count}} Album', + recentlyAdded: 'Nylig lagt til', + decadeDistribution: 'Album etter tiår', + decadeAlbums_one: '{{count}} Album', + decadeAlbums_other: '{{count}} Album', + decadeUnknown: 'Ukjent', + lfmTitle: 'Last.fm Statistikk', + lfmTopArtists: 'Toppartister', + lfmTopAlbums: 'Toppalbum', + lfmTopTracks: 'Toppspor', + lfmPlays: '{{count}} avspillinger', + lfmPeriodOverall: 'Alltid', + lfmPeriod7day: '7 dager', + lfmPeriod1month: '1 måned', + lfmPeriod3month: '3 måneder', + lfmPeriod6month: '6 måneder', + lfmPeriod12month: '12 måneder', + lfmNotConnected: 'Koble til Last.fm i Innstillinger for å se statistikken din.', + lfmRecentTracks: 'Siste Scrobble-innslag', + lfmNowPlaying: 'Spilles nå', + lfmJustNow: 'akkurat nå', + lfmMinutesAgo: 'For {{n}}m siden', + lfmHoursAgo: 'For {{n}}t siden', + lfmDaysAgo: 'For {{n}}d siden', + topRatedSongs: 'Høyest vurderte spor', + topRatedArtists: 'Høyest vurderte artister', + noRatedSongs: 'Ingen vurderte spor ennå. Vurder spor i album- eller spillelistevisning.', + noRatedArtists: 'Ingen vurderte artister ennå.', +}; diff --git a/src/locales/nb/tracks.ts b/src/locales/nb/tracks.ts new file mode 100644 index 00000000..37d0e25a --- /dev/null +++ b/src/locales/nb/tracks.ts @@ -0,0 +1,15 @@ +export const tracks = { + title: 'Spor', + subtitle: 'Bla. Søk. Oppdag.', + heroEyebrow: 'Sporet akkurat nå', + heroReroll: 'Velg et annet', + playSong: 'Spill av', + enqueueSong: 'Legg til i kø', + railRandom: 'Tilfeldig valg', + railHighlyRated: 'Høyt vurdert', + browseTitle: 'Bla gjennom alle spor', + browseUnsupported: 'Denne tjeneren lister ikke hele biblioteket på én gang. Bruk søket ovenfor for å finne bestemte spor.', + searchPlaceholder: 'Finn et spor etter tittel, artist eller album…', + count_one: '{{count}} spor', + count_other: '{{count}} spor', +}; diff --git a/src/locales/nb/tray.ts b/src/locales/nb/tray.ts new file mode 100644 index 00000000..41e58150 --- /dev/null +++ b/src/locales/nb/tray.ts @@ -0,0 +1,8 @@ +export const tray = { + playPause: 'Spill / Pause', + nextTrack: 'Neste spor', + previousTrack: 'Forrige spor', + showHide: 'Vis / Skjul', + exitPsysonic: 'Avslutt Psysonic', + nothingPlaying: 'Ingenting spilles', +}; diff --git a/src/locales/nb/whatsNew.ts b/src/locales/nb/whatsNew.ts new file mode 100644 index 00000000..78191a73 --- /dev/null +++ b/src/locales/nb/whatsNew.ts @@ -0,0 +1,8 @@ +export const whatsNew = { + title: 'Nyheter', + empty: 'Ingen endringslogg for denne versjonen ennå.', + bannerTitle: 'Changelog', + bannerCollapsed: 'Nyheter i v{{version}}', + dismiss: 'Skjul', + close: 'Lukk', +}; diff --git a/src/locales/nl.ts b/src/locales/nl.ts deleted file mode 100644 index c293f044..00000000 --- a/src/locales/nl.ts +++ /dev/null @@ -1,1823 +0,0 @@ -export const nlTranslation = { - sidebar: { - library: 'Bibliotheek', - mainstage: 'Hoofdpodium', - newReleases: 'Nieuw', - allAlbums: 'Alle albums', - randomAlbums: 'Willekeurige albums', - randomPicker: 'Mix samenstellen', - artists: 'Artiesten', - composers: 'Componisten', - randomMix: 'Willekeurige mix', - favorites: 'Favorieten', - nowPlaying: 'Nu bezig', - system: 'Systeem', - statistics: 'Statistieken', - settings: 'Instellingen', - help: 'Help', - expand: 'Zijbalk uitklappen', - collapse: 'Zijbalk inklappen', - downloadingTracks: '{{n}} nummers worden gecached…', - syncingTracks: 'Synchroniseren {{done}}/{{total}}…', - cancelDownload: 'Download annuleren', - offlineLibrary: 'Offline bibliotheek', - genres: 'Genres', - tracks: 'Nummers', - playlists: 'Playlists', - mostPlayed: 'Meest gespeeld', - losslessAlbums: 'Lossless', - radio: 'Internetradio', - folderBrowser: 'Mappenverkenner', - deviceSync: 'Apparaatsync', - libraryScope: 'Bibliotheekbereik', - allLibraries: 'Alle bibliotheken', - expandPlaylists: 'Afspeellijsten uitklappen', - collapsePlaylists: 'Afspeellijsten inklappen', - more: 'Meer', - feelingLucky: 'Geluksmix', - }, - home: { - hero: 'Uitgelicht', - starred: 'Persoonlijke favorieten', - recent: 'Recent toegevoegd', - mostPlayed: 'Meest gespeeld', - recentlyPlayed: 'Recent afgespeeld', - losslessAlbums: 'Lossless-albums', - discover: 'Ontdekken', - discoverSongs: 'Nummers ontdekken', - loadMore: 'Meer laden', - discoverMore: 'Meer ontdekken', - discoverArtists: 'Artiesten ontdekken', - discoverArtistsMore: 'Alle artiesten', - becauseYouLike: 'Omdat je hebt geluisterd…', - becauseYouLikeFor: 'Omdat je naar {{artist}} hebt geluisterd', - similarTo: 'Lijkt op {{artist}}', - becauseYouLikeTracks_one: '{{count}} nummer', - becauseYouLikeTracks_other: '{{count}} nummers' - }, - hero: { - eyebrow: 'Uitgelicht album', - playAlbum: 'Album afspelen', - enqueue: 'In wachtrij', - enqueueTooltip: 'Volledig album aan wachtrij toevoegen', - }, - search: { - placeholder: 'Zoek naar artiest, album of nummer…', - noResults: 'Geen resultaten voor "{{query}}"', - artists: 'Artiesten', - albums: 'Albums', - songs: 'Nummers', - clearLabel: 'Zoekopdracht wissen', - addedToQueueToast: '"{{title}}" toegevoegd aan de wachtrij', - title: 'Zoeken', - resultsFor: 'Resultaten voor "{{query}}"', - album: 'Album', - advanced: 'Geavanceerd zoeken', - advancedSearchTerm: 'Zoekterm', - advancedSearchPlaceholder: 'Titel, album, artiest…', - advancedGenre: 'Genre', - advancedAllGenres: 'Alle genres', - advancedYear: 'Jaar', - advancedYearFrom: 'van', - advancedYearTo: 'tot', - advancedAll: 'Alle', - advancedSearch: 'Zoeken', - advancedEmpty: 'Voer een zoekterm in of selecteer een filter.', - advancedNoResults: 'Geen resultaten gevonden.', - advancedGenreNote: 'Nummers worden willekeurig uit dit genre geselecteerd.', - recentSearches: 'Recente zoekopdrachten', - browse: 'Bladeren', - emptyHint: 'Wat wil je horen?', - genres: 'Genres', - }, - nowPlaying: { - tooltip: 'Wie luistert er?', - title: 'Wie luistert er?', - loading: 'Laden…', - nobody: 'Er luistert momenteel niemand.', - minutesAgo: '{{n}} min geleden', - nothingPlaying: 'Nog niets bezig. Start een nummer!', - aboutArtist: 'Over de artiest', - fromAlbum: 'Van dit album', - viewAlbum: 'Album openen', - goToArtist: 'Naar artiest', - readMore: 'Meer lezen', - showLess: 'Minder tonen', - genreInfo: 'Genre', - trackInfo: 'Trackinfo', - topSongs: 'Meest afgespeeld van deze artiest', - topSongsCredit: 'Topnummers van {{name}}', - trackPosition: 'Track {{pos}}', - playsCount_one: '{{count}} keer afgespeeld', - playsCount_other: '{{count}} keer afgespeeld', - releasedYearsAgo_one: '{{count}} jaar geleden', - releasedYearsAgo_other: '{{count}} jaar geleden', - discography: 'Discografie', - lastfmStats: 'Last.fm-statistieken', - thisTrack: 'Dit nummer', - thisArtist: 'Deze artiest', - listeners: 'luisteraars', - scrobbles: 'scrobbles', - yourScrobbles: 'door jou', - listenersN: '{{n}} luisteraars', - scrobblesN: '{{n}} scrobbles', - playsByYouN: '{{n}}× door jou afgespeeld', - openTrackOnLastfm: 'Nummer op Last.fm', - openArtistOnLastfm: 'Artiest op Last.fm', - rgTrackTooltip: 'ReplayGain (track)', - rgAlbumTooltip: 'ReplayGain (album)', - rgAutoTooltip: 'ReplayGain (auto)', - showMoreTracks: '{{count}} meer tonen', - showLessTracks: 'Minder tonen', - hideCard: 'Kaart verbergen', - layoutMenu: 'Lay-out', - visibleCards: 'Zichtbare kaarten', - hiddenCards: 'Verborgen kaarten', - noHiddenCards: 'Geen verborgen kaarten', - resetLayout: 'Lay-out resetten', - emptyColumn: 'Sleep kaarten hier', - }, - contextMenu: { - playNow: 'Nu afspelen', - playNext: 'Volgende afspelen', - addToQueue: 'Aan wachtrij toevoegen', - enqueueAlbum: 'Album in wachtrij', - enqueueAlbums_one: '{{count}} album in wachtrij', - enqueueAlbums_other: '{{count}} albums in wachtrij', - startRadio: 'Radio starten', - instantMix: 'Instant Mix', - instantMixFailed: 'Instant Mix mislukt — server- of pluginfout.', - cliMixNeedsTrack: 'Er speelt niets — start eerst afspelen en voer het mix-commando opnieuw uit.', - lfmLove: 'Liken op Last.fm', - lfmUnlove: 'Niet meer liken op Last.fm', - favorite: 'Favoriet', - favoriteArtist: 'Favoriete artiest', - favoriteAlbum: 'Favoriet album', - unfavorite: 'Verwijderen uit favorieten', - unfavoriteArtist: 'Artiest uit favorieten verwijderen', - unfavoriteAlbum: 'Album uit favorieten verwijderen', - removeFromQueue: 'Uit wachtrij verwijderen', - openAlbum: 'Album openen', - goToArtist: 'Naar artiest', - download: 'Downloaden (ZIP)', - addToPlaylist: 'Toevoegen aan playlist', - selectedPlaylists: '{{count}} playlists geselecteerd', - selectedAlbums: '{{count}} albums geselecteerd', - selectedArtists: '{{count}} artiesten geselecteerd', - songInfo: 'Nummerinfo', - shareLink: 'Deellink kopiëren', - shareCopied: 'Deellink gekopieerd naar het klembord.', - shareCopyFailed: 'Kopiëren naar het klembord is mislukt.', - }, - sharePaste: { - notLoggedIn: 'Log in en voeg de server toe voordat je een deellink plakt.', - noMatchingServer: 'Geen opgeslagen server komt overeen met deze link. Voeg een server toe met dit adres: {{url}}', - trackUnavailable: 'Dit nummer is niet op de server gevonden.', - albumUnavailable: 'Dit album is niet op de server gevonden.', - artistUnavailable: 'Deze artiest is niet op de server gevonden.', - composerUnavailable: 'Deze componist is niet op de server gevonden.', - openedTrack: 'Gedeeld nummer wordt afgespeeld.', - openedAlbum: 'Gedeeld album wordt geopend.', - openedArtist: 'Gedeelde artiest wordt geopend.', - openedComposer: 'Gedeelde componist wordt geopend.', - openedQueue_one: '{{count}} nummer van deellink wordt afgespeeld.', - openedQueue_other: '{{count}} nummers van deellink worden afgespeeld.', - openedQueuePartial: - '{{played}} van {{total}} nummers uit de link worden afgespeeld ({{skipped}} niet gevonden op deze server).', - queueAllUnavailable: 'Geen enkel nummer uit deze link is op de server gevonden.', - genericError: 'De deellink kon niet worden geopend.', - }, - albumDetail: { - back: 'Terug', - orbitDoubleClickHint: 'Dubbelklik om dit nummer aan de Orbit-wachtrij toe te voegen', - playAll: 'Alles afspelen', - shareAlbum: 'Album delen', - enqueue: 'In wachtrij', - enqueueTooltip: 'Volledig album aan wachtrij toevoegen', - artistBio: 'Artiest biografie', - download: 'Downloaden (ZIP)', - downloading: 'Laden…', - cacheOffline: 'Offline beschikbaar maken', - offlineCached: 'Offline beschikbaar', - offlineDownloading: 'Wordt gecached… ({{n}}/{{total}})', - removeOffline: 'Offline cache verwijderen', - offlineStorageFull: 'Offline opslag vol (limiet: {{mb}} MB). Verwijder een album uit je offline bibliotheek of verhoog de limiet in de instellingen.', - offlineStorageGoToSettings: 'Instellingen', - offlineStorageGoToLibrary: 'Offline bibliotheek', - favoriteAdd: 'Aan favorieten toevoegen', - favoriteRemove: 'Uit favorieten verwijderen', - favorite: 'Favoriet', - noBio: 'Geen biografie beschikbaar.', - moreByArtist: 'Meer van {{artist}}', - tracksCount: '{{n}} nummers', - goToArtist: 'Naar {{artist}}', - moreLabelAlbums: 'Meer albums op {{label}}', - trackTitle: 'Titel', - trackAlbum: 'Album', - trackArtist: 'Artiest', - trackGenre: 'Genre', - trackFormat: 'Formaat', - trackFavorite: 'Favoriet', - trackRating: 'Beoordeling', - trackDuration: 'Duur', - trackTotal: 'Totaal', - columns: 'Kolommen', - resetColumns: 'Standaard herstellen', - notFound: 'Album niet gevonden.', - bioModal: 'Artiest biografie', - bioClose: 'Sluiten', - ratingLabel: 'Beoordeling', - enlargeCover: 'Vergroten', - filterSongs: 'Filteren…', - sortNatural: 'Natuurlijk', - sortByTitle: 'A–Z (Titel)', - sortByArtist: 'A–Z (Artiest)', - sortByAlbum: 'A–Z (Album)', - }, - entityRating: { - albumShort: 'Albumbeoordeling', - artistShort: 'Artiestbeoordeling', - albumAriaLabel: 'Albumbeoordeling', - artistAriaLabel: 'Artiestbeoordeling', - selectedArtistsRatingAriaLabel: 'Sterrenbeoordeling voor {{count}} geselecteerde artiesten', - selectedAlbumsRatingAriaLabel: 'Sterrenbeoordeling voor {{count}} geselecteerde albums', - saveFailed: 'Beoordeling opslaan mislukt.', - }, - artistDetail: { - back: 'Terug', - albums: 'Albums', - album: 'Album', - playAll: 'Alles afspelen', - shareArtist: 'Artiest delen', - shuffle: 'Willekeurig', - radio: 'Radio', - loading: 'Laden…', - noRadio: 'Geen vergelijkbare nummers gevonden voor deze artiest.', - notFound: 'Artiest niet gevonden.', - albumsBy: 'Albums van {{name}}', - topTracks: 'Populaire nummers', - noAlbums: 'Geen albums gevonden.', - trackTitle: 'Titel', - trackAlbum: 'Album', - trackDuration: 'Duur', - favoriteAdd: 'Aan favorieten toevoegen', - favoriteRemove: 'Uit favorieten verwijderen', - favorite: 'Favoriet', - albumCount_one: '{{count}} album', - albumCount_other: '{{count}} albums', - openedInBrowser: 'Geopend in browser', - featuredOn: 'Ook te vinden op', - similarArtists: 'Vergelijkbare artiesten', - cacheOffline: 'Discografie offline opslaan', - offlineCached: 'Discografie gecached', - offlineDownloading: 'Cachen… ({{done}}/{{total}} albums)', - uploadImage: 'Artiestafbeelding uploaden', - uploadImageError: 'Uploaden van afbeelding mislukt', - releaseTypes: { - album: 'Album', - ep: 'EP', - single: 'Single', - compilation: 'Compilatie', - live: 'Live', - soundtrack: 'Soundtrack', - remix: 'Remix', - other: 'Overig', - }, - }, - favorites: { - title: 'Favorieten', - empty: 'Je hebt nog geen favorieten opgeslagen.', - artists: 'Artiesten', - albums: 'Albums', - songs: 'Nummers', - enqueueAll: 'Alles aan wachtrij toevoegen', - playAll: 'Alles afspelen', - removeSong: 'Verwijderen uit favorieten', - stations: 'Radiostations', - showingFiltered: 'Toont {{filtered}} van {{total}} ({{artist}})', - showingCount: 'Toont {{filtered}} van {{total}}', - clearArtistFilter: 'Artiestfilter wissen', - noFilterResults: 'Geen resultaten met de geselecteerde filters.', - allArtists: 'Alle artiesten', - topArtists: 'Top-artiesten op favorieten', - topArtistsSongCount_one: '{{count}} nummer', - topArtistsSongCount_other: '{{count}} nummers', - }, - randomLanding: { - title: 'Mix samenstellen', - mixByTracks: 'Mix op nummers', - mixByTracksDesc: 'Willekeurige selectie uit je volledige mediatheek', - mixByAlbums: 'Mix op albums', - mixByAlbumsDesc: 'Willekeurige albums voor nieuwe ontdekkingen', - mixByLucky: 'Geluksmix', - mixByLuckyDesc: 'Slimme Instant Mix op basis van topartiesten, albums en hoge beoordelingen', - }, - randomAlbums: { - title: 'Willekeurige albums', - refresh: 'Vernieuwen', - }, - genres: { - title: 'Genres', - genreCount: 'genres', - albumCount_one: '{{count}} album', - albumCount_other: '{{count}} albums', - loading: 'Genres laden…', - empty: 'Geen genres gevonden.', - albumsLoading: 'Albums laden…', - albumsEmpty: 'Geen albums gevonden voor dit genre.', - loadMore: 'Meer laden', - back: 'Terug', - }, - randomMix: { - title: 'Willekeurige mix', - remix: 'Opnieuw mixen', - remixTooltip: 'Nieuwe willekeurige nummers laden', - remixGenre: '{{genre}} mixen', - remixTooltipGenre: 'Nieuwe {{genre}}-nummers laden', - playAll: 'Alles afspelen', - trackTitle: 'Titel', - trackArtist: 'Artiest', - trackAlbum: 'Album', - trackFavorite: 'Favoriet', - trackDuration: 'Duur', - favoriteAdd: 'Aan favorieten toevoegen', - favoriteRemove: 'Uit favorieten verwijderen', - play: 'Afspelen', - trackGenre: 'Genre', - mixSettingsHeader: 'Mixinstellingen', - exclusionsHeader: 'Uitsluitingen', - filterPanelInexactSizeNote: 'De mixgrootte is een doel — grote verzoeken kunnen minder unieke nummers opleveren als de willekeurige pool van de server opraakt.', - mixSize: 'Lijstgrootte', - excludeAudiobooks: 'Luisterboeken en hoorspelen uitsluiten', - excludeAudiobooksDesc: 'Vergelijkt trefwoorden met genre, titel, album en artiest — bijv. Hörbuch, Audiobook, Spoken Word, …', - genreBlocked: 'Trefwoord geblokkeerd', - genreAddedToBlacklist: 'Aan filterlijst toegevoegd', - genreAlreadyBlocked: 'Al geblokkeerd', - artistBlocked: 'Artiest geblokkeerd', - artistAddedToBlacklist: 'Artiest aan filterlijst toegevoegd', - artistClickHint: 'Klik om deze artiest te blokkeren', - blacklistToggle: 'Trefwoordfilter', - genreMixTitle: 'Genremix', - genreMixDesc: 'Top 20 genres op aantal nummers — klik voor een willekeurige mix', - genreMixAll: 'Alle nummers', - genreMixLoadMore: '10 meer laden', - genreMixNoGenres: 'Geen genres gevonden op server.', - shuffleGenres: 'Andere genres tonen', - filterPanelTitle: 'Filters', - filterPanelDesc: 'Klik op een genre-tag of artiestennaam in de lijst om deze uit toekomstige mixes te weren.', - genreClickHint: 'Klik op een genre-tag om het\ntoe te voegen als filtertrefwoord.\nVergelijkt genre, titel, album & artiest.', - }, - luckyMix: { - done: 'Geluksmix klaar: {{count}} nummers', - failed: 'Kon de Geluksmix niet maken. Probeer opnieuw.', - unavailable: 'Geluksmix is niet beschikbaar voor deze server.', - cancelTooltip: 'Geluksmix-opbouw annuleren', - }, - albums: { - title: 'Alle albums', - sortByName: 'A–Z (Album)', - sortByArtist: 'A–Z (Artiest)', - sortNewest: 'Nieuwste eerst', - sortRandom: 'Willekeurig', - yearFrom: 'Van', - yearTo: 'Tot', - yearFilterClear: 'Jaarfilter wissen', - yearFilterLabel: 'Jaar', - compilationLabel: 'Compilaties', - compilationOnly: 'Alleen compilaties', - compilationHide: 'Compilaties verbergen', - compilationTooltipAll: 'Alle albums · klik: alleen compilaties', - compilationTooltipOnly: 'Alleen compilaties · klik: compilaties verbergen', - compilationTooltipHide: 'Compilaties verborgen · klik: toon alles', - select: 'Meervoudige selectie', - startSelect: 'Meervoudige selectie inschakelen', - cancelSelect: 'Annuleren', - selectionCount: '{{count}} geselecteerd', - downloadZips: 'ZIPs downloaden', - addOffline: 'Offline toevoegen', - enqueueSelected_one: 'In wachtrij ({{count}})', - enqueueSelected_other: 'In wachtrij ({{count}})', - enqueueQueued_one: '{{count}} album toegevoegd aan wachtrij', - enqueueQueued_other: '{{count}} albums toegevoegd aan wachtrij', - downloadingZip: 'Downloaden {{current}}/{{total}}: {{name}}', - downloadZipDone: '{{count}} ZIP(s) gedownload', - downloadZipFailed: 'Downloaden van {{name}} mislukt', - offlineQueuing: '{{count}} album(s) in wachtrij voor offline…', - offlineFailed: 'Toevoegen van {{name}} offline mislukt', - }, - tracks: { - title: 'Nummers', - subtitle: 'Bladeren. Zoeken. Ontdekken.', - heroEyebrow: 'Nummer van het moment', - heroReroll: 'Een ander kiezen', - playSong: 'Afspelen', - enqueueSong: 'Aan wachtrij toevoegen', - railRandom: 'Willekeurige selectie', - railHighlyRated: 'Hoog beoordeeld', - browseTitle: 'Alle nummers doorbladeren', - browseUnsupported: 'Deze server toont niet de hele bibliotheek in één keer. Gebruik de zoekbalk hierboven om specifieke nummers te vinden.', - searchPlaceholder: 'Zoek op titel, artiest of album…', - count_one: '{{count}} nummer', - count_other: '{{count}} nummers', - }, - artists: { - title: 'Artiesten', - search: 'Zoeken…', - all: 'Alle', - gridView: 'Rasterweergave', - listView: 'Lijstweergave', - imagesOn: 'Artiestafbeeldingen aan — kan netwerk- en systeembelasting verhogen', - imagesOff: 'Artiestafbeeldingen uit — toont alleen initialen', - loadMore: 'Meer laden', - notFound: 'Geen artiesten gevonden.', - albumCount_one: '{{count}} album', - albumCount_other: '{{count}} albums', - selectionCount: '{{count}} geselecteerd', - select: 'Meervoudige selectie', - startSelect: 'Meervoudige selectie inschakelen', - cancelSelect: 'Annuleren', - addToPlaylist: 'Toevoegen aan playlist', - }, - composers: { - title: 'Componisten', - search: 'Zoeken…', - notFound: 'Geen componisten gevonden.', - unsupported: 'Bladeren op componist vereist Navidrome 0.55 of nieuwer.', - loadFailed: 'Kan componisten niet laden.', - retry: 'Opnieuw proberen', - involvedIn_one: 'Betrokken bij {{count}} album', - involvedIn_other: 'Betrokken bij {{count}} albums', - }, - composerDetail: { - back: 'Terug', - notFound: 'Componist niet gevonden.', - about: 'Over deze componist', - works: 'Werken', - noWorks: 'Geen werken gevonden.', - workCount_one: '{{count}} werk', - workCount_other: '{{count}} werken', - shareComposer: 'Componist delen', - unknownComposer: 'Componist', - }, - login: { - subtitle: 'Jouw Navidrome-desktopspeler', - serverName: 'Servernaam (optioneel)', - serverNamePlaceholder: 'Mijn Navidrome', - serverUrl: 'Server-URL', - serverUrlPlaceholder: '192.168.1.100:4533 of https://music.voorbeeld.nl', - username: 'Gebruikersnaam', - usernamePlaceholder: 'admin', - password: 'Wachtwoord', - showPassword: 'Wachtwoord tonen', - hidePassword: 'Wachtwoord verbergen', - connect: 'Verbinden', - connecting: 'Verbinden…', - connected: 'Verbonden!', - error: 'Verbinding mislukt — controleer je gegevens.', - urlRequired: 'Voer een server-URL in.', - savedServers: 'Opgeslagen servers', - addNew: 'Of een nieuwe server toevoegen', - orMagicString: 'Of magic string', - magicStringPlaceholder: 'Plak een deelstring (psysonic1-…)', - magicStringInvalid: 'Ongeldige of onleesbare magic string.', - }, - connection: { - connected: 'Verbonden', - connectedTo: 'Verbonden met {{server}}', - disconnected: 'Verbroken', - disconnectedFrom: 'Kan {{server}} niet bereiken — klik om instellingen te controleren', - checking: 'Verbinden…', - extern: 'Extern', - offlineTitle: 'Geen serververbinding', - offlineSubtitle: 'Kan {{server}} niet bereiken. Controleer je netwerk of server.', - offlineModeBanner: 'Offline modus — afspelen vanuit lokale cache', - offlineNoCacheBanner: 'Geen serververbinding — {{server}} niet bereikbaar', - offlineLibraryTitle: 'Offline bibliotheek', - offlineLibraryEmpty: 'Nog geen albums gecached. Ga online, open een album en klik op "Offline beschikbaar maken".', - offlineAlbumCount: '{{n}} album', - offlineAlbumCount_plural: '{{n}} albums', - offlineFilterAll: 'Alles', - offlineFilterAlbums: 'Albums', - offlineFilterPlaylists: 'Afspeellijsten', - offlineFilterArtists: 'Discografieën', - retry: 'Opnieuw proberen', - serverSettings: 'Serverinstellingen', - switchServerTitle: 'Server wisselen', - switchServerHint: 'Klik om een andere opgeslagen server te kiezen.', - manageServers: 'Servers beheren…', - switchFailed: 'Wisselen mislukt — server niet bereikbaar.', - lastfmConnected: 'Last.fm verbonden als @{{user}}', - lastfmSessionInvalid: 'Sessie ongeldig — klik om opnieuw te verbinden', - }, - common: { - albums: 'Albums', - album: 'Album', - loading: 'Laden…', - loadingMore: 'Laden…', - loadingPlaylists: 'Afspeellijsten laden…', - noAlbums: 'Geen albums gevonden.', - downloading: 'Downloaden…', - downloadZip: 'Downloaden (ZIP)', - back: 'Terug', - cancel: 'Annuleren', - save: 'Opslaan', - delete: 'Verwijderen', - use: 'Gebruiken', - add: 'Toevoegen', - new: 'Nieuw', - active: 'Actief', - download: 'Downloaden', - chooseDownloadFolder: 'Downloadmap kiezen', - noFolderSelected: 'Geen map geselecteerd', - rememberDownloadFolder: 'Deze map onthouden', - filterGenre: 'Genre-filter', - filterSearchGenres: 'Genres zoeken…', - filterNoGenres: 'Geen genres gevonden', - filterClear: 'Wissen', - favorites: 'Favorieten', - favoritesTooltipOff: 'Alleen favorieten tonen', - favoritesTooltipOn: 'Alles tonen', - play: 'Afspelen', - bulkSelected: '{{count}} geselecteerd', - clearSelection: 'Selectie wissen', - bulkAddToPlaylist: 'Toevoegen aan afspeellijst', - bulkRemoveFromPlaylist: 'Verwijderen uit afspeellijst', - bulkClear: 'Selectie wissen', - updaterAvailable: 'Update beschikbaar', - updaterVersion: 'v{{version}} beschikbaar', - updaterWebsite: 'Website', - updaterModalTitle: 'Nieuwe versie beschikbaar', - updaterChangelog: 'Wat is er nieuw', - updaterDownloadBtn: 'Nu downloaden', - updaterSkipBtn: 'Deze versie overslaan', - updaterRemindBtn: 'Later herinneren', - updaterDone: 'Download voltooid', - updaterShowFolder: 'Tonen in map', - updaterInstallHint: 'Sluit Psysonic en voer het installatieprogramma handmatig uit.', - updaterAurHint: 'Update installeren via AUR:', - updaterErrorMsg: 'Downloaden mislukt', - updaterRetryBtn: 'Opnieuw proberen', - durationHoursMinutes: '{{hours}} u {{minutes}} min', - durationMinutesOnly: '{{minutes}} min', - updaterOpenGitHub: 'Openen op GitHub', - filters: 'Filters', - more: 'meer', - yearRange: 'Jaarbereik', - clearAll: 'Alles wissen', - }, - settings: { - title: 'Instellingen', - language: 'Taal', - languageEn: 'English', - languageDe: 'Deutsch', - languageEs: 'Español', - languageFr: 'Français', - languageNl: 'Nederlands', - languageNb: 'Norsk', - languageRu: 'Русский', - languageZh: '中文', - languageRo: 'Română', - font: 'Lettertype', - fontHintOpenDyslexic: 'Dyslexie-vriendelijk · geen Chinese ondersteuning', - theme: 'Thema', - appearance: 'Weergave', - servers: 'Servers', - serverName: 'Servernaam', - serverUrl: 'Server-URL', - serverUrlPlaceholder: '192.168.1.100:4533 of https://music.voorbeeld.nl', - serverUsername: 'Gebruikersnaam', - serverPassword: 'Wachtwoord', - addServer: 'Server toevoegen', - addServerTitle: 'Nieuwe server toevoegen', - useServer: 'Gebruiken', - deleteServer: 'Verwijderen', - noServers: 'Geen servers opgeslagen.', - serverActive: 'Actief', - confirmDeleteServer: 'Server "{{name}}" verwijderen?', - serverConnecting: 'Verbinden…', - serverConnected: 'Verbonden!', - serverFailed: 'Verbinding mislukt.', - testBtn: 'Verbinding testen', - testingBtn: 'Testen…', - serverCompatible: 'Gemaakt voor Navidrome. Andere Subsonic-compatibele servers (Gonic, Airsonic, …) kunnen met beperkte functionaliteit werken, omdat Psysonic veel Navidrome-specifieke API-endpoints gebruikt.', - userMgmtTitle: 'Gebruikersbeheer', - userMgmtDesc: 'Beheer gebruikers op deze server. Vereist admin-rechten.', - userMgmtNoAdmin: 'Je hebt admin-rechten nodig om gebruikers op deze server te beheren.', - userMgmtLoadError: 'Kon gebruikers niet laden.', - userMgmtLoadFriendly: 'Server antwoordde niet — meestal eenmalig.', - userMgmtRetry: 'Opnieuw proberen', - userMgmtEmpty: 'Geen gebruikers gevonden.', - userMgmtYouBadge: 'Jij', - userMgmtAdminBadge: 'Admin', - userMgmtAddUser: 'Gebruiker toevoegen', - userMgmtAddUserTitle: 'Nieuwe gebruiker', - userMgmtEditUserTitle: 'Gebruiker bewerken', - userMgmtUsername: 'Gebruikersnaam', - userMgmtName: 'Weergavenaam', - userMgmtEmail: 'E-mail', - userMgmtPassword: 'Wachtwoord', - userMgmtPasswordEditHint: 'Voer een nieuw wachtwoord in om het bij te werken.', - userMgmtRoleAdmin: 'Admin', - userMgmtLibraries: 'Bibliotheken', - userMgmtLibrariesAdminHint: 'Beheerders hebben automatisch toegang tot alle bibliotheken.', - userMgmtLibrariesEmpty: 'Geen bibliotheken beschikbaar op deze server.', - userMgmtLibrariesValidation: 'Selecteer ten minste één bibliotheek.', - userMgmtLibrariesUpdateError: 'Gebruiker opgeslagen, maar bibliotheektoewijzing mislukt', - userMgmtNoLibraries: 'Geen bibliotheken toegewezen', - userMgmtNeverSeen: 'Nooit', - userMgmtSave: 'Opslaan', - userMgmtCancel: 'Annuleren', - userMgmtDelete: 'Verwijderen', - userMgmtEdit: 'Bewerken', - userMgmtConfirmDelete: 'Gebruiker "{{username}}" verwijderen? Dit kan niet ongedaan worden gemaakt.', - userMgmtCreateError: 'Aanmaken van gebruiker mislukt.', - userMgmtUpdateError: 'Bijwerken van gebruiker mislukt.', - userMgmtDeleteError: 'Verwijderen van gebruiker mislukt.', - userMgmtCreated: 'Gebruiker aangemaakt.', - userMgmtUpdated: 'Gebruiker bijgewerkt.', - userMgmtDeleted: 'Gebruiker verwijderd.', - userMgmtValidationMissing: 'Gebruikersnaam, weergavenaam en wachtwoord zijn vereist.', - userMgmtValidationMissingIdentity: 'Gebruikersnaam en weergavenaam zijn vereist.', - userMgmtMagicStringGenerate: 'Magic string genereren', - userMgmtSaveAndMagicString: 'Opslaan en magic string kopiëren', - userMgmtMagicStringPasswordNavHint: - 'Navidrome slaat dit wachtwoord voor de gebruiker op. Als het afwijkt van het huidige wachtwoord, wordt het inlogwachtwoord op de server bijgewerkt.', - userMgmtMagicStringPlaintextWarning: - 'Wees voorzichtig met delen: de magic string bevat een onversleuteld wachtwoord (codering is geen encryptie). Wie de volledige string heeft, kan als deze gebruiker inloggen.', - userMgmtMagicStringCopied: 'Magic string naar het klembord gekopieerd.', - userMgmtMagicStringCopyFailed: 'Kopiëren naar het klembord is mislukt.', - userMgmtMagicStringLoginFailed: 'Wachtwoordcontrole mislukt — aanmeldgegevens konden niet worden geverifieerd.', - userMgmtMagicStringModalTitle: 'Magic string genereren', - userMgmtMagicStringModalDesc: 'Voer het Subsonic-wachtwoord voor „{{username}}" in. Het wordt opgenomen in de gekopieerde magic string.', - userMgmtMagicStringModalConfirm: 'String kopiëren', - audiomuseTitle: 'AudioMuse-AI (Navidrome)', - audiomuseDesc: - 'Zet aan als deze server de AudioMuse-AI Navidrome-plugin gebruikt. Schakelt Instant Mix per nummer in en toont vergelijkbare artiesten van de server i.p.v. Last.fm op artiestpagina’s.', - audiomuseIssueHint: - 'Instant Mix is onlangs mislukt — controleer de Navidrome-plugin en AudioMuse API. Zonder serverresultaten worden vergelijkbare artiesten via Last.fm geladen.', - connected: 'Verbonden', - failed: 'Mislukt', - eqTitle: 'Equalizer', - eqEnabled: 'Equalizer inschakelen', - eqPreset: 'Voorinstelling', - eqPresetCustom: 'Aangepast', - eqPresetBuiltin: 'Ingebouwde voorinstellingen', - eqPresetCustomGroup: 'Mijn voorinstellingen', - eqSavePreset: 'Opslaan als voorinstelling', - eqPresetName: 'Naam voorinstelling…', - eqDeletePreset: 'Voorinstelling verwijderen', - eqResetBands: 'Terugzetten naar vlak', - eqPreGain: 'Voorversterking', - eqResetPreGain: 'Voorversterking resetten', - eqAutoEqTitle: 'AutoEQ Hoofdtelefoon Zoeken', - eqAutoEqPlaceholder: 'Zoek hoofdtelefoon / IEM model…', - eqAutoEqSearching: 'Zoeken…', - eqAutoEqNoResults: 'Geen resultaten gevonden', - eqAutoEqError: 'Zoeken mislukt', - eqAutoEqRateLimit: 'GitHub limiet bereikt — probeer over een minuut opnieuw', - eqAutoEqFetchError: 'EQ-profiel kon niet worden geladen', - lfmTitle: 'Last.fm', - lfmConnect: 'Verbinden met Last.fm', - lfmConnecting: 'Wachten op autorisatie…', - lfmConfirm: 'Ik heb de app geautoriseerd', - lfmConnected: 'Verbonden als', - lfmDisconnect: 'Verbinding verbreken', - lfmConnectDesc: 'Verbind je Last.fm-account om scrobbling en Nu bezig-updates rechtstreeks vanuit Psysonic in te schakelen — geen Navidrome-configuratie vereist.', - lfmOpenBrowser: 'Er opent een browservenster. Autoriseer Psysonic op Last.fm en klik daarna op de knop hieronder.', - lfmScrobbles: '{{n}} scrobbles', - lfmMemberSince: 'Lid sinds {{year}}', - scrobbleEnabled: 'Scrobbling ingeschakeld', - scrobbleDesc: 'Nummers naar Last.fm sturen na 50% afspeeltijd', - behavior: 'App-gedrag', - cacheTitle: 'Max. opslaggrootte', - cacheDesc: 'Albumhoezen en artiestafbeeldingen. Als de cache vol is, worden de oudste items automatisch verwijderd. Offline albums worden niet automatisch verwijderd, maar wel bij handmatig leegmaken.', - cacheUsedImages: 'Afbeeldingen:', - cacheUsedOffline: 'Offline nummers:', - cacheUsedHot: 'Schijfgebruik:', - hotCacheTrackCount: 'Nummers in cache:', - cacheMaxLabel: 'Max. grootte', - cacheClearBtn: 'Cache wissen', - cacheClearWarning: 'Dit verwijdert ook alle offline albums uit de bibliotheek.', - cacheClearConfirm: 'Alles wissen', - cacheClearCancel: 'Annuleren', - offlineDirTitle: 'Offline-bibliotheek (In-app)', - offlineDirDesc: 'Opslaglocatie voor nummers die je offline beschikbaar maakt in Psysonic.', - offlineDirDefault: 'Standaard (app-gegevens)', - offlineDirChange: 'Map wijzigen', - offlineDirClear: 'Terugzetten naar standaard', - offlineDirHint: 'Nieuwe downloads worden op deze locatie opgeslagen. Bestaande downloads blijven op hun oorspronkelijke locatie.', - hotCacheTitle: 'Warme afspeelcache', - hotCacheDisclaimer: 'Laadt aankomende wachtrijtracks voor en bewaart eerdere. Indien ingeschakeld: schijfruimte en netwerk.', - hotCacheDirDefault: 'Standaard (app-gegevens)', - hotCacheDirChange: 'Map wijzigen', - hotCacheDirClear: 'Terugzetten naar standaard', - hotCacheDirHint: 'Een andere map kiest: de index in de app wordt gereset; oude bestanden blijven staan tot je ze verwijdert.', - hotCacheEnabled: 'Warme afspeelcache inschakelen', - hotCacheMaxMb: 'Maximale cachegrootte', - hotCacheDebounce: 'Uitstel bij wachtrijwijziging', - hotCacheDebounceImmediate: 'Direct', - hotCacheDebounceSeconds: '{{n}} s', - hotCacheClearBtn: 'Warme cache wissen', - audioOutputDevice: 'Audio-uitvoerapparaat', - audioOutputDeviceDesc: 'Kies via welk audioapparaat Psysonic afspeelt. Wijzigingen worden direct toegepast en starten het huidige nummer opnieuw.', - audioOutputDeviceDefault: 'Systeemstandaard', - audioOutputDeviceRefresh: 'Apparatenlijst vernieuwen', - audioOutputDeviceOsDefaultNow: 'huidige systeemuitvoer', - audioOutputDeviceListError: 'De lijst met audio-apparaten kon niet worden geladen.', - audioOutputDeviceNotInCurrentList: 'staat niet in de huidige lijst', - audioOutputDeviceMacNotice: 'Op macOS volgt de weergave om technische redenen altijd het standaard-uitvoerapparaat van het systeem. Wijzig het doel via Systeeminstellingen → Geluid of via het luidsprekerpictogram in de menubalk. Achtergrond: CoreAudio vraagt bij het openen van een niet-standaard stream om microfoontoestemming — dat vermijden we door altijd de systeemstandaard te gebruiken.', - hiResTitle: 'Natieve hi-res-weergave', - hiResEnabled: 'Natieve hi-res-weergave inschakelen', - hiResDesc: "Beperkt de uitvoer standaard tot 44,1 kHz voor maximale stabiliteit. Alleen inschakelen als hardware en netwerk hoge samplerates (88,2 kHz+) ondersteunen.", - showArtistImages: 'Artiestafbeeldingen weergeven', - showArtistImagesDesc: 'Laadt en toont artiestafbeeldingen in het artiestenoverzicht. Standaard uitgeschakeld om server-I/O en netwerkbelasting bij grote bibliotheken te beperken.', - showOrbitTrigger: '"Orbit" in de kop tonen', - showOrbitTriggerDesc: 'De knop in de kop voor starten of deelnemen aan een gedeelde luistersessie. Verberg hem als je Orbit niet gebruikt — je kunt hem hier weer aanzetten.', - showTrayIcon: 'Tray-pictogram weergeven', - showTrayIconDesc: 'Toont het Psysonic-pictogram in het systeemvak / de menubalk.', - minimizeToTray: 'Minimaliseren naar systeemvak', - minimizeToTrayDesc: 'Bij het sluiten van het venster blijft Psysonic actief in het systeemvak in plaats van af te sluiten.', - preloadMiniPlayer: 'Mini-speler vooraf laden', - preloadMiniPlayerDesc: 'Bouwt het venster van de mini-speler op de achtergrond bij het opstarten van de app, zodat het bij de eerste opening direct inhoud toont. Gebruikt iets meer geheugen.', - linuxWebkitSmoothScroll: 'Vloeiend muiswiel (Linux)', - linuxWebkitSmoothScrollDesc: 'Aan: traag naloop. Uit: regel voor regel, GTK-stijl.', - discordRichPresence: 'Discord Rich Presence', - discordRichPresenceDesc: 'Toont het huidige nummer op je Discord-profiel. Discord moet daarvoor geopend zijn.', - discordCoverSource: 'Hoesbron', - discordCoverSourceDesc: 'Waar de albumhoes voor je Discord-profiel vandaan komt.', - discordCoverNone: 'Geen (alleen app-icoon)', - discordCoverServer: 'Server (via albuminfo)', - discordCoverApple: 'Apple Music', - discordOptions: 'Geavanceerde Discord-opties', - discordTemplates: 'Aangepaste tekstsjablonen', - discordTemplatesDesc: 'Pas aan welke informatie wordt weergegeven op je Discord-profiel. Variabelen: {title}, {artist}, {album}', - discordTemplateDetails: 'Primaire regel (details)', - discordTemplateState: 'Secundaire regel (state)', - discordTemplateLargeText: 'Album-tooltip (largeText)', - nowPlayingEnabled: 'Weergeven in live-venster', - nowPlayingEnabledDesc: 'Stuurt het huidige nummer naar de live-luisteraarsweergave van de server. Uitschakelen om geen afspeelgegevens te verzenden.', - enableBandsintown: 'Bandsintown-tourdata', - enableBandsintownDesc: 'Toon aankomende concerten van de huidige artiest in het Info-tabblad. Gegevens komen van de openbare Bandsintown-API.', - lyricsServerFirst: 'Server-songtekst voorrang geven', - lyricsServerFirstDesc: 'Controleer eerst door de server geleverde songteksten (ingebedde tags, sidecar-bestanden) vóór LRCLIB. Uitschakelen om LRCLIB eerst te gebruiken.', - enableNeteaselyrics: 'Netease Cloud Music songteksten', - enableNeteaselyricsDesc: 'Gebruik Netease Cloud Music als laatste bron wanneer server en LRCLIB niets opleveren. Beste dekking voor Aziatische en internationale muziek.', - lyricsSourcesTitle: 'Songtekstbronnen', - lyricsSourcesDesc: 'Kies welke bronnen worden geraadpleegd en in welke volgorde. Sleep om te sorteren. Uitgeschakelde bronnen worden overgeslagen.', - lyricsSourceServer: 'Server', - lyricsSourceLrclib: 'LRCLIB', - lyricsSourceNetease: 'Netease Cloud Music', - lyricsModeStandard: 'Standaard', - lyricsModeStandardDesc: 'Drie bronnen in een vrij te ordenen lijst: server-tags, LRCLIB, Netease.', - lyricsModeLyricsplus: 'YouLyPlus (Karaoke)', - lyricsModeLyricsplusDesc: 'Woord-voor-woord-synchronisatie uit Apple Music, Spotify, Musixmatch en QQ (community-backend). Valt stil terug op de standaardbronnen als er niets wordt gevonden.', - lyricsStaticOnly: 'Alleen statische tekst weergeven', - lyricsStaticOnlyDesc: 'Gesynchroniseerde songteksten worden zonder auto-scroll en zonder woordmarkering als statische tekst weergegeven.', - downloadsTitle: 'ZIP-export & Archivering', - downloadsFolderDesc: 'Doelmap voor albums die je als ZIP-bestand naar je computer downloadt.', - downloadsDefault: 'Standaard downloadmap', - pickFolder: 'Selecteren', - pickFolderTitle: 'Downloadmap selecteren', - clearFolder: 'Map wissen', - logout: 'Uitloggen', - aboutTitle: 'Over Psysonic', - aboutDesc: 'Een moderne desktopmuziekspeler gebouwd voor Navidrome. Gebruikt de Subsonic-API plus Navidrome-specifieke extensies. Gebouwd op Tauri v2 met een native Rust audio-engine — licht en snel, maar boordevol functies: golfvorm-zoekbalk, gesynchroniseerde songteksten, Last.fm-integratie, 10-bands equalizer, crossfade, naadloos afspelen, Replay Gain, genres en een uitgebreide themabibliotheek.', - aboutLicense: 'Licentie', - aboutLicenseText: 'GNU GPL v3 — vrij te gebruiken, wijzigen en verspreiden onder dezelfde licentie.', - aboutRepo: 'Broncode op GitHub', - aboutVersion: 'Versie', - aboutBuiltWith: 'Gebouwd met Tauri · React · TypeScript · Rust/rodio', - aboutReleaseNotesLabel: 'Release-notities', - aboutReleaseNotesLink: 'Nieuws van deze versie openen', - aboutContributorsLabel: 'Bijdragers', - showChangelogOnUpdate: "'Wat is nieuw' tonen bij update", - showChangelogOnUpdateDesc: 'Toont een discrete changelog-banner boven Now Playing na een update. Klik opent de release-notities; X verbergt hem.', - randomMixTitle: 'Willekeurige mix-blacklist', - luckyMixMenuTitle: 'Toon Geluksmix in menu', - luckyMixMenuDesc: 'Schakelt Geluksmix in bij "Mix samenstellen" en als apart menu-item bij gesplitste navigatie. Alleen zichtbaar wanneer AudioMuse actief is op de huidige server.', - randomMixBlacklistTitle: 'Aangepaste filtertrefwoorden', - randomMixBlacklistDesc: 'Nummers worden uitgesloten als een trefwoord overeenkomt met hun genre, titel, album of artiest (actief wanneer het selectievakje hierboven is aangevinkt).', - randomMixBlacklistPlaceholder: 'Trefwoord toevoegen…', - randomMixBlacklistAdd: 'Toevoegen', - randomMixBlacklistEmpty: 'Nog geen aangepaste trefwoorden toegevoegd.', - randomMixHardcodedTitle: 'Ingebouwde trefwoorden (actief wanneer selectievakje is aangevinkt)', - tabAudio: 'Audio', - tabStorage: 'Offline & Cache', - tabAppearance: 'Weergave', - tabLibrary: 'Bibliotheek', - tabServers: 'Servers', - tabLyrics: 'Songteksten', - tabPersonalisation: 'Personalisatie', - tabIntegrations: 'Integraties', - inputKeybindingsTitle: 'Sneltoetsen', - aboutContributorsCount_one: '{{count}} bijdrage', - aboutContributorsCount_other: '{{count}} bijdragen', - searchPlaceholder: 'Instellingen zoeken…', - searchNoResults: 'Geen instellingen komen overeen met je zoekopdracht.', - aboutMaintainersLabel: 'Beheerders', - integrationsPrivacyTitle: 'Privacyverklaring', - integrationsPrivacyBody: 'Alle integraties op dit tabblad zijn opt-in en sturen, eenmaal ingeschakeld, gegevens naar externe diensten of naar je Navidrome-server. Last.fm ontvangt je luistergeschiedenis, Discord toont het nu spelende nummer in je profiel, Bandsintown wordt per artiest bevraagd voor tourdatums, en de "Nu aan het afspelen"-deling publiceert je huidige nummer bij andere gebruikers van je Navidrome-server. Wil je dit niet, laat dan de bijbehorende sectie gewoon uitgeschakeld.', - homeCustomizerTitle: 'Startpagina', - queueToolbarTitle: 'Wachtrij-werkbalk', - queueToolbarReset: 'Standaard herstellen', - queueToolbarSeparator: 'Scheiding', - sidebarTitle: 'Zijbalk', - sidebarReset: 'Standaard herstellen', - artistLayoutTitle: 'Secties artiestenpagina', - artistLayoutDesc: 'Versleep om te herschikken, schakel om individuele secties van de artiestenpagina te verbergen. Secties zonder gegevens worden automatisch overgeslagen.', - artistLayoutReset: 'Standaard herstellen', - artistLayoutBio: 'Biografie van de artiest', - artistLayoutTopTracks: 'Populaire nummers', - artistLayoutSimilar: 'Soortgelijke artiesten', - artistLayoutAlbums: 'Albums', - artistLayoutFeatured: 'Ook te horen op', - sidebarDrag: 'Slepen om te herordenen', - sidebarFixed: 'Altijd zichtbaar', - randomNavSplitTitle: 'Mix-navigatie splitsen', - randomNavSplitDesc: 'Toon "Willekeurige mix", "Willekeurige albums" en "Geluksmix" als afzonderlijke zijbalkitems in plaats van de "Mix samenstellen"-hub.', - tabInput: 'Invoer', - tabUsers: 'Gebruikers', - shortcutsReset: 'Standaard herstellen', - shortcutListening: 'Druk op een toets…', - shortcutUnbound: '—', - shortcutClear: 'Wissen', - globalShortcutsTitle: 'Globale sneltoetsen', - globalShortcutsNote: 'Werken systeembreed, ook als Psysonic op de achtergrond draait. Vereist Ctrl, Alt of Super als modifier.', - shortcutPlayPause: 'Afspelen / Pauzeren', - shortcutNext: 'Volgend nummer', - shortcutPrev: 'Vorig nummer', - shortcutVolumeUp: 'Volume omhoog', - shortcutVolumeDown: 'Volume omlaag', - shortcutSeekForward: '10s vooruitspoelen', - shortcutSeekBackward: '10s terugspoelen', - shortcutToggleQueue: 'Wachtrij tonen/verbergen', - shortcutOpenFolderBrowser: '{{folderBrowser}} openen', - shortcutFullscreenPlayer: 'Volledigschermspeler', - shortcutNativeFullscreen: 'Systeemvolledig scherm', - shortcutOpenMiniPlayer: 'Mini-speler openen', - shortcutStartSearch: 'Zoekopdracht starten', - shortcutStartAdvancedSearch: 'Geavanceerde zoekopdracht starten', - shortcutToggleSidebar: 'Zijbalk in-/uitschakelen', - shortcutMuteSound: 'Geluid dempen', - shortcutToggleEqualizer: 'Equalizer openen / schakelen', - shortcutToggleRepeat: 'Herhaling schakelen', - shortcutOpenNowPlaying: '"Nu speelt" openen', - shortcutShowLyrics: 'Songtekst tonen', - shortcutFavoriteCurrentTrack: 'Huidig nummer aan favorieten toevoegen', - shortcutOpenHelp: 'Help', - tabSystem: 'Systeem', - loggingTitle: 'Logboek', - loggingModeDesc: 'Bepaalt de uitgebreidheid van backendlogs in de terminal.', - loggingModeOff: 'Uit', - loggingModeNormal: 'Normaal', - loggingModeDebug: 'Debug', - loggingExport: 'Logs exporteren', - loggingExportSuccess: 'Logs geëxporteerd ({{count}} regels).', - loggingExportError: 'Kon logs niet exporteren.', - ratingsSectionTitle: 'Beoordelingen', - ratingsSkipStarTitle: 'Overslaan voor 1 ster', - ratingsSkipStarDesc: - 'Na meerdere overslagen op rij: nummer op 1 ster zetten. Alleen voor nummers die nog niet beoordeeld waren.', - ratingsSkipStarThresholdLabel: 'Overslagen', - ratingsMixFilterTitle: 'Filter op beoordeling', - ratingsMixFilterDesc: - 'Content met lage beoordeling filteren in {{mix}} en {{albums}}. Klik opnieuw op de gekozen ster om de drempel uit te zetten.', - ratingsMixMinSong: 'Nummers', - ratingsMixMinAlbum: 'Albums', - ratingsMixMinArtist: 'Artiesten', - ratingsMixMinThresholdAria: 'Minimum sterren: {{label}}', - backupTitle: 'Back-up & Herstel', - backupExport: 'Instellingen exporteren', - backupExportDesc: 'Slaat alle instellingen, serverprofielen, Last.fm-configuratie, thema, EQ en sneltoetsen op in een .psybkp-bestand. Wachtwoorden worden opgeslagen als leesbare tekst — bewaar het bestand veilig.', - backupImport: 'Instellingen importeren', - backupImportDesc: 'Herstelt instellingen vanuit een .psybkp-bestand. De app wordt herladen na het importeren.', - backupImportConfirm: 'Alle huidige instellingen worden overschreven. Doorgaan?', - backupSuccess: 'Back-up opgeslagen', - backupImportSuccess: 'Instellingen hersteld — herladen…', - backupImportError: 'Ongeldig of beschadigd back-upbestand.', - playbackTitle: 'Afspelen', - replayGain: 'Replay Gain', - replayGainDesc: 'Nummervolume normaliseren met ReplayGain-metadata', - replayGainMode: 'Modus', - replayGainAuto: 'Auto', - replayGainAutoDesc: 'Kiest album-gain wanneer aangrenzende nummers in de wachtrij van hetzelfde album zijn, anders nummer-gain.', - replayGainTrack: 'Nummer', - replayGainAlbum: 'Album', - replayGainPreGain: 'Pre-Gain (getagde bestanden)', - replayGainPreGainDesc: 'Universele boost bovenop elke ReplayGain-berekening. Handig als je bibliotheek over het geheel te zacht aanvoelt.', - replayGainFallback: 'Terugval (zonder tags / radio)', - replayGainFallbackDesc: 'Toegepast op nummers (en radiostreams) zonder ReplayGain-tags, zodat ongetagde inhoud er niet harder uitspringt dan de rest.', - normalization: 'Normalisatie', - normalizationDesc: 'Egaliseer de waargenomen luidheid tussen nummers, albums en radio.', - normalizationOff: 'Uit', - normalizationReplayGain: 'ReplayGain', - normalizationLufs: 'LUFS', - loudnessTargetLufs: 'Doel-LUFS', - loudnessTargetLufsDesc: 'Referentie-luidheid waarop alle nummers worden afgestemd. Lagere waarde = luidere uitvoer. Streamingdiensten zitten meestal rond -14 LUFS.', - loudnessPreAnalysisAttenuation: 'Demping vóór meting', - loudnessPreAnalysisAttenuationDesc: - 'Extra zachter tot de loudness van het nummer is opgeslagen. Streamen gebruikt daarna grove schattingen, geen volledige meting. 0 dB = uit; negatiever = zachter. Rechts staat de effectieve dB voor het huidige doel.', - loudnessPreAnalysisAttenuationRef: 'Effectief {{eff}} dB bij doel {{tgt}} LUFS.', - loudnessPreAnalysisAttenuationReset: 'Standaard', - loudnessFirstPlayNote: - 'Bij de eerste keer afspelen van een nieuw nummer kan het volume even fluctueren terwijl er gemeten wordt. De volgende keer gebruikt de speler de opgeslagen meting en blijft alles rotsvast. Komende nummers in de wachtrij worden meestal al tijdens het vorige nummer geanalyseerd, dus dit komt in de praktijk zelden voor.', - crossfade: 'Overgang', - crossfadeDesc: 'Fade tussen nummers', - crossfadeSecs: '{{n}} s', - notWithGapless: 'Niet beschikbaar als naadloos afspelen actief is', - notWithCrossfade: 'Niet beschikbaar als overgang actief is', - gapless: 'Naadloos afspelen', - gaplessDesc: 'Volgend nummer vooraf bufferen om stiltes tussen nummers te elimineren', - preservePlayNextOrder: '"Volgende afspelen"-volgorde behouden', - preservePlayNextOrderDesc: 'Nieuwe "Volgende afspelen"-items komen achter bestaande te staan in plaats van ervoor.', - trackPreviewsTitle: 'Track-voorvertoning', - trackPreviewsToggle: 'Track-voorvertoning inschakelen', - trackPreviewsDesc: 'Inline Play- en Voorvertoning-knoppen in trackslijsten tonen voor een korte sample midden in het nummer.', - trackPreviewStart: 'Startpositie', - trackPreviewStartDesc: 'Hoever in de track de voorvertoning start (% van de duur).', - trackPreviewDuration: 'Duur', - trackPreviewDurationDesc: 'Hoe lang elke voorvertoning speelt voordat hij stopt.', - trackPreviewDurationSecs: '{{n}} s', - trackPreviewLocationsTitle: 'Waar voorvertoningen verschijnen', - trackPreviewLocationsDesc: 'Kies in welke lijsten de voorvertoning-knoppen worden weergegeven.', - trackPreviewLocation_suggestions: 'In playlist-suggesties', - trackPreviewLocation_albums: 'In albumlijsten', - trackPreviewLocation_playlists: 'In playlists', - trackPreviewLocation_favorites: 'In favorieten', - trackPreviewLocation_artist: 'In top-tracks van artiest', - trackPreviewLocation_randomMix: 'In Random Mix', - preloadMode: 'Volgend nummer vooraf laden', - preloadModeDesc: 'Wanneer met het bufferen van het volgende nummer wordt begonnen', - nextTrackBufferingTitle: 'Buffering', - preloadHotCacheMutualExclusive: 'Preload en Hot Cache dienen hetzelfde doel — slechts één kan tegelijk actief zijn. Het inschakelen van de ene schakelt de andere automatisch uit.', - preloadOff: 'Uit', - preloadBalanced: 'Gebalanceerd (30 s voor einde)', - preloadEarly: 'Vroeg (na 5 s afspelen)', - preloadCustom: 'Aangepast', - preloadCustomSeconds: 'Seconden voor einde: {{n}}', - infiniteQueue: 'Oneindige wachtrij', - infiniteQueueDesc: 'Automatisch willekeurige nummers toevoegen als de wachtrij leeg raakt', - experimental: 'Experimenteel', - fsPlayerSection: 'Volledig scherm speler', - fsShowArtistPortrait: 'Artiestfoto tonen', - fsShowArtistPortraitDesc: 'Artiestfoto (of albumhoes) weergeven aan de rechterkant van de volledigschermspeler.', - fsPortraitDim: 'Verduistering foto', - fsLyricsStyle: 'Tekststijl', - fsLyricsStyleRail: 'Rail', - fsLyricsStyleRailDesc: 'Klassieke 5-regels schuifrail.', - fsLyricsStyleApple: 'Scrollen', - fsLyricsStyleAppleDesc: 'Volledig scherm scrolllijst.', - sidebarLyricsStyle: 'Scrollstijl voor tekst', - sidebarLyricsStyleClassic: 'Klassiek', - sidebarLyricsStyleClassicDesc: 'Actieve regel wordt gecentreerd.', - sidebarLyricsStyleApple: 'Apple Music-like', - sidebarLyricsStyleAppleDesc: 'Actieve regel verankerd bovenaan met vloeiende animatie.', - seekbarStyle: 'Zoekbalkstijl', - seekbarStyleDesc: 'Kies het uiterlijk van de afspeelbalk', - seekbarTruewave: 'Echte golfvorm', - seekbarPseudowave: 'Pseudo-golfvorm', - seekbarLinedot: 'Lijn & punt', - seekbarBar: 'Balk', - seekbarThick: 'Dikke balk', - seekbarSegmented: 'Gesegmenteerd', - seekbarNeon: 'Neon', - seekbarPulsewave: 'Pulsgolf', - seekbarParticletrail: 'Deeltjesspoor', - seekbarLiquidfill: 'Vloeistofbuis', - seekbarRetrotape: 'Retrotape', - themeSchedulerTitle: 'Thema-planner', - themeSchedulerEnable: 'Thema-planner inschakelen', - themeSchedulerEnableSub: 'Schakelt automatisch tussen twee thema\'s op basis van de tijd', - themeSchedulerDayTheme: 'Dagthema', - themeSchedulerDayStart: 'Dag begint om', - themeSchedulerNightTheme: 'Nachtthema', - themeSchedulerNightStart: 'Nacht begint om', - themeSchedulerActiveHint: "Thema-planner is actief - thema's worden automatisch gewisseld.", - visualOptionsTitle: 'Visuele Opties', - coverArtBackground: 'Cover Achtergrond', - coverArtBackgroundSub: 'Toon vervaagde cover als achtergrond in album/playlist headers', - playlistCoverPhoto: 'Playlist Coverfoto', - playlistCoverPhotoSub: 'Toon coverfoto raster in playlist detailweergave', - showBitrate: 'Toon Bitrate', - showBitrateSub: 'Toon audio bitrate in tracklijsten', - floatingPlayerBar: 'Zwevende Spelerbalk', - floatingPlayerBarSub: 'Houd de spelerbalk zwevend boven de inhoud', - uiScaleTitle: 'Interface schaal', - uiScaleLabel: 'Zoom', - }, - changelog: { - modalTitle: 'Wat is nieuw', - dontShowAgain: 'Niet meer weergeven', - close: 'Begrepen', - }, - whatsNew: { - title: 'Wat is nieuw', - empty: 'Nog geen changelog-item voor deze versie.', - bannerTitle: 'Changelog', - bannerCollapsed: 'Nieuw in v{{version}}', - dismiss: 'Verbergen', - close: 'Sluiten', - }, - help: { - title: 'Help', - searchPlaceholder: 'Help doorzoeken…', - noResults: 'Geen overeenkomende onderwerpen. Probeer een andere zoekterm.', - s1: 'Aan de slag', - q1: 'Welke servers zijn compatibel?', - a1: 'Psysonic is in de eerste plaats voor Navidrome gebouwd en volledig Subsonic-compatibel — Gonic, Airsonic, LMS en andere Subsonic-API-servers werken ook. Sommige geavanceerde functies (beoordelingen, smart playlists, Magic-String-delen, gebruikersbeheer) vereisen Navidrome.', - q2: 'Hoe voeg ik een server toe?', - a2: 'Instellingen → Servers → Server toevoegen. Voer de URL in (bijv. http://192.168.1.100:4533), gebruikersnaam en wachtwoord. Psysonic test de verbinding voor het opslaan — bij een fout wordt niets opgeslagen. U kunt zoveel servers toevoegen als u wilt en in de header tussen ze schakelen; er is altijd maar één actief.', - q3: 'Snelle UI-rondleiding?', - a3: 'Zijbalk (links) voor navigatie, Mainstage / pagina\'s in het midden, speelbalk onderaan, wachtrijpaneel rechts (te openen via het pictogram rechtsboven naast de Now-Playing-indicator). De zoekbalk bovenaan doorzoekt de hele bibliotheek; "Now Playing" toont wat andere gebruikers op dezelfde Navidrome-server momenteel luisteren.', - s2: 'Afspelen & Wachtrij', - q4: 'Hoe gebruik ik de wachtrij?', - a4: 'Open het wachtrijpaneel via de header rechtsboven. Sleep rijen om te herordenen, sleep ze naar buiten om te verwijderen, of gebruik de werkbalk om te shuffelen, de wachtrij als afspeellijst op te slaan of naar een nummer te springen. Sleep rijen uit het paneel om ze elders als overdracht te plaatsen.', - q5: 'Gapless versus Crossfade — wat is het verschil?', - a5: 'Gapless buffert het volgende nummer vooraf zodat er nul stilte tussen de nummers zit (ideaal voor live-albums en DJ-mixen). Crossfade vervaagt het huidige nummer terwijl het volgende invaagt over 1–10 s (ideaal voor gemixte mixen). Ze zijn wederzijds uitsluitend — een inschakelen schakelt de andere uit. Configureer in Instellingen → Audio.', - q6: 'Wat is de Infinite Queue?', - a6: 'Wanneer de wachtrij leegloopt en Herhalen uit staat, voegt Psysonic stilletjes vergelijkbare/willekeurige nummers uit uw bibliotheek toe zodat het afspelen nooit stopt. Auto-toegevoegde nummers verschijnen onder een "— Automatisch toegevoegd —" scheidingslijn. Schakelen via het oneindigheidspictogram in de wachtrij-header; in Instellingen → Wachtrij beperken tot een genre.', - q7: 'Meervoudige selectie en Shift-klik bereik?', - a7: 'Activeer "Selecteren" op Albums / Nieuwe releases / Random Albums / Afspeellijsten. Klik een item om het te toggelen, houd dan Shift en klik een ander item — alles ertussen in de zichtbare volgorde wordt geselecteerd. Shift-klikken breiden uit vanuit het laatst aangeklikte ankerpunt. De werkbalk biedt bulkacties (wachtrij, downloaden, verwijderen, etc.).', - q8: 'Sneltoetsen en globale hotkeys?', - a8: 'Standaard in-app-toetsen: Spatie = Afspelen / Pauzeren, Esc = sluit volledig scherm / modals, F1 = sneltoetsenoverzicht. Instellingen → Invoer laat u elke in-app-actie opnieuw toewijzen (ook akkoorden zoals Ctrl+Shift+P) en systeembrede globale snelkoppelingen instellen die ook werken wanneer Psysonic op de achtergrond draait. Mediatoetsen (Afspelen/Pauzeren, Volgende, Vorige) werken op alle platforms.', - s3: 'Audiotools', - q9: 'Replay Gain modi?', - a9: 'Instellingen → Audio → Replay Gain. Track-modus normaliseert elk nummer naar een doelniveau. Album-modus behoudt de luidheidscurve binnen een album. Auto-modus kiest Track of Album op basis van of de wachtrij van een enkel album komt. Nummers zonder Replay Gain-tags vallen terug op een configureerbare voorversterker.', - q10: 'Wat is Smart Loudness Normalization (LUFS)?', - a10: 'Een modern alternatief voor Replay Gain in Instellingen → Audio. Psysonic analyseert elk nummer naar LUFS / EBU R128 en slaat het resultaat op, zodat het volume consistent is over uw hele bibliotheek — ook nummers zonder Replay Gain-tags. Cold-cache-analyse loopt op de achtergrond en gebruikt 35–40% CPU gedurende ~1 minuut, daarna 0. Stel uw doel-luidheid (standaard −10 LUFS) één keer in.', - q11: 'EQ en AutoEQ?', - a11: 'Een 10-bands parametrische EQ in Instellingen → Audio → Equalizer met handmatige banden en presets. AutoEQ ernaast haalt een gemeten correctieprofiel voor uw hoofdtelefoonmodel op uit de AutoEQ-database en past het automatisch toe op de banden — kies uw hoofdtelefoon, de EQ klikt op de juiste curve.', - q12: 'Hoe wissel ik het audio-uitvoerapparaat?', - a12: 'Instellingen → Audio → Uitvoerapparaat. Psysonic toont alle beschikbare uitgangen en wisselt onmiddellijk wanneer u kiest. De vernieuwen-knop scant naar apparaten die na het opstarten zijn aangesloten. Linux ALSA-namen zoals "sysdefault" worden voor leesbaarheid automatisch opgeschoond.', - q13: 'Wat is de Hot Cache?', - a13: 'Hot Cache laadt het huidige nummer plus de volgende vooraf in RAM en op schijf zodat het afspelen zonder buffervertraging start — vooral nuttig op trage / externe servers. Eviction treedt in werking wanneer de groottelimiet wordt bereikt. Configureer grootte en de debounce-vertraging (zodat snelle skips niet over-fetchen) in Instellingen → Audio.', - s4: 'Bibliotheek & Ontdekking', - q14: 'Hoe werken beoordelingen en Skip-to-1★?', - a14: 'Psysonic ondersteunt 1–5 sterren-beoordelingen via OpenSubsonic (Navidrome ≥ 0.53). Beoordeel nummers in tracklijsten, in het rechtsklikmenu, of in de speelbalk onder de artiestnaam; albums op de albumpagina; artiesten op de artiestpagina. Skip-to-1★ (Instellingen → Bibliotheek → Beoordelingen) wijst automatisch 1 ster toe na een configureerbaar aantal opeenvolgende skips. Hetzelfde paneel laat u een minimum-beoordeling instellen voor gegenereerde mixen.', - q15: 'Hoe blader ik — Mappen, Genres, Tracks?', - a15: 'De mappenbrowser (zijbalk) loopt door de muziekmap van uw server in een Miller-kolomlay-out — klik op een map om in te duiken, klik op een nummer of het play-pictogram van een map om af te spelen / toe te voegen. Genres gebruikt een tag-cloud-weergave geschaald op aantal nummers; klik op een genre om het te openen. Tracks is een platte bibliotheekhub met kolomgesorteerde virtuele lijst en live zoeken.', - q16: 'Zoeken en geavanceerd zoeken?', - a16: 'De headerzoekbalk voert een snelle live zoekopdracht uit terwijl u typt over artiesten, albums en nummers. Open Geavanceerd zoeken (zijbalk) voor een rijkere weergave: filter op jaar, genre, beoordeling, formaat, kanalen, samplerate, BPM, stemming en combineer criteria. Rechtsklik op elk resultaat opent hetzelfde contextmenu als elders.', - q17: 'Wat zijn de Mixes (Random / Genre / Super Genre / Lucky)?', - a17: 'Random Mix bouwt een afspeellijst van willekeurige nummers uit uw bibliotheek; het Trefwoordfilter sluit audioboeken, comedy etc. uit op basis van genre / titel / album-substrings. Super Genre Mix groepeert uw bibliotheek in brede stijlen (Rock, Metal, Electronic, Jazz, Klassiek …) en bouwt een gefocuste mix uit één. Lucky Mix gebruikt uw luistergeschiedenis, beoordelingen en AudioMuse-AI vergelijkbare nummers om met één klik een directe afspeellijst samen te stellen.', - q18: 'Statistiekenpagina?', - a18: 'Statistieken (zijbalk) toont topartiesten, topalbums, topnummers, genre-uitsplitsing, luistertijd over tijd en per-bibliotheek-bereik wanneer u meer dan één muziekmap hebt geconfigureerd. Verschillende weergaven zijn exporteerbaar als deelbare kaartafbeelding.', - q19: 'Hoe download ik een album als ZIP?', - a19: 'Albumpagina → "Downloaden (ZIP)". De server comprimeert het album eerst — voor grote of verliesloze albums (FLAC / WAV) verschijnt de voortgangsbalk pas zodra het zippen is voltooid en de overdracht begint. Dit is normaal.', - s5: 'Songteksten', - q20: 'Waar komen de songteksten vandaan?', - a20: 'Drie bronnen, configureerbaar in Instellingen → Songteksten: uw Navidrome-server (ingebedde / OpenSubsonic-songteksten), LRCLIB (community-bijgedragen gesynchroniseerde songteksten) en NetEase Cloud Music (grote Aziatische + internationale catalogus). Elke bron kan worden in-/uitgeschakeld en op volgorde gesleept.', - q21: 'Hoe bekijk ik songteksten tijdens het afspelen?', - a21: 'Klik op het microfoonpictogram in de speelbalk om het Songteksten-tabblad in het wachtrijpaneel te openen. Gesynchroniseerde songteksten scrollen automatisch en ondersteunen klik-om-te-spoelen; pure tekst scrolt als een statisch blok. Schakel de volledig-scherm-speler in via de speelbalk-cover voor een meeslepende songteksten-weergave met mesh-blob-achtergrond.', - s6: 'Delen & Sociaal', - q22: 'Wat zijn Magic Strings?', - a22: 'Magic Strings zijn korte kopieer-plak-tokens die dingen tussen Psysonic-gebruikers delen zonder enige derde server. Server-Invite-strings laten een vriend met één plak op uw Navidrome onboarden; Album / Artiest / Wachtrij Magic Strings openen hetzelfde album / artiest / wachtrij bij de ontvanger. Genereer ze via het deel-menu, plak ze in de zoekbalk om te consumeren.', - q23: 'Wat is Orbit?', - a23: 'Orbit is gesynchroniseerd samen-luisteren: een host speelt een nummer, elke gast hoort het synchroon, en gasten kunnen nummers voorstellen die de host kan accepteren in de wachtrij. Start een sessie via de Orbit-knop in de header, deel de uitnodigingslink, en anderen kunnen vanuit elke Psysonic-installatie meedoen. De host beheert het afspelen (skippen, spoelen, wachtrij) — gasten krijgen een real-time weergave en een suggestiebox. Sessies zijn kortstondig en eindigen wanneer de host ze sluit.', - q24: 'Wat is de Now Playing-dropdown?', - a24: 'Het uitzendpictogram rechtsboven toont wat andere gebruikers op uw Navidrome-server momenteel luisteren, ververst elke 10 seconden. Uw eigen vermelding verdwijnt op het moment dat u pauzeert. Per-server, dus gebruikers op een andere actieve server worden niet getoond.', - s7: 'Personalisatie', - q25: 'Thema\'s en de Theme Scheduler?', - a25: 'Instellingen → Weergave → Thema kiest uit 60+ thema\'s in 8 groepen (Psysonic, Mediaplayer, Besturingssystemen, Spellen, Films, Series, Sociale media, Open Source Classics — Catppuccin / Nord / Gruvbox / Nightfox / Dracula). Auto-Switch Theme laat u een dag-thema + nacht-thema instellen met starttijden zodat Psysonic automatisch wisselt.', - q26: 'Kan ik de Zijbalk, Home en Artiestpagina aanpassen?', - a26: 'Ja — Instellingen → Personalisatie. De zijbalk-customizer laat u nav-items in de gewenste volgorde slepen en items die u niet gebruikt verbergen. De Home-customizer schakelt elke Mainstage-rail (Hero, Recent, Ontdekken, Recent afgespeeld, Met ster …) in/uit. De Artiestpagina-customizer herschikt de secties (Topnummers, Albums, Singles, Compilaties, Vergelijkbare artiesten, etc.) en laat u die u nooit bekijkt verbergen.', - q27: 'Wat is de Mini Player?', - a27: 'Een klein zwevend venster met cover, transportbedieningen en een compacte wachtrij. Open het via het mini-player-pictogram in de speelbalk of met zijn toetsenbordsneltoets. Het venster onthoudt zijn positie en grootte tussen sessies. Op Windows wordt de mini-webview bij het opstarten vooraf aangemaakt zodat openen direct is; Linux / macOS schakelen optioneel in via Instellingen → Weergave → Mini player vooraf laden.', - q28: 'Wat is de Floating Player Bar?', - a28: 'Een optionele speelbalk-stijl (Instellingen → Weergave) die loskomt van de onderste rand met een themed achtergrond, accentrand, afgeronde albumhoes en een gecentreerde volumesectie. Handig op hoge monitoren of compacte thema\'s.', - q29: 'Track preview op hover?', - a29: 'Hover over een tracknummer-rij, klik op de kleine voorbeeldknop op de cover, of activeer het voorbeeld vanuit het rechtsklikmenu — Psysonic streamt de eerste ~15 s door dezelfde Rust-audio-engine zodat luidheidsnormalisatie van toepassing is. Handig om door een album te bladeren dat u nog niet gehoord hebt.', - q30: 'Sleep timer?', - a30: 'Klik op het maan-pictogram in de speelbalk om de sleep timer te openen. Kies een duur (of "einde van het huidige nummer") en Psysonic vervaagt en pauzeert aan het einde. De knop toont een ronde ring en een ingebouwde aftelling terwijl de timer loopt.', - q31: 'UI-schaal, lettertype, seekbar-stijl?', - a31: 'Instellingen → Weergave — Interface-schaal (80–125% zonder de systeemlettergrootte te beïnvloeden), Lettertype (10 UI-fonts waaronder IBM Plex Mono, Fira Code, Geist, Golos Text…), Seekbar-stijl (Waveform geanalyseerd / pseudowave deterministisch / Lijn & Punt / Balk / Dikke balk / Gesegmenteerd / Neonlicht / Pulsgolf / Deeltjespoor / Vloeibare vulling / Retro Tape).', - s8: 'Power User', - q32: 'CLI player-bediening?', - a32: 'De Psysonic-binary doet ook dienst als afstandsbediening. Voorbeelden: psysonic --player play / pause / next / prev, --player volume 75, --player seek 15, --player shuffle, --player repeat off|all|one, --player rating 1-5. Wissel servers, audio-apparaten, bibliotheken; trigger Instant Mix; zoek artiesten / albums / nummers. Volledige lijst met psysonic --player --help. Shell-aanvulling voor bash en zsh via psysonic completions.', - q33: 'Smart Playlists (Navidrome)?', - a33: 'Smart Playlists zijn server-side dynamische afspeellijsten gedefinieerd door regels (genre = Rock EN jaar > 2020, etc.). De Afspeellijsten-pagina in Psysonic laat u ze maken, bewerken en verwijderen met een visuele regeleditor — Psysonic gebruikt daarvoor de Navidrome native API. Ze gedragen zich als normale afspeellijsten in de rest van de app en updaten automatisch wanneer uw bibliotheek verandert.', - q34: 'Instellingen back-uppen en herstellen?', - a34: 'Instellingen → Opslag → Back-up & Herstel exporteert serverprofielen, thema\'s, sneltoetsen en andere instellingen naar een enkel JSON-bestand. Importeer het op een andere machine of na een herinstallatie om alles in één keer te herstellen. Server-wachtwoorden zijn inbegrepen — bewaar het bestand privé.', - q35: 'Waar zie ik alle open-source-licenties?', - a35: 'Instellingen → Systeem → Open Source Licenties. De volledige afhankelijkheidslijst (cargo crates en npm-pakketten) wordt met gebundelde licentieteksten meegeleverd. Klik op een item voor de volledige tekst; het hoogtepuntblok bovenaan benadrukt de gebruikersbekende bibliotheken (Tauri, React, rodio, symphonia, etc.).', - s9: 'Offline & Sync', - q36: 'Offline modus — albums en afspeellijsten cachen?', - a36: 'Open een album of afspeellijst en klik op het downloadpictogram in de header — Psysonic cacht elk nummer lokaal zodat het van schijf afspeelt zonder netwerkoproep. De Offline Bibliotheek-pagina (zijbalk) toont alles wat is gecached, toont voortgang van lopende downloads, en laat u items verwijderen met het prullenbak-pictogram (dat verschijnt zodra een download is voltooid).', - q37: 'Offline opslaglimiet?', - a37: 'Instellingen → Bibliotheek → Offline laat u een maximale cachegrootte instellen. Wanneer de limiet wordt bereikt, toont de albumpagina-downloadknop een waarschuwingsbanner. Maak ruimte vrij door albums of afspeellijsten te verwijderen vanuit de Offline Bibliotheek-pagina.', - q38: 'Device Sync — muziek naar USB / SD?', - a38: 'Device Sync (zijbalk) kopieert albums, afspeellijsten of hele artiesten naar een externe schijf voor offline luisteren op andere apparaten. Kies een doelmap, kies bronnen uit de browsertabbladen, klik "Naar apparaat overzetten". Psysonic schrijft een manifest (psysonic-sync.json) zodat het weet welke bestanden er al zijn, ook als u Device Sync op een ander OS opent met een ander bestandsnaamsjabloon. Sjablonen ondersteunen {artist} / {album} / {title} / {track_number} / {disc_number} / {year}-tokens met / als mapscheidingsteken.', - s10: 'Integraties & Probleemoplossing', - q39: 'Last.fm scrobbling?', - a39: 'Instellingen → Integraties → Last.fm. Verbind uw account één keer en Psysonic scrobbled direct naar Last.fm — geen Navidrome-configuratie nodig. Een scrobble wordt verzonden nadat u 50% van een nummer heeft beluisterd. Now-playing pings worden bij het begin verzonden.', - q40: 'Discord Rich Presence?', - a40: 'Instellingen → Integraties → Discord toont uw huidige nummer op uw Discord-profiel. Kies tussen het app-pictogram, de hoezen van uw server (via getAlbumInfo2 — vereist een publiek bereikbare server) of Apple Music-hoezen. Pas de weergavestrings (details, status, tooltip) aan met token-templates.', - q41: 'Bandsintown tour data?', - a41: 'Opt-in onder Instellingen → Integraties → Now-Playing Info. Het Now Playing-tabblad op de Now Playing-pagina toont dan komende tour data voor de spelende artiest via de Bandsintown widget API. Standaard uit — er worden geen verzoeken gedaan totdat u inschakelt.', - q42: 'Internet Radio — live-streams afspelen?', - a42: 'Internet Radio (zijbalk) speelt elke live-stream die op uw Navidrome-server is opgeslagen (voeg stations toe via de Navidrome admin UI). Het afspelen loopt door de browser HTML5-audio-engine — de meeste EQ / Replay Gain / Loudness-instellingen zijn niet van toepassing op radio, maar ICY-metadata (huidige songnaam) wordt wel weergegeven. Ondersteunt MP3, AAC, OGG Vorbis en de meeste HLS-streams; codec-ondersteuning hangt af van het platform.', - q43: 'De verbindingstest mislukt — wat nu?', - a43: 'Controleer de URL inclusief poort dubbel (bijv. http://192.168.1.100:4533). Op een lokaal netwerk werkt http:// vaak waar https:// niet werkt (geen certificaat). Zorg ervoor dat geen firewall de poort blokkeert en dat de gebruikersnaam en wachtwoord correct zijn. Als uw server achter een reverse proxy zit, probeer dan eerst de directe URL om de oorzaak te isoleren.', - q44: 'Hoezen en artiestafbeeldingen laden traag.', - a44: 'Afbeeldingen worden bij de eerste weergave van uw server gehaald en vervolgens 30 dagen lokaal gecached. Als de opslag van uw server traag is, kan het eerste bezoek aan een pagina even duren; volgende bezoeken zijn onmiddellijk. De Hot Cache helpt ook voor nummers, maar de afbeeldingscache is onafhankelijk.', - q45: 'Linux-problemen — zwart scherm of geen geluid?', - a45: 'Zwart scherm is meestal een GPU / EGL-stuurprogrammakwestie in WebKitGTK — start met GDK_BACKEND=x11 WEBKIT_DISABLE_COMPOSITING_MODE=1 WEBKIT_DISABLE_DMABUF_RENDERER=1 (de AUR / .deb / .rpm-installers stellen deze automatisch in). Voor audio, zorg ervoor dat PipeWire of PulseAudio draait. Audio-uitval na slaap / wakker worden wordt nu automatisch afgehandeld door de post-sleep recovery hook.', - }, - queue: { - title: 'Wachtrij', - savePlaylist: 'Afspeellijst opslaan', - updatePlaylist: 'Afspeellijst bijwerken', - filterPlaylists: 'Afspeellijsten filteren…', - playlistName: 'Naam afspeellijst', - cancel: 'Annuleren', - save: 'Opslaan', - loadPlaylist: 'Afspeellijst laden', - loading: 'Laden…', - noPlaylists: 'Geen afspeellijsten gevonden.', - load: 'Wachtrij vervangen & afspelen', - appendToQueue: 'Toevoegen aan wachtrij', - delete: 'Verwijderen', - deleteConfirm: 'Afspeellijst "{{name}}" verwijderen?', - clear: 'Leegmaken', - shuffle: 'Wachtrij shufflen', - gapless: 'Naadloos', - crossfade: 'Overgang', - infiniteQueue: 'Oneindige wachtrij', - autoAdded: '— Automatisch toegevoegd —', - radioAdded: '— Radio —', - hide: 'Verbergen', - hideNowPlaying: 'Now playing info verbergen', - showNowPlaying: 'Now playing info weergeven', - close: 'Sluiten', - nextTracks: 'Volgende nummers', - shareQueue: 'Wachtrij-deellink kopiëren', - shareQueueEmpty: 'De wachtrij is leeg — niets om te delen.', - emptyQueue: 'De wachtrij is leeg.', - trackSingular: 'nummer', - trackPlural: 'nummers', - showRemaining: 'Resterende tijd tonen', - showTotal: 'Totale tijd tonen', - showEta: 'Geschatte eindtijd tonen', - replayGain: 'ReplayGain', - rgTrack: 'T {{db}} dB', - rgAlbum: 'A {{db}} dB', - rgPeak: 'Piek {{pk}}', - sourceOffline: 'Afspelen vanuit offlinebibliotheek', - sourceHot: 'Afspelen vanuit cache', - sourceStream: 'Afspelen vanuit netwerkstream', - clearCachedLoudnessWaveform: 'Clear cached loudness and waveform, then re-analyze this track', - recalculatingLoudnessWaveform: 'Recalculating loudness and waveform for this track…', - }, - miniPlayer: { - showQueue: 'Wachtrij tonen', - hideQueue: 'Wachtrij verbergen', - pinOnTop: 'Altijd boven', - pinOff: 'Losmaken', - openMainWindow: 'Hoofdvenster openen', - close: 'Sluiten', - emptyQueue: 'Wachtrij is leeg', - }, - statistics: { - title: 'Statistieken', - recentlyPlayed: 'Recent afgespeeld', - mostPlayed: 'Meest gespeelde albums', - highestRated: 'Best beoordeelde albums', - genreDistribution: 'Genreverdeling (Top 20)', - loadMore: 'Meer laden', - statArtists: 'Artiesten', - statArtistsTooltip: 'Alleen albumartiesten — artiesten die enkel als trackartiest voorkomen (featuring, gast, enz.) zonder eigen album worden niet meegeteld.', - statAlbums: 'Albums', - statSongs: 'Nummers', - statGenres: 'Genres', - statPlaytime: 'Totale speelduur', - genreInsights: 'Genre-inzichten', - formatDistribution: 'Formaatdistributie', - formatSample: 'Steekproef van {{n}} nummers', - computing: 'Berekenen…', - genreSongs: '{{count}} nummers', - genreAlbums: '{{count}} albums', - recentlyAdded: 'Recent toegevoegd', - decadeDistribution: 'Albums per decennium', - decadeAlbums_one: '{{count}} album', - decadeAlbums_other: '{{count}} albums', - decadeUnknown: 'Onbekend', - lfmTitle: 'Last.fm-statistieken', - lfmTopArtists: 'Topartiesten', - lfmTopAlbums: 'Topalbums', - lfmTopTracks: 'Topnummers', - lfmPlays: '{{count}} keer gespeeld', - lfmPeriodOverall: 'Alle tijd', - lfmPeriod7day: '7 dagen', - lfmPeriod1month: '1 maand', - lfmPeriod3month: '3 maanden', - lfmPeriod6month: '6 maanden', - lfmPeriod12month: '12 maanden', - lfmNotConnected: 'Verbind Last.fm in Instellingen om je statistieken te zien.', - lfmRecentTracks: 'Recente scrobbles', - lfmNowPlaying: 'Nu bezig', - lfmJustNow: 'zojuist', - lfmMinutesAgo: '{{n}} min geleden', - lfmHoursAgo: '{{n}} uur geleden', - lfmDaysAgo: '{{n}} dagen geleden', - topRatedSongs: 'Best beoordeelde nummers', - topRatedArtists: 'Best beoordeelde artiesten', - noRatedSongs: 'Nog geen beoordeelde nummers. Beoordeel nummers in album- of afspeellijstweergave.', - noRatedArtists: 'Nog geen beoordeelde artiesten.', - }, - player: { - regionLabel: 'Muziekspeler', - openFullscreen: 'Volledig-schermspeler openen', - fullscreen: 'Volledig-schermspeler', - closeFullscreen: 'Volledig scherm sluiten', - closeTooltip: 'Sluiten (Escape)', - noTitle: 'Geen titel', - stop: 'Stoppen', - prev: 'Vorig nummer', - play: 'Afspelen', - pause: 'Pauzeren', - previewActive: 'Voorbeeld speelt af', - previewLabel: 'Voorbeeld', - delayModalTitle: 'Timer', - delayPauseSection: 'Pauzeren na', - delayStartSection: 'Starten na', - delayPreviewPause: 'Pauze om', - delayPreviewStart: 'Start om', - delaySchedulePause: 'Pauze plannen', - delayScheduleStart: 'Start plannen', - delayCancelPause: 'Pauze-timer annuleren', - delayCancelStart: 'Start-timer annuleren', - delayInactivePause: 'Alleen beschikbaar tijdens afspelen.', - delayInactiveStart: 'Alleen in pauze met een geladen nummer of radio.', - delayCustomMinutes: 'Aangepaste vertraging (minuten)', - delayCustomPlaceholder: 'bijv. 2,5', - closeDelayModal: 'Sluiten', - delayIn: 'over', - delayFmtSec: '{{n}} s', - delayFmtMin: '{{n}} min', - delayFmtHr: '{{n}} u', - delayCancel: 'Annuleren', - delayApply: 'Toepassen', - next: 'Volgend nummer', - repeat: 'Herhalen', - repeatOff: 'Uit', - repeatAll: 'Alles', - repeatOne: 'Één', - progress: 'Nummervoortgang', - volume: 'Volume', - toggleQueue: 'Wachtrij in-/uitschakelen', - collapseQueueResize: 'Wachtrij inklappen, breedte wijzigen', - moreOptions: 'Meer opties', - equalizer: 'Equalizer', - miniPlayer: 'Minispeler', - lyrics: 'Songtekst', - fsLyricsToggle: 'Songtekst in volledig scherm', - lyricsLoading: 'Songtekst laden…', - lyricsNotFound: 'Geen songtekst gevonden voor dit nummer', - lyricsSourceServer: 'Bron: Server', - lyricsSourceLrclib: 'Bron: LRCLIB', - lyricsSourceNetease: 'Bron: Netease', - lyricsSourceLyricsplus: 'Bron: YouLyPlus', - showDuration: 'Toon duur', - showRemainingTime: 'Toon resterende tijd', - }, - nowPlayingInfo: { - tab: 'Info', - empty: 'Speel iets af om informatie te zien', - artist: 'Artiest', - songInfo: 'Nummer-info', - onTour: 'Op tour', - noTourEvents: 'Geen aankomende concerten', - tourLoading: 'Laden…', - poweredByBandsintown: 'Tourdata via Bandsintown', - bioReadMore: 'Meer tonen', - bioReadLess: 'Minder tonen', - showMoreTours_one: '{{count}} meer tonen', - showMoreTours_other: '{{count}} meer tonen', - showLessTours: 'Minder tonen', - enableBandsintownPrompt: 'Aankomende tourdata tonen?', - enableBandsintownPromptDesc: 'Optioneel. Laadt concerten van de huidige artiest via de openbare Bandsintown-API.', - enableBandsintownPrivacy: 'Bij inschakelen wordt de naam van de huidige artiest naar de Bandsintown-API gestuurd om tourdata op te halen. Er worden geen account- of persoonlijke gegevens verzonden.', - enableBandsintownAction: 'Inschakelen', - role: { - artist: 'Artiest', - albumArtist: 'Albumartiest', - composer: 'Componist', - }, - }, - songInfo: { - title: 'Nummerinfo', - songTitle: 'Titel', - artist: 'Artiest', - album: 'Album', - albumArtist: 'Albumartiest', - year: 'Jaar', - genre: 'Genre', - duration: 'Duur', - track: 'Track', - format: 'Formaat', - bitrate: 'Bitrate', - sampleRate: 'Samplefrequentie', - bitDepth: 'Bitdiepte', - channels: 'Kanalen', - fileSize: 'Bestandsgrootte', - path: 'Locatie', - replayGainTrack: 'RG Track Gain', - replayGainAlbum: 'RG Album Gain', - replayGainPeak: 'RG Track Peak', - mono: 'Mono', - stereo: 'Stereo', - }, - playlists: { - title: 'Playlists', - newPlaylist: 'Nieuwe playlist', - unnamed: 'Naamloze playlist', - createName: 'Playlistnaam…', - create: 'Aanmaken', - cancel: 'Annuleren', - empty: 'Nog geen playlists.', - emptyPlaylist: 'Deze playlist is leeg.', - addFirstSong: 'Voeg je eerste nummer toe', - notFound: 'Playlist niet gevonden.', - songs: '{{n}} nummers', - playAll: 'Alles afspelen', - shuffle: 'Willekeurig', - addToQueue: 'Aan wachtrij toevoegen', - back: 'Terug naar playlists', - deletePlaylist: 'Verwijderen', - confirmDelete: 'Nogmaals klikken om te bevestigen', - removeSong: 'Uit playlist verwijderen', - addSongs: 'Nummers toevoegen', - searchPlaceholder: 'Doorzoek bibliotheek…', - noResults: 'Geen resultaten.', - suggestions: 'Aanbevolen nummers', - noSuggestions: 'Geen suggesties beschikbaar.', - titleBadge: 'Playlist', - refreshSuggestions: 'Nieuwe suggesties', - addSong: 'Toevoegen aan playlist', - preview: 'Voorbeeld (30 s)', - previewStop: 'Voorbeeld stoppen', - playNextSuggestion: 'Hierna afspelen', - suggestionsHint: 'Dubbelklik op een rij om hem aan de afspeellijst toe te voegen', - addSelected: 'Geselecteerde toevoegen', - cacheOffline: 'Playlist offline opslaan', - offlineCached: 'Playlist gecached', - removeOffline: 'Verwijder uit offline cache', - offlineDownloading: 'Cachen… ({{done}}/{{total}} albums)', - publicLabel: 'Openbaar', - privateLabel: 'Privé', - editMeta: 'Playlist bewerken', - editNamePlaceholder: 'Playlistnaam…', - editCommentPlaceholder: 'Beschrijving toevoegen…', - editPublic: 'Openbare playlist', - editSave: 'Opslaan', - editCancel: 'Annuleren', - changeCover: 'Omslagafbeelding wijzigen', - changeCoverLabel: 'Foto wijzigen', - removeCover: 'Foto verwijderen', - coverUpdated: 'Omslag bijgewerkt', - metaSaved: 'Playlist bijgewerkt', - downloadZip: 'Downloaden (ZIP)', - // Toast notifications for multi-select - addSuccess: '{{count}} nummers toegevoegd aan {{playlist}}', - addPartial: '{{added}} toegevoegd, {{skipped}} overgeslagen (duplicaten)', - addAllSkipped: 'Alles overgeslagen ({{count}} duplicaten)', - addedAsDuplicates: '{{count}} nummers toegevoegd aan {{playlist}} (als duplicaten)', - duplicateConfirmTitle: 'Al in afspeellijst', - duplicateConfirmMessage: 'Alle {{count}} nummers staan al in "{{playlist}}". Toch als duplicaten toevoegen?', - duplicateConfirmAction: 'Toch toevoegen', - addError: 'Fout bij toevoegen van nummers', - createAndAddSuccess: 'Playlist "{{playlist}}" aangemaakt met {{count}} nummers', - createError: 'Fout bij aanmaken van playlist', - deleteSuccess: '{{count}} playlists verwijderd', - deleteFailed: 'Fout bij verwijderen van {{name}}', - deleteSelected: 'Geselecteerde verwijderen', - deleteSelectedPartial: 'Slechts {{n}} van de {{total}} geselecteerde playlists kunnen worden verwijderd (de andere zijn van iemand anders).', - mergeSuccess: '{{count}} nummers samengevoegd in {{playlist}}', - mergeNoNewSongs: 'Geen nieuwe nummers om toe te voegen', - mergeError: 'Fout bij samenvoegen van playlists', - mergeInto: 'Samenvoegen in', - selectionCount: '{{count}} geselecteerd', - select: 'Selecteren', - startSelect: 'Selectie inschakelen', - cancelSelect: 'Annuleren', - loadingAlbums: '{{count}} albums oplossen…', - loadingArtists: '{{count}} artiesten oplossen…', - myPlaylists: 'Mijn playlists', - noOtherPlaylists: 'Geen andere playlists beschikbaar', - addToPlaylistSuccess: '{{count}} nummers toegevoegd aan {{playlist}}', - addToPlaylistNoNew: 'Geen nieuwe nummers voor {{playlist}}', - addToPlaylistError: 'Fout bij toevoegen aan playlist', - removeSuccess: 'Nummer verwijderd van playlist', - removeError: 'Fout bij verwijderen uit playlist', - importCSV: 'CSV Importeren', - importCSVTooltip: 'Importeren vanuit Spotify CSV', - csvImportReport: 'CSV-importrapport', - csvImportTotal: 'Totaal', - csvImportAdded: 'Toegevoegd', - csvImportDuplicates: 'Duplicaten', - csvImportNotFound: 'Niet Gevonden', - csvImportNetworkErrors: 'Netwerkfouten', - csvImportDuplicatesTitle: 'Dubbele nummers (al in playlist):', - csvImportNotFoundTitle: 'Niet gevonden nummers:', - csvImportNetworkErrorsTitle: 'Netwerkfouten (import kan opnieuw proberen):', - csvImportDownloadReport: 'Rapport downloaden', - csvImportClose: 'Sluiten', - csvImportNoValidTracks: 'Geen geldige nummers gevonden in CSV-bestand', - csvImportFailed: 'CSV-import mislukt', - csvImportToast: '{{added}} toegevoegd, {{notFound}} niet gevonden, {{duplicates}} duplicaten', - csvImportDownloadSuccess: 'Rapport succesvol gedownload', - csvImportDownloadError: 'Rapport downloaden mislukt', - }, - smartPlaylists: { - sectionBasic: '1. Basis', - sectionGenres: '2. Genres', - sectionYearsAndFilters: '3. Jaren en filters', - genreMode: 'Genre-modus', - genreModeInclude: 'Genres opnemen', - genreModeExclude: 'Genres uitsluiten', - genreSearchPlaceholder: 'Genres filteren...', - availableGenres: 'Beschikbaar', - selectedGenres: 'Geselecteerd', - yearMode: 'Jaarmodus', - yearModeInclude: 'Bereik opnemen', - yearModeExclude: 'Bereik uitsluiten', - name: 'Naam (zonder prefix)', - limit: 'Limiet', - limitHint: 'Hoeveel nummers in de playlist moeten komen (1-{{max}}, meestal 50).', - artistContains: 'Artiest bevat…', - albumContains: 'Album bevat…', - titleContains: 'Titel bevat…', - minRating: 'Minimale beoordeling', - minRatingAria: 'Minimale beoordeling voor smart playlist', - minRatingHint: '0 schakelt de minimumdrempel uit; 1-5 behoudt nummers met een beoordeling boven de gekozen waarde.', - fromYear: 'Vanaf jaar', - toYear: 'Tot jaar', - excludeUnrated: 'Nummers zonder beoordeling uitsluiten', - compilationOnly: 'Alleen compilaties', - create: 'Nieuwe Smart Playlist', - save: 'Smart Playlist opslaan', - created: '{{name}} aangemaakt', - updated: '{{name}} bijgewerkt', - createFailed: 'Smart playlist kon niet worden aangemaakt.', - updateFailed: 'Smart playlist kon niet worden bijgewerkt.', - navidromeOnly: 'Smart playlists kunnen alleen op Navidrome-servers worden aangemaakt.', - loadFailed: 'Smart playlists konden niet vanuit Navidrome worden geladen.', - sortRandom: 'Sorteren: willekeurig', - sortTitleAsc: 'Sorteren: titel A-Z', - sortTitleDesc: 'Sorteren: titel Z-A', - sortYearDesc: 'Sorteren: jaar aflopend', - sortYearAsc: 'Sorteren: jaar oplopend', - sortPlayCountDesc: 'Sorteren: afspeeltelling aflopend', - }, - mostPlayed: { - title: 'Meest gespeeld', - topArtists: 'Topkunstenaars', - topAlbums: 'Topalbums', - plays: '{{n}} keer gespeeld', - sortMost: 'Meest gespeeld eerst', - sortLeast: 'Minst gespeeld eerst', - loadMore: 'Meer albums laden', - noData: 'Nog geen afspeelgegevens. Begin met luisteren!', - noArtists: 'Alle artiesten gefilterd.', - filterCompilations: 'Compilatie-artiesten verbergen (Various Artists, Soundtracks, etc.)', - filterCompilationsShort: 'Compilaties verbergen', - }, - losslessAlbums: { - empty: 'Nog geen lossless-albums in deze bibliotheek.', - unsupported: 'Deze server biedt geen metadata om lossless-albums te vinden.', - slowFetchHint: 'Laadt langzamer dan andere albumpagina\'s — Psysonic doorloopt de volledige songcatalogus op kwaliteit.', - }, - radio: { - title: 'Internetradio', - empty: 'Geen radiostations geconfigureerd.', - addStation: 'Station toevoegen', - editStation: 'Bewerken', - deleteStation: 'Station verwijderen', - confirmDelete: 'Klik opnieuw om te bevestigen', - stationName: 'Stationsnaam…', - streamUrl: 'Stream-URL…', - homepageUrl: 'Homepage-URL (optioneel)', - save: 'Opslaan', - cancel: 'Annuleren', - live: 'LIVE', - liveStream: 'Internetradio', - openHomepage: 'Homepage openen', - changeCoverLabel: 'Cover wijzigen', - removeCover: 'Cover verwijderen', - browseDirectory: 'Gids doorzoeken', - directoryPlaceholder: 'Stations zoeken…', - noResults: 'Geen stations gevonden.', - stationAdded: 'Station toegevoegd', - filterAll: 'Alle', - filterFavorites: 'Favorieten', - sortManual: 'Handmatig', - sortAZ: 'A → Z', - sortZA: 'Z → A', - sortNewest: 'Nieuwste', - favorite: 'Toevoegen aan favorieten', - unfavorite: 'Verwijderen uit favorieten', - noFavorites: 'Geen favoriete stations.', - listenerCount_one: '{{count}} luisteraar', - listenerCount_other: '{{count}} luisteraars', - recentlyPlayed: 'Recent gespeeld', - upNext: 'Volgende', - }, - folderBrowser: { - empty: 'Lege map', - error: 'Laden mislukt', - }, - deviceSync: { - title: 'Apparaatsync', - targetFolder: 'Doelmap', - noFolderChosen: 'Geen map gekozen', - selectDrive: 'Selecteer een schijf…', - refreshDrives: 'Schijven vernieuwen', - noDrivesDetected: 'Geen verwijderbare schijven gedetecteerd', - browseManual: 'Handmatig bladeren…', - free: 'vrij', - notMountedVolume: 'Het doel bevindt zich niet op een gekoppeld volume. De schijf is mogelijk losgekoppeld.', - chooseFolder: 'Kiezen…', - filenameTemplate: 'Bestandsnaamsjabloon', - targetDevice: 'Doelapparaat', - templateHint: 'Variabelen: {artist}, {album}, {title}, {track_number}, {disc_number}, {year}', - cleanupButton: 'Niet-geselecteerde bestanden verwijderen', - cleanupNothingToDelete: 'Niets te verwijderen — apparaat is al gesynchroniseerd.', - confirmCleanup: '{{count}} bestand(en) verwijderen van het apparaat die niet in de huidige selectie staan. Doorgaan?', - cleanupComplete: '{{count}} bestand(en) van het apparaat verwijderd.', - selectedSources: 'Geselecteerde bronnen', - noSourcesSelected: 'Geen bronnen geselecteerd. Klik op items in de browser om ze toe te voegen.', - clearAll: 'Alles wissen', - tabPlaylists: 'Afspeellijsten', - tabAlbums: 'Albums', - tabArtists: 'Artiesten', - searchPlaceholder: 'Zoeken…', - syncButton: 'Synchroniseren naar apparaat', - actionTransfer: 'Overdragen naar apparaat', - actionDelete: 'Verwijderen van apparaat', - actionApplyAll: 'Alle wijzigingen toepassen', - templatePreview: 'Voorbeeld', - templatePresetStandard: 'Standaard', - templatePresetMultiDisc: 'Multi-Disc', - templatePresetAltFolder: 'Alt. map', - tokenSlashHint: '/ = mapscheidingsteken', - cancel: 'Annuleren', - noTargetDir: 'Kies eerst een doelmap.', - noSources: 'Selecteer minimaal één bron.', - noTracks: 'Geen nummers gevonden in de geselecteerde bronnen.', - fetchError: 'Ophalen van nummers van de server mislukt.', - syncComplete: 'Synchronisatie voltooid.', - dismiss: 'Sluiten', - cancelSync: 'Annuleren', - syncCancelled: 'Synchronisatie geannuleerd ({{done}} / {{total}} overgebracht).', - colName: 'Naam', - colType: 'Type', - colStatus: 'Status', - onDevice: 'Apparaatbeheer', - addSources: 'Toevoegen…', - syncResult: '{{done}} overgedragen, {{skipped}} al up-to-date ({{total}} totaal)', - deleteFromDevice: 'Markeren voor verwijdering ({{count}})', - confirmDelete: '{{count}} item(s) van het apparaat verwijderen: {{names}}?', - deleteComplete: '{{count}} item(s) van het apparaat verwijderd.', - manifestImported: '{{count}} bron(nen) geïmporteerd uit apparaatmanifest.', - statusSynced: 'Gesynchroniseerd', - statusPending: 'In behandeling', - statusDeletion: 'Verwijdering', - markForDeletion: 'Markeren voor verwijdering', - removeSource: 'Verwijderen', - undoDeletion: 'Verwijdering ongedaan maken', - syncInBackground: 'Sync gestart op achtergrond — u kunt navigeren.', - syncInProgress: '{{done}} / {{total}} nummers…', - syncSummary: 'Synchronisatieoverzicht', - calculating: 'Vereiste payload berekenen…', - filesToAdd: 'Te toevoegen bestanden:', - filesToDelete: 'Te verwijderen bestanden:', - netChange: 'Nettoverandering:', - availableSpace: 'Beschikbare schijfruimte:', - spaceWarning: 'Waarschuwing: Het doelapparaat heeft niet genoeg gerapporteerde ruimte.', - proceed: 'Doorgaan met synchronisatie', - notEnoughSpace: 'Onvoldoende fysieke schijfruimte gedetecteerd!', - liveSearch: 'Live', - randomAlbumsLabel: 'Willekeurige albums', - }, - orbit: { - triggerLabel: 'Orbit', - triggerTooltip: 'Een gedeelde luistersessie starten of eraan deelnemen', - launchCreate: 'Sessie aanmaken', - launchJoin: 'Deelnemen aan sessie', - launchHelp: 'Hoe werkt dit?', - launchHelpSoon: 'Binnenkort beschikbaar', - joinModalTitle: 'Deelnemen aan een Orbit-sessie', - joinModalSub: 'Plak de uitnodigingslink die je host je gestuurd heeft.', - joinModalLinkLabel: 'Uitnodigingslink', - joinModalLinkPlaceholder: 'psysonic2-…', - joinModalLinkHelper: 'Werkt met elke geldige Orbit-link. Moet verwijzen naar de server waarop je nu bent aangemeld.', - joinModalPasteTooltip: 'Plakken vanaf klembord', - joinModalSubmit: 'Deelnemen', - joinModalBusy: 'Deelnemen…', - joinErrEmpty: 'Plak een uitnodigingslink.', - joinErrInvalid: 'Dat lijkt geen Orbit-uitnodigingslink.', - closeAria: 'Sluiten', - heroTitlePrefix: 'Luister samen met', - heroTitleBrand: 'Orbit', - heroSub: 'Start een sessie — andere gebruikers op {{server}} luisteren mee en kunnen nummers voorstellen.', - fallbackServer: 'deze server', - tipLan: 'Je bent momenteel verbonden via een thuisnetwerkadres. Gasten van buiten je netwerk kunnen niet deelnemen — schakel over naar een openbaar serveradres in de instellingen voordat je start.', - tipRemote: 'Zodat gasten van buiten je thuisnetwerk kunnen deelnemen, moet je serveradres publiek bereikbaar zijn. Als je server alleen intern is, schakel om voordat je start.', - labelName: 'Sessienaam', - namePlaceholder: 'Velvet Orbit', - reshuffleTooltip: 'Nieuwe suggestie', - reshuffleAria: 'Een nieuwe naam voorstellen', - helperName: 'Hoe de sessie voor je gasten verschijnt — laat staan of typ je eigen naam.', - labelMax: 'Max. gasten', - helperMax: 'Jij telt niet mee — dit beperkt alleen binnenkomende gasten.', - labelLink: 'Uitnodigingslink', - tooltipCopied: 'Gekopieerd', - tooltipCopy: 'Kopiëren', - ariaCopyLink: 'Uitnodigingslink kopiëren', - helperLink: 'Stuur deze link naar je gasten. Ze kunnen hem overal in Psysonic plakken met Ctrl+V.', - labelClearQueue: 'Eerst mijn wachtrij legen', - helperClearQueue: 'Begin de sessie met een lege wachtrij. Uit: bestaande nummers blijven en worden met gasten gedeeld.', - btnCancel: 'Annuleren', - btnStarting: 'Starten…', - btnStart: 'Orbit starten', - btnCopyAndStart: 'Link kopiëren & starten', - errNameRequired: 'Geef je sessie een naam.', - errStartFailed: 'Kon niet starten.', - hostLabel: 'Host: {{name}}', - participantsTooltip: 'Deelnemers', - settingsTooltip: 'Sessie-instellingen', - shareTooltip: 'Uitnodigingslink delen', - shuffleLabel: 'Volgende shuffle in', - catchUpLabel: 'inhalen', - catchUpTooltip: 'Spring naar de huidige positie van de host', - hostAway: 'Host offline', - hostOnline: 'Host online', - endTooltip: 'Sessie beëindigen', - leaveTooltip: 'Sessie verlaten', - helpTooltip: 'Hoe Orbit werkt', - diag: { - openTooltip: 'Diagnose — kopieerbaar gebeurtenissen-log', - title: 'Orbit-diagnose', - role: 'Rol', - hostTrack: 'Track-ID van host', - hostPos: 'Positie van host', - guestTrack: 'Mijn track-ID', - guestPos: 'Mijn positie', - drift: 'Verschil', - stateAge: 'Leeftijd van staat', - eventLog: 'Gebeurtenissen-log ({{count}})', - copyLabel: 'Kopiëren', - copyTooltip: 'Log naar klembord kopiëren', - clearLabel: 'Wissen', - clearTooltip: 'Buffer leegmaken', - empty: 'Nog geen gebeurtenissen — ze verschijnen zodra Orbit synchroniseert.', - hint: 'Open dit voor je het probleem reproduceert, klik dan Kopiëren en plak in de bugmelding.', - copied: '{{count}} regels gekopieerd', - copyFailed: 'Kon niet naar klembord kopiëren', - cleared: 'Buffer gewist', - }, - helpTitle: 'Hoe Orbit werkt', - helpIntro: 'Orbit maakt van Psysonic een gedeelde luisterruimte. Een host kiest de muziek; gasten luisteren synchroon mee en kunnen nummers voorstellen.', - helpHostOnly: '(host)', - helpSec1Title: 'Wat is Orbit?', - helpSec1Body: 'Een "samen luisteren"-modus — de host stuurt de weergave, gasten sluiten aan. Alles loopt via playlists op je eigen Navidrome-server; geen externe infrastructuur.', - helpSec2Title: 'Host en gasten', - helpSec2Body: 'De host bedient de weergave (play / pause / skip / seek) en beslist wanneer de sessie eindigt. Gasten volgen de weergave, kunnen nummers voorstellen en elk moment verlaten of opnieuw deelnemen. Alleen de host kan deelnemers kicken of permanent bannen.', - helpSec2WarnHead: 'Belangrijk: aparte accounts.', - helpSec2WarnBody: 'Elke deelnemer heeft een eigen Navidrome-account nodig. Als host en gast met dezelfde gebruiker inloggen botsen hun inzendingen en de host ziet nooit de suggesties van de gast.', - helpSec3Title: 'Starten en uitnodigen', - helpSec3Body: 'Klik op de "Orbit"-knop → Sessie aanmaken → het startmodal toont een kopieerklare uitnodigingslink en laat je optioneel je huidige wachtrij legen. Deel de link hoe je wilt. Terwijl een sessie draait, kopieert de deelknop in de sessiebalk de link op elk moment opnieuw.', - helpSec4Title: 'Deelnemen', - helpSec4Body: 'Plak de uitnodigingslink ergens in Psysonic met Ctrl+V / Cmd+V — de deelprompt verschijnt automatisch. Alternatief: "Orbit" → Deelnemen aan sessie → plak in het veld. Als de link naar een server verwijst waar je een account hebt, schakelt Psysonic voor je. Bij meerdere accounts op die server vraagt een kleine kiezer welke te gebruiken.', - helpSec5Title: 'Nummers voorstellen', - helpSec5Body: 'In elke lijst: dubbelklik op een rij, of rechtermuisknop → "Toevoegen aan Orbit-sessie". Een enkele klik toont een hint in plaats van het hele album in de gedeelde wachtrij te gooien — dat is bewust. Expliciete bulkacties zoals "Alles afspelen" of "Album afspelen" vragen eerst om bevestiging en voegen dan toe (vervangen nooit).', - helpSec6Title: 'De gedeelde wachtrij', - helpSec6Body: 'De wachtrij toont de komende nummers van de host — voor iedereen zichtbaar. Inkomende bulktoevoegingen worden altijd achteraan geplaatst, zodat suggesties van gasten niet verloren gaan. Auto-shuffle hergroepeert de wachtrij periodiek (instelbaar: 1 / 5 / 10 / 15 / 30 min). Als je weergave afwijkt van de host, brengt de "Inhalen"-knop in de sessiebalk je terug naar de live positie van de host.', - helpSec7Title: 'Goedkeuringen', - helpSec7Body: 'Standaard hebben gast-suggesties handmatige goedkeuring nodig — ze verschijnen in een "Goedkeuringen"-strook bovenaan het wachtrijpaneel met accepteer- / afwijsknoppen. Auto-goedkeuring kan in de sessie-instellingen aan, zodat alles direct doorgaat.', - helpSec8Title: 'Deelnemers en instellingen', - helpSec8Body: 'Open het instellingen-icoon in de sessiebalk voor shuffle-cadans, auto-goedkeuring en de "Nu shufflen"-sneltoets. Klik op het deelnemersaantal om te zien wie verbonden is — kicken (kan via de link opnieuw deelnemen) of bannen (voor de sessie uitgesloten). Gasten zien de deelnemerslijst ook, maar alleen-lezen.', - helpSec9Title: 'De sessie beëindigen', - helpSec9Body: 'Host-X → bevestigingsdialoog → de sessie sluit voor iedereen en de server-playlists worden automatisch opgeruimd. Gast-X → de gast verlaat, de sessie gaat door. Als de host 5 minuten stil blijft, verlaat de gast automatisch met een melding; korte reconnects binnen die tijd zijn onzichtbaar.', - participantsInviteLabel: 'Uitnodigingslink', - participantsCountLabel: '{{count}} in sessie', - participantsHost: 'host', - participantsEmpty: 'Nog geen gasten', - participantsKickTooltip: 'Uit sessie verwijderen', - participantsKickAria: '{{user}} verwijderen', - participantsRemoveTooltip: 'Uit sessie verwijderen', - participantsRemoveAria: '{{user}} uit deze sessie verwijderen', - participantsBanTooltip: 'Permanent bannen', - participantsBanAria: '{{user}} permanent bannen', - participantsMuteTooltip: 'Voorstellen blokkeren', - participantsUnmuteTooltip: 'Voorstellen toestaan', - participantsMuteAria: 'Voorstellen van {{user}} blokkeren', - participantsUnmuteAria: 'Voorstellen van {{user}} weer toestaan', - confirmRemoveTitle: 'Uit sessie verwijderen?', - confirmRemoveBody: '{{user}} wordt uit de sessie verwijderd, maar kan opnieuw deelnemen via je uitnodigingslink.', - confirmRemoveConfirm: 'Verwijderen', - confirmBanTitle: 'Permanent bannen?', - confirmBanBody: '{{user}} wordt verwijderd en kan niet meer aan deze sessie deelnemen. Onomkeerbaar voor de duur van de sessie.', - confirmBanConfirm: 'Bannen', - confirmCancel: 'Annuleren', - confirmJoinTitle: 'Deelnemen aan Orbit-sessie?', - confirmJoinBody: '{{host}} heeft je uitgenodigd voor "{{name}}". Aan de sessie deelnemen?', - confirmJoinConfirm: 'Deelnemen', - confirmLeaveTitle: 'Sessie verlaten?', - confirmLeaveBody: 'Wil je "{{name}}" verlaten? Je kunt altijd opnieuw deelnemen via de uitnodigingslink van {{host}}.', - confirmLeaveConfirm: 'Verlaten', - confirmEndTitle: 'Sessie voor iedereen beëindigen?', - confirmEndBody: '"{{name}}" wordt voor alle deelnemers gesloten. De sessie-playlists worden automatisch opgeruimd.', - confirmEndConfirm: 'Sessie beëindigen', - invalidLinkTitle: 'Uitnodigingslink is niet meer geldig', - invalidLinkBody: 'Deze Orbit-sessie bestaat niet meer of is al beëindigd. Vraag de host om een nieuwe uitnodigingslink.', - settingsTitle: 'Sessie-instellingen', - settingAutoApprove: 'Suggesties automatisch goedkeuren', - settingAutoApproveHint: 'Gast-suggesties komen direct in je wachtrij. Uit: ze blijven in de sessielijst voor latere beoordeling.', - settingAutoShuffle: 'Automatisch shufflen', - settingAutoShuffleHint: 'Periodieke Fisher-Yates-shuffle van de komende wachtrij. Uit: de volgorde verandert alleen wanneer je zelf herschikt.', - settingShuffleInterval: 'Opnieuw shufflen elke', - settingShuffleIntervalHint: 'Hoe vaak de komende wachtrij tijdens de sessie opnieuw wordt geshuffled.', - suggestBlockedMuted: 'De host heeft je voor deze sessie geblokkeerd — voorstellen uitgeschakeld.', - settingShuffleIntervalValue_one: '{{count}} min', - settingShuffleIntervalValue_other: '{{count}} min', - settingShuffleNow: 'Nu shufflen', - toastSuggested: '{{user}} stelde "{{title}}" voor', - toastSuggestedMany: '{{count}} nieuwe suggesties in de wachtrij', - toastShuffled: 'Wachtrij geshuffled', - toastJoined: 'Deelgenomen aan sessie', - toastLoginFirst: 'Log eerst in voordat je aan een sessie deelneemt', - toastSwitchServer: 'Schakel eerst naar {{url}} en plak opnieuw', - toastNoAccountForServer: 'Je hebt geen toegang tot {{url}}. Vraag de host om een uitnodiging.', - toastSwitchFailed: 'Kon niet schakelen naar {{url}}', - accountPickerTitle: 'Welk account?', - accountPickerSub: 'Je hebt meer dan één account voor {{url}}. Kies waarmee je wilt deelnemen.', - toastJoinFail: 'Kon niet deelnemen aan sessie', - joinErrNotFound: 'Sessie niet gevonden', - joinErrEnded: 'De sessie is beëindigd', - joinErrFull: 'De sessie is vol', - joinErrKicked: 'Je kunt niet opnieuw deelnemen aan deze sessie', - joinErrNoUser: 'Geen actieve server', - joinErrServerError: 'Kon niet deelnemen', - ctxAddToSession: 'Aan Orbit-sessie toevoegen', - ctxSuggestedToast: 'Aan sessie voorgesteld', - ctxSuggestFailed: 'Kon niet voorstellen — niet deelgenomen', - ctxAddToSessionHost: 'Aan Orbit-sessie toevoegen', - ctxAddedHostToast: 'Aan sessie toegevoegd', - ctxAddHostFailed: 'Kon niet toevoegen aan sessie', - bulkConfirmTitle: 'Alles aan de Orbit-wachtrij toevoegen?', - bulkConfirmBody: 'Dit zou {{count}} nummers in één keer in de gedeelde wachtrij plaatsen. Dat is veel voor je gasten. Doorgaan?', - bulkConfirmYes: 'Alles toevoegen', - bulkConfirmNo: 'Annuleren', - guestLive: 'Live', - guestPlaying: 'Speelt nu', - guestPaused: 'Gepauzeerd', - guestLoading: 'Laden…', - guestSuggestions: 'Suggesties', - guestUpNext: 'Volgende', - guestUpNextEmpty: 'Niets in de wachtrij. Open het contextmenu van een nummer en kies "Aan Orbit-sessie toevoegen".', - guestPendingTitle: 'Wacht op host', - guestPendingHint: 'Voorgesteld — verschijnt in de wachtrij zodra de host het oppakt.', - approvalTitle: 'Wacht op goedkeuring', - approvalFrom: 'Voorgesteld door {{user}}', - approvalAccept: 'Accepteren', - approvalDecline: 'Weigeren', - guestUpNextMore: '+ {{count}} meer in de wachtrij van de host', - guestSubmitter: 'door {{user}}', - queueAddedByHost: 'Toegevoegd door host', - queueAddedByYou: 'Toegevoegd door jou', - queueAddedByUser: 'Toegevoegd door {{user}}', - guestEmpty: 'Nog geen suggesties. Open het contextmenu van een nummer en kies "Aan Orbit-sessie toevoegen".', - guestFooter: 'De host bedient de weergave — je kunt de lijst niet wijzigen.', - exitKickedTitle: 'Je bent uit de sessie gebannen', - exitRemovedTitle: 'Je bent uit de sessie verwijderd', - exitEndedTitle: 'De host heeft de sessie beëindigd', - exitHostTimeoutTitle: 'Host niet bereikbaar', - exitHostTimeoutBody: '{{host}} heeft al een tijd geen update meer verstuurd, dus "{{name}}" is aan jouw kant gesloten. Je kunt altijd opnieuw deelnemen via de link.', - exitKickedBody: '{{host}} heeft je uit "{{name}}" gebannen. Je kunt niet opnieuw deelnemen.', - exitRemovedBody: '{{host}} heeft je uit "{{name}}" verwijderd. Je kunt altijd opnieuw deelnemen via de link.', - exitEndedBody: '"{{name}}" is beëindigd. Hopelijk had je plezier.', - exitOk: 'OK', - }, - tray: { - playPause: 'Afspelen / Pauzeren', - nextTrack: 'Volgende nummer', - previousTrack: 'Vorige nummer', - showHide: 'Tonen / Verbergen', - exitPsysonic: 'Psysonic afsluiten', - nothingPlaying: 'Niets wordt afgespeeld', - }, - licenses: { - title: 'Open-source licenties', - intro: 'Psysonic is gebouwd op open-source software. De onderstaande lijst toont elke afhankelijkheid die met de app wordt meegeleverd, met versie, licentie en volledige licentietekst.', - highlights: 'Belangrijke afhankelijkheden', - searchPlaceholder: 'Zoek op naam, versie of licentie…', - noResults: 'Geen resultaten.', - loading: 'Licenties laden…', - loadError: 'Licentiegegevens konden niet worden geladen.', - noLicenseText: 'Geen licentietekst meegeleverd voor deze afhankelijkheid.', - viewSource: 'Bron bekijken', - totalLine: '{{total}} afhankelijkheden — {{cargo}} cargo, {{npm}} npm', - generatedAt: 'Laatst gegenereerd {{date}}', - }, -}; diff --git a/src/locales/nl/albumDetail.ts b/src/locales/nl/albumDetail.ts new file mode 100644 index 00000000..60abf0fe --- /dev/null +++ b/src/locales/nl/albumDetail.ts @@ -0,0 +1,47 @@ +export const albumDetail = { + back: 'Terug', + orbitDoubleClickHint: 'Dubbelklik om dit nummer aan de Orbit-wachtrij toe te voegen', + playAll: 'Alles afspelen', + shareAlbum: 'Album delen', + enqueue: 'In wachtrij', + enqueueTooltip: 'Volledig album aan wachtrij toevoegen', + artistBio: 'Artiest biografie', + download: 'Downloaden (ZIP)', + downloading: 'Laden…', + cacheOffline: 'Offline beschikbaar maken', + offlineCached: 'Offline beschikbaar', + offlineDownloading: 'Wordt gecached… ({{n}}/{{total}})', + removeOffline: 'Offline cache verwijderen', + offlineStorageFull: 'Offline opslag vol (limiet: {{mb}} MB). Verwijder een album uit je offline bibliotheek of verhoog de limiet in de instellingen.', + offlineStorageGoToSettings: 'Instellingen', + offlineStorageGoToLibrary: 'Offline bibliotheek', + favoriteAdd: 'Aan favorieten toevoegen', + favoriteRemove: 'Uit favorieten verwijderen', + favorite: 'Favoriet', + noBio: 'Geen biografie beschikbaar.', + moreByArtist: 'Meer van {{artist}}', + tracksCount: '{{n}} nummers', + goToArtist: 'Naar {{artist}}', + moreLabelAlbums: 'Meer albums op {{label}}', + trackTitle: 'Titel', + trackAlbum: 'Album', + trackArtist: 'Artiest', + trackGenre: 'Genre', + trackFormat: 'Formaat', + trackFavorite: 'Favoriet', + trackRating: 'Beoordeling', + trackDuration: 'Duur', + trackTotal: 'Totaal', + columns: 'Kolommen', + resetColumns: 'Standaard herstellen', + notFound: 'Album niet gevonden.', + bioModal: 'Artiest biografie', + bioClose: 'Sluiten', + ratingLabel: 'Beoordeling', + enlargeCover: 'Vergroten', + filterSongs: 'Filteren…', + sortNatural: 'Natuurlijk', + sortByTitle: 'A–Z (Titel)', + sortByArtist: 'A–Z (Artiest)', + sortByAlbum: 'A–Z (Album)', +}; diff --git a/src/locales/nl/albums.ts b/src/locales/nl/albums.ts new file mode 100644 index 00000000..6ae11e7e --- /dev/null +++ b/src/locales/nl/albums.ts @@ -0,0 +1,32 @@ +export const albums = { + title: 'Alle albums', + sortByName: 'A–Z (Album)', + sortByArtist: 'A–Z (Artiest)', + sortNewest: 'Nieuwste eerst', + sortRandom: 'Willekeurig', + yearFrom: 'Van', + yearTo: 'Tot', + yearFilterClear: 'Jaarfilter wissen', + yearFilterLabel: 'Jaar', + compilationLabel: 'Compilaties', + compilationOnly: 'Alleen compilaties', + compilationHide: 'Compilaties verbergen', + compilationTooltipAll: 'Alle albums · klik: alleen compilaties', + compilationTooltipOnly: 'Alleen compilaties · klik: compilaties verbergen', + compilationTooltipHide: 'Compilaties verborgen · klik: toon alles', + select: 'Meervoudige selectie', + startSelect: 'Meervoudige selectie inschakelen', + cancelSelect: 'Annuleren', + selectionCount: '{{count}} geselecteerd', + downloadZips: 'ZIPs downloaden', + addOffline: 'Offline toevoegen', + enqueueSelected_one: 'In wachtrij ({{count}})', + enqueueSelected_other: 'In wachtrij ({{count}})', + enqueueQueued_one: '{{count}} album toegevoegd aan wachtrij', + enqueueQueued_other: '{{count}} albums toegevoegd aan wachtrij', + downloadingZip: 'Downloaden {{current}}/{{total}}: {{name}}', + downloadZipDone: '{{count}} ZIP(s) gedownload', + downloadZipFailed: 'Downloaden van {{name}} mislukt', + offlineQueuing: '{{count}} album(s) in wachtrij voor offline…', + offlineFailed: 'Toevoegen van {{name}} offline mislukt', +}; diff --git a/src/locales/nl/artistDetail.ts b/src/locales/nl/artistDetail.ts new file mode 100644 index 00000000..5b8e3922 --- /dev/null +++ b/src/locales/nl/artistDetail.ts @@ -0,0 +1,41 @@ +export const artistDetail = { + back: 'Terug', + albums: 'Albums', + album: 'Album', + playAll: 'Alles afspelen', + shareArtist: 'Artiest delen', + shuffle: 'Willekeurig', + radio: 'Radio', + loading: 'Laden…', + noRadio: 'Geen vergelijkbare nummers gevonden voor deze artiest.', + notFound: 'Artiest niet gevonden.', + albumsBy: 'Albums van {{name}}', + topTracks: 'Populaire nummers', + noAlbums: 'Geen albums gevonden.', + trackTitle: 'Titel', + trackAlbum: 'Album', + trackDuration: 'Duur', + favoriteAdd: 'Aan favorieten toevoegen', + favoriteRemove: 'Uit favorieten verwijderen', + favorite: 'Favoriet', + albumCount_one: '{{count}} album', + albumCount_other: '{{count}} albums', + openedInBrowser: 'Geopend in browser', + featuredOn: 'Ook te vinden op', + similarArtists: 'Vergelijkbare artiesten', + cacheOffline: 'Discografie offline opslaan', + offlineCached: 'Discografie gecached', + offlineDownloading: 'Cachen… ({{done}}/{{total}} albums)', + uploadImage: 'Artiestafbeelding uploaden', + uploadImageError: 'Uploaden van afbeelding mislukt', + releaseTypes: { + album: 'Album', + ep: 'EP', + single: 'Single', + compilation: 'Compilatie', + live: 'Live', + soundtrack: 'Soundtrack', + remix: 'Remix', + other: 'Overig', + }, +}; diff --git a/src/locales/nl/artists.ts b/src/locales/nl/artists.ts new file mode 100644 index 00000000..c380ceae --- /dev/null +++ b/src/locales/nl/artists.ts @@ -0,0 +1,18 @@ +export const artists = { + title: 'Artiesten', + search: 'Zoeken…', + all: 'Alle', + gridView: 'Rasterweergave', + listView: 'Lijstweergave', + imagesOn: 'Artiestafbeeldingen aan — kan netwerk- en systeembelasting verhogen', + imagesOff: 'Artiestafbeeldingen uit — toont alleen initialen', + loadMore: 'Meer laden', + notFound: 'Geen artiesten gevonden.', + albumCount_one: '{{count}} album', + albumCount_other: '{{count}} albums', + selectionCount: '{{count}} geselecteerd', + select: 'Meervoudige selectie', + startSelect: 'Meervoudige selectie inschakelen', + cancelSelect: 'Annuleren', + addToPlaylist: 'Toevoegen aan playlist', +}; diff --git a/src/locales/nl/changelog.ts b/src/locales/nl/changelog.ts new file mode 100644 index 00000000..2a97cfb7 --- /dev/null +++ b/src/locales/nl/changelog.ts @@ -0,0 +1,5 @@ +export const changelog = { + modalTitle: 'Wat is nieuw', + dontShowAgain: 'Niet meer weergeven', + close: 'Begrepen', +}; diff --git a/src/locales/nl/common.ts b/src/locales/nl/common.ts new file mode 100644 index 00000000..9c9c3c6b --- /dev/null +++ b/src/locales/nl/common.ts @@ -0,0 +1,56 @@ +export const common = { + albums: 'Albums', + album: 'Album', + loading: 'Laden…', + loadingMore: 'Laden…', + loadingPlaylists: 'Afspeellijsten laden…', + noAlbums: 'Geen albums gevonden.', + downloading: 'Downloaden…', + downloadZip: 'Downloaden (ZIP)', + back: 'Terug', + cancel: 'Annuleren', + save: 'Opslaan', + delete: 'Verwijderen', + use: 'Gebruiken', + add: 'Toevoegen', + new: 'Nieuw', + active: 'Actief', + download: 'Downloaden', + chooseDownloadFolder: 'Downloadmap kiezen', + noFolderSelected: 'Geen map geselecteerd', + rememberDownloadFolder: 'Deze map onthouden', + filterGenre: 'Genre-filter', + filterSearchGenres: 'Genres zoeken…', + filterNoGenres: 'Geen genres gevonden', + filterClear: 'Wissen', + favorites: 'Favorieten', + favoritesTooltipOff: 'Alleen favorieten tonen', + favoritesTooltipOn: 'Alles tonen', + play: 'Afspelen', + bulkSelected: '{{count}} geselecteerd', + clearSelection: 'Selectie wissen', + bulkAddToPlaylist: 'Toevoegen aan afspeellijst', + bulkRemoveFromPlaylist: 'Verwijderen uit afspeellijst', + bulkClear: 'Selectie wissen', + updaterAvailable: 'Update beschikbaar', + updaterVersion: 'v{{version}} beschikbaar', + updaterWebsite: 'Website', + updaterModalTitle: 'Nieuwe versie beschikbaar', + updaterChangelog: 'Wat is er nieuw', + updaterDownloadBtn: 'Nu downloaden', + updaterSkipBtn: 'Deze versie overslaan', + updaterRemindBtn: 'Later herinneren', + updaterDone: 'Download voltooid', + updaterShowFolder: 'Tonen in map', + updaterInstallHint: 'Sluit Psysonic en voer het installatieprogramma handmatig uit.', + updaterAurHint: 'Update installeren via AUR:', + updaterErrorMsg: 'Downloaden mislukt', + updaterRetryBtn: 'Opnieuw proberen', + durationHoursMinutes: '{{hours}} u {{minutes}} min', + durationMinutesOnly: '{{minutes}} min', + updaterOpenGitHub: 'Openen op GitHub', + filters: 'Filters', + more: 'meer', + yearRange: 'Jaarbereik', + clearAll: 'Alles wissen', +}; diff --git a/src/locales/nl/composerDetail.ts b/src/locales/nl/composerDetail.ts new file mode 100644 index 00000000..5105f10d --- /dev/null +++ b/src/locales/nl/composerDetail.ts @@ -0,0 +1,11 @@ +export const composerDetail = { + back: 'Terug', + notFound: 'Componist niet gevonden.', + about: 'Over deze componist', + works: 'Werken', + noWorks: 'Geen werken gevonden.', + workCount_one: '{{count}} werk', + workCount_other: '{{count}} werken', + shareComposer: 'Componist delen', + unknownComposer: 'Componist', +}; diff --git a/src/locales/nl/composers.ts b/src/locales/nl/composers.ts new file mode 100644 index 00000000..96de19fb --- /dev/null +++ b/src/locales/nl/composers.ts @@ -0,0 +1,10 @@ +export const composers = { + title: 'Componisten', + search: 'Zoeken…', + notFound: 'Geen componisten gevonden.', + unsupported: 'Bladeren op componist vereist Navidrome 0.55 of nieuwer.', + loadFailed: 'Kan componisten niet laden.', + retry: 'Opnieuw proberen', + involvedIn_one: 'Betrokken bij {{count}} album', + involvedIn_other: 'Betrokken bij {{count}} albums', +}; diff --git a/src/locales/nl/connection.ts b/src/locales/nl/connection.ts new file mode 100644 index 00000000..0b7737b0 --- /dev/null +++ b/src/locales/nl/connection.ts @@ -0,0 +1,28 @@ +export const connection = { + connected: 'Verbonden', + connectedTo: 'Verbonden met {{server}}', + disconnected: 'Verbroken', + disconnectedFrom: 'Kan {{server}} niet bereiken — klik om instellingen te controleren', + checking: 'Verbinden…', + extern: 'Extern', + offlineTitle: 'Geen serververbinding', + offlineSubtitle: 'Kan {{server}} niet bereiken. Controleer je netwerk of server.', + offlineModeBanner: 'Offline modus — afspelen vanuit lokale cache', + offlineNoCacheBanner: 'Geen serververbinding — {{server}} niet bereikbaar', + offlineLibraryTitle: 'Offline bibliotheek', + offlineLibraryEmpty: 'Nog geen albums gecached. Ga online, open een album en klik op "Offline beschikbaar maken".', + offlineAlbumCount: '{{n}} album', + offlineAlbumCount_plural: '{{n}} albums', + offlineFilterAll: 'Alles', + offlineFilterAlbums: 'Albums', + offlineFilterPlaylists: 'Afspeellijsten', + offlineFilterArtists: 'Discografieën', + retry: 'Opnieuw proberen', + serverSettings: 'Serverinstellingen', + switchServerTitle: 'Server wisselen', + switchServerHint: 'Klik om een andere opgeslagen server te kiezen.', + manageServers: 'Servers beheren…', + switchFailed: 'Wisselen mislukt — server niet bereikbaar.', + lastfmConnected: 'Last.fm verbonden als @{{user}}', + lastfmSessionInvalid: 'Sessie ongeldig — klik om opnieuw te verbinden', +}; diff --git a/src/locales/nl/contextMenu.ts b/src/locales/nl/contextMenu.ts new file mode 100644 index 00000000..87b678ee --- /dev/null +++ b/src/locales/nl/contextMenu.ts @@ -0,0 +1,32 @@ +export const contextMenu = { + playNow: 'Nu afspelen', + playNext: 'Volgende afspelen', + addToQueue: 'Aan wachtrij toevoegen', + enqueueAlbum: 'Album in wachtrij', + enqueueAlbums_one: '{{count}} album in wachtrij', + enqueueAlbums_other: '{{count}} albums in wachtrij', + startRadio: 'Radio starten', + instantMix: 'Instant Mix', + instantMixFailed: 'Instant Mix mislukt — server- of pluginfout.', + cliMixNeedsTrack: 'Er speelt niets — start eerst afspelen en voer het mix-commando opnieuw uit.', + lfmLove: 'Liken op Last.fm', + lfmUnlove: 'Niet meer liken op Last.fm', + favorite: 'Favoriet', + favoriteArtist: 'Favoriete artiest', + favoriteAlbum: 'Favoriet album', + unfavorite: 'Verwijderen uit favorieten', + unfavoriteArtist: 'Artiest uit favorieten verwijderen', + unfavoriteAlbum: 'Album uit favorieten verwijderen', + removeFromQueue: 'Uit wachtrij verwijderen', + openAlbum: 'Album openen', + goToArtist: 'Naar artiest', + download: 'Downloaden (ZIP)', + addToPlaylist: 'Toevoegen aan playlist', + selectedPlaylists: '{{count}} playlists geselecteerd', + selectedAlbums: '{{count}} albums geselecteerd', + selectedArtists: '{{count}} artiesten geselecteerd', + songInfo: 'Nummerinfo', + shareLink: 'Deellink kopiëren', + shareCopied: 'Deellink gekopieerd naar het klembord.', + shareCopyFailed: 'Kopiëren naar het klembord is mislukt.', +}; diff --git a/src/locales/nl/deviceSync.ts b/src/locales/nl/deviceSync.ts new file mode 100644 index 00000000..d53fbe26 --- /dev/null +++ b/src/locales/nl/deviceSync.ts @@ -0,0 +1,73 @@ +export const deviceSync = { + title: 'Apparaatsync', + targetFolder: 'Doelmap', + noFolderChosen: 'Geen map gekozen', + selectDrive: 'Selecteer een schijf…', + refreshDrives: 'Schijven vernieuwen', + noDrivesDetected: 'Geen verwijderbare schijven gedetecteerd', + browseManual: 'Handmatig bladeren…', + free: 'vrij', + notMountedVolume: 'Het doel bevindt zich niet op een gekoppeld volume. De schijf is mogelijk losgekoppeld.', + chooseFolder: 'Kiezen…', + filenameTemplate: 'Bestandsnaamsjabloon', + targetDevice: 'Doelapparaat', + templateHint: 'Variabelen: {artist}, {album}, {title}, {track_number}, {disc_number}, {year}', + cleanupButton: 'Niet-geselecteerde bestanden verwijderen', + cleanupNothingToDelete: 'Niets te verwijderen — apparaat is al gesynchroniseerd.', + confirmCleanup: '{{count}} bestand(en) verwijderen van het apparaat die niet in de huidige selectie staan. Doorgaan?', + cleanupComplete: '{{count}} bestand(en) van het apparaat verwijderd.', + selectedSources: 'Geselecteerde bronnen', + noSourcesSelected: 'Geen bronnen geselecteerd. Klik op items in de browser om ze toe te voegen.', + clearAll: 'Alles wissen', + tabPlaylists: 'Afspeellijsten', + tabAlbums: 'Albums', + tabArtists: 'Artiesten', + searchPlaceholder: 'Zoeken…', + syncButton: 'Synchroniseren naar apparaat', + actionTransfer: 'Overdragen naar apparaat', + actionDelete: 'Verwijderen van apparaat', + actionApplyAll: 'Alle wijzigingen toepassen', + templatePreview: 'Voorbeeld', + templatePresetStandard: 'Standaard', + templatePresetMultiDisc: 'Multi-Disc', + templatePresetAltFolder: 'Alt. map', + tokenSlashHint: '/ = mapscheidingsteken', + cancel: 'Annuleren', + noTargetDir: 'Kies eerst een doelmap.', + noSources: 'Selecteer minimaal één bron.', + noTracks: 'Geen nummers gevonden in de geselecteerde bronnen.', + fetchError: 'Ophalen van nummers van de server mislukt.', + syncComplete: 'Synchronisatie voltooid.', + dismiss: 'Sluiten', + cancelSync: 'Annuleren', + syncCancelled: 'Synchronisatie geannuleerd ({{done}} / {{total}} overgebracht).', + colName: 'Naam', + colType: 'Type', + colStatus: 'Status', + onDevice: 'Apparaatbeheer', + addSources: 'Toevoegen…', + syncResult: '{{done}} overgedragen, {{skipped}} al up-to-date ({{total}} totaal)', + deleteFromDevice: 'Markeren voor verwijdering ({{count}})', + confirmDelete: '{{count}} item(s) van het apparaat verwijderen: {{names}}?', + deleteComplete: '{{count}} item(s) van het apparaat verwijderd.', + manifestImported: '{{count}} bron(nen) geïmporteerd uit apparaatmanifest.', + statusSynced: 'Gesynchroniseerd', + statusPending: 'In behandeling', + statusDeletion: 'Verwijdering', + markForDeletion: 'Markeren voor verwijdering', + removeSource: 'Verwijderen', + undoDeletion: 'Verwijdering ongedaan maken', + syncInBackground: 'Sync gestart op achtergrond — u kunt navigeren.', + syncInProgress: '{{done}} / {{total}} nummers…', + syncSummary: 'Synchronisatieoverzicht', + calculating: 'Vereiste payload berekenen…', + filesToAdd: 'Te toevoegen bestanden:', + filesToDelete: 'Te verwijderen bestanden:', + netChange: 'Nettoverandering:', + availableSpace: 'Beschikbare schijfruimte:', + spaceWarning: 'Waarschuwing: Het doelapparaat heeft niet genoeg gerapporteerde ruimte.', + proceed: 'Doorgaan met synchronisatie', + notEnoughSpace: 'Onvoldoende fysieke schijfruimte gedetecteerd!', + liveSearch: 'Live', + randomAlbumsLabel: 'Willekeurige albums', +}; diff --git a/src/locales/nl/entityRating.ts b/src/locales/nl/entityRating.ts new file mode 100644 index 00000000..db771802 --- /dev/null +++ b/src/locales/nl/entityRating.ts @@ -0,0 +1,9 @@ +export const entityRating = { + albumShort: 'Albumbeoordeling', + artistShort: 'Artiestbeoordeling', + albumAriaLabel: 'Albumbeoordeling', + artistAriaLabel: 'Artiestbeoordeling', + selectedArtistsRatingAriaLabel: 'Sterrenbeoordeling voor {{count}} geselecteerde artiesten', + selectedAlbumsRatingAriaLabel: 'Sterrenbeoordeling voor {{count}} geselecteerde albums', + saveFailed: 'Beoordeling opslaan mislukt.', +}; diff --git a/src/locales/nl/favorites.ts b/src/locales/nl/favorites.ts new file mode 100644 index 00000000..a728046d --- /dev/null +++ b/src/locales/nl/favorites.ts @@ -0,0 +1,19 @@ +export const favorites = { + title: 'Favorieten', + empty: 'Je hebt nog geen favorieten opgeslagen.', + artists: 'Artiesten', + albums: 'Albums', + songs: 'Nummers', + enqueueAll: 'Alles aan wachtrij toevoegen', + playAll: 'Alles afspelen', + removeSong: 'Verwijderen uit favorieten', + stations: 'Radiostations', + showingFiltered: 'Toont {{filtered}} van {{total}} ({{artist}})', + showingCount: 'Toont {{filtered}} van {{total}}', + clearArtistFilter: 'Artiestfilter wissen', + noFilterResults: 'Geen resultaten met de geselecteerde filters.', + allArtists: 'Alle artiesten', + topArtists: 'Top-artiesten op favorieten', + topArtistsSongCount_one: '{{count}} nummer', + topArtistsSongCount_other: '{{count}} nummers', +}; diff --git a/src/locales/nl/folderBrowser.ts b/src/locales/nl/folderBrowser.ts new file mode 100644 index 00000000..1ee00008 --- /dev/null +++ b/src/locales/nl/folderBrowser.ts @@ -0,0 +1,4 @@ +export const folderBrowser = { + empty: 'Lege map', + error: 'Laden mislukt', +}; diff --git a/src/locales/nl/genres.ts b/src/locales/nl/genres.ts new file mode 100644 index 00000000..722f4747 --- /dev/null +++ b/src/locales/nl/genres.ts @@ -0,0 +1,12 @@ +export const genres = { + title: 'Genres', + genreCount: 'genres', + albumCount_one: '{{count}} album', + albumCount_other: '{{count}} albums', + loading: 'Genres laden…', + empty: 'Geen genres gevonden.', + albumsLoading: 'Albums laden…', + albumsEmpty: 'Geen albums gevonden voor dit genre.', + loadMore: 'Meer laden', + back: 'Terug', +}; diff --git a/src/locales/nl/help.ts b/src/locales/nl/help.ts new file mode 100644 index 00000000..e5f0de6f --- /dev/null +++ b/src/locales/nl/help.ts @@ -0,0 +1,105 @@ +export const help = { + title: 'Help', + searchPlaceholder: 'Help doorzoeken…', + noResults: 'Geen overeenkomende onderwerpen. Probeer een andere zoekterm.', + s1: 'Aan de slag', + q1: 'Welke servers zijn compatibel?', + a1: 'Psysonic is in de eerste plaats voor Navidrome gebouwd en volledig Subsonic-compatibel — Gonic, Airsonic, LMS en andere Subsonic-API-servers werken ook. Sommige geavanceerde functies (beoordelingen, smart playlists, Magic-String-delen, gebruikersbeheer) vereisen Navidrome.', + q2: 'Hoe voeg ik een server toe?', + a2: 'Instellingen → Servers → Server toevoegen. Voer de URL in (bijv. http://192.168.1.100:4533), gebruikersnaam en wachtwoord. Psysonic test de verbinding voor het opslaan — bij een fout wordt niets opgeslagen. U kunt zoveel servers toevoegen als u wilt en in de header tussen ze schakelen; er is altijd maar één actief.', + q3: 'Snelle UI-rondleiding?', + a3: 'Zijbalk (links) voor navigatie, Mainstage / pagina\'s in het midden, speelbalk onderaan, wachtrijpaneel rechts (te openen via het pictogram rechtsboven naast de Now-Playing-indicator). De zoekbalk bovenaan doorzoekt de hele bibliotheek; "Now Playing" toont wat andere gebruikers op dezelfde Navidrome-server momenteel luisteren.', + s2: 'Afspelen & Wachtrij', + q4: 'Hoe gebruik ik de wachtrij?', + a4: 'Open het wachtrijpaneel via de header rechtsboven. Sleep rijen om te herordenen, sleep ze naar buiten om te verwijderen, of gebruik de werkbalk om te shuffelen, de wachtrij als afspeellijst op te slaan of naar een nummer te springen. Sleep rijen uit het paneel om ze elders als overdracht te plaatsen.', + q5: 'Gapless versus Crossfade — wat is het verschil?', + a5: 'Gapless buffert het volgende nummer vooraf zodat er nul stilte tussen de nummers zit (ideaal voor live-albums en DJ-mixen). Crossfade vervaagt het huidige nummer terwijl het volgende invaagt over 1–10 s (ideaal voor gemixte mixen). Ze zijn wederzijds uitsluitend — een inschakelen schakelt de andere uit. Configureer in Instellingen → Audio.', + q6: 'Wat is de Infinite Queue?', + a6: 'Wanneer de wachtrij leegloopt en Herhalen uit staat, voegt Psysonic stilletjes vergelijkbare/willekeurige nummers uit uw bibliotheek toe zodat het afspelen nooit stopt. Auto-toegevoegde nummers verschijnen onder een "— Automatisch toegevoegd —" scheidingslijn. Schakelen via het oneindigheidspictogram in de wachtrij-header; in Instellingen → Wachtrij beperken tot een genre.', + q7: 'Meervoudige selectie en Shift-klik bereik?', + a7: 'Activeer "Selecteren" op Albums / Nieuwe releases / Random Albums / Afspeellijsten. Klik een item om het te toggelen, houd dan Shift en klik een ander item — alles ertussen in de zichtbare volgorde wordt geselecteerd. Shift-klikken breiden uit vanuit het laatst aangeklikte ankerpunt. De werkbalk biedt bulkacties (wachtrij, downloaden, verwijderen, etc.).', + q8: 'Sneltoetsen en globale hotkeys?', + a8: 'Standaard in-app-toetsen: Spatie = Afspelen / Pauzeren, Esc = sluit volledig scherm / modals, F1 = sneltoetsenoverzicht. Instellingen → Invoer laat u elke in-app-actie opnieuw toewijzen (ook akkoorden zoals Ctrl+Shift+P) en systeembrede globale snelkoppelingen instellen die ook werken wanneer Psysonic op de achtergrond draait. Mediatoetsen (Afspelen/Pauzeren, Volgende, Vorige) werken op alle platforms.', + s3: 'Audiotools', + q9: 'Replay Gain modi?', + a9: 'Instellingen → Audio → Replay Gain. Track-modus normaliseert elk nummer naar een doelniveau. Album-modus behoudt de luidheidscurve binnen een album. Auto-modus kiest Track of Album op basis van of de wachtrij van een enkel album komt. Nummers zonder Replay Gain-tags vallen terug op een configureerbare voorversterker.', + q10: 'Wat is Smart Loudness Normalization (LUFS)?', + a10: 'Een modern alternatief voor Replay Gain in Instellingen → Audio. Psysonic analyseert elk nummer naar LUFS / EBU R128 en slaat het resultaat op, zodat het volume consistent is over uw hele bibliotheek — ook nummers zonder Replay Gain-tags. Cold-cache-analyse loopt op de achtergrond en gebruikt 35–40% CPU gedurende ~1 minuut, daarna 0. Stel uw doel-luidheid (standaard −10 LUFS) één keer in.', + q11: 'EQ en AutoEQ?', + a11: 'Een 10-bands parametrische EQ in Instellingen → Audio → Equalizer met handmatige banden en presets. AutoEQ ernaast haalt een gemeten correctieprofiel voor uw hoofdtelefoonmodel op uit de AutoEQ-database en past het automatisch toe op de banden — kies uw hoofdtelefoon, de EQ klikt op de juiste curve.', + q12: 'Hoe wissel ik het audio-uitvoerapparaat?', + a12: 'Instellingen → Audio → Uitvoerapparaat. Psysonic toont alle beschikbare uitgangen en wisselt onmiddellijk wanneer u kiest. De vernieuwen-knop scant naar apparaten die na het opstarten zijn aangesloten. Linux ALSA-namen zoals "sysdefault" worden voor leesbaarheid automatisch opgeschoond.', + q13: 'Wat is de Hot Cache?', + a13: 'Hot Cache laadt het huidige nummer plus de volgende vooraf in RAM en op schijf zodat het afspelen zonder buffervertraging start — vooral nuttig op trage / externe servers. Eviction treedt in werking wanneer de groottelimiet wordt bereikt. Configureer grootte en de debounce-vertraging (zodat snelle skips niet over-fetchen) in Instellingen → Audio.', + s4: 'Bibliotheek & Ontdekking', + q14: 'Hoe werken beoordelingen en Skip-to-1★?', + a14: 'Psysonic ondersteunt 1–5 sterren-beoordelingen via OpenSubsonic (Navidrome ≥ 0.53). Beoordeel nummers in tracklijsten, in het rechtsklikmenu, of in de speelbalk onder de artiestnaam; albums op de albumpagina; artiesten op de artiestpagina. Skip-to-1★ (Instellingen → Bibliotheek → Beoordelingen) wijst automatisch 1 ster toe na een configureerbaar aantal opeenvolgende skips. Hetzelfde paneel laat u een minimum-beoordeling instellen voor gegenereerde mixen.', + q15: 'Hoe blader ik — Mappen, Genres, Tracks?', + a15: 'De mappenbrowser (zijbalk) loopt door de muziekmap van uw server in een Miller-kolomlay-out — klik op een map om in te duiken, klik op een nummer of het play-pictogram van een map om af te spelen / toe te voegen. Genres gebruikt een tag-cloud-weergave geschaald op aantal nummers; klik op een genre om het te openen. Tracks is een platte bibliotheekhub met kolomgesorteerde virtuele lijst en live zoeken.', + q16: 'Zoeken en geavanceerd zoeken?', + a16: 'De headerzoekbalk voert een snelle live zoekopdracht uit terwijl u typt over artiesten, albums en nummers. Open Geavanceerd zoeken (zijbalk) voor een rijkere weergave: filter op jaar, genre, beoordeling, formaat, kanalen, samplerate, BPM, stemming en combineer criteria. Rechtsklik op elk resultaat opent hetzelfde contextmenu als elders.', + q17: 'Wat zijn de Mixes (Random / Genre / Super Genre / Lucky)?', + a17: 'Random Mix bouwt een afspeellijst van willekeurige nummers uit uw bibliotheek; het Trefwoordfilter sluit audioboeken, comedy etc. uit op basis van genre / titel / album-substrings. Super Genre Mix groepeert uw bibliotheek in brede stijlen (Rock, Metal, Electronic, Jazz, Klassiek …) en bouwt een gefocuste mix uit één. Lucky Mix gebruikt uw luistergeschiedenis, beoordelingen en AudioMuse-AI vergelijkbare nummers om met één klik een directe afspeellijst samen te stellen.', + q18: 'Statistiekenpagina?', + a18: 'Statistieken (zijbalk) toont topartiesten, topalbums, topnummers, genre-uitsplitsing, luistertijd over tijd en per-bibliotheek-bereik wanneer u meer dan één muziekmap hebt geconfigureerd. Verschillende weergaven zijn exporteerbaar als deelbare kaartafbeelding.', + q19: 'Hoe download ik een album als ZIP?', + a19: 'Albumpagina → "Downloaden (ZIP)". De server comprimeert het album eerst — voor grote of verliesloze albums (FLAC / WAV) verschijnt de voortgangsbalk pas zodra het zippen is voltooid en de overdracht begint. Dit is normaal.', + s5: 'Songteksten', + q20: 'Waar komen de songteksten vandaan?', + a20: 'Drie bronnen, configureerbaar in Instellingen → Songteksten: uw Navidrome-server (ingebedde / OpenSubsonic-songteksten), LRCLIB (community-bijgedragen gesynchroniseerde songteksten) en NetEase Cloud Music (grote Aziatische + internationale catalogus). Elke bron kan worden in-/uitgeschakeld en op volgorde gesleept.', + q21: 'Hoe bekijk ik songteksten tijdens het afspelen?', + a21: 'Klik op het microfoonpictogram in de speelbalk om het Songteksten-tabblad in het wachtrijpaneel te openen. Gesynchroniseerde songteksten scrollen automatisch en ondersteunen klik-om-te-spoelen; pure tekst scrolt als een statisch blok. Schakel de volledig-scherm-speler in via de speelbalk-cover voor een meeslepende songteksten-weergave met mesh-blob-achtergrond.', + s6: 'Delen & Sociaal', + q22: 'Wat zijn Magic Strings?', + a22: 'Magic Strings zijn korte kopieer-plak-tokens die dingen tussen Psysonic-gebruikers delen zonder enige derde server. Server-Invite-strings laten een vriend met één plak op uw Navidrome onboarden; Album / Artiest / Wachtrij Magic Strings openen hetzelfde album / artiest / wachtrij bij de ontvanger. Genereer ze via het deel-menu, plak ze in de zoekbalk om te consumeren.', + q23: 'Wat is Orbit?', + a23: 'Orbit is gesynchroniseerd samen-luisteren: een host speelt een nummer, elke gast hoort het synchroon, en gasten kunnen nummers voorstellen die de host kan accepteren in de wachtrij. Start een sessie via de Orbit-knop in de header, deel de uitnodigingslink, en anderen kunnen vanuit elke Psysonic-installatie meedoen. De host beheert het afspelen (skippen, spoelen, wachtrij) — gasten krijgen een real-time weergave en een suggestiebox. Sessies zijn kortstondig en eindigen wanneer de host ze sluit.', + q24: 'Wat is de Now Playing-dropdown?', + a24: 'Het uitzendpictogram rechtsboven toont wat andere gebruikers op uw Navidrome-server momenteel luisteren, ververst elke 10 seconden. Uw eigen vermelding verdwijnt op het moment dat u pauzeert. Per-server, dus gebruikers op een andere actieve server worden niet getoond.', + s7: 'Personalisatie', + q25: 'Thema\'s en de Theme Scheduler?', + a25: 'Instellingen → Weergave → Thema kiest uit 60+ thema\'s in 8 groepen (Psysonic, Mediaplayer, Besturingssystemen, Spellen, Films, Series, Sociale media, Open Source Classics — Catppuccin / Nord / Gruvbox / Nightfox / Dracula). Auto-Switch Theme laat u een dag-thema + nacht-thema instellen met starttijden zodat Psysonic automatisch wisselt.', + q26: 'Kan ik de Zijbalk, Home en Artiestpagina aanpassen?', + a26: 'Ja — Instellingen → Personalisatie. De zijbalk-customizer laat u nav-items in de gewenste volgorde slepen en items die u niet gebruikt verbergen. De Home-customizer schakelt elke Mainstage-rail (Hero, Recent, Ontdekken, Recent afgespeeld, Met ster …) in/uit. De Artiestpagina-customizer herschikt de secties (Topnummers, Albums, Singles, Compilaties, Vergelijkbare artiesten, etc.) en laat u die u nooit bekijkt verbergen.', + q27: 'Wat is de Mini Player?', + a27: 'Een klein zwevend venster met cover, transportbedieningen en een compacte wachtrij. Open het via het mini-player-pictogram in de speelbalk of met zijn toetsenbordsneltoets. Het venster onthoudt zijn positie en grootte tussen sessies. Op Windows wordt de mini-webview bij het opstarten vooraf aangemaakt zodat openen direct is; Linux / macOS schakelen optioneel in via Instellingen → Weergave → Mini player vooraf laden.', + q28: 'Wat is de Floating Player Bar?', + a28: 'Een optionele speelbalk-stijl (Instellingen → Weergave) die loskomt van de onderste rand met een themed achtergrond, accentrand, afgeronde albumhoes en een gecentreerde volumesectie. Handig op hoge monitoren of compacte thema\'s.', + q29: 'Track preview op hover?', + a29: 'Hover over een tracknummer-rij, klik op de kleine voorbeeldknop op de cover, of activeer het voorbeeld vanuit het rechtsklikmenu — Psysonic streamt de eerste ~15 s door dezelfde Rust-audio-engine zodat luidheidsnormalisatie van toepassing is. Handig om door een album te bladeren dat u nog niet gehoord hebt.', + q30: 'Sleep timer?', + a30: 'Klik op het maan-pictogram in de speelbalk om de sleep timer te openen. Kies een duur (of "einde van het huidige nummer") en Psysonic vervaagt en pauzeert aan het einde. De knop toont een ronde ring en een ingebouwde aftelling terwijl de timer loopt.', + q31: 'UI-schaal, lettertype, seekbar-stijl?', + a31: 'Instellingen → Weergave — Interface-schaal (80–125% zonder de systeemlettergrootte te beïnvloeden), Lettertype (10 UI-fonts waaronder IBM Plex Mono, Fira Code, Geist, Golos Text…), Seekbar-stijl (Waveform geanalyseerd / pseudowave deterministisch / Lijn & Punt / Balk / Dikke balk / Gesegmenteerd / Neonlicht / Pulsgolf / Deeltjespoor / Vloeibare vulling / Retro Tape).', + s8: 'Power User', + q32: 'CLI player-bediening?', + a32: 'De Psysonic-binary doet ook dienst als afstandsbediening. Voorbeelden: psysonic --player play / pause / next / prev, --player volume 75, --player seek 15, --player shuffle, --player repeat off|all|one, --player rating 1-5. Wissel servers, audio-apparaten, bibliotheken; trigger Instant Mix; zoek artiesten / albums / nummers. Volledige lijst met psysonic --player --help. Shell-aanvulling voor bash en zsh via psysonic completions.', + q33: 'Smart Playlists (Navidrome)?', + a33: 'Smart Playlists zijn server-side dynamische afspeellijsten gedefinieerd door regels (genre = Rock EN jaar > 2020, etc.). De Afspeellijsten-pagina in Psysonic laat u ze maken, bewerken en verwijderen met een visuele regeleditor — Psysonic gebruikt daarvoor de Navidrome native API. Ze gedragen zich als normale afspeellijsten in de rest van de app en updaten automatisch wanneer uw bibliotheek verandert.', + q34: 'Instellingen back-uppen en herstellen?', + a34: 'Instellingen → Opslag → Back-up & Herstel exporteert serverprofielen, thema\'s, sneltoetsen en andere instellingen naar een enkel JSON-bestand. Importeer het op een andere machine of na een herinstallatie om alles in één keer te herstellen. Server-wachtwoorden zijn inbegrepen — bewaar het bestand privé.', + q35: 'Waar zie ik alle open-source-licenties?', + a35: 'Instellingen → Systeem → Open Source Licenties. De volledige afhankelijkheidslijst (cargo crates en npm-pakketten) wordt met gebundelde licentieteksten meegeleverd. Klik op een item voor de volledige tekst; het hoogtepuntblok bovenaan benadrukt de gebruikersbekende bibliotheken (Tauri, React, rodio, symphonia, etc.).', + s9: 'Offline & Sync', + q36: 'Offline modus — albums en afspeellijsten cachen?', + a36: 'Open een album of afspeellijst en klik op het downloadpictogram in de header — Psysonic cacht elk nummer lokaal zodat het van schijf afspeelt zonder netwerkoproep. De Offline Bibliotheek-pagina (zijbalk) toont alles wat is gecached, toont voortgang van lopende downloads, en laat u items verwijderen met het prullenbak-pictogram (dat verschijnt zodra een download is voltooid).', + q37: 'Offline opslaglimiet?', + a37: 'Instellingen → Bibliotheek → Offline laat u een maximale cachegrootte instellen. Wanneer de limiet wordt bereikt, toont de albumpagina-downloadknop een waarschuwingsbanner. Maak ruimte vrij door albums of afspeellijsten te verwijderen vanuit de Offline Bibliotheek-pagina.', + q38: 'Device Sync — muziek naar USB / SD?', + a38: 'Device Sync (zijbalk) kopieert albums, afspeellijsten of hele artiesten naar een externe schijf voor offline luisteren op andere apparaten. Kies een doelmap, kies bronnen uit de browsertabbladen, klik "Naar apparaat overzetten". Psysonic schrijft een manifest (psysonic-sync.json) zodat het weet welke bestanden er al zijn, ook als u Device Sync op een ander OS opent met een ander bestandsnaamsjabloon. Sjablonen ondersteunen {artist} / {album} / {title} / {track_number} / {disc_number} / {year}-tokens met / als mapscheidingsteken.', + s10: 'Integraties & Probleemoplossing', + q39: 'Last.fm scrobbling?', + a39: 'Instellingen → Integraties → Last.fm. Verbind uw account één keer en Psysonic scrobbled direct naar Last.fm — geen Navidrome-configuratie nodig. Een scrobble wordt verzonden nadat u 50% van een nummer heeft beluisterd. Now-playing pings worden bij het begin verzonden.', + q40: 'Discord Rich Presence?', + a40: 'Instellingen → Integraties → Discord toont uw huidige nummer op uw Discord-profiel. Kies tussen het app-pictogram, de hoezen van uw server (via getAlbumInfo2 — vereist een publiek bereikbare server) of Apple Music-hoezen. Pas de weergavestrings (details, status, tooltip) aan met token-templates.', + q41: 'Bandsintown tour data?', + a41: 'Opt-in onder Instellingen → Integraties → Now-Playing Info. Het Now Playing-tabblad op de Now Playing-pagina toont dan komende tour data voor de spelende artiest via de Bandsintown widget API. Standaard uit — er worden geen verzoeken gedaan totdat u inschakelt.', + q42: 'Internet Radio — live-streams afspelen?', + a42: 'Internet Radio (zijbalk) speelt elke live-stream die op uw Navidrome-server is opgeslagen (voeg stations toe via de Navidrome admin UI). Het afspelen loopt door de browser HTML5-audio-engine — de meeste EQ / Replay Gain / Loudness-instellingen zijn niet van toepassing op radio, maar ICY-metadata (huidige songnaam) wordt wel weergegeven. Ondersteunt MP3, AAC, OGG Vorbis en de meeste HLS-streams; codec-ondersteuning hangt af van het platform.', + q43: 'De verbindingstest mislukt — wat nu?', + a43: 'Controleer de URL inclusief poort dubbel (bijv. http://192.168.1.100:4533). Op een lokaal netwerk werkt http:// vaak waar https:// niet werkt (geen certificaat). Zorg ervoor dat geen firewall de poort blokkeert en dat de gebruikersnaam en wachtwoord correct zijn. Als uw server achter een reverse proxy zit, probeer dan eerst de directe URL om de oorzaak te isoleren.', + q44: 'Hoezen en artiestafbeeldingen laden traag.', + a44: 'Afbeeldingen worden bij de eerste weergave van uw server gehaald en vervolgens 30 dagen lokaal gecached. Als de opslag van uw server traag is, kan het eerste bezoek aan een pagina even duren; volgende bezoeken zijn onmiddellijk. De Hot Cache helpt ook voor nummers, maar de afbeeldingscache is onafhankelijk.', + q45: 'Linux-problemen — zwart scherm of geen geluid?', + a45: 'Zwart scherm is meestal een GPU / EGL-stuurprogrammakwestie in WebKitGTK — start met GDK_BACKEND=x11 WEBKIT_DISABLE_COMPOSITING_MODE=1 WEBKIT_DISABLE_DMABUF_RENDERER=1 (de AUR / .deb / .rpm-installers stellen deze automatisch in). Voor audio, zorg ervoor dat PipeWire of PulseAudio draait. Audio-uitval na slaap / wakker worden wordt nu automatisch afgehandeld door de post-sleep recovery hook.', +}; diff --git a/src/locales/nl/hero.ts b/src/locales/nl/hero.ts new file mode 100644 index 00000000..76e49af4 --- /dev/null +++ b/src/locales/nl/hero.ts @@ -0,0 +1,6 @@ +export const hero = { + eyebrow: 'Uitgelicht album', + playAlbum: 'Album afspelen', + enqueue: 'In wachtrij', + enqueueTooltip: 'Volledig album aan wachtrij toevoegen', +}; diff --git a/src/locales/nl/home.ts b/src/locales/nl/home.ts new file mode 100644 index 00000000..a372bb99 --- /dev/null +++ b/src/locales/nl/home.ts @@ -0,0 +1,19 @@ +export const home = { + hero: 'Uitgelicht', + starred: 'Persoonlijke favorieten', + recent: 'Recent toegevoegd', + mostPlayed: 'Meest gespeeld', + recentlyPlayed: 'Recent afgespeeld', + losslessAlbums: 'Lossless-albums', + discover: 'Ontdekken', + discoverSongs: 'Nummers ontdekken', + loadMore: 'Meer laden', + discoverMore: 'Meer ontdekken', + discoverArtists: 'Artiesten ontdekken', + discoverArtistsMore: 'Alle artiesten', + becauseYouLike: 'Omdat je hebt geluisterd…', + becauseYouLikeFor: 'Omdat je naar {{artist}} hebt geluisterd', + similarTo: 'Lijkt op {{artist}}', + becauseYouLikeTracks_one: '{{count}} nummer', + becauseYouLikeTracks_other: '{{count}} nummers' +}; diff --git a/src/locales/nl/index.ts b/src/locales/nl/index.ts new file mode 100644 index 00000000..9c48f817 --- /dev/null +++ b/src/locales/nl/index.ts @@ -0,0 +1,91 @@ +import { sidebar } from './sidebar'; +import { home } from './home'; +import { hero } from './hero'; +import { search } from './search'; +import { nowPlaying } from './nowPlaying'; +import { contextMenu } from './contextMenu'; +import { sharePaste } from './sharePaste'; +import { albumDetail } from './albumDetail'; +import { entityRating } from './entityRating'; +import { artistDetail } from './artistDetail'; +import { favorites } from './favorites'; +import { randomLanding } from './randomLanding'; +import { randomAlbums } from './randomAlbums'; +import { genres } from './genres'; +import { randomMix } from './randomMix'; +import { luckyMix } from './luckyMix'; +import { albums } from './albums'; +import { tracks } from './tracks'; +import { artists } from './artists'; +import { composers } from './composers'; +import { composerDetail } from './composerDetail'; +import { login } from './login'; +import { connection } from './connection'; +import { common } from './common'; +import { settings } from './settings'; +import { changelog } from './changelog'; +import { whatsNew } from './whatsNew'; +import { help } from './help'; +import { queue } from './queue'; +import { miniPlayer } from './miniPlayer'; +import { statistics } from './statistics'; +import { player } from './player'; +import { nowPlayingInfo } from './nowPlayingInfo'; +import { songInfo } from './songInfo'; +import { playlists } from './playlists'; +import { smartPlaylists } from './smartPlaylists'; +import { mostPlayed } from './mostPlayed'; +import { losslessAlbums } from './losslessAlbums'; +import { radio } from './radio'; +import { folderBrowser } from './folderBrowser'; +import { deviceSync } from './deviceSync'; +import { orbit } from './orbit'; +import { tray } from './tray'; +import { licenses } from './licenses'; + +export const nlTranslation = { + sidebar, + home, + hero, + search, + nowPlaying, + contextMenu, + sharePaste, + albumDetail, + entityRating, + artistDetail, + favorites, + randomLanding, + randomAlbums, + genres, + randomMix, + luckyMix, + albums, + tracks, + artists, + composers, + composerDetail, + login, + connection, + common, + settings, + changelog, + whatsNew, + help, + queue, + miniPlayer, + statistics, + player, + nowPlayingInfo, + songInfo, + playlists, + smartPlaylists, + mostPlayed, + losslessAlbums, + radio, + folderBrowser, + deviceSync, + orbit, + tray, + licenses, +}; diff --git a/src/locales/nl/licenses.ts b/src/locales/nl/licenses.ts new file mode 100644 index 00000000..ffe83a5c --- /dev/null +++ b/src/locales/nl/licenses.ts @@ -0,0 +1,13 @@ +export const licenses = { + title: 'Open-source licenties', + intro: 'Psysonic is gebouwd op open-source software. De onderstaande lijst toont elke afhankelijkheid die met de app wordt meegeleverd, met versie, licentie en volledige licentietekst.', + highlights: 'Belangrijke afhankelijkheden', + searchPlaceholder: 'Zoek op naam, versie of licentie…', + noResults: 'Geen resultaten.', + loading: 'Licenties laden…', + loadError: 'Licentiegegevens konden niet worden geladen.', + noLicenseText: 'Geen licentietekst meegeleverd voor deze afhankelijkheid.', + viewSource: 'Bron bekijken', + totalLine: '{{total}} afhankelijkheden — {{cargo}} cargo, {{npm}} npm', + generatedAt: 'Laatst gegenereerd {{date}}', +}; diff --git a/src/locales/nl/login.ts b/src/locales/nl/login.ts new file mode 100644 index 00000000..8a8903a7 --- /dev/null +++ b/src/locales/nl/login.ts @@ -0,0 +1,22 @@ +export const login = { + subtitle: 'Jouw Navidrome-desktopspeler', + serverName: 'Servernaam (optioneel)', + serverNamePlaceholder: 'Mijn Navidrome', + serverUrl: 'Server-URL', + serverUrlPlaceholder: '192.168.1.100:4533 of https://music.voorbeeld.nl', + username: 'Gebruikersnaam', + usernamePlaceholder: 'admin', + password: 'Wachtwoord', + showPassword: 'Wachtwoord tonen', + hidePassword: 'Wachtwoord verbergen', + connect: 'Verbinden', + connecting: 'Verbinden…', + connected: 'Verbonden!', + error: 'Verbinding mislukt — controleer je gegevens.', + urlRequired: 'Voer een server-URL in.', + savedServers: 'Opgeslagen servers', + addNew: 'Of een nieuwe server toevoegen', + orMagicString: 'Of magic string', + magicStringPlaceholder: 'Plak een deelstring (psysonic1-…)', + magicStringInvalid: 'Ongeldige of onleesbare magic string.', +}; diff --git a/src/locales/nl/losslessAlbums.ts b/src/locales/nl/losslessAlbums.ts new file mode 100644 index 00000000..939cf555 --- /dev/null +++ b/src/locales/nl/losslessAlbums.ts @@ -0,0 +1,5 @@ +export const losslessAlbums = { + empty: 'Nog geen lossless-albums in deze bibliotheek.', + unsupported: 'Deze server biedt geen metadata om lossless-albums te vinden.', + slowFetchHint: 'Laadt langzamer dan andere albumpagina\'s — Psysonic doorloopt de volledige songcatalogus op kwaliteit.', +}; diff --git a/src/locales/nl/luckyMix.ts b/src/locales/nl/luckyMix.ts new file mode 100644 index 00000000..b6d9bcaa --- /dev/null +++ b/src/locales/nl/luckyMix.ts @@ -0,0 +1,6 @@ +export const luckyMix = { + done: 'Geluksmix klaar: {{count}} nummers', + failed: 'Kon de Geluksmix niet maken. Probeer opnieuw.', + unavailable: 'Geluksmix is niet beschikbaar voor deze server.', + cancelTooltip: 'Geluksmix-opbouw annuleren', +}; diff --git a/src/locales/nl/miniPlayer.ts b/src/locales/nl/miniPlayer.ts new file mode 100644 index 00000000..2fe05d31 --- /dev/null +++ b/src/locales/nl/miniPlayer.ts @@ -0,0 +1,9 @@ +export const miniPlayer = { + showQueue: 'Wachtrij tonen', + hideQueue: 'Wachtrij verbergen', + pinOnTop: 'Altijd boven', + pinOff: 'Losmaken', + openMainWindow: 'Hoofdvenster openen', + close: 'Sluiten', + emptyQueue: 'Wachtrij is leeg', +}; diff --git a/src/locales/nl/mostPlayed.ts b/src/locales/nl/mostPlayed.ts new file mode 100644 index 00000000..5980b10b --- /dev/null +++ b/src/locales/nl/mostPlayed.ts @@ -0,0 +1,13 @@ +export const mostPlayed = { + title: 'Meest gespeeld', + topArtists: 'Topkunstenaars', + topAlbums: 'Topalbums', + plays: '{{n}} keer gespeeld', + sortMost: 'Meest gespeeld eerst', + sortLeast: 'Minst gespeeld eerst', + loadMore: 'Meer albums laden', + noData: 'Nog geen afspeelgegevens. Begin met luisteren!', + noArtists: 'Alle artiesten gefilterd.', + filterCompilations: 'Compilatie-artiesten verbergen (Various Artists, Soundtracks, etc.)', + filterCompilationsShort: 'Compilaties verbergen', +}; diff --git a/src/locales/nl/nowPlaying.ts b/src/locales/nl/nowPlaying.ts new file mode 100644 index 00000000..695852b4 --- /dev/null +++ b/src/locales/nl/nowPlaying.ts @@ -0,0 +1,47 @@ +export const nowPlaying = { + tooltip: 'Wie luistert er?', + title: 'Wie luistert er?', + loading: 'Laden…', + nobody: 'Er luistert momenteel niemand.', + minutesAgo: '{{n}} min geleden', + nothingPlaying: 'Nog niets bezig. Start een nummer!', + aboutArtist: 'Over de artiest', + fromAlbum: 'Van dit album', + viewAlbum: 'Album openen', + goToArtist: 'Naar artiest', + readMore: 'Meer lezen', + showLess: 'Minder tonen', + genreInfo: 'Genre', + trackInfo: 'Trackinfo', + topSongs: 'Meest afgespeeld van deze artiest', + topSongsCredit: 'Topnummers van {{name}}', + trackPosition: 'Track {{pos}}', + playsCount_one: '{{count}} keer afgespeeld', + playsCount_other: '{{count}} keer afgespeeld', + releasedYearsAgo_one: '{{count}} jaar geleden', + releasedYearsAgo_other: '{{count}} jaar geleden', + discography: 'Discografie', + lastfmStats: 'Last.fm-statistieken', + thisTrack: 'Dit nummer', + thisArtist: 'Deze artiest', + listeners: 'luisteraars', + scrobbles: 'scrobbles', + yourScrobbles: 'door jou', + listenersN: '{{n}} luisteraars', + scrobblesN: '{{n}} scrobbles', + playsByYouN: '{{n}}× door jou afgespeeld', + openTrackOnLastfm: 'Nummer op Last.fm', + openArtistOnLastfm: 'Artiest op Last.fm', + rgTrackTooltip: 'ReplayGain (track)', + rgAlbumTooltip: 'ReplayGain (album)', + rgAutoTooltip: 'ReplayGain (auto)', + showMoreTracks: '{{count}} meer tonen', + showLessTracks: 'Minder tonen', + hideCard: 'Kaart verbergen', + layoutMenu: 'Lay-out', + visibleCards: 'Zichtbare kaarten', + hiddenCards: 'Verborgen kaarten', + noHiddenCards: 'Geen verborgen kaarten', + resetLayout: 'Lay-out resetten', + emptyColumn: 'Sleep kaarten hier', +}; diff --git a/src/locales/nl/nowPlayingInfo.ts b/src/locales/nl/nowPlayingInfo.ts new file mode 100644 index 00000000..16c30447 --- /dev/null +++ b/src/locales/nl/nowPlayingInfo.ts @@ -0,0 +1,24 @@ +export const nowPlayingInfo = { + tab: 'Info', + empty: 'Speel iets af om informatie te zien', + artist: 'Artiest', + songInfo: 'Nummer-info', + onTour: 'Op tour', + noTourEvents: 'Geen aankomende concerten', + tourLoading: 'Laden…', + poweredByBandsintown: 'Tourdata via Bandsintown', + bioReadMore: 'Meer tonen', + bioReadLess: 'Minder tonen', + showMoreTours_one: '{{count}} meer tonen', + showMoreTours_other: '{{count}} meer tonen', + showLessTours: 'Minder tonen', + enableBandsintownPrompt: 'Aankomende tourdata tonen?', + enableBandsintownPromptDesc: 'Optioneel. Laadt concerten van de huidige artiest via de openbare Bandsintown-API.', + enableBandsintownPrivacy: 'Bij inschakelen wordt de naam van de huidige artiest naar de Bandsintown-API gestuurd om tourdata op te halen. Er worden geen account- of persoonlijke gegevens verzonden.', + enableBandsintownAction: 'Inschakelen', + role: { + artist: 'Artiest', + albumArtist: 'Albumartiest', + composer: 'Componist', + }, +}; diff --git a/src/locales/nl/orbit.ts b/src/locales/nl/orbit.ts new file mode 100644 index 00000000..63553dfa --- /dev/null +++ b/src/locales/nl/orbit.ts @@ -0,0 +1,200 @@ +export const orbit = { + triggerLabel: 'Orbit', + triggerTooltip: 'Een gedeelde luistersessie starten of eraan deelnemen', + launchCreate: 'Sessie aanmaken', + launchJoin: 'Deelnemen aan sessie', + launchHelp: 'Hoe werkt dit?', + launchHelpSoon: 'Binnenkort beschikbaar', + joinModalTitle: 'Deelnemen aan een Orbit-sessie', + joinModalSub: 'Plak de uitnodigingslink die je host je gestuurd heeft.', + joinModalLinkLabel: 'Uitnodigingslink', + joinModalLinkPlaceholder: 'psysonic2-…', + joinModalLinkHelper: 'Werkt met elke geldige Orbit-link. Moet verwijzen naar de server waarop je nu bent aangemeld.', + joinModalPasteTooltip: 'Plakken vanaf klembord', + joinModalSubmit: 'Deelnemen', + joinModalBusy: 'Deelnemen…', + joinErrEmpty: 'Plak een uitnodigingslink.', + joinErrInvalid: 'Dat lijkt geen Orbit-uitnodigingslink.', + closeAria: 'Sluiten', + heroTitlePrefix: 'Luister samen met', + heroTitleBrand: 'Orbit', + heroSub: 'Start een sessie — andere gebruikers op {{server}} luisteren mee en kunnen nummers voorstellen.', + fallbackServer: 'deze server', + tipLan: 'Je bent momenteel verbonden via een thuisnetwerkadres. Gasten van buiten je netwerk kunnen niet deelnemen — schakel over naar een openbaar serveradres in de instellingen voordat je start.', + tipRemote: 'Zodat gasten van buiten je thuisnetwerk kunnen deelnemen, moet je serveradres publiek bereikbaar zijn. Als je server alleen intern is, schakel om voordat je start.', + labelName: 'Sessienaam', + namePlaceholder: 'Velvet Orbit', + reshuffleTooltip: 'Nieuwe suggestie', + reshuffleAria: 'Een nieuwe naam voorstellen', + helperName: 'Hoe de sessie voor je gasten verschijnt — laat staan of typ je eigen naam.', + labelMax: 'Max. gasten', + helperMax: 'Jij telt niet mee — dit beperkt alleen binnenkomende gasten.', + labelLink: 'Uitnodigingslink', + tooltipCopied: 'Gekopieerd', + tooltipCopy: 'Kopiëren', + ariaCopyLink: 'Uitnodigingslink kopiëren', + helperLink: 'Stuur deze link naar je gasten. Ze kunnen hem overal in Psysonic plakken met Ctrl+V.', + labelClearQueue: 'Eerst mijn wachtrij legen', + helperClearQueue: 'Begin de sessie met een lege wachtrij. Uit: bestaande nummers blijven en worden met gasten gedeeld.', + btnCancel: 'Annuleren', + btnStarting: 'Starten…', + btnStart: 'Orbit starten', + btnCopyAndStart: 'Link kopiëren & starten', + errNameRequired: 'Geef je sessie een naam.', + errStartFailed: 'Kon niet starten.', + hostLabel: 'Host: {{name}}', + participantsTooltip: 'Deelnemers', + settingsTooltip: 'Sessie-instellingen', + shareTooltip: 'Uitnodigingslink delen', + shuffleLabel: 'Volgende shuffle in', + catchUpLabel: 'inhalen', + catchUpTooltip: 'Spring naar de huidige positie van de host', + hostAway: 'Host offline', + hostOnline: 'Host online', + endTooltip: 'Sessie beëindigen', + leaveTooltip: 'Sessie verlaten', + helpTooltip: 'Hoe Orbit werkt', + diag: { + openTooltip: 'Diagnose — kopieerbaar gebeurtenissen-log', + title: 'Orbit-diagnose', + role: 'Rol', + hostTrack: 'Track-ID van host', + hostPos: 'Positie van host', + guestTrack: 'Mijn track-ID', + guestPos: 'Mijn positie', + drift: 'Verschil', + stateAge: 'Leeftijd van staat', + eventLog: 'Gebeurtenissen-log ({{count}})', + copyLabel: 'Kopiëren', + copyTooltip: 'Log naar klembord kopiëren', + clearLabel: 'Wissen', + clearTooltip: 'Buffer leegmaken', + empty: 'Nog geen gebeurtenissen — ze verschijnen zodra Orbit synchroniseert.', + hint: 'Open dit voor je het probleem reproduceert, klik dan Kopiëren en plak in de bugmelding.', + copied: '{{count}} regels gekopieerd', + copyFailed: 'Kon niet naar klembord kopiëren', + cleared: 'Buffer gewist', + }, + helpTitle: 'Hoe Orbit werkt', + helpIntro: 'Orbit maakt van Psysonic een gedeelde luisterruimte. Een host kiest de muziek; gasten luisteren synchroon mee en kunnen nummers voorstellen.', + helpHostOnly: '(host)', + helpSec1Title: 'Wat is Orbit?', + helpSec1Body: 'Een "samen luisteren"-modus — de host stuurt de weergave, gasten sluiten aan. Alles loopt via playlists op je eigen Navidrome-server; geen externe infrastructuur.', + helpSec2Title: 'Host en gasten', + helpSec2Body: 'De host bedient de weergave (play / pause / skip / seek) en beslist wanneer de sessie eindigt. Gasten volgen de weergave, kunnen nummers voorstellen en elk moment verlaten of opnieuw deelnemen. Alleen de host kan deelnemers kicken of permanent bannen.', + helpSec2WarnHead: 'Belangrijk: aparte accounts.', + helpSec2WarnBody: 'Elke deelnemer heeft een eigen Navidrome-account nodig. Als host en gast met dezelfde gebruiker inloggen botsen hun inzendingen en de host ziet nooit de suggesties van de gast.', + helpSec3Title: 'Starten en uitnodigen', + helpSec3Body: 'Klik op de "Orbit"-knop → Sessie aanmaken → het startmodal toont een kopieerklare uitnodigingslink en laat je optioneel je huidige wachtrij legen. Deel de link hoe je wilt. Terwijl een sessie draait, kopieert de deelknop in de sessiebalk de link op elk moment opnieuw.', + helpSec4Title: 'Deelnemen', + helpSec4Body: 'Plak de uitnodigingslink ergens in Psysonic met Ctrl+V / Cmd+V — de deelprompt verschijnt automatisch. Alternatief: "Orbit" → Deelnemen aan sessie → plak in het veld. Als de link naar een server verwijst waar je een account hebt, schakelt Psysonic voor je. Bij meerdere accounts op die server vraagt een kleine kiezer welke te gebruiken.', + helpSec5Title: 'Nummers voorstellen', + helpSec5Body: 'In elke lijst: dubbelklik op een rij, of rechtermuisknop → "Toevoegen aan Orbit-sessie". Een enkele klik toont een hint in plaats van het hele album in de gedeelde wachtrij te gooien — dat is bewust. Expliciete bulkacties zoals "Alles afspelen" of "Album afspelen" vragen eerst om bevestiging en voegen dan toe (vervangen nooit).', + helpSec6Title: 'De gedeelde wachtrij', + helpSec6Body: 'De wachtrij toont de komende nummers van de host — voor iedereen zichtbaar. Inkomende bulktoevoegingen worden altijd achteraan geplaatst, zodat suggesties van gasten niet verloren gaan. Auto-shuffle hergroepeert de wachtrij periodiek (instelbaar: 1 / 5 / 10 / 15 / 30 min). Als je weergave afwijkt van de host, brengt de "Inhalen"-knop in de sessiebalk je terug naar de live positie van de host.', + helpSec7Title: 'Goedkeuringen', + helpSec7Body: 'Standaard hebben gast-suggesties handmatige goedkeuring nodig — ze verschijnen in een "Goedkeuringen"-strook bovenaan het wachtrijpaneel met accepteer- / afwijsknoppen. Auto-goedkeuring kan in de sessie-instellingen aan, zodat alles direct doorgaat.', + helpSec8Title: 'Deelnemers en instellingen', + helpSec8Body: 'Open het instellingen-icoon in de sessiebalk voor shuffle-cadans, auto-goedkeuring en de "Nu shufflen"-sneltoets. Klik op het deelnemersaantal om te zien wie verbonden is — kicken (kan via de link opnieuw deelnemen) of bannen (voor de sessie uitgesloten). Gasten zien de deelnemerslijst ook, maar alleen-lezen.', + helpSec9Title: 'De sessie beëindigen', + helpSec9Body: 'Host-X → bevestigingsdialoog → de sessie sluit voor iedereen en de server-playlists worden automatisch opgeruimd. Gast-X → de gast verlaat, de sessie gaat door. Als de host 5 minuten stil blijft, verlaat de gast automatisch met een melding; korte reconnects binnen die tijd zijn onzichtbaar.', + participantsInviteLabel: 'Uitnodigingslink', + participantsCountLabel: '{{count}} in sessie', + participantsHost: 'host', + participantsEmpty: 'Nog geen gasten', + participantsKickTooltip: 'Uit sessie verwijderen', + participantsKickAria: '{{user}} verwijderen', + participantsRemoveTooltip: 'Uit sessie verwijderen', + participantsRemoveAria: '{{user}} uit deze sessie verwijderen', + participantsBanTooltip: 'Permanent bannen', + participantsBanAria: '{{user}} permanent bannen', + participantsMuteTooltip: 'Voorstellen blokkeren', + participantsUnmuteTooltip: 'Voorstellen toestaan', + participantsMuteAria: 'Voorstellen van {{user}} blokkeren', + participantsUnmuteAria: 'Voorstellen van {{user}} weer toestaan', + confirmRemoveTitle: 'Uit sessie verwijderen?', + confirmRemoveBody: '{{user}} wordt uit de sessie verwijderd, maar kan opnieuw deelnemen via je uitnodigingslink.', + confirmRemoveConfirm: 'Verwijderen', + confirmBanTitle: 'Permanent bannen?', + confirmBanBody: '{{user}} wordt verwijderd en kan niet meer aan deze sessie deelnemen. Onomkeerbaar voor de duur van de sessie.', + confirmBanConfirm: 'Bannen', + confirmCancel: 'Annuleren', + confirmJoinTitle: 'Deelnemen aan Orbit-sessie?', + confirmJoinBody: '{{host}} heeft je uitgenodigd voor "{{name}}". Aan de sessie deelnemen?', + confirmJoinConfirm: 'Deelnemen', + confirmLeaveTitle: 'Sessie verlaten?', + confirmLeaveBody: 'Wil je "{{name}}" verlaten? Je kunt altijd opnieuw deelnemen via de uitnodigingslink van {{host}}.', + confirmLeaveConfirm: 'Verlaten', + confirmEndTitle: 'Sessie voor iedereen beëindigen?', + confirmEndBody: '"{{name}}" wordt voor alle deelnemers gesloten. De sessie-playlists worden automatisch opgeruimd.', + confirmEndConfirm: 'Sessie beëindigen', + invalidLinkTitle: 'Uitnodigingslink is niet meer geldig', + invalidLinkBody: 'Deze Orbit-sessie bestaat niet meer of is al beëindigd. Vraag de host om een nieuwe uitnodigingslink.', + settingsTitle: 'Sessie-instellingen', + settingAutoApprove: 'Suggesties automatisch goedkeuren', + settingAutoApproveHint: 'Gast-suggesties komen direct in je wachtrij. Uit: ze blijven in de sessielijst voor latere beoordeling.', + settingAutoShuffle: 'Automatisch shufflen', + settingAutoShuffleHint: 'Periodieke Fisher-Yates-shuffle van de komende wachtrij. Uit: de volgorde verandert alleen wanneer je zelf herschikt.', + settingShuffleInterval: 'Opnieuw shufflen elke', + settingShuffleIntervalHint: 'Hoe vaak de komende wachtrij tijdens de sessie opnieuw wordt geshuffled.', + suggestBlockedMuted: 'De host heeft je voor deze sessie geblokkeerd — voorstellen uitgeschakeld.', + settingShuffleIntervalValue_one: '{{count}} min', + settingShuffleIntervalValue_other: '{{count}} min', + settingShuffleNow: 'Nu shufflen', + toastSuggested: '{{user}} stelde "{{title}}" voor', + toastSuggestedMany: '{{count}} nieuwe suggesties in de wachtrij', + toastShuffled: 'Wachtrij geshuffled', + toastJoined: 'Deelgenomen aan sessie', + toastLoginFirst: 'Log eerst in voordat je aan een sessie deelneemt', + toastSwitchServer: 'Schakel eerst naar {{url}} en plak opnieuw', + toastNoAccountForServer: 'Je hebt geen toegang tot {{url}}. Vraag de host om een uitnodiging.', + toastSwitchFailed: 'Kon niet schakelen naar {{url}}', + accountPickerTitle: 'Welk account?', + accountPickerSub: 'Je hebt meer dan één account voor {{url}}. Kies waarmee je wilt deelnemen.', + toastJoinFail: 'Kon niet deelnemen aan sessie', + joinErrNotFound: 'Sessie niet gevonden', + joinErrEnded: 'De sessie is beëindigd', + joinErrFull: 'De sessie is vol', + joinErrKicked: 'Je kunt niet opnieuw deelnemen aan deze sessie', + joinErrNoUser: 'Geen actieve server', + joinErrServerError: 'Kon niet deelnemen', + ctxAddToSession: 'Aan Orbit-sessie toevoegen', + ctxSuggestedToast: 'Aan sessie voorgesteld', + ctxSuggestFailed: 'Kon niet voorstellen — niet deelgenomen', + ctxAddToSessionHost: 'Aan Orbit-sessie toevoegen', + ctxAddedHostToast: 'Aan sessie toegevoegd', + ctxAddHostFailed: 'Kon niet toevoegen aan sessie', + bulkConfirmTitle: 'Alles aan de Orbit-wachtrij toevoegen?', + bulkConfirmBody: 'Dit zou {{count}} nummers in één keer in de gedeelde wachtrij plaatsen. Dat is veel voor je gasten. Doorgaan?', + bulkConfirmYes: 'Alles toevoegen', + bulkConfirmNo: 'Annuleren', + guestLive: 'Live', + guestPlaying: 'Speelt nu', + guestPaused: 'Gepauzeerd', + guestLoading: 'Laden…', + guestSuggestions: 'Suggesties', + guestUpNext: 'Volgende', + guestUpNextEmpty: 'Niets in de wachtrij. Open het contextmenu van een nummer en kies "Aan Orbit-sessie toevoegen".', + guestPendingTitle: 'Wacht op host', + guestPendingHint: 'Voorgesteld — verschijnt in de wachtrij zodra de host het oppakt.', + approvalTitle: 'Wacht op goedkeuring', + approvalFrom: 'Voorgesteld door {{user}}', + approvalAccept: 'Accepteren', + approvalDecline: 'Weigeren', + guestUpNextMore: '+ {{count}} meer in de wachtrij van de host', + guestSubmitter: 'door {{user}}', + queueAddedByHost: 'Toegevoegd door host', + queueAddedByYou: 'Toegevoegd door jou', + queueAddedByUser: 'Toegevoegd door {{user}}', + guestEmpty: 'Nog geen suggesties. Open het contextmenu van een nummer en kies "Aan Orbit-sessie toevoegen".', + guestFooter: 'De host bedient de weergave — je kunt de lijst niet wijzigen.', + exitKickedTitle: 'Je bent uit de sessie gebannen', + exitRemovedTitle: 'Je bent uit de sessie verwijderd', + exitEndedTitle: 'De host heeft de sessie beëindigd', + exitHostTimeoutTitle: 'Host niet bereikbaar', + exitHostTimeoutBody: '{{host}} heeft al een tijd geen update meer verstuurd, dus "{{name}}" is aan jouw kant gesloten. Je kunt altijd opnieuw deelnemen via de link.', + exitKickedBody: '{{host}} heeft je uit "{{name}}" gebannen. Je kunt niet opnieuw deelnemen.', + exitRemovedBody: '{{host}} heeft je uit "{{name}}" verwijderd. Je kunt altijd opnieuw deelnemen via de link.', + exitEndedBody: '"{{name}}" is beëindigd. Hopelijk had je plezier.', + exitOk: 'OK', +}; diff --git a/src/locales/nl/player.ts b/src/locales/nl/player.ts new file mode 100644 index 00000000..d9dec61d --- /dev/null +++ b/src/locales/nl/player.ts @@ -0,0 +1,56 @@ +export const player = { + regionLabel: 'Muziekspeler', + openFullscreen: 'Volledig-schermspeler openen', + fullscreen: 'Volledig-schermspeler', + closeFullscreen: 'Volledig scherm sluiten', + closeTooltip: 'Sluiten (Escape)', + noTitle: 'Geen titel', + stop: 'Stoppen', + prev: 'Vorig nummer', + play: 'Afspelen', + pause: 'Pauzeren', + previewActive: 'Voorbeeld speelt af', + previewLabel: 'Voorbeeld', + delayModalTitle: 'Timer', + delayPauseSection: 'Pauzeren na', + delayStartSection: 'Starten na', + delayPreviewPause: 'Pauze om', + delayPreviewStart: 'Start om', + delaySchedulePause: 'Pauze plannen', + delayScheduleStart: 'Start plannen', + delayCancelPause: 'Pauze-timer annuleren', + delayCancelStart: 'Start-timer annuleren', + delayInactivePause: 'Alleen beschikbaar tijdens afspelen.', + delayInactiveStart: 'Alleen in pauze met een geladen nummer of radio.', + delayCustomMinutes: 'Aangepaste vertraging (minuten)', + delayCustomPlaceholder: 'bijv. 2,5', + closeDelayModal: 'Sluiten', + delayIn: 'over', + delayFmtSec: '{{n}} s', + delayFmtMin: '{{n}} min', + delayFmtHr: '{{n}} u', + delayCancel: 'Annuleren', + delayApply: 'Toepassen', + next: 'Volgend nummer', + repeat: 'Herhalen', + repeatOff: 'Uit', + repeatAll: 'Alles', + repeatOne: 'Één', + progress: 'Nummervoortgang', + volume: 'Volume', + toggleQueue: 'Wachtrij in-/uitschakelen', + collapseQueueResize: 'Wachtrij inklappen, breedte wijzigen', + moreOptions: 'Meer opties', + equalizer: 'Equalizer', + miniPlayer: 'Minispeler', + lyrics: 'Songtekst', + fsLyricsToggle: 'Songtekst in volledig scherm', + lyricsLoading: 'Songtekst laden…', + lyricsNotFound: 'Geen songtekst gevonden voor dit nummer', + lyricsSourceServer: 'Bron: Server', + lyricsSourceLrclib: 'Bron: LRCLIB', + lyricsSourceNetease: 'Bron: Netease', + lyricsSourceLyricsplus: 'Bron: YouLyPlus', + showDuration: 'Toon duur', + showRemainingTime: 'Toon resterende tijd', +}; diff --git a/src/locales/nl/playlists.ts b/src/locales/nl/playlists.ts new file mode 100644 index 00000000..87d7c1a7 --- /dev/null +++ b/src/locales/nl/playlists.ts @@ -0,0 +1,101 @@ +export const playlists = { + title: 'Playlists', + newPlaylist: 'Nieuwe playlist', + unnamed: 'Naamloze playlist', + createName: 'Playlistnaam…', + create: 'Aanmaken', + cancel: 'Annuleren', + empty: 'Nog geen playlists.', + emptyPlaylist: 'Deze playlist is leeg.', + addFirstSong: 'Voeg je eerste nummer toe', + notFound: 'Playlist niet gevonden.', + songs: '{{n}} nummers', + playAll: 'Alles afspelen', + shuffle: 'Willekeurig', + addToQueue: 'Aan wachtrij toevoegen', + back: 'Terug naar playlists', + deletePlaylist: 'Verwijderen', + confirmDelete: 'Nogmaals klikken om te bevestigen', + removeSong: 'Uit playlist verwijderen', + addSongs: 'Nummers toevoegen', + searchPlaceholder: 'Doorzoek bibliotheek…', + noResults: 'Geen resultaten.', + suggestions: 'Aanbevolen nummers', + noSuggestions: 'Geen suggesties beschikbaar.', + titleBadge: 'Playlist', + refreshSuggestions: 'Nieuwe suggesties', + addSong: 'Toevoegen aan playlist', + preview: 'Voorbeeld (30 s)', + previewStop: 'Voorbeeld stoppen', + playNextSuggestion: 'Hierna afspelen', + suggestionsHint: 'Dubbelklik op een rij om hem aan de afspeellijst toe te voegen', + addSelected: 'Geselecteerde toevoegen', + cacheOffline: 'Playlist offline opslaan', + offlineCached: 'Playlist gecached', + removeOffline: 'Verwijder uit offline cache', + offlineDownloading: 'Cachen… ({{done}}/{{total}} albums)', + publicLabel: 'Openbaar', + privateLabel: 'Privé', + editMeta: 'Playlist bewerken', + editNamePlaceholder: 'Playlistnaam…', + editCommentPlaceholder: 'Beschrijving toevoegen…', + editPublic: 'Openbare playlist', + editSave: 'Opslaan', + editCancel: 'Annuleren', + changeCover: 'Omslagafbeelding wijzigen', + changeCoverLabel: 'Foto wijzigen', + removeCover: 'Foto verwijderen', + coverUpdated: 'Omslag bijgewerkt', + metaSaved: 'Playlist bijgewerkt', + downloadZip: 'Downloaden (ZIP)', + // Toast notifications for multi-select + addSuccess: '{{count}} nummers toegevoegd aan {{playlist}}', + addPartial: '{{added}} toegevoegd, {{skipped}} overgeslagen (duplicaten)', + addAllSkipped: 'Alles overgeslagen ({{count}} duplicaten)', + addedAsDuplicates: '{{count}} nummers toegevoegd aan {{playlist}} (als duplicaten)', + duplicateConfirmTitle: 'Al in afspeellijst', + duplicateConfirmMessage: 'Alle {{count}} nummers staan al in "{{playlist}}". Toch als duplicaten toevoegen?', + duplicateConfirmAction: 'Toch toevoegen', + addError: 'Fout bij toevoegen van nummers', + createAndAddSuccess: 'Playlist "{{playlist}}" aangemaakt met {{count}} nummers', + createError: 'Fout bij aanmaken van playlist', + deleteSuccess: '{{count}} playlists verwijderd', + deleteFailed: 'Fout bij verwijderen van {{name}}', + deleteSelected: 'Geselecteerde verwijderen', + deleteSelectedPartial: 'Slechts {{n}} van de {{total}} geselecteerde playlists kunnen worden verwijderd (de andere zijn van iemand anders).', + mergeSuccess: '{{count}} nummers samengevoegd in {{playlist}}', + mergeNoNewSongs: 'Geen nieuwe nummers om toe te voegen', + mergeError: 'Fout bij samenvoegen van playlists', + mergeInto: 'Samenvoegen in', + selectionCount: '{{count}} geselecteerd', + select: 'Selecteren', + startSelect: 'Selectie inschakelen', + cancelSelect: 'Annuleren', + loadingAlbums: '{{count}} albums oplossen…', + loadingArtists: '{{count}} artiesten oplossen…', + myPlaylists: 'Mijn playlists', + noOtherPlaylists: 'Geen andere playlists beschikbaar', + addToPlaylistSuccess: '{{count}} nummers toegevoegd aan {{playlist}}', + addToPlaylistNoNew: 'Geen nieuwe nummers voor {{playlist}}', + addToPlaylistError: 'Fout bij toevoegen aan playlist', + removeSuccess: 'Nummer verwijderd van playlist', + removeError: 'Fout bij verwijderen uit playlist', + importCSV: 'CSV Importeren', + importCSVTooltip: 'Importeren vanuit Spotify CSV', + csvImportReport: 'CSV-importrapport', + csvImportTotal: 'Totaal', + csvImportAdded: 'Toegevoegd', + csvImportDuplicates: 'Duplicaten', + csvImportNotFound: 'Niet Gevonden', + csvImportNetworkErrors: 'Netwerkfouten', + csvImportDuplicatesTitle: 'Dubbele nummers (al in playlist):', + csvImportNotFoundTitle: 'Niet gevonden nummers:', + csvImportNetworkErrorsTitle: 'Netwerkfouten (import kan opnieuw proberen):', + csvImportDownloadReport: 'Rapport downloaden', + csvImportClose: 'Sluiten', + csvImportNoValidTracks: 'Geen geldige nummers gevonden in CSV-bestand', + csvImportFailed: 'CSV-import mislukt', + csvImportToast: '{{added}} toegevoegd, {{notFound}} niet gevonden, {{duplicates}} duplicaten', + csvImportDownloadSuccess: 'Rapport succesvol gedownload', + csvImportDownloadError: 'Rapport downloaden mislukt', +}; diff --git a/src/locales/nl/queue.ts b/src/locales/nl/queue.ts new file mode 100644 index 00000000..c2377534 --- /dev/null +++ b/src/locales/nl/queue.ts @@ -0,0 +1,45 @@ +export const queue = { + title: 'Wachtrij', + savePlaylist: 'Afspeellijst opslaan', + updatePlaylist: 'Afspeellijst bijwerken', + filterPlaylists: 'Afspeellijsten filteren…', + playlistName: 'Naam afspeellijst', + cancel: 'Annuleren', + save: 'Opslaan', + loadPlaylist: 'Afspeellijst laden', + loading: 'Laden…', + noPlaylists: 'Geen afspeellijsten gevonden.', + load: 'Wachtrij vervangen & afspelen', + appendToQueue: 'Toevoegen aan wachtrij', + delete: 'Verwijderen', + deleteConfirm: 'Afspeellijst "{{name}}" verwijderen?', + clear: 'Leegmaken', + shuffle: 'Wachtrij shufflen', + gapless: 'Naadloos', + crossfade: 'Overgang', + infiniteQueue: 'Oneindige wachtrij', + autoAdded: '— Automatisch toegevoegd —', + radioAdded: '— Radio —', + hide: 'Verbergen', + hideNowPlaying: 'Now playing info verbergen', + showNowPlaying: 'Now playing info weergeven', + close: 'Sluiten', + nextTracks: 'Volgende nummers', + shareQueue: 'Wachtrij-deellink kopiëren', + shareQueueEmpty: 'De wachtrij is leeg — niets om te delen.', + emptyQueue: 'De wachtrij is leeg.', + trackSingular: 'nummer', + trackPlural: 'nummers', + showRemaining: 'Resterende tijd tonen', + showTotal: 'Totale tijd tonen', + showEta: 'Geschatte eindtijd tonen', + replayGain: 'ReplayGain', + rgTrack: 'T {{db}} dB', + rgAlbum: 'A {{db}} dB', + rgPeak: 'Piek {{pk}}', + sourceOffline: 'Afspelen vanuit offlinebibliotheek', + sourceHot: 'Afspelen vanuit cache', + sourceStream: 'Afspelen vanuit netwerkstream', + clearCachedLoudnessWaveform: 'Clear cached loudness and waveform, then re-analyze this track', + recalculatingLoudnessWaveform: 'Recalculating loudness and waveform for this track…', +}; diff --git a/src/locales/nl/radio.ts b/src/locales/nl/radio.ts new file mode 100644 index 00000000..7329097f --- /dev/null +++ b/src/locales/nl/radio.ts @@ -0,0 +1,35 @@ +export const radio = { + title: 'Internetradio', + empty: 'Geen radiostations geconfigureerd.', + addStation: 'Station toevoegen', + editStation: 'Bewerken', + deleteStation: 'Station verwijderen', + confirmDelete: 'Klik opnieuw om te bevestigen', + stationName: 'Stationsnaam…', + streamUrl: 'Stream-URL…', + homepageUrl: 'Homepage-URL (optioneel)', + save: 'Opslaan', + cancel: 'Annuleren', + live: 'LIVE', + liveStream: 'Internetradio', + openHomepage: 'Homepage openen', + changeCoverLabel: 'Cover wijzigen', + removeCover: 'Cover verwijderen', + browseDirectory: 'Gids doorzoeken', + directoryPlaceholder: 'Stations zoeken…', + noResults: 'Geen stations gevonden.', + stationAdded: 'Station toegevoegd', + filterAll: 'Alle', + filterFavorites: 'Favorieten', + sortManual: 'Handmatig', + sortAZ: 'A → Z', + sortZA: 'Z → A', + sortNewest: 'Nieuwste', + favorite: 'Toevoegen aan favorieten', + unfavorite: 'Verwijderen uit favorieten', + noFavorites: 'Geen favoriete stations.', + listenerCount_one: '{{count}} luisteraar', + listenerCount_other: '{{count}} luisteraars', + recentlyPlayed: 'Recent gespeeld', + upNext: 'Volgende', +}; diff --git a/src/locales/nl/randomAlbums.ts b/src/locales/nl/randomAlbums.ts new file mode 100644 index 00000000..0b83318a --- /dev/null +++ b/src/locales/nl/randomAlbums.ts @@ -0,0 +1,4 @@ +export const randomAlbums = { + title: 'Willekeurige albums', + refresh: 'Vernieuwen', +}; diff --git a/src/locales/nl/randomLanding.ts b/src/locales/nl/randomLanding.ts new file mode 100644 index 00000000..88f72a3d --- /dev/null +++ b/src/locales/nl/randomLanding.ts @@ -0,0 +1,9 @@ +export const randomLanding = { + title: 'Mix samenstellen', + mixByTracks: 'Mix op nummers', + mixByTracksDesc: 'Willekeurige selectie uit je volledige mediatheek', + mixByAlbums: 'Mix op albums', + mixByAlbumsDesc: 'Willekeurige albums voor nieuwe ontdekkingen', + mixByLucky: 'Geluksmix', + mixByLuckyDesc: 'Slimme Instant Mix op basis van topartiesten, albums en hoge beoordelingen', +}; diff --git a/src/locales/nl/randomMix.ts b/src/locales/nl/randomMix.ts new file mode 100644 index 00000000..66f2846f --- /dev/null +++ b/src/locales/nl/randomMix.ts @@ -0,0 +1,39 @@ +export const randomMix = { + title: 'Willekeurige mix', + remix: 'Opnieuw mixen', + remixTooltip: 'Nieuwe willekeurige nummers laden', + remixGenre: '{{genre}} mixen', + remixTooltipGenre: 'Nieuwe {{genre}}-nummers laden', + playAll: 'Alles afspelen', + trackTitle: 'Titel', + trackArtist: 'Artiest', + trackAlbum: 'Album', + trackFavorite: 'Favoriet', + trackDuration: 'Duur', + favoriteAdd: 'Aan favorieten toevoegen', + favoriteRemove: 'Uit favorieten verwijderen', + play: 'Afspelen', + trackGenre: 'Genre', + mixSettingsHeader: 'Mixinstellingen', + exclusionsHeader: 'Uitsluitingen', + filterPanelInexactSizeNote: 'De mixgrootte is een doel — grote verzoeken kunnen minder unieke nummers opleveren als de willekeurige pool van de server opraakt.', + mixSize: 'Lijstgrootte', + excludeAudiobooks: 'Luisterboeken en hoorspelen uitsluiten', + excludeAudiobooksDesc: 'Vergelijkt trefwoorden met genre, titel, album en artiest — bijv. Hörbuch, Audiobook, Spoken Word, …', + genreBlocked: 'Trefwoord geblokkeerd', + genreAddedToBlacklist: 'Aan filterlijst toegevoegd', + genreAlreadyBlocked: 'Al geblokkeerd', + artistBlocked: 'Artiest geblokkeerd', + artistAddedToBlacklist: 'Artiest aan filterlijst toegevoegd', + artistClickHint: 'Klik om deze artiest te blokkeren', + blacklistToggle: 'Trefwoordfilter', + genreMixTitle: 'Genremix', + genreMixDesc: 'Top 20 genres op aantal nummers — klik voor een willekeurige mix', + genreMixAll: 'Alle nummers', + genreMixLoadMore: '10 meer laden', + genreMixNoGenres: 'Geen genres gevonden op server.', + shuffleGenres: 'Andere genres tonen', + filterPanelTitle: 'Filters', + filterPanelDesc: 'Klik op een genre-tag of artiestennaam in de lijst om deze uit toekomstige mixes te weren.', + genreClickHint: 'Klik op een genre-tag om het\ntoe te voegen als filtertrefwoord.\nVergelijkt genre, titel, album & artiest.', +}; diff --git a/src/locales/nl/search.ts b/src/locales/nl/search.ts new file mode 100644 index 00000000..35bc877d --- /dev/null +++ b/src/locales/nl/search.ts @@ -0,0 +1,29 @@ +export const search = { + placeholder: 'Zoek naar artiest, album of nummer…', + noResults: 'Geen resultaten voor "{{query}}"', + artists: 'Artiesten', + albums: 'Albums', + songs: 'Nummers', + clearLabel: 'Zoekopdracht wissen', + addedToQueueToast: '"{{title}}" toegevoegd aan de wachtrij', + title: 'Zoeken', + resultsFor: 'Resultaten voor "{{query}}"', + album: 'Album', + advanced: 'Geavanceerd zoeken', + advancedSearchTerm: 'Zoekterm', + advancedSearchPlaceholder: 'Titel, album, artiest…', + advancedGenre: 'Genre', + advancedAllGenres: 'Alle genres', + advancedYear: 'Jaar', + advancedYearFrom: 'van', + advancedYearTo: 'tot', + advancedAll: 'Alle', + advancedSearch: 'Zoeken', + advancedEmpty: 'Voer een zoekterm in of selecteer een filter.', + advancedNoResults: 'Geen resultaten gevonden.', + advancedGenreNote: 'Nummers worden willekeurig uit dit genre geselecteerd.', + recentSearches: 'Recente zoekopdrachten', + browse: 'Bladeren', + emptyHint: 'Wat wil je horen?', + genres: 'Genres', +}; diff --git a/src/locales/nl/settings.ts b/src/locales/nl/settings.ts new file mode 100644 index 00000000..421fb0fd --- /dev/null +++ b/src/locales/nl/settings.ts @@ -0,0 +1,440 @@ +export const settings = { + title: 'Instellingen', + language: 'Taal', + languageEn: 'English', + languageDe: 'Deutsch', + languageEs: 'Español', + languageFr: 'Français', + languageNl: 'Nederlands', + languageNb: 'Norsk', + languageRu: 'Русский', + languageZh: '中文', + languageRo: 'Română', + font: 'Lettertype', + fontHintOpenDyslexic: 'Dyslexie-vriendelijk · geen Chinese ondersteuning', + theme: 'Thema', + appearance: 'Weergave', + servers: 'Servers', + serverName: 'Servernaam', + serverUrl: 'Server-URL', + serverUrlPlaceholder: '192.168.1.100:4533 of https://music.voorbeeld.nl', + serverUsername: 'Gebruikersnaam', + serverPassword: 'Wachtwoord', + addServer: 'Server toevoegen', + addServerTitle: 'Nieuwe server toevoegen', + useServer: 'Gebruiken', + deleteServer: 'Verwijderen', + noServers: 'Geen servers opgeslagen.', + serverActive: 'Actief', + confirmDeleteServer: 'Server "{{name}}" verwijderen?', + serverConnecting: 'Verbinden…', + serverConnected: 'Verbonden!', + serverFailed: 'Verbinding mislukt.', + testBtn: 'Verbinding testen', + testingBtn: 'Testen…', + serverCompatible: 'Gemaakt voor Navidrome. Andere Subsonic-compatibele servers (Gonic, Airsonic, …) kunnen met beperkte functionaliteit werken, omdat Psysonic veel Navidrome-specifieke API-endpoints gebruikt.', + userMgmtTitle: 'Gebruikersbeheer', + userMgmtDesc: 'Beheer gebruikers op deze server. Vereist admin-rechten.', + userMgmtNoAdmin: 'Je hebt admin-rechten nodig om gebruikers op deze server te beheren.', + userMgmtLoadError: 'Kon gebruikers niet laden.', + userMgmtLoadFriendly: 'Server antwoordde niet — meestal eenmalig.', + userMgmtRetry: 'Opnieuw proberen', + userMgmtEmpty: 'Geen gebruikers gevonden.', + userMgmtYouBadge: 'Jij', + userMgmtAdminBadge: 'Admin', + userMgmtAddUser: 'Gebruiker toevoegen', + userMgmtAddUserTitle: 'Nieuwe gebruiker', + userMgmtEditUserTitle: 'Gebruiker bewerken', + userMgmtUsername: 'Gebruikersnaam', + userMgmtName: 'Weergavenaam', + userMgmtEmail: 'E-mail', + userMgmtPassword: 'Wachtwoord', + userMgmtPasswordEditHint: 'Voer een nieuw wachtwoord in om het bij te werken.', + userMgmtRoleAdmin: 'Admin', + userMgmtLibraries: 'Bibliotheken', + userMgmtLibrariesAdminHint: 'Beheerders hebben automatisch toegang tot alle bibliotheken.', + userMgmtLibrariesEmpty: 'Geen bibliotheken beschikbaar op deze server.', + userMgmtLibrariesValidation: 'Selecteer ten minste één bibliotheek.', + userMgmtLibrariesUpdateError: 'Gebruiker opgeslagen, maar bibliotheektoewijzing mislukt', + userMgmtNoLibraries: 'Geen bibliotheken toegewezen', + userMgmtNeverSeen: 'Nooit', + userMgmtSave: 'Opslaan', + userMgmtCancel: 'Annuleren', + userMgmtDelete: 'Verwijderen', + userMgmtEdit: 'Bewerken', + userMgmtConfirmDelete: 'Gebruiker "{{username}}" verwijderen? Dit kan niet ongedaan worden gemaakt.', + userMgmtCreateError: 'Aanmaken van gebruiker mislukt.', + userMgmtUpdateError: 'Bijwerken van gebruiker mislukt.', + userMgmtDeleteError: 'Verwijderen van gebruiker mislukt.', + userMgmtCreated: 'Gebruiker aangemaakt.', + userMgmtUpdated: 'Gebruiker bijgewerkt.', + userMgmtDeleted: 'Gebruiker verwijderd.', + userMgmtValidationMissing: 'Gebruikersnaam, weergavenaam en wachtwoord zijn vereist.', + userMgmtValidationMissingIdentity: 'Gebruikersnaam en weergavenaam zijn vereist.', + userMgmtMagicStringGenerate: 'Magic string genereren', + userMgmtSaveAndMagicString: 'Opslaan en magic string kopiëren', + userMgmtMagicStringPasswordNavHint: + 'Navidrome slaat dit wachtwoord voor de gebruiker op. Als het afwijkt van het huidige wachtwoord, wordt het inlogwachtwoord op de server bijgewerkt.', + userMgmtMagicStringPlaintextWarning: + 'Wees voorzichtig met delen: de magic string bevat een onversleuteld wachtwoord (codering is geen encryptie). Wie de volledige string heeft, kan als deze gebruiker inloggen.', + userMgmtMagicStringCopied: 'Magic string naar het klembord gekopieerd.', + userMgmtMagicStringCopyFailed: 'Kopiëren naar het klembord is mislukt.', + userMgmtMagicStringLoginFailed: 'Wachtwoordcontrole mislukt — aanmeldgegevens konden niet worden geverifieerd.', + userMgmtMagicStringModalTitle: 'Magic string genereren', + userMgmtMagicStringModalDesc: 'Voer het Subsonic-wachtwoord voor „{{username}}" in. Het wordt opgenomen in de gekopieerde magic string.', + userMgmtMagicStringModalConfirm: 'String kopiëren', + audiomuseTitle: 'AudioMuse-AI (Navidrome)', + audiomuseDesc: + 'Zet aan als deze server de AudioMuse-AI Navidrome-plugin gebruikt. Schakelt Instant Mix per nummer in en toont vergelijkbare artiesten van de server i.p.v. Last.fm op artiestpagina’s.', + audiomuseIssueHint: + 'Instant Mix is onlangs mislukt — controleer de Navidrome-plugin en AudioMuse API. Zonder serverresultaten worden vergelijkbare artiesten via Last.fm geladen.', + connected: 'Verbonden', + failed: 'Mislukt', + eqTitle: 'Equalizer', + eqEnabled: 'Equalizer inschakelen', + eqPreset: 'Voorinstelling', + eqPresetCustom: 'Aangepast', + eqPresetBuiltin: 'Ingebouwde voorinstellingen', + eqPresetCustomGroup: 'Mijn voorinstellingen', + eqSavePreset: 'Opslaan als voorinstelling', + eqPresetName: 'Naam voorinstelling…', + eqDeletePreset: 'Voorinstelling verwijderen', + eqResetBands: 'Terugzetten naar vlak', + eqPreGain: 'Voorversterking', + eqResetPreGain: 'Voorversterking resetten', + eqAutoEqTitle: 'AutoEQ Hoofdtelefoon Zoeken', + eqAutoEqPlaceholder: 'Zoek hoofdtelefoon / IEM model…', + eqAutoEqSearching: 'Zoeken…', + eqAutoEqNoResults: 'Geen resultaten gevonden', + eqAutoEqError: 'Zoeken mislukt', + eqAutoEqRateLimit: 'GitHub limiet bereikt — probeer over een minuut opnieuw', + eqAutoEqFetchError: 'EQ-profiel kon niet worden geladen', + lfmTitle: 'Last.fm', + lfmConnect: 'Verbinden met Last.fm', + lfmConnecting: 'Wachten op autorisatie…', + lfmConfirm: 'Ik heb de app geautoriseerd', + lfmConnected: 'Verbonden als', + lfmDisconnect: 'Verbinding verbreken', + lfmConnectDesc: 'Verbind je Last.fm-account om scrobbling en Nu bezig-updates rechtstreeks vanuit Psysonic in te schakelen — geen Navidrome-configuratie vereist.', + lfmOpenBrowser: 'Er opent een browservenster. Autoriseer Psysonic op Last.fm en klik daarna op de knop hieronder.', + lfmScrobbles: '{{n}} scrobbles', + lfmMemberSince: 'Lid sinds {{year}}', + scrobbleEnabled: 'Scrobbling ingeschakeld', + scrobbleDesc: 'Nummers naar Last.fm sturen na 50% afspeeltijd', + behavior: 'App-gedrag', + cacheTitle: 'Max. opslaggrootte', + cacheDesc: 'Albumhoezen en artiestafbeeldingen. Als de cache vol is, worden de oudste items automatisch verwijderd. Offline albums worden niet automatisch verwijderd, maar wel bij handmatig leegmaken.', + cacheUsedImages: 'Afbeeldingen:', + cacheUsedOffline: 'Offline nummers:', + cacheUsedHot: 'Schijfgebruik:', + hotCacheTrackCount: 'Nummers in cache:', + cacheMaxLabel: 'Max. grootte', + cacheClearBtn: 'Cache wissen', + cacheClearWarning: 'Dit verwijdert ook alle offline albums uit de bibliotheek.', + cacheClearConfirm: 'Alles wissen', + cacheClearCancel: 'Annuleren', + offlineDirTitle: 'Offline-bibliotheek (In-app)', + offlineDirDesc: 'Opslaglocatie voor nummers die je offline beschikbaar maakt in Psysonic.', + offlineDirDefault: 'Standaard (app-gegevens)', + offlineDirChange: 'Map wijzigen', + offlineDirClear: 'Terugzetten naar standaard', + offlineDirHint: 'Nieuwe downloads worden op deze locatie opgeslagen. Bestaande downloads blijven op hun oorspronkelijke locatie.', + hotCacheTitle: 'Warme afspeelcache', + hotCacheDisclaimer: 'Laadt aankomende wachtrijtracks voor en bewaart eerdere. Indien ingeschakeld: schijfruimte en netwerk.', + hotCacheDirDefault: 'Standaard (app-gegevens)', + hotCacheDirChange: 'Map wijzigen', + hotCacheDirClear: 'Terugzetten naar standaard', + hotCacheDirHint: 'Een andere map kiest: de index in de app wordt gereset; oude bestanden blijven staan tot je ze verwijdert.', + hotCacheEnabled: 'Warme afspeelcache inschakelen', + hotCacheMaxMb: 'Maximale cachegrootte', + hotCacheDebounce: 'Uitstel bij wachtrijwijziging', + hotCacheDebounceImmediate: 'Direct', + hotCacheDebounceSeconds: '{{n}} s', + hotCacheClearBtn: 'Warme cache wissen', + audioOutputDevice: 'Audio-uitvoerapparaat', + audioOutputDeviceDesc: 'Kies via welk audioapparaat Psysonic afspeelt. Wijzigingen worden direct toegepast en starten het huidige nummer opnieuw.', + audioOutputDeviceDefault: 'Systeemstandaard', + audioOutputDeviceRefresh: 'Apparatenlijst vernieuwen', + audioOutputDeviceOsDefaultNow: 'huidige systeemuitvoer', + audioOutputDeviceListError: 'De lijst met audio-apparaten kon niet worden geladen.', + audioOutputDeviceNotInCurrentList: 'staat niet in de huidige lijst', + audioOutputDeviceMacNotice: 'Op macOS volgt de weergave om technische redenen altijd het standaard-uitvoerapparaat van het systeem. Wijzig het doel via Systeeminstellingen → Geluid of via het luidsprekerpictogram in de menubalk. Achtergrond: CoreAudio vraagt bij het openen van een niet-standaard stream om microfoontoestemming — dat vermijden we door altijd de systeemstandaard te gebruiken.', + hiResTitle: 'Natieve hi-res-weergave', + hiResEnabled: 'Natieve hi-res-weergave inschakelen', + hiResDesc: "Beperkt de uitvoer standaard tot 44,1 kHz voor maximale stabiliteit. Alleen inschakelen als hardware en netwerk hoge samplerates (88,2 kHz+) ondersteunen.", + showArtistImages: 'Artiestafbeeldingen weergeven', + showArtistImagesDesc: 'Laadt en toont artiestafbeeldingen in het artiestenoverzicht. Standaard uitgeschakeld om server-I/O en netwerkbelasting bij grote bibliotheken te beperken.', + showOrbitTrigger: '"Orbit" in de kop tonen', + showOrbitTriggerDesc: 'De knop in de kop voor starten of deelnemen aan een gedeelde luistersessie. Verberg hem als je Orbit niet gebruikt — je kunt hem hier weer aanzetten.', + showTrayIcon: 'Tray-pictogram weergeven', + showTrayIconDesc: 'Toont het Psysonic-pictogram in het systeemvak / de menubalk.', + minimizeToTray: 'Minimaliseren naar systeemvak', + minimizeToTrayDesc: 'Bij het sluiten van het venster blijft Psysonic actief in het systeemvak in plaats van af te sluiten.', + preloadMiniPlayer: 'Mini-speler vooraf laden', + preloadMiniPlayerDesc: 'Bouwt het venster van de mini-speler op de achtergrond bij het opstarten van de app, zodat het bij de eerste opening direct inhoud toont. Gebruikt iets meer geheugen.', + linuxWebkitSmoothScroll: 'Vloeiend muiswiel (Linux)', + linuxWebkitSmoothScrollDesc: 'Aan: traag naloop. Uit: regel voor regel, GTK-stijl.', + discordRichPresence: 'Discord Rich Presence', + discordRichPresenceDesc: 'Toont het huidige nummer op je Discord-profiel. Discord moet daarvoor geopend zijn.', + discordCoverSource: 'Hoesbron', + discordCoverSourceDesc: 'Waar de albumhoes voor je Discord-profiel vandaan komt.', + discordCoverNone: 'Geen (alleen app-icoon)', + discordCoverServer: 'Server (via albuminfo)', + discordCoverApple: 'Apple Music', + discordOptions: 'Geavanceerde Discord-opties', + discordTemplates: 'Aangepaste tekstsjablonen', + discordTemplatesDesc: 'Pas aan welke informatie wordt weergegeven op je Discord-profiel. Variabelen: {title}, {artist}, {album}', + discordTemplateDetails: 'Primaire regel (details)', + discordTemplateState: 'Secundaire regel (state)', + discordTemplateLargeText: 'Album-tooltip (largeText)', + nowPlayingEnabled: 'Weergeven in live-venster', + nowPlayingEnabledDesc: 'Stuurt het huidige nummer naar de live-luisteraarsweergave van de server. Uitschakelen om geen afspeelgegevens te verzenden.', + enableBandsintown: 'Bandsintown-tourdata', + enableBandsintownDesc: 'Toon aankomende concerten van de huidige artiest in het Info-tabblad. Gegevens komen van de openbare Bandsintown-API.', + lyricsServerFirst: 'Server-songtekst voorrang geven', + lyricsServerFirstDesc: 'Controleer eerst door de server geleverde songteksten (ingebedde tags, sidecar-bestanden) vóór LRCLIB. Uitschakelen om LRCLIB eerst te gebruiken.', + enableNeteaselyrics: 'Netease Cloud Music songteksten', + enableNeteaselyricsDesc: 'Gebruik Netease Cloud Music als laatste bron wanneer server en LRCLIB niets opleveren. Beste dekking voor Aziatische en internationale muziek.', + lyricsSourcesTitle: 'Songtekstbronnen', + lyricsSourcesDesc: 'Kies welke bronnen worden geraadpleegd en in welke volgorde. Sleep om te sorteren. Uitgeschakelde bronnen worden overgeslagen.', + lyricsSourceServer: 'Server', + lyricsSourceLrclib: 'LRCLIB', + lyricsSourceNetease: 'Netease Cloud Music', + lyricsModeStandard: 'Standaard', + lyricsModeStandardDesc: 'Drie bronnen in een vrij te ordenen lijst: server-tags, LRCLIB, Netease.', + lyricsModeLyricsplus: 'YouLyPlus (Karaoke)', + lyricsModeLyricsplusDesc: 'Woord-voor-woord-synchronisatie uit Apple Music, Spotify, Musixmatch en QQ (community-backend). Valt stil terug op de standaardbronnen als er niets wordt gevonden.', + lyricsStaticOnly: 'Alleen statische tekst weergeven', + lyricsStaticOnlyDesc: 'Gesynchroniseerde songteksten worden zonder auto-scroll en zonder woordmarkering als statische tekst weergegeven.', + downloadsTitle: 'ZIP-export & Archivering', + downloadsFolderDesc: 'Doelmap voor albums die je als ZIP-bestand naar je computer downloadt.', + downloadsDefault: 'Standaard downloadmap', + pickFolder: 'Selecteren', + pickFolderTitle: 'Downloadmap selecteren', + clearFolder: 'Map wissen', + logout: 'Uitloggen', + aboutTitle: 'Over Psysonic', + aboutDesc: 'Een moderne desktopmuziekspeler gebouwd voor Navidrome. Gebruikt de Subsonic-API plus Navidrome-specifieke extensies. Gebouwd op Tauri v2 met een native Rust audio-engine — licht en snel, maar boordevol functies: golfvorm-zoekbalk, gesynchroniseerde songteksten, Last.fm-integratie, 10-bands equalizer, crossfade, naadloos afspelen, Replay Gain, genres en een uitgebreide themabibliotheek.', + aboutLicense: 'Licentie', + aboutLicenseText: 'GNU GPL v3 — vrij te gebruiken, wijzigen en verspreiden onder dezelfde licentie.', + aboutRepo: 'Broncode op GitHub', + aboutVersion: 'Versie', + aboutBuiltWith: 'Gebouwd met Tauri · React · TypeScript · Rust/rodio', + aboutReleaseNotesLabel: 'Release-notities', + aboutReleaseNotesLink: 'Nieuws van deze versie openen', + aboutContributorsLabel: 'Bijdragers', + showChangelogOnUpdate: "'Wat is nieuw' tonen bij update", + showChangelogOnUpdateDesc: 'Toont een discrete changelog-banner boven Now Playing na een update. Klik opent de release-notities; X verbergt hem.', + randomMixTitle: 'Willekeurige mix-blacklist', + luckyMixMenuTitle: 'Toon Geluksmix in menu', + luckyMixMenuDesc: 'Schakelt Geluksmix in bij "Mix samenstellen" en als apart menu-item bij gesplitste navigatie. Alleen zichtbaar wanneer AudioMuse actief is op de huidige server.', + randomMixBlacklistTitle: 'Aangepaste filtertrefwoorden', + randomMixBlacklistDesc: 'Nummers worden uitgesloten als een trefwoord overeenkomt met hun genre, titel, album of artiest (actief wanneer het selectievakje hierboven is aangevinkt).', + randomMixBlacklistPlaceholder: 'Trefwoord toevoegen…', + randomMixBlacklistAdd: 'Toevoegen', + randomMixBlacklistEmpty: 'Nog geen aangepaste trefwoorden toegevoegd.', + randomMixHardcodedTitle: 'Ingebouwde trefwoorden (actief wanneer selectievakje is aangevinkt)', + tabAudio: 'Audio', + tabStorage: 'Offline & Cache', + tabAppearance: 'Weergave', + tabLibrary: 'Bibliotheek', + tabServers: 'Servers', + tabLyrics: 'Songteksten', + tabPersonalisation: 'Personalisatie', + tabIntegrations: 'Integraties', + inputKeybindingsTitle: 'Sneltoetsen', + aboutContributorsCount_one: '{{count}} bijdrage', + aboutContributorsCount_other: '{{count}} bijdragen', + searchPlaceholder: 'Instellingen zoeken…', + searchNoResults: 'Geen instellingen komen overeen met je zoekopdracht.', + aboutMaintainersLabel: 'Beheerders', + integrationsPrivacyTitle: 'Privacyverklaring', + integrationsPrivacyBody: 'Alle integraties op dit tabblad zijn opt-in en sturen, eenmaal ingeschakeld, gegevens naar externe diensten of naar je Navidrome-server. Last.fm ontvangt je luistergeschiedenis, Discord toont het nu spelende nummer in je profiel, Bandsintown wordt per artiest bevraagd voor tourdatums, en de "Nu aan het afspelen"-deling publiceert je huidige nummer bij andere gebruikers van je Navidrome-server. Wil je dit niet, laat dan de bijbehorende sectie gewoon uitgeschakeld.', + homeCustomizerTitle: 'Startpagina', + queueToolbarTitle: 'Wachtrij-werkbalk', + queueToolbarReset: 'Standaard herstellen', + queueToolbarSeparator: 'Scheiding', + sidebarTitle: 'Zijbalk', + sidebarReset: 'Standaard herstellen', + artistLayoutTitle: 'Secties artiestenpagina', + artistLayoutDesc: 'Versleep om te herschikken, schakel om individuele secties van de artiestenpagina te verbergen. Secties zonder gegevens worden automatisch overgeslagen.', + artistLayoutReset: 'Standaard herstellen', + artistLayoutBio: 'Biografie van de artiest', + artistLayoutTopTracks: 'Populaire nummers', + artistLayoutSimilar: 'Soortgelijke artiesten', + artistLayoutAlbums: 'Albums', + artistLayoutFeatured: 'Ook te horen op', + sidebarDrag: 'Slepen om te herordenen', + sidebarFixed: 'Altijd zichtbaar', + randomNavSplitTitle: 'Mix-navigatie splitsen', + randomNavSplitDesc: 'Toon "Willekeurige mix", "Willekeurige albums" en "Geluksmix" als afzonderlijke zijbalkitems in plaats van de "Mix samenstellen"-hub.', + tabInput: 'Invoer', + tabUsers: 'Gebruikers', + shortcutsReset: 'Standaard herstellen', + shortcutListening: 'Druk op een toets…', + shortcutUnbound: '—', + shortcutClear: 'Wissen', + globalShortcutsTitle: 'Globale sneltoetsen', + globalShortcutsNote: 'Werken systeembreed, ook als Psysonic op de achtergrond draait. Vereist Ctrl, Alt of Super als modifier.', + shortcutPlayPause: 'Afspelen / Pauzeren', + shortcutNext: 'Volgend nummer', + shortcutPrev: 'Vorig nummer', + shortcutVolumeUp: 'Volume omhoog', + shortcutVolumeDown: 'Volume omlaag', + shortcutSeekForward: '10s vooruitspoelen', + shortcutSeekBackward: '10s terugspoelen', + shortcutToggleQueue: 'Wachtrij tonen/verbergen', + shortcutOpenFolderBrowser: '{{folderBrowser}} openen', + shortcutFullscreenPlayer: 'Volledigschermspeler', + shortcutNativeFullscreen: 'Systeemvolledig scherm', + shortcutOpenMiniPlayer: 'Mini-speler openen', + shortcutStartSearch: 'Zoekopdracht starten', + shortcutStartAdvancedSearch: 'Geavanceerde zoekopdracht starten', + shortcutToggleSidebar: 'Zijbalk in-/uitschakelen', + shortcutMuteSound: 'Geluid dempen', + shortcutToggleEqualizer: 'Equalizer openen / schakelen', + shortcutToggleRepeat: 'Herhaling schakelen', + shortcutOpenNowPlaying: '"Nu speelt" openen', + shortcutShowLyrics: 'Songtekst tonen', + shortcutFavoriteCurrentTrack: 'Huidig nummer aan favorieten toevoegen', + shortcutOpenHelp: 'Help', + tabSystem: 'Systeem', + loggingTitle: 'Logboek', + loggingModeDesc: 'Bepaalt de uitgebreidheid van backendlogs in de terminal.', + loggingModeOff: 'Uit', + loggingModeNormal: 'Normaal', + loggingModeDebug: 'Debug', + loggingExport: 'Logs exporteren', + loggingExportSuccess: 'Logs geëxporteerd ({{count}} regels).', + loggingExportError: 'Kon logs niet exporteren.', + ratingsSectionTitle: 'Beoordelingen', + ratingsSkipStarTitle: 'Overslaan voor 1 ster', + ratingsSkipStarDesc: + 'Na meerdere overslagen op rij: nummer op 1 ster zetten. Alleen voor nummers die nog niet beoordeeld waren.', + ratingsSkipStarThresholdLabel: 'Overslagen', + ratingsMixFilterTitle: 'Filter op beoordeling', + ratingsMixFilterDesc: + 'Content met lage beoordeling filteren in {{mix}} en {{albums}}. Klik opnieuw op de gekozen ster om de drempel uit te zetten.', + ratingsMixMinSong: 'Nummers', + ratingsMixMinAlbum: 'Albums', + ratingsMixMinArtist: 'Artiesten', + ratingsMixMinThresholdAria: 'Minimum sterren: {{label}}', + backupTitle: 'Back-up & Herstel', + backupExport: 'Instellingen exporteren', + backupExportDesc: 'Slaat alle instellingen, serverprofielen, Last.fm-configuratie, thema, EQ en sneltoetsen op in een .psybkp-bestand. Wachtwoorden worden opgeslagen als leesbare tekst — bewaar het bestand veilig.', + backupImport: 'Instellingen importeren', + backupImportDesc: 'Herstelt instellingen vanuit een .psybkp-bestand. De app wordt herladen na het importeren.', + backupImportConfirm: 'Alle huidige instellingen worden overschreven. Doorgaan?', + backupSuccess: 'Back-up opgeslagen', + backupImportSuccess: 'Instellingen hersteld — herladen…', + backupImportError: 'Ongeldig of beschadigd back-upbestand.', + playbackTitle: 'Afspelen', + replayGain: 'Replay Gain', + replayGainDesc: 'Nummervolume normaliseren met ReplayGain-metadata', + replayGainMode: 'Modus', + replayGainAuto: 'Auto', + replayGainAutoDesc: 'Kiest album-gain wanneer aangrenzende nummers in de wachtrij van hetzelfde album zijn, anders nummer-gain.', + replayGainTrack: 'Nummer', + replayGainAlbum: 'Album', + replayGainPreGain: 'Pre-Gain (getagde bestanden)', + replayGainPreGainDesc: 'Universele boost bovenop elke ReplayGain-berekening. Handig als je bibliotheek over het geheel te zacht aanvoelt.', + replayGainFallback: 'Terugval (zonder tags / radio)', + replayGainFallbackDesc: 'Toegepast op nummers (en radiostreams) zonder ReplayGain-tags, zodat ongetagde inhoud er niet harder uitspringt dan de rest.', + normalization: 'Normalisatie', + normalizationDesc: 'Egaliseer de waargenomen luidheid tussen nummers, albums en radio.', + normalizationOff: 'Uit', + normalizationReplayGain: 'ReplayGain', + normalizationLufs: 'LUFS', + loudnessTargetLufs: 'Doel-LUFS', + loudnessTargetLufsDesc: 'Referentie-luidheid waarop alle nummers worden afgestemd. Lagere waarde = luidere uitvoer. Streamingdiensten zitten meestal rond -14 LUFS.', + loudnessPreAnalysisAttenuation: 'Demping vóór meting', + loudnessPreAnalysisAttenuationDesc: + 'Extra zachter tot de loudness van het nummer is opgeslagen. Streamen gebruikt daarna grove schattingen, geen volledige meting. 0 dB = uit; negatiever = zachter. Rechts staat de effectieve dB voor het huidige doel.', + loudnessPreAnalysisAttenuationRef: 'Effectief {{eff}} dB bij doel {{tgt}} LUFS.', + loudnessPreAnalysisAttenuationReset: 'Standaard', + loudnessFirstPlayNote: + 'Bij de eerste keer afspelen van een nieuw nummer kan het volume even fluctueren terwijl er gemeten wordt. De volgende keer gebruikt de speler de opgeslagen meting en blijft alles rotsvast. Komende nummers in de wachtrij worden meestal al tijdens het vorige nummer geanalyseerd, dus dit komt in de praktijk zelden voor.', + crossfade: 'Overgang', + crossfadeDesc: 'Fade tussen nummers', + crossfadeSecs: '{{n}} s', + notWithGapless: 'Niet beschikbaar als naadloos afspelen actief is', + notWithCrossfade: 'Niet beschikbaar als overgang actief is', + gapless: 'Naadloos afspelen', + gaplessDesc: 'Volgend nummer vooraf bufferen om stiltes tussen nummers te elimineren', + preservePlayNextOrder: '"Volgende afspelen"-volgorde behouden', + preservePlayNextOrderDesc: 'Nieuwe "Volgende afspelen"-items komen achter bestaande te staan in plaats van ervoor.', + trackPreviewsTitle: 'Track-voorvertoning', + trackPreviewsToggle: 'Track-voorvertoning inschakelen', + trackPreviewsDesc: 'Inline Play- en Voorvertoning-knoppen in trackslijsten tonen voor een korte sample midden in het nummer.', + trackPreviewStart: 'Startpositie', + trackPreviewStartDesc: 'Hoever in de track de voorvertoning start (% van de duur).', + trackPreviewDuration: 'Duur', + trackPreviewDurationDesc: 'Hoe lang elke voorvertoning speelt voordat hij stopt.', + trackPreviewDurationSecs: '{{n}} s', + trackPreviewLocationsTitle: 'Waar voorvertoningen verschijnen', + trackPreviewLocationsDesc: 'Kies in welke lijsten de voorvertoning-knoppen worden weergegeven.', + trackPreviewLocation_suggestions: 'In playlist-suggesties', + trackPreviewLocation_albums: 'In albumlijsten', + trackPreviewLocation_playlists: 'In playlists', + trackPreviewLocation_favorites: 'In favorieten', + trackPreviewLocation_artist: 'In top-tracks van artiest', + trackPreviewLocation_randomMix: 'In Random Mix', + preloadMode: 'Volgend nummer vooraf laden', + preloadModeDesc: 'Wanneer met het bufferen van het volgende nummer wordt begonnen', + nextTrackBufferingTitle: 'Buffering', + preloadHotCacheMutualExclusive: 'Preload en Hot Cache dienen hetzelfde doel — slechts één kan tegelijk actief zijn. Het inschakelen van de ene schakelt de andere automatisch uit.', + preloadOff: 'Uit', + preloadBalanced: 'Gebalanceerd (30 s voor einde)', + preloadEarly: 'Vroeg (na 5 s afspelen)', + preloadCustom: 'Aangepast', + preloadCustomSeconds: 'Seconden voor einde: {{n}}', + infiniteQueue: 'Oneindige wachtrij', + infiniteQueueDesc: 'Automatisch willekeurige nummers toevoegen als de wachtrij leeg raakt', + experimental: 'Experimenteel', + fsPlayerSection: 'Volledig scherm speler', + fsShowArtistPortrait: 'Artiestfoto tonen', + fsShowArtistPortraitDesc: 'Artiestfoto (of albumhoes) weergeven aan de rechterkant van de volledigschermspeler.', + fsPortraitDim: 'Verduistering foto', + fsLyricsStyle: 'Tekststijl', + fsLyricsStyleRail: 'Rail', + fsLyricsStyleRailDesc: 'Klassieke 5-regels schuifrail.', + fsLyricsStyleApple: 'Scrollen', + fsLyricsStyleAppleDesc: 'Volledig scherm scrolllijst.', + sidebarLyricsStyle: 'Scrollstijl voor tekst', + sidebarLyricsStyleClassic: 'Klassiek', + sidebarLyricsStyleClassicDesc: 'Actieve regel wordt gecentreerd.', + sidebarLyricsStyleApple: 'Apple Music-like', + sidebarLyricsStyleAppleDesc: 'Actieve regel verankerd bovenaan met vloeiende animatie.', + seekbarStyle: 'Zoekbalkstijl', + seekbarStyleDesc: 'Kies het uiterlijk van de afspeelbalk', + seekbarTruewave: 'Echte golfvorm', + seekbarPseudowave: 'Pseudo-golfvorm', + seekbarLinedot: 'Lijn & punt', + seekbarBar: 'Balk', + seekbarThick: 'Dikke balk', + seekbarSegmented: 'Gesegmenteerd', + seekbarNeon: 'Neon', + seekbarPulsewave: 'Pulsgolf', + seekbarParticletrail: 'Deeltjesspoor', + seekbarLiquidfill: 'Vloeistofbuis', + seekbarRetrotape: 'Retrotape', + themeSchedulerTitle: 'Thema-planner', + themeSchedulerEnable: 'Thema-planner inschakelen', + themeSchedulerEnableSub: 'Schakelt automatisch tussen twee thema\'s op basis van de tijd', + themeSchedulerDayTheme: 'Dagthema', + themeSchedulerDayStart: 'Dag begint om', + themeSchedulerNightTheme: 'Nachtthema', + themeSchedulerNightStart: 'Nacht begint om', + themeSchedulerActiveHint: "Thema-planner is actief - thema's worden automatisch gewisseld.", + visualOptionsTitle: 'Visuele Opties', + coverArtBackground: 'Cover Achtergrond', + coverArtBackgroundSub: 'Toon vervaagde cover als achtergrond in album/playlist headers', + playlistCoverPhoto: 'Playlist Coverfoto', + playlistCoverPhotoSub: 'Toon coverfoto raster in playlist detailweergave', + showBitrate: 'Toon Bitrate', + showBitrateSub: 'Toon audio bitrate in tracklijsten', + floatingPlayerBar: 'Zwevende Spelerbalk', + floatingPlayerBarSub: 'Houd de spelerbalk zwevend boven de inhoud', + uiScaleTitle: 'Interface schaal', + uiScaleLabel: 'Zoom', +}; diff --git a/src/locales/nl/sharePaste.ts b/src/locales/nl/sharePaste.ts new file mode 100644 index 00000000..9bc1ae22 --- /dev/null +++ b/src/locales/nl/sharePaste.ts @@ -0,0 +1,18 @@ +export const sharePaste = { + notLoggedIn: 'Log in en voeg de server toe voordat je een deellink plakt.', + noMatchingServer: 'Geen opgeslagen server komt overeen met deze link. Voeg een server toe met dit adres: {{url}}', + trackUnavailable: 'Dit nummer is niet op de server gevonden.', + albumUnavailable: 'Dit album is niet op de server gevonden.', + artistUnavailable: 'Deze artiest is niet op de server gevonden.', + composerUnavailable: 'Deze componist is niet op de server gevonden.', + openedTrack: 'Gedeeld nummer wordt afgespeeld.', + openedAlbum: 'Gedeeld album wordt geopend.', + openedArtist: 'Gedeelde artiest wordt geopend.', + openedComposer: 'Gedeelde componist wordt geopend.', + openedQueue_one: '{{count}} nummer van deellink wordt afgespeeld.', + openedQueue_other: '{{count}} nummers van deellink worden afgespeeld.', + openedQueuePartial: + '{{played}} van {{total}} nummers uit de link worden afgespeeld ({{skipped}} niet gevonden op deze server).', + queueAllUnavailable: 'Geen enkel nummer uit deze link is op de server gevonden.', + genericError: 'De deellink kon niet worden geopend.', +}; diff --git a/src/locales/nl/sidebar.ts b/src/locales/nl/sidebar.ts new file mode 100644 index 00000000..747b6eac --- /dev/null +++ b/src/locales/nl/sidebar.ts @@ -0,0 +1,37 @@ +export const sidebar = { + library: 'Bibliotheek', + mainstage: 'Hoofdpodium', + newReleases: 'Nieuw', + allAlbums: 'Alle albums', + randomAlbums: 'Willekeurige albums', + randomPicker: 'Mix samenstellen', + artists: 'Artiesten', + composers: 'Componisten', + randomMix: 'Willekeurige mix', + favorites: 'Favorieten', + nowPlaying: 'Nu bezig', + system: 'Systeem', + statistics: 'Statistieken', + settings: 'Instellingen', + help: 'Help', + expand: 'Zijbalk uitklappen', + collapse: 'Zijbalk inklappen', + downloadingTracks: '{{n}} nummers worden gecached…', + syncingTracks: 'Synchroniseren {{done}}/{{total}}…', + cancelDownload: 'Download annuleren', + offlineLibrary: 'Offline bibliotheek', + genres: 'Genres', + tracks: 'Nummers', + playlists: 'Playlists', + mostPlayed: 'Meest gespeeld', + losslessAlbums: 'Lossless', + radio: 'Internetradio', + folderBrowser: 'Mappenverkenner', + deviceSync: 'Apparaatsync', + libraryScope: 'Bibliotheekbereik', + allLibraries: 'Alle bibliotheken', + expandPlaylists: 'Afspeellijsten uitklappen', + collapsePlaylists: 'Afspeellijsten inklappen', + more: 'Meer', + feelingLucky: 'Geluksmix', +}; diff --git a/src/locales/nl/smartPlaylists.ts b/src/locales/nl/smartPlaylists.ts new file mode 100644 index 00000000..ddf63d4f --- /dev/null +++ b/src/locales/nl/smartPlaylists.ts @@ -0,0 +1,41 @@ +export const smartPlaylists = { + sectionBasic: '1. Basis', + sectionGenres: '2. Genres', + sectionYearsAndFilters: '3. Jaren en filters', + genreMode: 'Genre-modus', + genreModeInclude: 'Genres opnemen', + genreModeExclude: 'Genres uitsluiten', + genreSearchPlaceholder: 'Genres filteren...', + availableGenres: 'Beschikbaar', + selectedGenres: 'Geselecteerd', + yearMode: 'Jaarmodus', + yearModeInclude: 'Bereik opnemen', + yearModeExclude: 'Bereik uitsluiten', + name: 'Naam (zonder prefix)', + limit: 'Limiet', + limitHint: 'Hoeveel nummers in de playlist moeten komen (1-{{max}}, meestal 50).', + artistContains: 'Artiest bevat…', + albumContains: 'Album bevat…', + titleContains: 'Titel bevat…', + minRating: 'Minimale beoordeling', + minRatingAria: 'Minimale beoordeling voor smart playlist', + minRatingHint: '0 schakelt de minimumdrempel uit; 1-5 behoudt nummers met een beoordeling boven de gekozen waarde.', + fromYear: 'Vanaf jaar', + toYear: 'Tot jaar', + excludeUnrated: 'Nummers zonder beoordeling uitsluiten', + compilationOnly: 'Alleen compilaties', + create: 'Nieuwe Smart Playlist', + save: 'Smart Playlist opslaan', + created: '{{name}} aangemaakt', + updated: '{{name}} bijgewerkt', + createFailed: 'Smart playlist kon niet worden aangemaakt.', + updateFailed: 'Smart playlist kon niet worden bijgewerkt.', + navidromeOnly: 'Smart playlists kunnen alleen op Navidrome-servers worden aangemaakt.', + loadFailed: 'Smart playlists konden niet vanuit Navidrome worden geladen.', + sortRandom: 'Sorteren: willekeurig', + sortTitleAsc: 'Sorteren: titel A-Z', + sortTitleDesc: 'Sorteren: titel Z-A', + sortYearDesc: 'Sorteren: jaar aflopend', + sortYearAsc: 'Sorteren: jaar oplopend', + sortPlayCountDesc: 'Sorteren: afspeeltelling aflopend', +}; diff --git a/src/locales/nl/songInfo.ts b/src/locales/nl/songInfo.ts new file mode 100644 index 00000000..74c0d3cf --- /dev/null +++ b/src/locales/nl/songInfo.ts @@ -0,0 +1,23 @@ +export const songInfo = { + title: 'Nummerinfo', + songTitle: 'Titel', + artist: 'Artiest', + album: 'Album', + albumArtist: 'Albumartiest', + year: 'Jaar', + genre: 'Genre', + duration: 'Duur', + track: 'Track', + format: 'Formaat', + bitrate: 'Bitrate', + sampleRate: 'Samplefrequentie', + bitDepth: 'Bitdiepte', + channels: 'Kanalen', + fileSize: 'Bestandsgrootte', + path: 'Locatie', + replayGainTrack: 'RG Track Gain', + replayGainAlbum: 'RG Album Gain', + replayGainPeak: 'RG Track Peak', + mono: 'Mono', + stereo: 'Stereo', +}; diff --git a/src/locales/nl/statistics.ts b/src/locales/nl/statistics.ts new file mode 100644 index 00000000..ce5ce1c4 --- /dev/null +++ b/src/locales/nl/statistics.ts @@ -0,0 +1,47 @@ +export const statistics = { + title: 'Statistieken', + recentlyPlayed: 'Recent afgespeeld', + mostPlayed: 'Meest gespeelde albums', + highestRated: 'Best beoordeelde albums', + genreDistribution: 'Genreverdeling (Top 20)', + loadMore: 'Meer laden', + statArtists: 'Artiesten', + statArtistsTooltip: 'Alleen albumartiesten — artiesten die enkel als trackartiest voorkomen (featuring, gast, enz.) zonder eigen album worden niet meegeteld.', + statAlbums: 'Albums', + statSongs: 'Nummers', + statGenres: 'Genres', + statPlaytime: 'Totale speelduur', + genreInsights: 'Genre-inzichten', + formatDistribution: 'Formaatdistributie', + formatSample: 'Steekproef van {{n}} nummers', + computing: 'Berekenen…', + genreSongs: '{{count}} nummers', + genreAlbums: '{{count}} albums', + recentlyAdded: 'Recent toegevoegd', + decadeDistribution: 'Albums per decennium', + decadeAlbums_one: '{{count}} album', + decadeAlbums_other: '{{count}} albums', + decadeUnknown: 'Onbekend', + lfmTitle: 'Last.fm-statistieken', + lfmTopArtists: 'Topartiesten', + lfmTopAlbums: 'Topalbums', + lfmTopTracks: 'Topnummers', + lfmPlays: '{{count}} keer gespeeld', + lfmPeriodOverall: 'Alle tijd', + lfmPeriod7day: '7 dagen', + lfmPeriod1month: '1 maand', + lfmPeriod3month: '3 maanden', + lfmPeriod6month: '6 maanden', + lfmPeriod12month: '12 maanden', + lfmNotConnected: 'Verbind Last.fm in Instellingen om je statistieken te zien.', + lfmRecentTracks: 'Recente scrobbles', + lfmNowPlaying: 'Nu bezig', + lfmJustNow: 'zojuist', + lfmMinutesAgo: '{{n}} min geleden', + lfmHoursAgo: '{{n}} uur geleden', + lfmDaysAgo: '{{n}} dagen geleden', + topRatedSongs: 'Best beoordeelde nummers', + topRatedArtists: 'Best beoordeelde artiesten', + noRatedSongs: 'Nog geen beoordeelde nummers. Beoordeel nummers in album- of afspeellijstweergave.', + noRatedArtists: 'Nog geen beoordeelde artiesten.', +}; diff --git a/src/locales/nl/tracks.ts b/src/locales/nl/tracks.ts new file mode 100644 index 00000000..6096b51e --- /dev/null +++ b/src/locales/nl/tracks.ts @@ -0,0 +1,15 @@ +export const tracks = { + title: 'Nummers', + subtitle: 'Bladeren. Zoeken. Ontdekken.', + heroEyebrow: 'Nummer van het moment', + heroReroll: 'Een ander kiezen', + playSong: 'Afspelen', + enqueueSong: 'Aan wachtrij toevoegen', + railRandom: 'Willekeurige selectie', + railHighlyRated: 'Hoog beoordeeld', + browseTitle: 'Alle nummers doorbladeren', + browseUnsupported: 'Deze server toont niet de hele bibliotheek in één keer. Gebruik de zoekbalk hierboven om specifieke nummers te vinden.', + searchPlaceholder: 'Zoek op titel, artiest of album…', + count_one: '{{count}} nummer', + count_other: '{{count}} nummers', +}; diff --git a/src/locales/nl/tray.ts b/src/locales/nl/tray.ts new file mode 100644 index 00000000..969f12a4 --- /dev/null +++ b/src/locales/nl/tray.ts @@ -0,0 +1,8 @@ +export const tray = { + playPause: 'Afspelen / Pauzeren', + nextTrack: 'Volgende nummer', + previousTrack: 'Vorige nummer', + showHide: 'Tonen / Verbergen', + exitPsysonic: 'Psysonic afsluiten', + nothingPlaying: 'Niets wordt afgespeeld', +}; diff --git a/src/locales/nl/whatsNew.ts b/src/locales/nl/whatsNew.ts new file mode 100644 index 00000000..fe371772 --- /dev/null +++ b/src/locales/nl/whatsNew.ts @@ -0,0 +1,8 @@ +export const whatsNew = { + title: 'Wat is nieuw', + empty: 'Nog geen changelog-item voor deze versie.', + bannerTitle: 'Changelog', + bannerCollapsed: 'Nieuw in v{{version}}', + dismiss: 'Verbergen', + close: 'Sluiten', +}; diff --git a/src/locales/ro.ts b/src/locales/ro.ts deleted file mode 100644 index f309ee17..00000000 --- a/src/locales/ro.ts +++ /dev/null @@ -1,1876 +0,0 @@ -export const roTranslation = { - sidebar: { - library: 'Librărie', - mainstage: 'Scena Principală', - newReleases: 'Lansări Noi', - allAlbums: 'Toate Albumele', - randomAlbums: 'Albume Aleatorii', - randomPicker: 'Construiește un Mix', - artists: 'Artiști', - composers: 'Compozitori', - randomMix: 'Mix Aleatoriu', - favorites: 'Favorite', - nowPlaying: 'Se Redă Acum', - system: 'Sistem', - statistics: 'Statistici', - settings: 'Setări', - help: 'Ajutor', - expand: 'Extinde bara laterală', - collapse: 'Restrânge bara laterală', - - downloadingTracks: 'Se descarcă {{n}} piese…', - syncingTracks: 'Se sincronizează {{done}}/{{total}}…', - cancelDownload: 'Anulează descărcarea', - offlineLibrary: 'Librărie Offline', - genres: 'Genuri', - tracks: 'Piese', - playlists: 'Playlisturi', - smartPlaylists: 'Playlisturi Smart', - mostPlayed: 'Cele mai Redate', - losslessAlbums: 'Lossless', - radio: 'Radio Internet', - folderBrowser: 'Browser de foldere', - deviceSync: 'Sincronizare Dispozitive', - libraryScope: 'Domeniul bibliotecii', - allLibraries: 'Toate librăriile', - expandPlaylists: 'Extinde playlisturi', - collapsePlaylists: 'Restrânge playlisturi', - more: 'Mai mult', - feelingLucky: 'Mix Norocos', - }, - home: { - hero: 'Promovat', - starred: 'Evaluate', - recent: 'Adăugate Recent', - mostPlayed: 'Cele mai Redate', - recentlyPlayed: 'Redate Recent', - losslessAlbums: 'Albume Lossless', - discover: 'Descoperă', - discoverSongs: 'Descoperă Piese', - loadMore: 'Încarcă mai Mult', - discoverMore: 'Descoperă mai Mult', - discoverArtists: 'Descoperă Artiști', - discoverArtistsMore: 'Toți Artiștii', - becauseYouLike: 'Deoarece ai ascultat…', - becauseYouLikeFor: 'Deoarece ai ascultat {{artist}}', - similarTo: 'Similar cu {{artist}}', - becauseYouLikeTracks_one: '{{count}} piesă', - becauseYouLikeTracks_other: '{{count}} piese' - }, - hero: { - eyebrow: 'Album Promovat', - playAlbum: 'Redă Album', - enqueue: 'Pune în coadă', - enqueueTooltip: 'Adaugă întregul album în coadă', - }, - search: { - placeholder: 'Caută un artist, album sau piesă…', - noResults: 'Niciun rezultat pentru "{{query}}"', - artists: 'Artiști', - albums: 'Albume', - songs: 'Piese', - clearLabel: 'Șterge căutarea', - addedToQueueToast: 'Adăugat "{{title}}" în coadă', - title: 'Caută', - resultsFor: 'Rezultate pentru "{{query}}"', - album: 'Album', - advanced: 'Căutare avansată', - advancedSearchTerm: 'Termen de căutare', - advancedSearchPlaceholder: 'Titlu, album, artist…', - advancedGenre: 'Gen', - advancedAllGenres: 'Toate genurile', - advancedYear: 'An', - advancedYearFrom: 'de la', - advancedYearTo: 'până la', - advancedAll: 'Toate', - advancedSearch: 'Căutare', - advancedEmpty: 'Introdu un termen de căutare sau alege un filtru pentru a începe', - advancedNoResults: 'Niciun rezultat găsit.', - advancedGenreNote: 'Piesele sunt alese aleatoriu din acest gen', - recentSearches: 'Căutări Recente', - browse: 'Răsfoiește', - emptyHint: 'Ce vrei să auzi?', - genres: 'Genuri', - }, - nowPlaying: { - tooltip: 'Cine ascultă?', - title: 'Cine ascultă?', - loading: 'Se încarcă…', - nobody: 'Nimeni nu ascultă momentan.', - minutesAgo: 'acum {{n}}m', - nothingPlaying: 'Nu se redă nimic încă. Începe o piesă!', - aboutArtist: 'Despre Artist', - fromAlbum: 'Din acest Album', - viewAlbum: 'Vezi Albumul', - goToArtist: 'Către Artist', - readMore: 'Mai mult', - showLess: 'Mai puțin', - genreInfo: 'Gen', - trackInfo: 'Informații despre Piesă', - topSongs: 'Cele mai redate din acest artist', - topSongsCredit: 'Top piese de la {{name}}', - trackPosition: 'Piesa {{pos}}', - playsCount_one: '{{count}} redare', - playsCount_other: '{{count}} redări', - releasedYearsAgo_one: 'acum {{count}} an', - releasedYearsAgo_other: 'acum {{count}} ani', - discography: 'Discografie', - lastfmStats: 'Statistici Last.fm', - thisTrack: 'Această piesă', - thisArtist: 'Acest artist', - listeners: 'ascultători', - scrobbles: 'scrobble-uri', - yourScrobbles: 'de tine', - listenersN: '{{n}} ascultători', - scrobblesN: '{{n}} scrobble-uri', - playsByYouN: 'redate {{n}}× de tine', - openTrackOnLastfm: 'Piesă în Last.fm', - openArtistOnLastfm: 'Artist în Last.fm', - rgTrackTooltip: 'ReplayGain (piesă)', - rgAlbumTooltip: 'ReplayGain (album)', - rgAutoTooltip: 'ReplayGain (auto)', - showMoreTracks: 'Arată încă {{count}}', - showLessTracks: 'Arată mai puțin', - hideCard: 'Ascunde cardul', - layoutMenu: 'Layout', - visibleCards: 'Carduri vizibile', - hiddenCards: 'Carduri ascunse', - noHiddenCards: 'Niciun card ascuns', - resetLayout: 'Resetează layout-ul', - emptyColumn: 'Lasă cardurile aici', - }, - contextMenu: { - playNow: 'Redă acum', - playNext: 'Redă următorul', - addToQueue: 'Adaugă la coadă', - enqueueAlbum: 'Adaugă Albumul la coadă', - enqueueAlbums_one: 'Adaugă la coadă {{count}} Album', - enqueueAlbums_other: 'Adaugă la coadă {{count}} Albume', - startRadio: 'Pornește Radioul', - instantMix: 'Mix Instant', - instantMixFailed: 'Nu s-a putut crea Mixul Instant — eroare de server sau plugin.', - cliMixNeedsTrack: 'Nimic nu este redat — pornește redarea mai întâi, apoi rulează comanda mix din nou.', - lfmLove: 'Apreciază în Last.fm', - lfmUnlove: 'Elimină aprecierea în Last.fm', - favorite: 'Favorit', - favoriteArtist: 'Artist Favorit', - favoriteAlbum: 'Album Favorit', - unfavorite: 'Șterge din Favorite', - unfavoriteArtist: 'Șterge Artistul din Favorite', - unfavoriteAlbum: 'Șterge Albumul din Favorite', - removeFromQueue: 'Șterge din Coadă', - removeFromPlaylist: 'Șterge din Playlist', - openAlbum: 'Deschide Albumul', - goToArtist: 'Vezi Artistul', - download: 'Descarcă (ZIP)', - addToPlaylist: 'Adaugă la Playlist', - selectedPlaylists: '{{count}} playlisturi selectate', - selectedAlbums: '{{count}} albume selectate', - selectedArtists: '{{count}} artiști selectați', - songInfo: 'Informații despre Piesă', - shareLink: 'Copiază link-ul', - shareCopied: 'Link copiat în clipboard.', - shareCopyFailed: 'Nu s-a putut copia în clipboard.', - }, - sharePaste: { - notLoggedIn: 'Loghează-te și adaugă serverul înainte de a lipi link-ul distribuit.', - noMatchingServer: 'Niciun server nu corespunde cu acest link. Adaugă un server cu această adresă: {{url}}', - trackUnavailable: 'Această piesă nu a fost găsită în server.', - albumUnavailable: 'Acest album nu a fost găsit în server.', - artistUnavailable: 'Acest artist nu a fost găsit în server.', - composerUnavailable: 'Acest compozitor nu a fost găsit pe server.', - openedTrack: 'Se redă piesa distribuită.', - openedAlbum: 'Se deschide albumul distribuit.', - openedArtist: 'Se deschide artistul distribuit.', - openedComposer: 'Se deschide compozitorul distribuit.', - openedQueue_one: 'Se redă {{count}} piesă din link-ul distribuit.', - openedQueue_other: 'Se redau {{count}} piese din link-ul distribuit.', - openedQueuePartial: - 'Se redau {{played}} din {{total}} piese din link ({{skipped}} nu au fost găsite în server).', - queueAllUnavailable: 'Nicio piesă din acest link nu a fost găsită în server.', - genericError: 'Nu s-a putut deschide link-ul distribuit.', - }, - albumDetail: { - back: 'Înapoi', - orbitDoubleClickHint: 'Apasă dublu-clic pentru a adăuga această piesă în coada Orbit', - playAll: 'Redă tot', - shareAlbum: 'Distribuie Albumul', - enqueue: 'Adaugă în coadă', - enqueueTooltip: 'Adaugă întregul album în coadă', - artistBio: 'Biografia Artistului', - download: 'Descarcă (ZIP)', - downloading: 'Se încarcă…', - cacheOffline: 'Fă disponibil offline', - offlineCached: 'Disponibil offline', - offlineDownloading: 'Se salvează în cache… ({{n}}/{{total}})', - removeOffline: 'Șterge cache-ul offline', - offlineStorageFull: 'Stocare offline plină (limită: {{mb}} MB). Eliberează spațiu ștergând un album din Librăria Offline, sau mărește limita în Setări.', - offlineStorageGoToLibrary: 'Librăria Offline', - offlineStorageGoToSettings: 'Setări', - favoriteAdd: 'Adaugă la Favorite', - favoriteRemove: 'Șterge din Favorite', - favorite: 'Favorit', - noBio: 'Nicio biografie disponibilă.', - moreByArtist: 'Mai multe de la {{artist}}', - tracksCount: '{{n}} Piese', - goToArtist: 'Către {{artist}}', - moreLabelAlbums: 'Mai multe albume în {{label}}', - trackTitle: 'Titlu', - trackAlbum: 'Album', - trackArtist: 'Artist', - trackGenre: 'Gen', - trackFormat: 'Format', - trackFavorite: 'Favorit', - trackRating: 'Rating', - trackDuration: 'Durată', - trackTotal: 'Total', - columns: 'Coloane', - resetColumns: 'Resetează la predefinite', - notFound: 'Albumul nu a fost găsit.', - bioModal: 'Biografia Artistului', - bioClose: 'Închide', - ratingLabel: 'Rating', - enlargeCover: 'Extinde', - filterSongs: 'Filtrează piese…', - sortNatural: 'Natural', - sortByTitle: 'A–Z (Titlu)', - sortByArtist: 'A–Z (Artist)', - sortByAlbum: 'A–Z (Album)', - }, - entityRating: { - albumShort: 'Rating album', - artistShort: 'Rating artist', - albumAriaLabel: 'Rating album', - artistAriaLabel: 'Rating artist', - selectedArtistsRatingAriaLabel: 'Rating în stele pentru {{count}} artiști selectați', - selectedAlbumsRatingAriaLabel: 'Rating în stele pentru {{count}} albume selectate ', - saveFailed: 'Nu s-a putut salva rating-ul.', - }, - artistDetail: { - back: 'Înapoi', - albums: 'Albume', - album: 'Album', - playAll: 'Redă tot', - shareArtist: 'Distribuie artistul', - shuffle: 'Amestecă', - radio: 'Radio', - loading: 'Se încarcă…', - noRadio: 'Nicio piesă similară găsită pentru acest artist.', - notFound: 'Artistul nu a fost găsit.', - albumsBy: 'Albume de {{name}}', - topTracks: 'Top Piese', - noAlbums: 'Niciun album găsit.', - trackTitle: 'Titlu', - trackAlbum: 'Album', - trackDuration: 'Durată', - favoriteAdd: 'Adaugă la Favorite', - favoriteRemove: 'Șterge de la Favorite', - favorite: 'Favorit', - albumCount_one: '{{count}} Album', - albumCount_other: '{{count}} Albume', - openedInBrowser: 'Deschide în browser', - featuredOn: 'Apare de asemenea în', - similarArtists: 'Artiști similari', - cacheOffline: 'Salvează discografia offline', - offlineCached: 'Discografie stocată în cache', - offlineDownloading: 'Se salvează în cache… ({{done}}/{{total}} albume)', - uploadImage: 'Încarcă imaginea artistului', - uploadImageError: 'Nu s-a reușit încărcarea imaginii', - releaseTypes: { - album: 'Album', - ep: 'EP', - single: 'Single', - compilation: 'Compilație', - live: 'Live', - soundtrack: 'Soundtrack', - remix: 'Remix', - other: 'Altul', - }, - }, - favorites: { - title: 'Favorite', - empty: "Nu ai salvat nimic la favorite încă.", - artists: 'Artiști', - albums: 'Albume', - songs: 'Piese', - enqueueAll: 'Adaugă tot la coadă', - playAll: 'Redă tot', - removeSong: 'Șterge de la favorite', - stations: 'Stații Radio', - showingFiltered: 'Se afișează {{filtered}} din {{total}} ({{artist}})', - showingCount: 'Se afișează {{filtered}} din {{total}}', - clearArtistFilter: 'Șterge filtrul de artist', - noFilterResults: 'Niciun rezultat cu filtrele selectate.', - allArtists: 'Toți Artiștii', - topArtists: 'Top Artiști din Favorite', - topArtistsSongCount_one: '{{count}} piesă', - topArtistsSongCount_other: '{{count}} piese', - }, - randomLanding: { - title: 'Crează un Mix', - mixByTracks: 'Mix după Piese', - mixByTracksDesc: 'Selecție aleatorie de piese din întreaga librărie', - mixByAlbums: 'Mix după Albume', - mixByAlbumsDesc: 'Selecție aleatorie de albume pentru următoarea ta descoperire', - mixByLucky: 'Mix Norocos', - mixByLuckyDesc: 'Mix instant inteligent din artiștii, albumele și ratingurile tale de top', - }, - randomAlbums: { - title: 'Albume aleatorii', - refresh: 'Reîmprospătează', - }, - genres: { - title: 'Genuri', - genreCount: 'Genuri', - albumCount_one: '{{count}} album', - albumCount_other: '{{count}} albume', - loading: 'Se încarcă genuri…', - empty: 'Niciun gen găsit.', - albumsLoading: 'Se încarcă albume…', - albumsEmpty: 'Niciun album găsit pentru acest gen.', - loadMore: 'Încarcă mai mult', - back: 'Înapoi', - }, - randomMix: { - title: 'Mix Aleatoriu', - remix: 'Remix', - remixTooltip: 'Încarcă noi piese aleatorii', - remixGenre: 'Remix {{genre}}', - remixTooltipGenre: 'Încarcă piese {{genre}} noi', - playAll: 'Redă tot', - trackTitle: 'Titlu', - trackArtist: 'Artist', - trackAlbum: 'Album', - trackFavorite: 'Favorit', - trackDuration: 'Durată', - favoriteAdd: 'Adaugă la Favorites', - favoriteRemove: 'Șterge din Favorite', - play: 'Redă', - trackGenre: 'Gen', - mixSettingsHeader: 'Setări Mix', - exclusionsHeader: 'Excluderi', - filterPanelInexactSizeNote: 'Mărimea mixului este o țintă — cererile mari pot returna mai puține piese dacă colecția serverului este mai mică.', - mixSize: 'Mărimea playlistului', - excludeAudiobooks: 'Exclude audiobookuri & redări radio', - excludeAudiobooksDesc: 'Potrivește cuvinte cheie cu gen, titlu, album și artist - ex. Hörbuch, Audiobook, Spoken Word, …', - genreBlocked: 'Cuvânt cheie blocat', - genreAddedToBlacklist: 'Adăugat la lista de filtre', - genreAlreadyBlocked: 'Deja blocat', - artistBlocked: 'Artist blocat', - artistAddedToBlacklist: 'Artist adăugat la lista de filtre', - artistClickHint: 'Clic pentru a bloca acest artist', - blacklistToggle: 'Filtru de cuvinte cheie', - genreMixTitle: 'Mix de Genuri', - genreMixDesc: 'Top 20 genuri după numărul de piese - clic pentru a încărca un mix aleatoriu', - genreMixAll: 'Toate piesele', - genreMixLoadMore: 'Încarcă încă 10', - genreMixNoGenres: 'Niciun gen găsit pe server.', - shuffleGenres: 'Arată genuri diferite', - filterPanelTitle: 'Filtre', - filterPanelDesc: 'Apasă pe un tag de gen sau nume de artist în lista de piese de mai jos pentru a o bloca din mixuri viitoare.', - genreClickHint: 'Apasă pe un tag de gen pentru a-l adăuga\nca un filtru de cuvânt cheie.\nFiltrul corespunde cu gen, titlu, album & artist.', - }, - luckyMix: { - done: 'Mix Norocos pregătit: {{count}} piese', - failed: 'Nu s-a putut crea Mixul Norocos. Încercați din nou.', - unavailable: 'Mixul Norocos nu este disponibil pentru acest server.', - cancelTooltip: 'Anulează crearea Mixului Norocos', - }, - albums: { - title: 'Toate albumele', - sortByName: 'A–Z (Album)', - sortByArtist: 'A–Z (Artist)', - sortNewest: 'Cele mai noi primele', - sortRandom: 'Aleatoriu', - yearFrom: 'De la', - yearTo: 'Până la', - yearFilterClear: 'Golește filtrul de an', - yearFilterLabel: 'An', - compilationLabel: 'Compilații', - compilationOnly: 'Doar compilații', - compilationHide: 'Ascunde compilațiile', - compilationTooltipAll: 'Toate albumele · clic: doar compilații', - compilationTooltipOnly: 'Doar compilații · clic: ascunde compilațiile', - compilationTooltipHide: 'Compilații ascunse · clic: arată toate', - select: 'Multi-selecție', - startSelect: 'Activează multi-selecția', - cancelSelect: 'Anulează', - selectionCount: '{{count}} selectate', - downloadZips: 'Descarcă ZIPuri', - addOffline: 'Adaugă Offline', - enqueueSelected_one: 'Adaugă în coadă ({{count}})', - enqueueSelected_other: 'Adaugă în coadă ({{count}})', - enqueueQueued_one: 'Adăugat {{count}} album în coadă', - enqueueQueued_other: 'Adăugat {{count}} albume în coadă', - downloadingZip: 'Se descarcă {{current}}/{{total}}: {{name}}', - downloadZipDone: '{{count}} ZIP(uri) descărcate', - downloadZipFailed: 'Nu s-a reușit descărcarea {{name}}', - offlineQueuing: 'Se adaugă în coadă {{count}} album(e) pentru offline…', - offlineFailed: 'Nu s-a reușit adăugarea {{name}} offline', - }, - tracks: { - title: 'Piese', - subtitle: 'Răsfoiește. Caută. Descoperă.', - heroEyebrow: 'Piesa momentului', - heroReroll: 'Alege alta', - playSong: 'Redă', - enqueueSong: 'Adaugă în coadă', - railRandom: 'Alegere aleatorie', - railHighlyRated: 'Foarte apreciate', - browseTitle: 'Caută toate piesele', - browseUnsupported: "Acest server nu afișează toată librăria deodată. Folosește căutarea de mai sus pentru a găsi piese specifice.", - searchPlaceholder: 'Găsește o piesă după titlu, artist sau album…', - count_one: '{{count}} piesă', - count_other: '{{count}} piese', - }, - artists: { - title: 'Artiști', - search: 'Caută…', - all: 'Tot', - gridView: 'Vizualizare grilă', - listView: 'Vizualizare listă', - imagesOn: 'Imagini artist pornit — poate mări încărcarea rețelei și a sistemului', - imagesOff: 'Imagini artist oprit — se arată doar inițialele', - loadMore: 'Încarcă mai mult', - notFound: 'Niciun artist găsit.', - albumCount_one: '{{count}} Album', - albumCount_other: '{{count}} Albume', - selectionCount: '{{count}} selectați', - select: 'Multi-selecție', - startSelect: 'Activează multi-selecția', - cancelSelect: 'Anulează', - addToPlaylist: 'Adaugă la Playlist', - }, - composers: { - title: 'Compozitori', - search: 'Caută…', - notFound: 'Niciun compozitor găsit.', - unsupported: 'Căutarea dupa Compozitori necesită Navidrome 0.55 sau mai nou.', - loadFailed: 'Nu s-au putut încărca compozitorii.', - retry: 'Reîncearcă', - involvedIn_one: 'Implicat în {{count}} album', - involvedIn_other: 'Implicat în {{count}} albume', - }, - composerDetail: { - back: 'Înapoi', - notFound: 'Compozitorul nu a fost găsit.', - about: 'Despre acest compozitor', - works: 'Lucrări', - noWorks: 'Nicio lucrare găsită.', - workCount_one: '{{count}} lucrare', - workCount_other: '{{count}} lucrări', - shareComposer: 'Distribuie compozitorul', - unknownComposer: 'Compozitor', - }, - login: { - subtitle: 'Playerul tău Navidrome Desktop', - serverName: 'Numele Serverului (opțional)', - serverNamePlaceholder: 'Navidrome-ul meu', - serverUrl: 'URL Server', - serverUrlPlaceholder: '192.168.1.100:4533 sau https://music.example.com', - username: 'Nume utilizator', - usernamePlaceholder: 'admin', - password: 'Parolă', - showPassword: 'Arată parola', - hidePassword: 'Ascunde parola', - connect: 'Conectează-te', - connecting: 'Se conectează…', - connected: 'Conectat!', - error: 'Conexiunea a eșuat – verifică detaliile.', - urlRequired: 'Introdu un server URL.', - savedServers: 'Servere salvate', - addNew: 'Sau adaugă un nou server', - orMagicString: 'Sau un string magic', - magicStringPlaceholder: 'Lipește un string distribuit (psysonic1-…)', - magicStringInvalid: 'String magic invalid sau ilizibil.', - }, - connection: { - connected: 'Conectat', - connectedTo: 'Conectat la {{server}}', - disconnected: 'Deconectat', - disconnectedFrom: 'Nu s-a putut ajunge la {{server}} — apasă pentru a verifica setările', - checking: 'Se conectează…', - extern: 'Extern', - offlineTitle: 'Nicio conexiune la server', - offlineSubtitle: 'Nu s-a putut ajunge la {{server}}. Verifică rețeaua sau serverul.', - offlineModeBanner: 'Modul Offline — se redă din cache-ul local', - offlineNoCacheBanner: 'Nicio conexiune la server — nu s-a putut ajunge la {{server}}', - offlineLibraryTitle: 'Librărie offline', - offlineLibraryEmpty: 'Niciun album adăugat în cache. Conectează-te, deschide un album și apasă "Fă disponibil offline".', - offlineAlbumCount: '{{n}} album', - offlineAlbumCount_plural: '{{n}} albume', - offlineFilterAll: 'Toate', - offlineFilterAlbums: 'Albume', - offlineFilterPlaylists: 'Playlisturi', - offlineFilterArtists: 'Discografii', - retry: 'Reîncearcă', - serverSettings: 'Setările serverului', - switchServerTitle: 'Schimbă serverul', - switchServerHint: 'Apasă pentru a alege alt server salvat.', - manageServers: 'Gestionează serverele…', - switchFailed: 'Nu s-a putut schimba — nu s-a putut ajunge la server.', - lastfmConnected: 'Last.fm conectat ca @{{user}}', - lastfmSessionInvalid: 'Sesiune invalidă — apasă pentru a te reconecta', - }, - common: { - albums: 'Albume', - album: 'Album', - loading: 'Se încarcă…', - loadingMore: 'Se încarcă…', - loadingPlaylists: 'Se încarcă Playlisturi…', - noAlbums: 'Niciun album găsit.', - downloading: 'Se descarcă…', - downloadZip: 'Descarcă (ZIP)', - back: 'Înapoi', - cancel: 'Anulează', - close: 'Închide', - save: 'Salvează', - delete: 'Șterge', - use: 'Folosește', - add: 'Adaugă', - new: 'Nou', - active: 'Activ', - download: 'Descarcă', - chooseDownloadFolder: 'Alege folderul de descărcare', - noFolderSelected: 'Niciun folder selectat', - rememberDownloadFolder: 'Ține minte acest folder', - filterGenre: 'Filtru de gen', - filterSearchGenres: 'Caută genuri…', - filterNoGenres: 'Niciun gen nu corespunde', - filterClear: 'Golește', - favorites: 'Favorite', - favoritesTooltipOff: 'Arată doar favorite', - favoritesTooltipOn: 'Arată tot', - play: 'Redă', - bulkSelected: '{{count}} selectate', - clearSelection: 'Golește selecția', - bulkAddToPlaylist: 'Adaugă la Playlist', - bulkRemoveFromPlaylist: 'Șterge din Playlist', - bulkClear: 'Golește selecția', - updaterAvailable: 'Update disponibil', - updaterVersion: 'v{{version}} este disponibil', - updaterWebsite: 'Website', - updaterModalTitle: 'Nouă versiune disponibilă', - updaterChangelog: "Ce este nou", - updaterDownloadBtn: 'Descarcă acum', - updaterSkipBtn: 'Sari peste această Versiune', - updaterRemindBtn: 'Amintește-mi mai târziu', - updaterDone: 'Descărcare finalizată', - updaterShowFolder: 'Arată în Folder', - updaterInstallHint: 'Închide Psysonic și rulează programul de instalare manual.', - updaterAurHint: 'Instalează update-ul prin AUR:', - updaterErrorMsg: 'Descărcare eșuată', - updaterRetryBtn: 'Reîncearcă', - updaterInstallNow: 'Instalează acum', - updaterMacReadyTitle: 'Pregătit de instalare', - updaterMacReady: 'Acest update descarcă, verifică și este aplicat în loc — nu este nevoie de DMG. Aplicația își dă restart automat când e gata.', - updaterTrustNotarized: 'Notarizat de Apple', - updaterTrustSignature: 'Semnătură verificată', - updaterMacDoneTitle: 'Update instalat', - updaterRestartingIn: 'Se restartează în {{n}}s…', - updaterRestarting: 'Se restartează…', - updaterRestartNow: 'Restart acum', - durationHoursMinutes: '{{hours}}h {{minutes}}m', - durationMinutesOnly: '{{minutes}}m', - updaterOpenGitHub: 'Deschide în GitHub', - filters: 'Filtre', - more: 'mai mult', - yearRange: 'Interval de an', - clearAll: 'Golește tot', - }, - settings: { - title: 'Setări', - language: 'Limbă', - languageEn: 'Engleză', - languageDe: 'Germană', - languageFr: 'Franceză', - languageNl: 'Olandeză', - languageZh: 'Chineză', - languageNb: 'Norvegiană', - languageRu: 'Rusă', - languageEs: 'Spaniolă', - languageRo: 'Română', - font: 'Font', - fontHintOpenDyslexic: 'Prietenos cu dislexia · Chineza nu este suportată', - theme: 'Temă', - appearance: 'Aparență', - servers: 'Servere', - serverName: 'Nume Server', - serverUrl: 'URL Server', - serverUrlPlaceholder: '192.168.1.100:4533 sau https://music.example.com', - serverUsername: 'Nume utilizator', - serverPassword: 'Parolă', - addServer: 'Adaugă Server', - addServerTitle: 'Adaugă Server nou', - useServer: 'Folosește', - deleteServer: 'Șterge', - noServers: 'Niciun server salvat.', - serverActive: 'Activ', - confirmDeleteServer: 'Șterge server "{{name}}"?', - serverConnecting: 'Se conectează…', - serverConnected: 'Conectat!', - serverFailed: 'Conexiune eșuată.', - testBtn: 'Testează Conexiunea', - testingBtn: 'Se testează…', - serverCompatible: 'Făcut pentru Navidrome. Alte servere compatibile cu Subsonic (Gonic, Airsonic, …) pot rula cu funcționalitate redusă, deoarece Psysonic folosește multe endpointuri API specifice Navidrome.', - userMgmtTitle: 'Gestionarea Utilizatorilor', - userMgmtDesc: 'Gestionează utilizatorii de pe acest server. Necesită privilegii admin.', - userMgmtNoAdmin: 'Ai nevoie de privilegii de admin pentru a gestiona utilizatorii de pe acest server.', - userMgmtLoadError: 'Eroare la încărcarea utilizatorilor.', - userMgmtLoadFriendly: 'Serverul nu a răspuns — acesta este de obicei un caz singular.', - userMgmtRetry: 'Reîncearcă', - userMgmtEmpty: 'Niciun utilizator găsit.', - userMgmtYouBadge: 'Tu', - userMgmtAdminBadge: 'Admin', - userMgmtAddUser: 'Adaugă Utilizator', - userMgmtAddUserTitle: 'Adaugă Nou Utilizator', - userMgmtEditUserTitle: 'Editează Utilizatorul', - userMgmtUsername: 'Nume utilizator', - userMgmtName: 'Nume afișaj', - userMgmtEmail: 'Email', - userMgmtPassword: 'Parolă', - userMgmtPasswordEditHint: 'Introdu o parolă nouă pentru a o actualiza.', - userMgmtRoleAdmin: 'Admin', - userMgmtLibraries: 'Librării', - userMgmtLibrariesAdminHint: 'Utilizatorii Admin au acces automat la toate librăriile.', - userMgmtLibrariesEmpty: 'Nicio librărie disponibilă pe acest server.', - userMgmtLibrariesValidation: 'Alege cel puțin o librărie.', - userMgmtLibrariesUpdateError: 'Utilizator salvat, dar atribuirea librăriilor a eșuat', - userMgmtNoLibraries: 'Nicio librărie asignată', - userMgmtNeverSeen: 'Niciodată', - userMgmtSave: 'Salvează', - userMgmtCancel: 'Anulează', - userMgmtDelete: 'Șterge', - userMgmtEdit: 'Editează', - userMgmtConfirmDelete: 'Șterge utilizatorul "{{username}}"? Acestă acțiune nu poate fi anulată.', - userMgmtCreateError: 'Nu s-a putut crea utilizatorul.', - userMgmtUpdateError: 'Nu s-a putut actualiza utilizatorul.', - userMgmtDeleteError: 'Nu s-a putut șterge utilizatorul.', - userMgmtCreated: 'Utilizator creat.', - userMgmtUpdated: 'Utilizator actualizat.', - userMgmtDeleted: 'Utilizator șters.', - userMgmtValidationMissing: 'Numele de utilizator, numele de afișaj și parola sunt necesare.', - userMgmtValidationMissingIdentity: 'Numele de utilizator și numele de afișaj sunt necesare.', - userMgmtMagicStringGenerate: 'Generează string-ul magic', - userMgmtSaveAndMagicString: 'Salvează și obține string-ul magic', - userMgmtMagicStringPasswordNavHint: - 'Navidrome va salva această parolă pentru utilizator. Dacă diferă de cea curentă, serverul va actualiza parola de login.', - userMgmtMagicStringPlaintextWarning: - 'Distribuie string-ul magic cu grijă: conține o parolă necriptată (codificarea nu este criptare). Oricine cu string-ul complet se poate conecta ca acest utilizator.', - userMgmtMagicStringCopied: 'String-ul magic copiat în clipboard.', - userMgmtMagicStringCopyFailed: 'Nu s-a putut copia în clipboard.', - userMgmtMagicStringLoginFailed: 'Verificarea parolei a eșuat — credențialele nu au putut fi verificate.', - userMgmtMagicStringModalTitle: 'Generează string-ul magic', - userMgmtMagicStringModalDesc: 'Introdu parola Subsonic pentru "{{username}}". Este inclusă în string-ul magic copiat.', - userMgmtMagicStringModalConfirm: 'Copiază string-ul', - audiomuseTitle: 'AudioMuse-AI (Navidrome)', - audiomuseDesc: - 'Pornește dacă acest server are AudioMuse-AI Navidrome plugin configurat. Activează Mixul Instant din piese si folosește artiști similari de pe partea de server în loc de Last.fm pe paginile de artiști.', - audiomuseIssueHint: - 'Mixul Instant a eșuat recent — verifică plugin-ul Navidrome și API-ul AudioMuse. Artiștii similari sunt bazați pe Last.fm când serverul nu returnează nimic.', - connected: 'Conectat', - failed: 'Eșuat', - eqTitle: 'Egalizator', - eqEnabled: 'Activează Egalizatorul', - eqPreset: 'Preset', - eqPresetCustom: 'Personalizat', - eqPresetBuiltin: 'Preseturi încorporate', - eqPresetCustomGroup: 'Preseturile mele', - eqSavePreset: 'Salvează ca Preset', - eqPresetName: 'Nume preset…', - eqDeletePreset: 'Șterge preset', - eqResetBands: 'Resetează la Plat', - eqPreGain: 'Pre-gain', - eqResetPreGain: 'Resetează pre-gain', - eqAutoEqTitle: 'Căutare Căști AutoEQ', - eqAutoEqPlaceholder: 'Caută model căști / IEM…', - eqAutoEqSearching: 'Se caută…', - eqAutoEqNoResults: 'Niciun rezultat găsit', - eqAutoEqError: 'Căutarea a eșuat', - eqAutoEqRateLimit: 'Limita ratei GitHub a fost atinsă — încearcă din nou într-un minut', - eqAutoEqFetchError: 'Nu s-a putut lua profilul EQ', - lfmTitle: 'Last.fm', - lfmConnect: 'Conectează-te cu Last.fm', - lfmConnecting: 'Se așteaptă autorizarea…', - lfmConfirm: 'Am autorizat aplicația', - lfmConnected: 'Conectat ca', - lfmDisconnect: 'Deconectează-te', - lfmConnectDesc: 'Conectează contul tău Last.fm pentru a pornit scrobbling și update-uri Now Playing direct din Psysonic — nicio nevoie configurare Navidrome necesară.', - lfmOpenBrowser: 'O fereastră browser se va deschide. Autorizează Psysonic în Last.fm, apoi apasă pe butonul de mai jos.', - lfmScrobbles: '{{n}} scrobble-uri', - lfmMemberSince: 'Membru din {{year}}', - scrobbleEnabled: 'Scrobbling dezactivat', - scrobbleDesc: 'Trimite piese la Last.fm după 50% timp de redare', - behavior: 'Comportamentul Aplicației', - cacheTitle: 'Spațiu de stocare maxim', - cacheDesc: 'Artă copertă și imagini artist. Când este plin, cele mai vechi intrări sunt șterse automat. Albumele offline nu sunt șterse automat, dar vor fi șterse când memoria cache este curățată manual.', - cacheUsedImages: 'Imagini:', - cacheUsedOffline: 'Piese offline:', - cacheUsedHot: 'Mărimea pe disc:', - hotCacheTrackCount: 'Piese în memoria cache:', - cacheMaxLabel: 'Mărimea maximă', - cacheClearBtn: 'Golește memoria cache', - waveformCacheClearBtn: 'Golește cache-ul formelor de undă', - cacheClearWarning: 'Aceasta va înlătura de asemenea toate albumele offline din librărie.', - cacheClearConfirm: 'Golește totul', - cacheClearCancel: 'Anulează', - waveformCacheCleared: 'Cache-ul formelor de undă golit ({{count}} rows).', - waveformCacheClearFailed: 'Golirea cache-ului formelor de undă a eșuat.', - offlineDirTitle: 'Librărie offline (În Aplicație)', - offlineDirDesc: 'Locația stocării pieselor pe care le faci disponibile offline în Psysonic.', - offlineDirDefault: 'Implicit (App Data)', - offlineDirChange: 'Schimbă directorul', - offlineDirClear: 'Resetează la implicit', - offlineDirHint: 'Noile descărcări vor folosi această locație. Descărcările existente rămân la adresa originală.', - hotCacheTitle: 'Cache-ul hot playback', - hotCacheDisclaimer: 'Preîncarcă piesele ce urmează din coadă și păstrează anterioarele. Când este pornit, folosește spațiu pe disc și rețea.', - hotCacheDirDefault: 'Implicit (App Data)', - hotCacheDirChange: 'Schimbă folderul', - hotCacheDirClear: 'Resetează la implicit', - hotCacheDirHint: 'Schimbarea folderului resetează indexul din aplicație; fișierele aflate deja pe disc stau unde sunt până când le ștergi.', - hotCacheEnabled: 'Activează cache-ul hot playback cache', - hotCacheMaxMb: 'Mărimea maximă cache', - hotCacheDebounce: 'Debounce la schimbarea cozii', - hotCacheDebounceImmediate: 'Imediat', - hotCacheDebounceSeconds: '{{n}} s', - hotCacheClearBtn: 'Golește hot cache', - audioOutputDevice: 'Dispozitiv de ieșire audio', - audioOutputDeviceDesc: 'Alege prin ce dispozitiv audio să redea Psysonic. Schimbările au efect imediat și re-încep piesa curentă.', - audioOutputDeviceDefault: 'Implicit sistem', - audioOutputDeviceRefresh: 'Reîmprospătează lista dispozitivelor', - audioOutputDeviceOsDefaultNow: 'ieșirea curentă a sistemului', - audioOutputDeviceListError: 'Nu s-a putut încărca lista dispozitivelor audio', - audioOutputDeviceNotInCurrentList: 'nu există în lista curentă', - audioOutputDeviceMacNotice: 'În macOS, redarea urmărește mereu dispozitivul audio de ieșire al sistemului din motive tehnice. Schimbă ținta în Setări → Sunet sau iconița difuzor din bara de meniu. Fundal: CoreAudio declanșează un prompt de permisiune de microfon când se deschide un stream non-implicit — îl evităm folosind opțiunea implicită a sistemului mereu.', - hiResTitle: 'Playback Hi-Res nativ', - hiResEnabled: 'Pornește playback-ul hi-res nativ', - hiResDesc: "Forțează ieșire implicită de 44.1 kHz pentru stabilitate maximă. Pornește doar dacă sistemul hardware și rețeaua suport fiabil rate mari de eșantionare (88.2 kHz+).", - showArtistImages: 'Afișează Imagini Artist', - showArtistImagesDesc: 'Încarcă și afișează imagini artist în Prezentarea generală a Artiștilor. Oprit implicit pentru a reduce I/O pe server și încărcarea rețelei pe librării mari.', - showOrbitTrigger: 'Afișează "Orbit" în antet', - showOrbitTriggerDesc: 'Declanșatorul din bara de sus pentru a începe sau intra într-o sesiune de ascultare distribuită. Ascunde-l dacă nu folosești Orbit - îl poți porni înapoi aici.', - showTrayIcon: 'Afișează Iconița Tavă', - showTrayIconDesc: 'Afișează iconița Psysonic în zona notificărilor de sistem / bara de meniu.', - minimizeToTray: 'Minimizează în Tavă', - minimizeToTrayDesc: 'La închiderea ferestrei, continuă rularea Psysonic în tava de sistem în loc de ieșire', - preloadMiniPlayer: 'Preîncarcă mini player', - preloadMiniPlayerDesc: 'Crează fereastra mini player în fundal la deschiderea aplicației pentru a arăta conținut instantaneu la prima deschidere. Folosește puțină extra memorie.', - discordRichPresence: 'Prezență Discord Rich', - discordRichPresenceDesc: 'Arată piesa redată curent pe profilul tău de Discord. Necesită Discord să ruleze.', - useCustomTitlebar: 'Bară de titlu personalizată', - useCustomTitlebarDesc: 'Înlocuiește bara de titlu a sistemului cu una care corespunde cu tema aplicației. Dezactivează pentru a folosi bara de titlu nativ GNOME/GTK.', - linuxWebkitSmoothScroll: 'Rotiță lină (Linux)', - linuxWebkitSmoothScrollDesc: 'Pornit: scroll inert. Oprit: linie cu linie, în stil GTK.', - discordCoverSource: 'Sursa artei de copertă', - discordCoverSourceDesc: 'De unde să fie preluată arta de album afișată pe profilul tău de Discord.', - discordCoverNone: 'Niciuna (doar iconița aplicației)', - discordCoverServer: 'Server (prin informații album)', - discordCoverApple: 'Apple Music', - discordOptions: 'Opțiuni avansate Discord', - discordTemplates: 'Șablon text personalizat', - discordTemplatesDesc: 'Personalizează ce informații sunt afișate pe profilul tău de Discord. Variabile: {title}, {artist}, {album}', - discordTemplateDetails: 'Linia principală (detalii)', - discordTemplateState: 'Linia secundară (status)', - discordTemplateLargeText: 'Tooltip album (largeText)', - nowPlayingEnabled: 'Se afișează în Now Playing', - nowPlayingEnabledDesc: 'Difuzează piesa redată curent către vizualizatorul de ascultare live a serverului. Dezactivează pentru a opri trimiterea datelor de redare.', - enableBandsintown: 'Date de turneu Bandsintown', - enableBandsintownDesc: 'Arată concertele următoare pentru artisul curent în tab-ul Informații. Datele sunt preluate din API-ul public Bandsintown.', - lyricsServerFirst: 'Preferă versurile de pe server', - lyricsServerFirstDesc: 'Verifică versurile furnizate de server (tag-uri încorporate, fișiere sidecar) înainte de interogarea LRCLIB. Dezactivează pentru a folosi LRCLIB primul.', - enableNeteaselyrics: 'Versuri Netease Cloud Music', - enableNeteaselyricsDesc: 'Folosește Netease Cloud Music ca ultimă soluție pentru versuri când serverul și LRCLIB nu returnează nimic. Cea mai bună acoperire pentru muzică Asiatică și internațională.', - lyricsSourcesTitle: 'Sursă versuri', - lyricsSourcesDesc: 'Alege ce surse se interoghează pentru versuri și în ce ordine. Trage pentru a reordona. Sursele dezactivate sunt ignorate complet.', - lyricsSourceServer: 'Server', - lyricsSourceLrclib: 'LRCLIB', - lyricsSourceNetease: 'Netease Cloud Music', - lyricsModeStandard: 'Standard', - lyricsModeStandardDesc: 'Trei surse în o listă ordonabilă: tag-uri server, LRCLIB, Netease.', - lyricsModeLyricsplus: 'YouLyPlus (Karaoke)', - lyricsModeLyricsplusDesc: 'Sincronizare cuvânt-cu-cuvânt preluată din Apple Music, Spotify, Musixmatch & QQ (backend comunitate). Recurge în tăcere la sursele standard când nimic nu este găsit.', - lyricsStaticOnly: 'Afișează versurile doar ca text static', - lyricsStaticOnlyDesc: 'Redă versurile sincronizate fără scroll automat și fără evidențierea cuvintelor.', - downloadsTitle: 'Export ZIP & Arhivare', - downloadsFolderDesc: 'Folder destinație pentru albumele pe care le descarci ca fișiere ZIP în calculator.', - downloadsDefault: 'Folderul Download Implicit', - pickFolder: 'Selectează', - pickFolderTitle: 'Selectează Folderul de Download', - clearFolder: 'Golește folderul de download', - logout: 'Deconectare', - aboutTitle: 'Despre Psysonic', - aboutDesc: 'Un player muzical desktop modern făcut pentru Navidrome. Folosește API-ul Subsonic plus extensiile specifice Navidrome. Construit cu Tauri v2 cu un motor audio nativ Rust — ușor și rapid, dar împachetat cu funcționalități: bară de redare cu forme de undă, versuri sincronizate, integrare Last.fm, EQ 10 benzi, crossfade, redare fără spațiu între piese, Replay Gain, navigarea pe gen, și o librărie largă de teme.', - aboutLicense: 'Licență', - aboutLicenseText: 'GNU GPL v3 — liber de utilizat, modificat, și distribuit sub aceeași licență.', - aboutRepo: 'Cod Sursă pe GitHub', - aboutVersion: 'Versiune', - aboutBuiltWith: 'Construit cu Tauri · React · TypeScript · Rust/rodio', - aboutMaintainersLabel: 'Dezvoltatori', - aboutReleaseNotesLabel: 'Notițe lansare', - aboutReleaseNotesLink: "Deschide ce e nou pentru această versiune", - aboutContributorsLabel: 'Contribuabili', - showChangelogOnUpdate: "Arată 'Ce este nou' în update", - showChangelogOnUpdateDesc: "Arată un banner discret cu lista modificărilor deasupra Now Playing după un update. Apasă pentru a deschide lista modificărilor; X îl respinge.", - randomMixTitle: 'Lista neagră Mix Aleatoriu', - luckyMixMenuTitle: 'Arată Mixul Norocos în meniu', - luckyMixMenuDesc: 'Activează Mixul Norocos în Construiește un Mix și ca un element separat în meniu când navigarea împărțită este pornită. Vizibil doar când AudioMuse este activat pe serverul activ.', - randomMixBlacklistTitle: 'Cuvinte cheie personalizate pentru filtre', - randomMixBlacklistDesc: 'Piesele sunt excluse când orice cuvânt cheie corespunde cu genul, titlul, albumul sau artistul lor (activ când checkbox-ul de deasupra este pornit).', - randomMixBlacklistPlaceholder: 'Adaugă cuvânt cheie…', - randomMixBlacklistAdd: 'Adaugă', - randomMixBlacklistEmpty: 'Niciun cuvânt cheie adăugat încă.', - randomMixHardcodedTitle: 'Cuvinte cheie predefinite (activ când checkbox-ul este pornit)', - tabAudio: 'Audio', - tabStorage: 'Offline & Cache', - tabAppearance: 'Aparență', - tabLibrary: 'Librărie', - tabServers: 'Servere', - tabLyrics: 'Versuri', - tabPersonalisation: 'Personalizare', - tabIntegrations: 'Integrări', - inputKeybindingsTitle: 'Scurtături tastatură', - aboutContributorsCount_one: '{{count}} contribuție', - aboutContributorsCount_other: '{{count}} contribuții', - searchPlaceholder: 'Caută setări…', - searchNoResults: 'Nicio setare nu corespunde cu ce ai căutat.', - integrationsPrivacyTitle: 'Notificare de confidențialitate', - integrationsPrivacyBody: 'Toate integrările din acest tab sunt opționale și trimit date către servicii externe sau server-ul tău Navidrome când sunt activate. Last.fm primește istoricul ascultărilor tale, Discord arată piesa redată curent în profilul tău, Bandsintown e interogat per artist pentru a aduce date de turnee, și distribuirea Now-Playing publică piesa curentă către alți useri din server-ul tău Navidrome. Dacă nu vrei vreo opțiune, doar lasă secțiunea corespunzătoare dezactivată', - homeCustomizerTitle: 'Pagina Principală', - queueToolbarTitle: 'Toolbar Coadă', - queueToolbarReset: 'Resetează la implicit', - queueToolbarSeparator: 'Separator', - sidebarTitle: 'Bara laterală', - sidebarReset: 'Resetează la implicit', - artistLayoutTitle: 'Secțiunile paginii artistului', - artistLayoutDesc: 'Trage pentru a reordona, comutați pentru a ascunde secțiuni individuale ale paginii de artist. Secțiunile fără date sunt ignorate automat.', - artistLayoutReset: 'Resetează la implicit', - artistLayoutBio: 'Biografie artist', - artistLayoutTopTracks: 'Top piese', - artistLayoutSimilar: 'Artiști similari', - artistLayoutAlbums: 'Albume', - artistLayoutFeatured: 'Prezentat și pe', - sidebarDrag: 'Trage pentru a reordona', - sidebarFixed: 'Mereu vizibil', - randomNavSplitTitle: 'Navigare Mix împărțită', - randomNavSplitDesc: 'Arată "Mix Aleatoriu", "Albume Aleatorii", și "Mix Norocos" ca intrări separate în bara laterală în loc de hub-ul "Construiește un Mix".', - tabInput: 'Input', - tabUsers: 'Useri', - tabSystem: 'Sistem', - loggingTitle: 'Logging', - loggingModeDesc: 'Controlează verbozitatea log-urilor din backend în terminal.', - loggingModeOff: 'Oprit', - loggingModeNormal: 'Normal', - loggingModeDebug: 'Debug', - loggingExport: 'Exportă log-uri', - loggingExportSuccess: 'Log-uri exportate ({{count}} linii).', - loggingExportError: 'Nu s-au putut exporta log-urile.', - ratingsSectionTitle: 'Ratinguri', - ratingsSkipStarTitle: 'Sari peste 1 stea', - ratingsSkipStarDesc: - 'După mai multe salturi la rând, setează ratingul piesei la 1★. Doar pentru piesele care nu au fost deja evaluate.', - ratingsSkipStarThresholdLabel: 'Salturi', - ratingsMixFilterTitle: 'Filtrează după rating', - ratingsMixFilterDesc: - 'Filtrează elementele cu scor mic în {{mix}} și {{albums}}. Apasă pe steaua selectată din nou pentru a opri limita.', - ratingsMixMinSong: 'Piese', - ratingsMixMinAlbum: 'Albume', - ratingsMixMinArtist: 'Artiști', - ratingsMixMinThresholdAria: 'Stele minime: {{label}}', - backupTitle: 'Backup & Restaurare', - backupExport: 'Setări de export', - backupExportDesc: 'Salvează toate setările, profilele de server, configurări Last.fm, teme, EQ și combinații de taste către un fișier .psybkp. Parolele sunt stocate ca text — păstrează fișierul în siguranță.', - backupImport: 'Setări de Import', - backupImportDesc: 'Restaurează setări dintr-in fișier .psybkp. Aplicația se va reîncărca după import.', - backupImportConfirm: 'Aceasta va suprascrie toate setările curente. Continuați?', - backupSuccess: 'Backup salvat', - backupImportSuccess: 'Setări restaurate — se reîncarcă…', - backupImportError: 'Fișier de backup invalid sau corupt.', - shortcutsReset: 'Resetează la implicite', - shortcutListening: 'Apasă o tastă…', - shortcutUnbound: '—', - globalShortcutsTitle: 'Scurtături globale', - globalShortcutsNote: 'Funcționează la nivel de sistem și când Psysonic este în fundal. Necesită Ctrl, Alt, sau Super ca un modificator.', - shortcutClear: 'Golește', - shortcutPlayPause: 'Redă / Pauză', - shortcutNext: 'Următoarea piesă', - shortcutPrev: 'Piesa anterioară', - shortcutVolumeUp: 'Ridică volumul', - shortcutVolumeDown: 'Coboară volumul', - shortcutSeekForward: 'Dă înainte 10s', - shortcutSeekBackward: 'Dă înapoi 10s', - shortcutToggleQueue: 'Comutați coada', - shortcutOpenFolderBrowser: 'Deschide {{folderBrowser}}', - shortcutFullscreenPlayer: 'Player pe ecran complet', - shortcutNativeFullscreen: 'Ecran complet nativ', - shortcutOpenMiniPlayer: 'Deschide mini player', - shortcutStartSearch: 'Începe o căutare', - shortcutStartAdvancedSearch: 'Începe o căutare avansată', - shortcutToggleSidebar: 'Comutați bara laterală', - shortcutMuteSound: 'Opriți sunetul', - shortcutToggleEqualizer: 'Porniți / Comutați Egalizatorul', - shortcutToggleRepeat: 'Comutați repetarea', - shortcutOpenNowPlaying: 'Deschide "Now Playing"', - shortcutShowLyrics: 'Arată Versurile', - shortcutFavoriteCurrentTrack: 'Adaugă piesa curentă la favorite', - shortcutOpenHelp: 'Ajutor', - playbackTitle: 'Redare', - replayGain: 'Replay Gain', - replayGainDesc: 'Normalizează volumul pieselor folosind metadata ReplayGain', - replayGainMode: 'Mod', - replayGainAuto: 'Auto', - replayGainAutoDesc: 'Alege volumul albumului când piesele vecine din coadă sunt din același album, altfel volumul piesei.', - replayGainTrack: 'Piesă', - replayGainAlbum: 'Album', - replayGainPreGain: 'Pre-Gain (fișiere etichetate)', - replayGainPreGainDesc: 'Boost universal adăugat peste fiecare calculare ReplayGain. Folosește pentru a compensa dacă librăria ta se simte prea liniștită per total.', - replayGainFallback: 'Rezervă (neetichetat / radio)', - replayGainFallbackDesc: 'Aplicat la piesele (și stream-urile radio) care nu au tag-uri ReplayGain deloc, pentru ca conținutul neetichetat să nu se audă mai gălăgios decât restul.', - normalization: 'Normalizare', - normalizationDesc: 'Aliniază volumul perceput peste piese, albume și radio.', - normalizationOff: 'Oprit', - normalizationReplayGain: 'ReplayGain', - normalizationLufs: 'LUFS', - loudnessTargetLufs: 'Țintă LUFS', - loudnessTargetLufsDesc: 'Volumul de referință la care toate piesele sunt ajustate. Numere mai mici = volum mai mare. Serviciile de streaming sunt setate în mod obișnuit la -14 LUFS.', - loudnessPreAnalysisAttenuation: 'Atenuare pre-analiză', - loudnessPreAnalysisAttenuationDesc: - 'Extra coborâre a volumului până când nivelul pentru această piesă este salvat. Streaming apoi folosește presupuneri aproximative, nu o măsurătoare completă. 0 dB = oprit; mai jos = mai încet. Numărul din dreapta este nivelul dB efectif pentru ținta curentă.', - loudnessPreAnalysisAttenuationRef: '{{eff}} dB efectiv cu ținta {{tgt}} LUFS.', - loudnessPreAnalysisAttenuationReset: 'Resetează la implicit', - loudnessFirstPlayNote: - 'Prima redate a unei piese noi își poate schimba brusc volumul cât este măsurată. Următoarea redare folosește măsurătoarea stocată și este stabilă. Piesele următoare din coadă sunt de obicei pre-analizate în timpul piesei anterioare, deci acest fenomen se întâmplă rar în practică.', - crossfade: 'Crossfade', - crossfadeDesc: 'Estompează între piese', - crossfadeSecs: '{{n}} s', - notWithGapless: 'Nu este valabil cât Gapless este activ', - notWithCrossfade: 'Nu este valabil cât Crossfade este activ', - gapless: 'Playback Gapless', - gaplessDesc: 'Pre-încarcă următoarea piesă pentru a elimina spațiile dintre piese', - preservePlayNextOrder: 'Prezervă ordinea "Redă următoarea"', - preservePlayNextOrderDesc: 'Elementele Redă Următoarea noi adăugate sunt puse după cele adăugate mai devreme în loc să sară în față.', - trackPreviewsTitle: 'Previzualizări Piese', - trackPreviewsToggle: 'Pornește previzualizările pieselor', - trackPreviewsDesc: 'Arată butoanele de Redare și Pre-vizualizare în rând în listele de piese pentru o mostră rapidă din mijlocul piesei.', - trackPreviewStart: 'Poziția de începere', - trackPreviewStartDesc: 'Cât de departe în piesă să înceapă pre-vizualizarea (% din lungimea piesei).', - trackPreviewDuration: 'Durată', - trackPreviewDurationDesc: 'Cât de mult se redă fiecare pre-vizualizare până se oprește.', - trackPreviewDurationSecs: '{{n}} s', - trackPreviewLocationsTitle: 'Unde apar pre-vizualizările', - trackPreviewLocationsDesc: 'Alege ce liste arată butoanele de pre-vizualizare în linie.', - trackPreviewLocation_suggestions: 'Sugestii în playlist', - trackPreviewLocation_albums: 'Liste de piese în album', - trackPreviewLocation_playlists: 'În playlist-uri', - trackPreviewLocation_favorites: 'În favorite', - trackPreviewLocation_artist: 'În top piese ale artistului', - trackPreviewLocation_randomMix: 'În Mixul Aleatoriu', - preloadMode: 'Preîncarcă Următoarea Piesă', - preloadModeDesc: 'Când să înceapă preîncărcarea următoarei piese din coadă', - nextTrackBufferingTitle: 'Preîncarcă', - preloadHotCacheMutualExclusive: 'Preîncarcarea și Hot Cache au același scop — doar una poate fi activată deodată. Pornirea unei opțiuni o dezactivează pe cealaltă.', - preloadOff: 'Oprit', - preloadBalanced: 'Balansat (30 s înainte de sfârșit)', - preloadEarly: 'Devreme (după 5 s de redare)', - preloadCustom: 'Personalizat', - preloadCustomSeconds: 'Secunde înainte de sfârșit: {{n}}', - infiniteQueue: 'Coadă Infinită', - infiniteQueueDesc: 'Adaugă automat piese aleatorii când coada se golește', - experimental: 'Experimental', - fsPlayerSection: 'Player pe ecran complet', - fsLyricsStyle: 'Stilul versurilor', - fsLyricsStyleRail: 'Șină', - fsLyricsStyleRailDesc: 'Șină clasica pe 5 linii.', - fsLyricsStyleApple: 'Derulare', - fsLyricsStyleAppleDesc: 'Listă în derulare pe ecran complet.', - sidebarLyricsStyle: 'Stilul derulării versurilor', - sidebarLyricsStyleClassic: 'Clasic', - sidebarLyricsStyleClassicDesc: 'Derulează linia activă în centru.', - sidebarLyricsStyleApple: 'Ca Apple Music', - sidebarLyricsStyleAppleDesc: 'Linia activă este ancorată aproape de vârf cu animații netede.', - fsShowArtistPortrait: 'Arată poza artisului', - fsShowArtistPortraitDesc: 'Arată poza artistului (sau arta albumului) în partea dreaptă a playerului pe ecran complet.', - fsPortraitDim: 'Estomparea fotografiei', - seekbarStyle: 'Stilul barei de redare', - seekbarStyleDesc: 'Alege aspectul barei de redare a playerului', - seekbarTruewave: 'Truewave', - seekbarPseudowave: 'Pseudowave', - seekbarLinedot: 'Linie & Punct', - seekbarBar: 'Bară', - seekbarThick: 'Bară groasă', - seekbarSegmented: 'Segmentat', - seekbarNeon: 'Strălucire Neon', - seekbarPulsewave: 'Undă de Puls', - seekbarParticletrail: 'Urmă de Particule', - seekbarLiquidfill: 'Lichid', - seekbarRetrotape: 'Bandă Retro', - themeSchedulerTitle: 'Schimbă Tema automat', - themeSchedulerEnable: 'Pornește temele programate', - themeSchedulerEnableSub: 'Schimbă automat între două teme pe baza orei din zi', - themeSchedulerDayTheme: 'Temă de zi', - themeSchedulerDayStart: 'Ziua începe la', - themeSchedulerNightTheme: 'Temă de noapte', - themeSchedulerNightStart: 'Noaptea începe la', - themeSchedulerActiveHint: 'Temele programate sunt active - aceste schimbări de teme sunt gestionate automat.', - visualOptionsTitle: 'Opțiuni vizuale', - coverArtBackground: 'Arta de fundal a copertei', - coverArtBackgroundSub: 'Arată arta de copertă blurată ca fundal în antetele albumelor/playlisturilor', - playlistCoverPhoto: 'Poza de copertă a playlistului', - playlistCoverPhotoSub: 'Arată poza grilă de copertă în afișajul de detalii al playlistului', - showBitrate: 'Arată Bitrate', - showBitrateSub: 'Arată bitrate-ul audio în listările de piese', - floatingPlayerBar: 'Bară Player plutitoare', - floatingPlayerBarSub: 'Păstrează bara playerului plutind deasupra conținutului', - uiScaleTitle: 'Scara interfaței', - uiScaleLabel: 'Zoom', - }, - changelog: { - modalTitle: "Ce este nou", - dontShowAgain: "Nu arăta din nou", - close: 'Am înțeles', - }, - whatsNew: { - title: "Ce este nou", - empty: 'Nicio intrare în lista de schimbări pentru această versiune încă.', - bannerTitle: 'Lista de schimbări', - bannerCollapsed: "Ce este nou în v{{version}}", - dismiss: 'Respinge', - close: 'Închide', - }, - help: { - title: 'Ajutor', - searchPlaceholder: 'Caută Ajutor…', - noResults: 'Niciun topic corespunzător. Încearcă un alt termen de căutare.', - // ── Section 1: Getting Started ───────────────────────────────────────── - s1: 'Pentru început', - q1: 'Ce servere sunt compatibile?', - a1: 'Psysonic este construit în principal pentru Navidrome și este complet compatibil cu serverele Subsonic - Gonic, Airsonic, LMS și alte servere pe bază de API Subsonic de asemenea funcționează. Unele funcționalități avansate (ratinguri, playlisturi inteligente, distribuirea magic strings, managementul utilizatorilor) necesită Navidrome', - q2: 'Cum adaug un server?', - a2: 'Setări → Servere → Adaugă Server. Introdu URL-ul serverului (ex. 192.168.1.100:4533), numele de utilizator, și parola. Psysonic verifică conexiunea înainte de a salva — nimic nu este stocat dacă conexiunea eșuează. Poți adăuga și schimba oricâte servere dorești în bara de sus oricând; doar unul este activ deodată', - q3: 'Tur rapid al UI?', - a3: 'Bara laterală (stâng) pentru navigare, Scena Principală / paginile din mijloc, Bara de Redare jos, și Panoul Cozii în dreapta (comută din bara de dreapta-sus lângă indicatorul Se Redă Acum). Bara de căutare de sus caută în toată librăria; "Se Redă Acum" arată ce ascultă alți utilizatori de pe același server Navidrome acum', - // ── Section 2: Playback & Queue ──────────────────────────────────────── - s2: 'Redare & Coadă', - q4: 'Cum folosesc coada?', - a4: 'Deschide Panoul Cozii din bara din dreapta-sus. Trage rândurile pentru a le reordona, lasă-le afară pentru a înlătura, sau folosește bara cozii pentru a amesteca, salva coada ca playlist, sau sări la o piesă.Trage rândurile din panou și lasă-le altundeva pentru a le transfera.', - q5: 'Gapless vs Crossfade - care este diferența?', - a5: 'Gapless preîncarcă următoarea piesă pentru a elimina liniștea dintre piese (cel mai bine pentru albume live și mixuri DJ). Crossfade estompează piesa curentă în timp ce următoarea este introdusă gradual pe parcursul a 1-10 s (cel mai bun pentru mixuri amestecate). Ele sunt opțiuni mutual exclusive - pornirea uneia o dezactivează pe cealaltă. Configurează ambele în Setări → Audio.', - q6: 'Ce este Coada Infinită?', - a6: 'Când coada se golește și Repetă este oprit, Psysonic adaugă în liniște piese aleatorii din librăria ta așa că redarea nu se oprește niciodată. Piesele auto-adăugate apar mai jos "— Adăugat automat —" divizate în coadă. Comutați-l cu iconița infinit din antetul cozii. Poți de asemenea restricționa piesele auto-adăugate către un gen specific în Setări → Coadă.', - q7: 'Selecție multiplă și interval Shift-clic?', - a7: 'Activează "Selectează" pe Albume / Lansări Noi / Albume Aleatorii / Playlisturi. Apasă pe un element pentru a-l comuta, apoi ține Shift și apasă pe alt element pentru a selecta totul dintre elementele alese în ordinea vizibilă. Shift-clicurile se extind de la cel mai recent element selectat. Bara de deasupra grilei oferă acțiuni în masă (adaugă în coadă, descarcă, șterge, etc.).', - q8: 'Scurtături ale tastaturii și taste globale?', - a8: 'Taste implicite în aplicație: Space = Redă / Pauză, Esc = închide ecranul complet / modale, F1 = cheat-sheet scurtături. În Setări → Input poți reconfigura fiecare acțiune din aplicație (chiar și combinații cum ar fi Ctrl+Shift+P) și seta scurtături globale la nivel de sistem care funcționează chiar și când Psysonic este în fundal sau minimizat. Tastele media (Redă/Pauză, Următoarea, Anterioara) funcționează pe toate platformele.', - // ── Section 3: Audio Tools ───────────────────────────────────────────── - s3: 'Unelte Audio', - q9: 'Moduri Replay Gain?', - a9: 'Setări → Audio → Replay Gain. Modul piesă normalizează fiecare piesă la un nivel țintă. Modul album păstrează curba de zgomot din album. Modul auto alege Piesă sau Album verificând dacă coada este formată dintr-un singur album. Piesele fără etichete Replay Gain ajung la o valoare preamp configurabilă', - q10: 'Ce este Normalizarea Zgomotului Inteligentă (LUFS)?', - a10: 'O alternativă modernă la Replay Gain în Setări → Audio. Psysonic analizează fiecare piesă la LUFS / EBU R128 și stochează rezultatul, ca volumul să fie consistent pe întreaga librărie - incluzând piesele fără etichete Replay Gain. Analiza cold-cache rulează în fundal și folosește în jur de 35-40 % CPU pentru ~1 minut, apoi coboară la 0. Setează nivelul de zgomot țintă (implicit -10 LUFS) o dată', - q11: 'EQ și AutoEQ?', - a11: 'Un EQ parametric pe 10 benzi se află în Setări → Audio → Egalizator cu benzi manuale și presetări. AutoEQ de lângă trage un profil de măsurătoare de corecție pentru modelul tău de căști din baza de date AutoEQ și o aplică pe benzi automat - alege-ți căștile și EQ-ul se aranjează la curba corectă', - q12: 'Cum schimb dispozitivul audio de ieșire?', - a12: 'Setări → Audio → Dispozitiv de Ieșire. Psysonic listează fiecare ieșire posibilă și se schimbă instant când alegi una. Butonul de reîmprospătare rescanează dispozitivele care au fost conectare după pornire. Numele Linux ALSA ca "sysdefault" sunt auto-curățate pentru lizibilitate', - q13: 'Ce este Hot Cache?', - a13: 'Hot Cache preîncarcă piesa curentă plus următoarele în RAM și pe disc pentru ca redarea să înceapă fără încărcare - folositor mai ales pe servere încete / îndepărtate. Piesele sunt eliminate din memorie când limita este atinsă. Configurează limita și întârzierea adăugării (pentru ca săriturile rapide să nu adauge piesele) în Setări → Audio.', - // ── Section 4: Library & Discovery ───────────────────────────────────── - s4: 'Librărie și Descoperire', - q14: 'Cum funcționează ratingurile și Sari-peste-1★?', - a14: 'Psysonic suportă ratinguri 1–5 stele prin OpenSubsonic (necesită Navidrome ≥ 0.53). Evaluează piese în lista de piese, în meniul clic-dreapta, sau în bara redării sub numele artistului; albumele pe pagina de album; artiștii pe pagina de artist. Sari-peste-1★ (Setări → Librărie → Ratinguri) auto-asignează 1 stea după un număr configurabil de sărituri consecutive. În același panou poți seta un filtru de rating minim pentru Mixul Aleatoriu sau alte mixuri generate', - q15: 'Cum răsfoiesc - Foldere, Genuri, Piese?', - a15: 'Browserul de foldere (bara laterală) parcurge prin directorul muzică al serverului tău folosind o schemă Miller-column - apasă pe un folder pentru a intra în el, apasă pe iconița de redare a unei piese pentru a o reda / adăuga în coadă. Genurile folosesc o vizualizare etichetă-nor scalată de numărul de piese; apasă pe un gen pentru a-l deschide. Piese este un hub librărie plată cu o listă virtuală cu coloane sortabile și search live.', - q16: 'Căutare și Căutare Avansată?', - a16: 'Bara de căutare rulează o căutare live rapidă prin artiști, albume și piese pe măsură ce scrii. Deschide Căutarea Avansată (bara laterală) pentru un afișaj mai amănunțit: filtrează după an, gen, rating, format, canale, sample rate, BPM, stare, și combină criterii. Clic-dreapta pe orice rezultat pentru același meniu de context folosit orinde altundeva în aplicație.', - q17: 'Ce sunt Mixurile (Aleatoriu / Gen / Super Gen / Norocos)?', - a17: 'Mixul Aleatoriu construiește un playlist din piese aleatorii din librăria ta; Filtrul Cuvinte Cheie exclude cărți audio, comedie, etc. substringuri după gen / titlu / album. Mixul Super Gen îți grupează librăria în stiluir largi (Rock, Metal, Electronic, Jazz, Clasic…) și construiește un mix focusat din unul. Mixul Norocos folosește istoricul ascultării tale, ratinguri și piese similare AudioMuse-AI pentru a asambla un playlist instant cu un clic.', - q18: 'Pagină de statistici?', - a18: 'Statistici (bara laterală) arată top artiști, top albume, top piese, detalii genuri, ascultarea în timp, și per-librărie când ai mai mult de un folder de muzică configurat. Mai multe vizualizări sunt exportabile ca o imagine card.', - q19: 'Cum descarc un album ca ZIP?', - a19: 'Pagină album → "Descarcă (ZIP)". Serverul compresează albumul prima oară — pentru albume mari sau necompresate (FLAC / WAV) bara de progres apare doar după ce arhivarea este completată și începe transferul. Acest lucru este normal.', - // ── Section 5: Lyrics ────────────────────────────────────────────────── - s5: 'Versuri', - q20: 'De unde vin versurile?', - a20: 'Trei surse, configurabile în Setări → Versuri: serverul tău Navidrome (versuri încorporate/ OpenSubsonic), LRCLIB (versuri contribuite de comunitate sincronizate), și NetEase Cloud Music (catalog larg Chinez și internațional). Poți porni sau dezactiva fiecare sursă și reordona prioritatea lor trăgând de ele.', - q21: 'Cum văd versurile în timpul redării?', - a21: 'Apasă pe iconița microfon din bara redării pentru a deschide tab-ul Versuri în panoul Cozii. Versurile sincronizate se auto-derulează și suportă clic-pentru-căutare; versurile pur text derulează ca un bloc static. Comutează Playerul pe Ecran Complet din arta barei de redare pentru o vedere imersivă de versuri cu fundal mesh-blob.', - // ── Section 6: Sharing & Social ──────────────────────────────────────── - s6: 'Distribuire & Social', - q22: 'Ce sunt Stringurile Magice?', - a22: 'Stringurile Magice sunt jetoane copy-paste care distribuie informații între utilizatorii Psysonic fără niciun server terț. Stringurile Invitație-Server permit un prieten în Navidrome-ul tău cu o lipire; Stringurile Album / Artist / Coada Magică deschid același album / artist / coadă în Psysonic-ul instalat al recipientului. Generează-le din meniul de distribuire, lipește-le în bara de căutare pentru a le folosi.', - q23: 'Ce este Orbit?', - a23: 'Orbit este o ascultare-împreună sincronizată: o gazdă redă o piesă, fiecare oaspete o aude în sincron, și oaspeții pot sugera piese pe care gazda să le accepte în coadă. Începe o sesiune din butonul Orbit de sus, distribuie link-ul de invitație, și alții pot intra oricând din orice instalare Psysonic. Gazda controlează redarea (săriri, căutări, coadă) — oaspeții primesc o vizionare în timp real și o cutie de sugestii. Sesiunile sunt efemere și se termină când sunt închise de gazdă.', - q24: 'Ce este dropdown-ul Se Redă Acum?', - a24: 'Iconița de difuzare din antetul din dreapta-sus arată ce ascultă alți utilizatori din serverul tău Navidrome, reactualizat la fiecare 10 secunde. Intrarea ta dispare în momentul în care pui pauză. Acest lucru este per-server, deci utilizatorii activi de pe alte servere nu sunt afișați.', - // ── Section 7: Personalization ───────────────────────────────────────── - s7: 'Personalizare', - q25: 'Teme și Programatorul de Teme?', - a25: 'Setări → Aparență → Temă alege din 60+ teme din 8 grupe (Psysonic, Mediaplayer, Sisteme de Operare, Jocuri, Filme, Seriale, Social Media, Clasice Open Source — Catppuccin / Nord / Gruvbox / Nightfox / Dracula). Auto-comutatorul de Teme îți permite să alegi teme zi + noapte cu timpuri de începere prin care Psysonic să comute automat.', - q26: 'Pot customiza paginile Bara laterală, Acasă și Artist?', - a26: 'Da — Setări → Personalizare. Customizatorul bării laterale îți permite tragerea elementelor de navigare în ordinea pe care o dorești și ascunde cele pe care nu le folosești. Customizatorul Acasă comută fiecare șină din Scena Principală (Promovat, Recent, Descoperă, Redat Recent, Evaluate…). Customizatorul paginii de Artist reordonează secțiunile (Top Piese, Albume, Singleuri, Compilații, Artiști Similari, etc.) și te lasă să ascunzi cele la care nu te uiți niciodată.', - q27: 'Ce este Mini Playerul?', - a27: 'O fereastră mică plutitoare cu arta coperții, controale de transport și o coadă compactă. Deschide-o din iconița mini-playerului barei de redare sau prin scurtătura ei de tastatură. Fereastra ține minte poziția ei și mărimea între sesiuni. Pe Windows webview-ul miniatură este pre-creat la pornire pentru ca deschiderea să fie instantanee; Linux / macOS aleg asta prin Setări → Aparență → Preîncarcă mini player.', - q28: 'Ce este Bara de Redare Plutitoare?', - a28: 'Un stil de bară de redare opțional (Setări → Aparență) care se detașează de marginea de jos cu un fundal tematic, margine accentuată, artă de album rotunjită și o secțiune de volum centrată. Folositor pe monitoare înalte sau teme compacte.', - q29: 'Previzualizare piesă pe hover?', - a29: 'Hover peste un rând de piesă, clic pe butonul mic de previzualizare de pe copertă, sau declanșează previzualizarea din meniul clic-dreapta — Psysonic redă primele ~15 s prin același motor audio Rust ca normalizarea zgomotului să fie aplicată. Folositor pentru filtrarea unui album pe care nu l-ai mai auzit.', - q30: 'Cronometru de somn?', - a30: 'Apasă iconița lună în bara de redare pentru a deschide cronometrul de somn. Alege o durată (sau "sfârșitul piesei curente") și Psysonic estompează și pune pe pauză la final. Butonul arată un inel circular și un cronometru în buton cât timp cronometrul rulează.', - q31: 'Scalare UI, font, stil bară de căutare?', - a31: 'Setări → Aparență — Scară Interfață (80–125 % fără a afecta mărimea fontului de sistem), Font (10 fonturi UI incluzând IBM Plex Mono, Fira Code, Geist, Golos Text…), Stil Bară de Căutare (Formă de undă analizată / pseudoundă deterministică / Linie & Punct / Bară / Bară Groasă / Segmentat / Strălucire Neon / Pulse Wave / Urmă de Particule / Lichid / Bandă Retro).', - // ── Section 8: Power User ────────────────────────────────────────────── - s8: 'Utilizatori Avansați', - q32: 'Controale player din CLI?', - a32: 'Binarul Psysonic este dublat ca o telecomandă. Exemple: psysonic --player play / pause / next / prev, --player volume 75, --player seek 15, --player shuffle, --player repeat off|all|one, --player rating 1-5. Schimbă servere, dispozitive audio, librării; declanșează Mixul Instant; caută artiști / albume / piese. Rulează psysonic --player --help pentru lista completă. Completările Shell pentru bash și zsh sunt disponibile via completări psysonic.', - q33: 'Playlisturi Inteligente (Navidrome)?', - a33: 'Playlisturile Inteligente sunt playlisturi dinamice pe partea Navidrome definite de reguli (gen = Rock ȘI an > 2020, etc.). Pagina de Playlisturi în Psysonic îți permite crearea, editarea și ștergerea lor cu un editor de reguli vizual - Psysonic comunică cu API-ul nativ Navidrome pentru asta. Ele se comportă ca playlisturi normale în restul aplicației și se actualizează pe măsură ce librăria ta se schimbă.', - q34: 'Backup și restaurarea setărilor?', - a34: 'Setări → Stocare → Backup & Restaurare exportă profilele serverului, temele, scurtăturile de tastatură și alte setări într-un singur fișier JSON. Importă fișierul pe alt calculator sau după o reinstalare pentru a restaura totul deodată. Parolele serverului sunt incluse — ține fișierul privat.', - q35: 'Unde pot vedea toate licențele open-source?', - a35: 'Setări → Sistem → Licențe Open Source. Toată lista de dependințe (cargo crates și npm packages) sunt livrate în build cu textele licențelor adunate. Apasă pe un element pentru textul complet; blocul evidențiat de sus menționează toate librăriile recunoscubile de utilizator (Tauri, React, rodio, symphonia, etc.).', - // ── Section 9: Offline & Sync ────────────────────────────────────────── - s9: 'Offline & Sincronizare', - q36: 'Modul Offline — adăugarea albumelor și playlisturilor în cache?', - a36: 'Deschide orice album sau playlist și apasă pe iconița de download din antet — Psysonic descarcă fiecare piesă local pentru a putea fi redată fără niciun apel la rețea. Pagina Librărie Offline (bara laterală) listează tot ce este în cache, afișează progresul în desfășurare, și îți permite să elimini intrări cu iconița de gunoi (care apare doar după ce descărcarea este completă).', - q37: 'Limită de stocare Offline?', - a37: 'Setări → Librărie → Offline îți permite să setezi o mărime maximă a cache. Când limita este atinsă, butonul de descărcare din pagina albumului arată un banner de avertisment. Eliberează spațiu prin eliminarea albumelor sau playlisturilor din pagina Librărie Offline.', - q38: 'Sincronizare Dispozitiv — copiază muzică la USB / SD?', - a38: 'Sincronizare Dispozitiv (bara laterală) copiază albume, playlisturi sau artiști compleți pe un dispozitiv extern pentru ascultare offline. Alege un folder țintă, sursele din tab-urile browser, apasă "Transfer la Dispozitiv". Psysonic scrie un manifest (psysonic-sync.json) pentru ca să știe ce fișiere sunt deja acolo chiar dacă deschizi Sincronizare Dispozitiv pe un alt sistem de operare cu alt șablon de nume de fișiere. Șabloanele suportă {artist} / {album} / {title} / {track_number} / {disc_number} / {year} jetoane cu / fără separatoare de folder.', - // ── Section 10: Integrations & Troubleshooting ───────────────────────── - s10: 'Integrări & Depanare', - q39: 'Scrobbling Last.fm?', - a39: 'Setări → Integrări → Last.fm. Conectează-ți contul o singură dată și Psysonic efectuează scrobble direct către Last.fm — nicio configurare Navidrome necesară. Un scrobble este trimis după ce ai ascultat 50 % dintr-o piesă. Pingurile se redă acum sunt trimise la început.', - q40: 'Prezență Discord Rich?', - a40: 'Setări → Integrări → Discord arată piesa curentă în ascultare pe profilul tău de Discord. Alege între iconița aplicației, arta de copertă a serverului (prin getAlbumInfo2 — necesită un server accesibil public), sau coperți Apple Music. Customizează stringurile de afișare (detalii, stadiu, tooltip) cu jetoane de șablon.', - q41: 'Date turneu Bandsintown?', - a41: 'Activează în Setări → Integrări → Info Se Redă Acum. Tab-ul Se Redă Acum pe pagina Se Redă Acum va afișa apoi datele turneurilor care urmează pentru artisul redat curent prin API-ul widget Bandsintown. Oprit implicit — nicio cerere nu este făcută până când nu o pornești.', - q42: 'Radio Internet — redarea streamurilor live?', - a42: 'Radio Internet (bara laterală) redă orice stream live stocat pe serverul tău Navidrome (adaugă stații prin UI admin Navidrome). Redarea rulează prin motorul audio HTML5 — cele mai multe setări EQ / Replay Gain / Zgomot nu se aplică la radio, dar metadata ICY (numele piesei curente) este arătat. Suportă MP3, AAC, OGG Vorbis și cele mai multe streamuri HLS; suportul codec depinde de platformă.', - q43: 'Testul conexiunii eșuează — ce fac acum?', - a43: 'Verifică de două ori URL-ul incluzând portul (ex. http://192.168.1.100:4533). Pe o rețea locală http:// de obicei funcționează unde https:// nu o face (niciun certificat). Asigură-te că niciun firewall nu blochează portul și că numele de utilizator și parola sunt corecte. Dacă serverul tău este în spatele unui reverse proxy, încearcă URL-ul direct prima oară pentru a izola cauza.', - q44: 'Arta copertei și imaginile artiștilor se încarcă încet.', - a44: 'Imaginile sunt preluate de pe serverul tău la prima vedere și apoi stocate în cache pentru 30 de zile. Dacă stocarea serverului tău este înceată, prima vizită către o pagină poate dura un moment; vizitele consecutive sunt instantanee. Hot Cache de asemenea ajută pentru piese dar nu pentru cache-ul imaginii.', - q45: 'Probleme pe Linux - ecran negru sau niciun audio?', - a45: 'Aceasta este de obicei o problemă de driver GPU/EGL în WebKitGTK. Pornește cu GDK_BACKEND=x11 WEBKIT_DISABLE_COMPOSITING_MODE=1 WEBKIT_DISABLE_DMABUF_RENDERER=1. Pachetul AUR și installer-ele oficiale .deb/.rpm fac asta automat.', - }, - queue: { - title: 'Coadă', - savePlaylist: 'Salvează Playlist', - updatePlaylist: 'Actualizează Playlist', - filterPlaylists: 'Filtrează playlisturi…', - playlistName: 'Nume Playlist', - cancel: 'Anulează', - save: 'Salvează', - loadPlaylist: 'Încarcă Playlist', - loading: 'Se încarcă…', - noPlaylists: 'Niciun playlist găsit.', - load: 'Înlocuiește coadă & redare', - appendToQueue: 'Adaugă la coadă', - delete: 'Șterge', - deleteConfirm: 'Șterge playlist "{{name}}"?', - clear: 'Golește', - shuffle: 'Amestecă coada', - gapless: 'Gapless', - crossfade: 'Crossfade', - infiniteQueue: 'Coadă infinită', - autoAdded: '— Adăugat automat—', - radioAdded: '— Radio —', - hide: 'Ascunde', - hideNowPlaying: 'Ascunde informația now playing', - showNowPlaying: 'Arată informația now playing', - close: 'Închide', - nextTracks: 'Următoarele Piese', - shareQueue: 'Copiază link-ul distribuirii cozii', - shareQueueEmpty: 'Coada este goală — nimic de distribuit.', - emptyQueue: 'Coada este goală.', - trackSingular: 'piesă', - trackPlural: 'piese', - showRemaining: 'Arată timpul rămas', - showTotal: 'Arată timpul total', - showEta: 'Arată timpul estimativ până la final', - replayGain: 'ReplayGain', - rgTrack: 'P {{db}} dB', - rgAlbum: 'A {{db}} dB', - rgPeak: 'Vârf {{pk}}', - sourceOffline: 'Se redă din librăria offline', - sourceHot: 'Se redă din cache', - sourceStream: 'Se redă din stream-ul de rețea', - clearCachedLoudnessWaveform: 'Golește zgomotul si formele de undă din cache, apoi reanalizează piesa', - recalculatingLoudnessWaveform: 'Se recalculează zgomotul și formele de undă pentru această piesă…', - }, - miniPlayer: { - showQueue: 'Arată coada', - hideQueue: 'Ascunde coada', - pinOnTop: 'Fixează sus', - pinOff: 'Anulează fixarea', - openMainWindow: 'Deschide fereastra principală', - close: 'Închide', - emptyQueue: 'Coada este goală', - }, - statistics: { - title: 'Statistici', - recentlyPlayed: 'Redate recent', - mostPlayed: 'Cele mai Redate Albume', - highestRated: 'Cele mai Votate Albume', - genreDistribution: 'Distribuția de Genuri (Top 20)', - loadMore: 'Încearcă mai mult', - statArtists: 'Artiști', - statArtistsTooltip: 'Doar albume de artiști — artiștii care apar doar ca un artist la nivel de piesă (prezentate, oaspete, etc.) fără albumul lor nu sunt incluși.', - statAlbums: 'Albume', - statSongs: 'Piese', - statGenres: 'Genuri', - statPlaytime: 'Timpul total de redare', - genreInsights: 'Perspectivele Genurilor', - formatDistribution: 'Distribuția Formatului', - formatSample: 'Eșantion de {{n}} piese', - computing: 'Se calculează…', - genreSongs: '{{count}} Piese', - genreAlbums: '{{count}} Albume', - recentlyAdded: 'Adăugate recent', - decadeDistribution: 'Albume după Deceniu', - decadeAlbums_one: '{{count}} Album', - decadeAlbums_other: '{{count}} Albume', - decadeUnknown: 'Necunoscut', - lfmTitle: 'Statistici Last.fm', - lfmTopArtists: 'Artiști de top', - lfmTopAlbums: 'Albume de top', - lfmTopTracks: 'Piese de top', - lfmPlays: '{{count}} redări', - lfmPeriodOverall: 'Din tot timpul', - lfmPeriod7day: '7 Zile', - lfmPeriod1month: '1 Lună', - lfmPeriod3month: '3 Luni', - lfmPeriod6month: '6 Luni', - lfmPeriod12month: '12 Luni', - lfmNotConnected: 'Conectează Last.fm în Setări pentru a îți vedea statisticile.', - lfmRecentTracks: 'Scrobble-uri Recente', - lfmNowPlaying: 'Now Playing', - lfmJustNow: 'tocmai acum', - lfmMinutesAgo: 'acum {{n}}m', - lfmHoursAgo: 'acum {{n}}h', - lfmDaysAgo: 'acum {{n}}d', - topRatedSongs: 'Cele mai bine cotate Piese', - topRatedArtists: 'Cei mai bine cotați Artiști', - noRatedSongs: 'Nicio piesă evaluată încă. Evaluează piese în afișajul de album sau playlist.', - noRatedArtists: 'Niciun artist evaluat încă.', - exportShare: 'Distribuie', - exportTitle: 'Distribuie Albumele din Top', - exportSubtitle: 'Generează o imagine distribuibilă cu cele mai redate albume ale tale.', - exportFormat: 'Format', - exportFormatStory: 'Poveste', - exportFormatSquare: 'Pătrat', - exportFormatTwitter: 'Card Twitter', - exportGrid: 'Grilă', - exportGridLabel: '{{n}}×{{n}}', - exportPreview: 'Previzualizare', - exportGenerate: 'Generează', - exportSave: 'Salvează imaginea…', - exportCancel: 'Anulează', - exportFooterLabel: 'Top Albume', - exportNotEnough: 'Ai nevoie de cel puțin {{count}} albume în librăria ta pentru o grilă {{n}}×{{n}}.', - exportSaving: 'Se salvează…', - exportSaved: 'Salvat.', - exportSaveFailed: 'Nu s-a putut salva imaginea.', - }, - player: { - regionLabel: 'Player Muzică', - openFullscreen: 'Deschide Playerul pe ecran complet', - fullscreen: 'Player pe ecran complet', - closeFullscreen: 'Închide ecranul complet', - closeTooltip: 'Închide (Esc)', - noTitle: 'Fără Titlu', - stop: 'Stop', - prev: 'Piesa anterioară', - play: 'Redă', - pause: 'Pauză', - previewActive: 'Previzualizează redarea', - previewLabel: 'Previzualizare', - delayModalTitle: 'Temporizator', - delayPauseSection: 'Pune pauză după', - delayStartSection: 'Începe după', - delayPreviewPause: 'Se pune pauză la', - delayPreviewStart: 'Începe la', - delaySchedulePause: 'Programează pauza', - delayScheduleStart: 'Programează pornirea', - delayCancelPause: 'Anulează temporizatorul de pauză', - delayCancelStart: 'Anulează temporizatorul de start', - delayInactivePause: 'Disponibil până când ceva este redat.', - delayInactiveStart: 'Disponibil când o piesă sau un radio încărcat este în pauză.', - delayCustomMinutes: 'Întârziere personalizată (minute)', - delayCustomPlaceholder: 'ex. 2.5', - closeDelayModal: 'Închide', - delayIn: 'în', - delayFmtSec: '{{n}}s', - delayFmtMin: '{{n}} min', - delayFmtHr: '{{n}} h', - delayCancel: 'Anulează', - delayApply: 'Aplică', - next: 'Următoarea Piesă', - repeat: 'Repetă', - repeatOff: 'Oprit', - repeatAll: 'Tot', - repeatOne: 'Unul', - progress: 'Progresul Piesei', - volume: 'Volum', - toggleQueue: 'Comutați Coada', - collapseQueueResize: 'Strânge coada, redimensionează', - moreOptions: 'Mai multe opțiuni', - equalizer: 'Egalizator', - miniPlayer: 'Player Mini', - lyrics: 'Versuri', - fsLyricsToggle: 'Versuri în ecran complet', - lyricsLoading: 'Se încarcă versurile…', - lyricsNotFound: 'Niciun vers găsit pentru această piesă', - lyricsSourceServer: 'Sursa: Server', - lyricsSourceLrclib: 'Sursa: LRCLIB', - lyricsSourceNetease: 'Sursa: Netease', - lyricsSourceLyricsplus: 'Sursa: YouLyPlus', - showDuration: 'Arată durata', - showRemainingTime: 'Arată timpul rămas', - }, - nowPlayingInfo: { - tab: 'Informații', - empty: 'Redă ceva pentru a vedea informații', - artist: 'Artist', - songInfo: 'Informații piesă', - onTour: 'În turneu', - noTourEvents: 'Niciun show următor', - tourLoading: 'Se încarcă…', - poweredByBandsintown: 'Date turneu prin Bandsintown', - bioReadMore: 'Citește mai multe', - bioReadLess: 'Arată mai puțin', - showMoreTours_one: 'Arată cu {{count}} mai mult', - showMoreTours_other: 'Arată cu {{count}} mai mult', - showLessTours: 'Arată mai puțin', - enableBandsintownPrompt: 'Vezi date următoare de turnee?', - enableBandsintownPromptDesc: 'Opțional. Încarcă concertele pentru artistul curent prin API-ul public Bandsintown.', - enableBandsintownPrivacy: 'Când este pornit, numele artistului piesei curente redate este trimis către API-ul Bandsintown pentru a prelua datele turneelor. Nimic din datele personale sau ale contului nu părăsesc dispozitivul.', - enableBandsintownAction: 'Pornește', - role: { - artist: 'Artist', - albumArtist: 'Artist album', - composer: 'Compozitor', - }, - }, - songInfo: { - title: 'Informație piesă', - songTitle: 'Titlu', - artist: 'Artist', - album: 'Album', - albumArtist: 'Artist Album', - year: 'An', - genre: 'Gen', - duration: 'Durată', - track: 'Piesă', - format: 'Format', - bitrate: 'Bitrate', - sampleRate: 'Rată de Sample', - bitDepth: 'Adâncimea Biților', - channels: 'Canale', - fileSize: 'Mărime fișier', - path: 'Cale', - replayGainTrack: 'RG Gain Piesă', - replayGainAlbum: 'RG Gain Album', - replayGainPeak: 'RG Vârf Piesă', - mono: 'Mono', - stereo: 'Stereo', - }, - playlists: { - title: 'Playlisturi', - newPlaylist: 'Playlist nou', - unnamed: 'Playlist fără nume', - createName: 'Nume Playlist…', - create: 'Crează', - cancel: 'Anulează', - empty: 'Niciun playlist deocamdată.', - emptyPlaylist: 'Acest playlist este gol.', - addFirstSong: 'Adaugă prima ta piesă', - notFound: 'Playlistul nu a fost găsit.', - songs: '{{n}} piese', - playAll: 'Redă tot', - shuffle: 'Amestecă', - addToQueue: 'Adaugă la Coadă', - back: 'Înapoi la Playlisturi', - deletePlaylist: 'Șterge', - confirmDelete: 'Apasă din nou pentru a confirma', - removeSong: 'Șterge din playlist', - addSongs: 'Adaugă Piese', - searchPlaceholder: 'Caută în librărie…', - noResults: 'Niciun rezultat.', - suggestions: 'Piese sugerate', - noSuggestions: 'Nicio sugestie disponibilă.', - titleBadge: 'Playlist', - refreshSuggestions: 'Sugestii noi', - addSong: 'Adaugă la playlist', - preview: 'Previzualizare (30s)', - previewStop: 'Oprește previzualiarea', - playNextSuggestion: 'Redă următorul', - suggestionsHint: 'Dublu-clic pe un rând pentru a-l adăuga în playlist', - addSelected: 'Adaugă selectate', - cacheOffline: 'Adaugă playlistul în memoria cache offline', - offlineCached: 'Playlist adăugat în cache', - removeOffline: 'Șterge din cache-ul offline', - offlineDownloading: 'Se descarcă… ({{done}}/{{total}} albume)', - publicLabel: 'Public', - privateLabel: 'Privat', - editMeta: 'Editează playlist', - editNamePlaceholder: 'Nume playlist…', - editCommentPlaceholder: 'Adaugă o descriere…', - editPublic: 'Playlist public', - editSave: 'Salvează', - editCancel: 'Anulează', - changeCover: 'Schimbă imaginea de copertă', - changeCoverLabel: 'Schimbă poza', - removeCover: 'Șterge poza', - coverUpdated: 'Copertă actualizată', - metaSaved: 'Playlist actualizat', - downloadZip: 'Descarcă (ZIP)', - // Toast notifications for multi-select - addSuccess: '{{count}} piese adăugate la {{playlist}}', - addPartial: '{{added}} adăugate, {{skipped}} sărite (duplicate)', - addAllSkipped: 'Toate sărite ({{count}} duplicate)', - addedAsDuplicates: '{{count}} piese adăugate la {{playlist}} (ca duplicate)', - duplicateConfirmTitle: 'Deja în playlist', - duplicateConfirmMessage: 'Toate {{count}} piese sunt deja în "{{playlist}}". Adaugă-le din nou ca duplicate?', - duplicateConfirmAction: 'Adaugă oricum', - addError: 'Eroare la adăugarea pieselor', - createAndAddSuccess: 'Playlist "{{playlist}}" creat cu {{count}} piese', - createError: 'Eroare la crearea playlistului', - deleteSuccess: '{{count}} playlisturi șterse', - deleteFailed: 'Eroare la ștergerea {{name}}', - deleteSelected: 'Șterge selectate', - deleteSelectedPartial: 'Doar {{n}} din {{total}} playlisturi selectate pot fi șterse (celelalte aparțin altcuiva).', - mergeSuccess: '{{count}} piese comasate în {{playlist}}', - mergeNoNewSongs: 'Nicio piesă nouă de adăugat', - mergeError: 'Eroare la comasarea playlisturilor', - mergeInto: 'Comasează în', - selectionCount: '{{count}} selectate', - select: 'Selectează', - startSelect: 'Pornește selecția', - cancelSelect: 'Anulează', - loadingAlbums: 'Se rezolvă {{count}} albume…', - loadingArtists: 'Se rezolvă {{count}} artiști…', - myPlaylists: 'Playlisturile mele', - noOtherPlaylists: 'Niciun alt playlist disponibil', - addToPlaylistSuccess: '{{count}} piese adăugate în {{playlist}}', - addToPlaylistNoNew: 'Nicio piesă nouă adăugată în {{playlist}}', - addToPlaylistError: 'Eroare la adăugarea în playlist', - removeSuccess: 'Piesă ștearsă din playlist', - removeError: 'Eroare la ștergerea piesei din playlist', - importCSV: 'Import CSV', - importCSVTooltip: 'Import din CSV Spotify', - csvImportReport: 'Raport Import CSV', - csvImportTotal: 'Total', - csvImportAdded: 'Adăugate', - csvImportDuplicates: 'Duplicate', - csvImportNotFound: 'Negăsite', - csvImportNetworkErrors: 'Erori de rețea', - csvImportDuplicatesTitle: 'Piese duplicate (Deja în Playlist):', - csvImportNotFoundTitle: 'Piese negăsite:', - csvImportNetworkErrorsTitle: 'Erori de rețea (se poate reîncerca importul):', - csvImportDownloadReport: 'Descarcă Raport', - csvImportClose: 'Închide', - csvImportNoValidTracks: 'Nicio piesă validă găsită în fișierul CSV', - csvImportFailed: 'Nu s-a reușit importul fișierului CSV', - csvImportToast: '{{added}} adăugate, {{notFound}} negăsite, {{duplicates}} duplicate', - csvImportDownloadSuccess: 'Pagina de raport descărcată cu succes', - csvImportDownloadError: 'Nu s-a putut descărca raportul', - }, - smartPlaylists: { - sectionBasic: '1. De bază', - sectionGenres: '2. Genuri', - sectionYearsAndFilters: '3. Ani și filtre', - genreMode: 'Mod gen', - genreModeInclude: 'Include genuri', - genreModeExclude: 'Exclude genuri', - genreSearchPlaceholder: 'Filtrează genuri...', - availableGenres: 'Disponibil', - selectedGenres: 'Selectat', - yearMode: 'Mod an', - yearModeInclude: 'Include distanță', - yearModeExclude: 'Exclude distanță', - name: 'Nume (fără prefix)', - limit: 'Limită', - limitHint: 'Cât de multe piese să fie incluse în playlist (1-{{max}}, de obicei 50).', - artistContains: 'Artistul conține…', - albumContains: 'Albumul conține…', - titleContains: 'Titlul conține…', - minRating: 'Rating minim', - minRatingAria: 'Rating minim pentru playlist inteligent', - minRatingHint: '0 dezactivează limita minimă; 1-5 păstrează piesele cu rating peste valoarea selectată.', - fromYear: 'Din anul', - toYear: 'Până la anul', - excludeUnrated: 'Exclude piesele fără rating', - compilationOnly: 'Doar compilații', - create: 'Nou Playlist Inteligent', - save: 'Salvează Playlist Inteligent', - created: 'Creat {{name}}', - updated: 'Actualizat {{name}}', - createFailed: 'Nu s-a putut crea playlistul inteligent.', - updateFailed: 'Nu s-a putut actualiza playlistul inteligent.', - navidromeOnly: 'Playlisturile inteligente pot fi create doar pe servere Navidrome.', - loadFailed: 'Nu s-a putut încărca playlistul inteligent din Navidrome.', - sortRandom: 'Sortează: aleatoriu', - sortTitleAsc: 'Sortează: titlu A-Z', - sortTitleDesc: 'Sortează: titlu Z-A', - sortYearDesc: 'Sortează: an desc', - sortYearAsc: 'Sortează: an asc', - sortPlayCountDesc: 'Sortează: număr de redări desc', - }, - mostPlayed: { - title: 'Cele mai Redate', - topArtists: 'Top Artiști', - topAlbums: 'Top Albume', - plays: '{{n}} redări', - sortMost: 'Cele mai multe redări primele', - sortLeast: 'Cele mai puține redări primele', - loadMore: 'Încarcă mai multe albume', - noData: 'Nu există date de redare încă. Începe ascultarea!', - noArtists: 'Toți artiștii sunt filtrați.', - filterCompilations: 'Ascunde artiștii din compilații (Artiști variați, Coloane sonore, etc.)', - filterCompilationsShort: 'Ascunde compilațiile', - }, - losslessAlbums: { - empty: 'Niciun album lossless în această librărie încă.', - unsupported: 'Acest server nu expune metadata necesară pentru a găsi albumele lossless.', - slowFetchHint: 'Se încarcă mai încet decât alte pagini de album — Psysonic parcurge prin tot catalogul pieselor după calitate.', - }, - radio: { - title: 'Radio Internet', - empty: 'Nicio stație radio configurată.', - addStation: 'Adaugă Stație', - editStation: 'Editează', - deleteStation: 'Șterge stație', - confirmDelete: 'Apasă din nou pentru a confirma', - stationName: 'Numele stației…', - streamUrl: 'URL-ul streamului…', - homepageUrl: 'URL-ul paginii principale (opțional)', - save: 'Salvează', - cancel: 'Anulează', - live: 'LIVE', - liveStream: 'Radio Internet', - openHomepage: 'Deschide pagina principală', - changeCoverLabel: 'Schimbă coperta', - removeCover: 'Șterge coperta', - browseDirectory: 'Caută Director', - directoryPlaceholder: 'Caută stații…', - noResults: 'Nicio stație găsită.', - stationAdded: 'Stație adăugată', - filterAll: 'Toate', - filterFavorites: 'Favorite', - sortManual: 'Manual', - sortAZ: 'A → Z', - sortZA: 'Z → A', - sortNewest: 'Cele mai noi', - favorite: 'Adaugă la favorite', - unfavorite: 'Șterge din favorites', - noFavorites: 'Nicio stație favorită.', - listenerCount_one: '{{count}} ascultător', - listenerCount_other: '{{count}} ascultători', - recentlyPlayed: 'Redate recent', - upNext: 'Urmează', - }, - folderBrowser: { - empty: 'Folder gol', - error: 'Nu s-a putut încărca', - }, - deviceSync: { - title: 'Sincronizare Dispozitiv', - targetFolder: 'Folder Țintă', - noFolderChosen: 'Niciun folder ales', - selectDrive: 'Selectați un drive…', - refreshDrives: 'Reactualizați drive-urile', - noDrivesDetected: 'Niciun drive înlăturabil detectat', - browseManual: 'Caută manual…', - free: 'liber', - notMountedVolume: 'Ținta nu este pe un volum montat. Drive-ul este posibil deconectat.', - chooseFolder: 'Alege…', - targetDevice: 'Dispozitiv țintă', - schemaLabel: 'Schemă de numire', - schemaHint: 'Schemă fixă pentru sincronizare de încredere între sisteme de operare. Playlisturile sunt scrise ca .m3u8 care referă piesele albumului — niciun duplicat pe dispozitiv.', - migrateButton: 'Reorganizează fișiere existente…', - migrateTooltip: 'Renumește fișiere existente de pe dispozitiv în noua schemă (din șablonul numelui de fișier vechi).', - migrateTitle: 'Reorganizează fișiere existente', - migrateLoading: 'Se analizează fișiere existente…', - migrateNothingToDo: 'Toate fișierele existente corespund deja cu noua schemă — nimic de făcut.', - migrateNoTemplate: 'Niciun șablon de nume de fișier găsit pe dispozitiv. Migrarea se aplică doar când stick-ul a fost sincronizat cu o versiune de Psysonic care a suportat șabloane personalizate.', - migrateFilesToRename: 'fișiere vor fi redenumite', - migrateUnchanged: '{{n}} fișiere sunt deja în calea corectă', - migrateCollisions: '{{n}} fișiere nu au putut fi redenumite automat (mai multe piese sunt mapate către aceași țintă). Ele vor fi lăsate neatinse — următoarea sincronizare le re-descarcă în locația corectă.', - migratePreviewNote: 'Șablonul vechi: {{tpl}}', - migrateExecuting: 'Se redenumesc fișierele…', - migrateSuccess: '{{n}} fișiere redenumite cu succes', - migrateFailed: '{{n}} redenumiri au eșuat', - migrateShowErrors: 'Arată erorile', - migrateStart: 'Începe redenumirea', - onDevice: 'Manager de dispozitive', - addSources: 'Adaugă…', - colName: 'Nume', - colType: 'Tip', - colStatus: 'Status', - syncResult: '{{done}} transferate, {{skipped}} deja la zi ({{total}} total)', - deleteFromDevice: 'Marchează pentru ștergere ({{count}})', - confirmDelete: 'Șterge {{count}} element(e) din dispozitiv: {{names}}?', - deleteComplete: '{{count}} element(e) șterse din dispozitiv.', - manifestImported: '{{count}} surse importate din manifestul dispozitivului.', - selectedSources: 'Sursele selectate', - noSourcesSelected: 'Nicio sursă selectată. Apasă elementele din browser pentru a le adăuga.', - clearAll: 'Golește tot', - tabPlaylists: 'Playlisturi', - tabAlbums: 'Albume', - tabArtists: 'Artiști', - searchPlaceholder: 'Caută…', - syncButton: 'Sincronizează la Dispozitiv', - actionTransfer: 'Transferă la Dispozitiv', - actionDelete: 'Șterge din Dispozitiv', - actionApplyAll: 'Aplică toate schimbările', - cancel: 'Anulează', - noTargetDir: 'Alege un folder țintă mai întâi.', - noSources: 'Alege cel puțin o sursă.', - noTracks: 'Nicio piesă găsită în sursele selectate.', - fetchError: 'Nu s-a reușit preluarea pieselor de pe server.', - syncComplete: 'Sincronizare completă.', - dismiss: 'Îndepărtează', - cancelSync: 'Anulează', - syncCancelled: 'Sincronizare anulată ({{done}} / {{total}} transferate).', - statusSynced: 'Sincronizat', - statusPending: 'În așteptare', - statusDeletion: 'Ștergere', - markForDeletion: 'Marchează pentru Ștergere', - undoDeletion: 'Anulează ștergerea', - removeSource: 'Elimină', - syncInBackground: 'Sincronizare pornită în fundal — poți naviga în alte părți.', - syncInProgress: '{{done}} / {{total}} piese…', - scanningDevice: 'Se scanează dispozitivul…', - syncSummary: 'Sumar sincronizare', - calculating: 'Se calculează încărcătura necesară…', - filesToAdd: 'Fișiere de Adăugat:', - filesToDelete: 'Fișiere de Șterse:', - netChange: 'Schimbarea netă:', - availableSpace: 'Spațiu pe Disc disponibil:', - spaceWarning: 'Alertă: Dispozitivul țintă nu are destul spațiu raportat.', - proceed: 'Continuă cu Sincronizarea', - notEnoughSpace: 'Nu s-a detectat destul spațiu fizic pe disc!', - liveSearch: 'Live', - randomAlbumsLabel: 'Albume aleatorii', - }, - orbit: { - triggerLabel: 'Orbit', - triggerTooltip: 'Pornește sau intră în o sesiune de ascultare distribuită', - launchCreate: 'Crează o sesiune', - launchJoin: 'Intră într-o sesiune', - launchHelp: 'Cum funcționează asta?', - launchHelpSoon: 'În curând', - joinModalTitle: 'Intră într-o sesiune Orbit', - joinModalSub: 'Lipește link-ul de invitație pe care organizatorul ți l-a trimis.', - joinModalLinkLabel: 'Link-ul de invitație', - joinModalLinkPlaceholder: 'psysonic2-…', - joinModalLinkHelper: 'Funcționează cu orice link valid Orbit. Trebuie să arate spre serverul în care ești conectat acum.', - joinModalPasteTooltip: 'Lipește din clipboard', - joinModalSubmit: 'Intră', - joinModalBusy: 'Se intră…', - joinErrEmpty: 'Lipește un link de invitație.', - joinErrInvalid: 'Asta nu arată ca un link de invitație Orbit.', - closeAria: 'Închide', - heroTitlePrefix: 'Ascultă împreună cu', - heroTitleBrand: 'Orbit', - heroSub: 'Pornește o sesiune — alți utilizatori de pe {{server}} vor asculta deodată și pot sugera piese.', - fallbackServer: 'acest server', - tipLan: "Ești conectat acum printr-o adresă de rețea locală. Invitații din afara rețelei tale nu pot intra — schimbă pe o adresă publică de server în setări înainte de a începe.", - tipRemote: 'Pentru ca oaspeții din afara rețelei să poată intra, serverul tău trebuie să fie accesibil public. Dacă serverul tău este doar intern, schimbă înainte de a începe.', - labelName: 'Numele sesiunii', - namePlaceholder: 'Velvet Orbit', - reshuffleTooltip: 'Nouă sugestie', - reshuffleAria: 'Sugerează un nou nume', - helperName: 'Cum apare sesiunea către oaspeții tăi — păstrează-l sau folosește-l pe al tău.', - labelMax: 'Max oaspeți', - helperMax: "Tu nu ești numărat — se ține cont doar de oaspeții care intră.", - labelLink: 'Link-ul de invitație', - tooltipCopied: 'Copiat', - tooltipCopy: 'Copiază', - ariaCopyLink: 'Copiază link-ul de invitație', - helperLink: 'Trimite acest link către invitații tăi. Ei îl pot lipi oriunde în Psysonic cu Ctrl+V.', - labelClearQueue: 'Golește-mi coada mai întâi', - helperClearQueue: 'Începe sesiunea cu o coadă proaspătă goală. Oprit: piesele pe care le ai deja în coadă rămân și sunt distribuite cu oaspeții.', - btnCancel: 'Anulează', - btnStarting: 'Se începe…', - btnStart: 'Începe Orbit', - btnCopyAndStart: 'Copiază acest link & începe', - errNameRequired: 'Dă un nume sesiunii tale.', - errStartFailed: "Nu s-a putut începe.", - hostLabel: 'Gazdă: {{name}}', - participantsTooltip: 'Participanți', - settingsTooltip: 'Setările sesiunii', - shareTooltip: 'Distribuie link-ul de invitație', - shuffleLabel: 'Coada se re-amestecă în', - catchUpLabel: 'ajunge din urmă', - catchUpTooltip: "Sari către poziția curentă a gazdei", - hostAway: 'Gazdă offline', - hostOnline: 'Gazdă online', - endTooltip: 'Termină sesiunea', - leaveTooltip: 'Părăsește sesiunea', - helpTooltip: 'Cum funcționează Orbit', - diag: { - openTooltip: 'Diagnostice — log-uri evenimente copiabile', - title: 'Diagnostice Orbit', - role: 'Rol', - hostTrack: 'Id piesă gazdă', - hostPos: 'Poziție gazdă', - guestTrack: 'Id-ul piesei mele', - guestPos: 'Id-ul poziției mele', - drift: 'Drift', - stateAge: 'Status vârstă', - eventLog: 'Log-uri evenimente ({{count}})', - copyLabel: 'Copiază', - copyTooltip: 'Copiază log-urile în clipboard', - clearLabel: 'Golește', - clearTooltip: 'Șterge buffer-ul', - empty: 'Niciun eveniment deocamdată — evenimentele apar ca sincronizare Orbit.', - hint: 'Deschide asta înainte de a reproduce o problemă, apoi apasă Copiază și lipește în raportul problemei.', - copied: 'S-au copiat {{count}} linii de eveniment', - copyFailed: 'Nu s-a putut copia în clipboard', - cleared: 'Buffer curățat', - }, - helpTitle: 'Cum funcționează Orbit', - helpIntro: 'Orbit transformă Psysonic într-o cameră distribuită de ascultare. O gazdă alege muzica; oaspeții ascultă în sincron și pot sugera piese.', - helpHostOnly: '(gazdă)', - helpSec1Title: 'Ce este Orbit?', - helpSec1Body: "Un mod \"ascultă împreună\" — gazda controlează redarea, oaspeții se alătură. Totul rulează prin playlisturile de pe serverul tău Navidrome; nicio infrastructură externă.", - helpSec2Title: 'Gazdă și oaspeți', - helpSec2Body: 'Gazda controlează redarea (redă / pauză / sari / caută) și decide când sesiunea se termină. Oaspeții urmează redarea gazdei, pot sugera piese, și pot ieși și re-intra oricând. Doar gazda poate da afară sau bana permanent un participant.', - helpSec2WarnHead: 'Important: conturi separate.', - helpSec2WarnBody: "Fiecare participant are nevoie de contul său Navidrome. Dacă gazda și oaspetele se conectează cu același utilizator propunerile lor se ciocnesc și gazda nu va vedea propunerile oaspetului.", - helpSec3Title: 'Pornirea și invitarea', - helpSec3Body: 'Apasă pe butonul "Orbit" → Crează o sesiune → modalul de pornire arată un link de invitație gata de copiat și te lasă opțional să golești coada curentă. Împarte acel link oricum dorești. Cât timp o sesiune este în derulare, butonul de distribuire din bara sesiunii de sus copiază link-ul din nou oricând.', - helpSec4Title: 'Intrare', - helpSec4Body: 'Lipește link-ul de invitație oriunde în Psysonic cu Ctrl+V / Cmd+V — prompt-ul de alăturare se deschide automat. Alternativă: "Orbit" → Intră într-o sesiune → lipește în câmpul prezentat. Dacă link-ul arată către un server pe care ai un cont, Psysonic îl schimbă pentru tine. Când ai mai mult de un cont pe acel server, un alegător mic te va întreba pe care să îl folosești.', - helpSec5Title: 'Sugerarea pieselor', - helpSec5Body: 'În orice listă de piese: dublu-clic pe un rând, sau clic-dreapta → "Adaugă la sesiunea Orbit". Un clic singular arată o sugestie în loc de a pune tot albumul în coada distribuită — asta este intenționat. Acțiunile explicite în masă cum ar fi "Redă Tot" sau "Redă Album" întreabă pentru confirmare mai întâi și după adaugă (niciodată schimbă).', - helpSec6Title: 'Coadă distribuită', - helpSec6Body: "Coada afișează piesele următoare ale gazdei — vizibile către toți. Adăugările în masă care sosesc sunt mereu adăugate, deci sugestiile oaspeților nu sunt pierdute. Auto-amestecarea reordonează coada periodic (configrabil: 1 / 5 / 10 / 15 / 30 min). Dacă redarea se Îndepărtează de gazdă, butonul de \"Ajunge din urmă\" în bara sesiunii sare înapoi către poziția live a gazdei.", - helpSec7Title: 'Aprobări', - helpSec7Body: 'Implicit, sugestiile oaspeților au nevoie de aprobare manuală — apar în banda "Aprobări" în vârful panoului cozii cu butoane de acceptă / respinge. Auto-aprobarea poate fi pornită în setările sesiunii pentru ca toate sugestiile să intre din prima.', - helpSec8Title: 'Participanți și setări', - helpSec8Body: 'Deschide iconița de setări din bara sesiunii pentru cadența amestecării, auto-aprobare, și scurtătura "Amestecă acum". Apasă pe numărul de participanți pentru a vedea cine este conectat — dă afară (se poate reconecta cu link-ul) sau ban (blocat din sesiune). Oaspeții pot vedea de asemenea lista de participanți, doar nu o pot modifica.', - helpSec9Title: 'Sfârșirea sesiunii', - helpSec9Body: "Gazdă X → dialog confirmare → sesiunea se închide pentru toată lumea și playlisturile serverului sunt curățate automat. Oaspete X → oaspetele pleacă, sesiunea continuă să ruleze. Dacă gazda nu răspunde pentru 5 minute oaspetele iese automat cu o notificare; reconectările scurte din acel interval sunt invizibile.", - participantsInviteLabel: 'Link-ul de invitație', - participantsCountLabel: '{{count}} în sesiune', - participantsHost: 'gazdă', - participantsEmpty: 'Niciun oaspete deocamdată', - participantsKickTooltip: 'Înlătură din sesiune', - participantsKickAria: 'Înlătură {{user}}', - participantsRemoveTooltip: 'Înlătură din sesiune', - participantsRemoveAria: 'Înlătură {{user}} din această sesiune', - participantsBanTooltip: 'Banează permanent', - participantsBanAria: 'Banează permanent {{user}}', - participantsMuteTooltip: 'Dezactivează sugestiile', - participantsUnmuteTooltip: 'Permite sugestiile', - participantsMuteAria: 'Dezactivează sugestii de la {{user}}', - participantsUnmuteAria: 'Permite sugestii de la {{user}}', - confirmRemoveTitle: 'Înlătură din sesiune?', - confirmRemoveBody: '{{user}} va fi dat afară din sesiune, dar poate reintra prin link-ul tău de invitație.', - confirmRemoveConfirm: 'Înlătură', - confirmBanTitle: 'Banezi permanent?', - confirmBanBody: '{{user}} va fi înlăturat și blocat din reintrarea în această sesiune. Acest lucru nu poate fi anulat pe durata sesiunii.', - confirmBanConfirm: 'Ban', - confirmCancel: 'Anulează', - confirmJoinTitle: 'Te alături sesiunii Orbit?', - confirmJoinBody: '{{host}} te-a invitat în "{{name}}". Intri în sesiune?', - confirmJoinConfirm: 'Intră', - confirmLeaveTitle: 'Părăsești sesiunea?', - confirmLeaveBody: 'Părăsești "{{name}}"? Poți reintra prin link-ul de invitație al {{host}} oricând.', - confirmLeaveConfirm: 'Pleacă', - confirmEndTitle: 'Termini sesiunea pentru toți?', - confirmEndBody: '"{{name}}" va închide pentru toți participanții. Playlisturile sesiunii sunt curățate automat.', - confirmEndConfirm: 'Termină sesiunea', - invalidLinkTitle: 'Link-ul de invitație nu mai este valid', - invalidLinkBody: 'Această sesiune Orbit nu mai există sau s-a terminat deja. Roagă gazda pentru un link de invitație proaspăt.', - settingsTitle: 'Setările sesiunii', - settingAutoApprove: 'Auto-aprobă sugestiile', - settingAutoApproveHint: "Sugestiile oaspeților intră în coadă instant. Oprit: ele rămân în lista sesiunii pentru ca tu să le revizuiești mai târziu.", - settingAutoShuffle: 'Reamestecare automată', - settingAutoShuffleHint: "Amestecare periodică Fisher–Yates a cozii care urmează. Oprit: ordinea se schimbă doar când o rearanjezi.", - settingShuffleInterval: 'Reamestecă la fiecare', - settingShuffleIntervalHint: 'Cât de des se reamestecă coada în timp ce sesiunea rulează.', - suggestBlockedMuted: 'Gazda te-a oprit din a trimite sugestii pentru această sesiune — sugestiile sunt oprite.', - settingShuffleIntervalValue_one: '{{count}} min', - settingShuffleIntervalValue_other: '{{count}} min', - settingShuffleNow: 'Amestecă acum', - toastSuggested: '{{user}} a sugerat "{{title}}"', - toastSuggestedMany: '{{count}} noi sugestii în coadă', - toastShuffled: 'Coadă amestecată', - toastJoined: 'A intrat în sesiune', - toastLoginFirst: 'Log in before joining a session', - toastSwitchServer: 'Schimbă la {{url}} mai întâi, apoi lipește din nou', - toastNoAccountForServer: "Nu ai acces la {{url}}. Cere o invitație gazdei.", - toastSwitchFailed: "Nu s-a putut schimba la {{url}}", - accountPickerTitle: 'Ce cont?', - accountPickerSub: 'Ai mai mult de un cont pentru {{url}}. Alege unul cu care să intri în sesiune.', - toastJoinFail: "Nu s-a putut alătura sesiunii", - joinErrNotFound: 'Sesiunea nu a fost găsită', - joinErrEnded: 'Sesiunea s-a terminat', - joinErrFull: 'Sesiunea este plină', - joinErrKicked: "Nu poți reintra în această sesiune", - joinErrNoUser: 'Niciun server activ', - joinErrServerError: "Nu s-a putut intra", - ctxAddToSession: 'Adaugă la sesiunea Orbit', - ctxSuggestedToast: 'Sugerat la sesiune', - ctxSuggestFailed: "Nu s-a putut sugera — neintrat", - ctxAddToSessionHost: 'Adaugă la sesiunea Orbit', - ctxAddedHostToast: 'Adăugat la sesiune', - ctxAddHostFailed: "Nu s-a putut adăuga la sesiune", - bulkConfirmTitle: 'Adaugi tot în coada Orbit?', - bulkConfirmBody: "Asta va lăsa {{count}} piese în coada distribuită deodată. Asta este mult pentru toți oaspeții să remarce. Continui?", - bulkConfirmYes: 'Adaugă tot', - bulkConfirmNo: 'Anulează', - guestLive: 'Live', - guestPlaying: 'Se redă acum', - guestPaused: 'Pauză', - guestLoading: 'Se încarcă…', - guestSuggestions: 'Sugestii', - guestUpNext: 'Urmează', - guestUpNextEmpty: 'Nimic în coadă. Deschide meniul de context a unei piese și alege "Adaugă la sesiunea Orbit" pentru a sugera una.', - guestPendingTitle: 'Se așteaptă gazda', - guestPendingHint: 'Sugerat — va apărea în coadă când gazda o va alege.', - approvalTitle: 'Aprobări în așteptare', - approvalFrom: 'Sugerat de{{user}}', - approvalAccept: 'Accept', - approvalDecline: 'Respinge', - guestUpNextMore: '+ {{count}} mai multe în coada gazdei', - guestSubmitter: 'de {{user}}', - queueAddedByHost: 'Adăugat de gazdă', - queueAddedByYou: 'Adăugat de tine', - queueAddedByUser: 'Adăugat de {{user}}', - guestEmpty: 'Nicio sugestie încă. Deschide meniul de context a unei piese și alege "Adaugă la sesiunea Orbit".', - guestFooter: "Gazda controlează redarea — nu poți schimba lista.", - exitKickedTitle: 'Ai fost banat din sesiune', - exitRemovedTitle: 'Ai fost înlăturat din sesiune', - exitEndedTitle: 'Gazda a încheiat sesiunea', - exitHostTimeoutTitle: 'Gazda n-a mai răspuns', - exitHostTimeoutBody: "{{host}} nu a mai trimis un update de ceva timp, așa că \"{{name}}\" a fost închis pe partea ta. Poți reintra oricând cu link-ul de invitație.", - exitKickedBody: '{{host}} te-a banat din "{{name}}". Nu poți reintra', - exitRemovedBody: '{{host}} te-a înlăturat din "{{name}}". Poți reintra oricând cu link-ul de invitație.', - exitEndedBody: '"{{name}}" s-a terminat. Sper că te-ai distrat.', - exitOk: 'OK', - }, - tray: { - playPause: 'Redă / Pauză', - nextTrack: 'Următoarea Piesă', - previousTrack: 'Piesa Anterioară', - showHide: 'Arată / Ascunde', - exitPsysonic: 'Ieși din Psysonic', - nothingPlaying: 'Nimic nu este redat', - }, - licenses: { - title: 'Licențe Open Source', - intro: 'Psysonic este construit pe software open-source. Lista de mai jos arată fiecare dependință a aplicației, cu versiunea, licența și textul complet al licenței ei.', - highlights: 'Dependințe cheie', - searchPlaceholder: 'Caută după nume, versiune sau licență…', - noResults: 'Nicio potrivire.', - loading: 'Se încarcă licențele…', - loadError: 'Nu s-au putut încărca datele licenței.', - noLicenseText: 'Niciun text de licență inclus pentru această dependință.', - viewSource: 'Vezi sursa', - totalLine: '{{total}} dependințe — {{cargo}} cargo, {{npm}} npm', - generatedAt: 'Ultima dată a generării {{date}}', - }, -}; diff --git a/src/locales/ro/albumDetail.ts b/src/locales/ro/albumDetail.ts new file mode 100644 index 00000000..1c493e80 --- /dev/null +++ b/src/locales/ro/albumDetail.ts @@ -0,0 +1,47 @@ +export const albumDetail = { + back: 'Înapoi', + orbitDoubleClickHint: 'Apasă dublu-clic pentru a adăuga această piesă în coada Orbit', + playAll: 'Redă tot', + shareAlbum: 'Distribuie Albumul', + enqueue: 'Adaugă în coadă', + enqueueTooltip: 'Adaugă întregul album în coadă', + artistBio: 'Biografia Artistului', + download: 'Descarcă (ZIP)', + downloading: 'Se încarcă…', + cacheOffline: 'Fă disponibil offline', + offlineCached: 'Disponibil offline', + offlineDownloading: 'Se salvează în cache… ({{n}}/{{total}})', + removeOffline: 'Șterge cache-ul offline', + offlineStorageFull: 'Stocare offline plină (limită: {{mb}} MB). Eliberează spațiu ștergând un album din Librăria Offline, sau mărește limita în Setări.', + offlineStorageGoToLibrary: 'Librăria Offline', + offlineStorageGoToSettings: 'Setări', + favoriteAdd: 'Adaugă la Favorite', + favoriteRemove: 'Șterge din Favorite', + favorite: 'Favorit', + noBio: 'Nicio biografie disponibilă.', + moreByArtist: 'Mai multe de la {{artist}}', + tracksCount: '{{n}} Piese', + goToArtist: 'Către {{artist}}', + moreLabelAlbums: 'Mai multe albume în {{label}}', + trackTitle: 'Titlu', + trackAlbum: 'Album', + trackArtist: 'Artist', + trackGenre: 'Gen', + trackFormat: 'Format', + trackFavorite: 'Favorit', + trackRating: 'Rating', + trackDuration: 'Durată', + trackTotal: 'Total', + columns: 'Coloane', + resetColumns: 'Resetează la predefinite', + notFound: 'Albumul nu a fost găsit.', + bioModal: 'Biografia Artistului', + bioClose: 'Închide', + ratingLabel: 'Rating', + enlargeCover: 'Extinde', + filterSongs: 'Filtrează piese…', + sortNatural: 'Natural', + sortByTitle: 'A–Z (Titlu)', + sortByArtist: 'A–Z (Artist)', + sortByAlbum: 'A–Z (Album)', +}; diff --git a/src/locales/ro/albums.ts b/src/locales/ro/albums.ts new file mode 100644 index 00000000..fea58cc4 --- /dev/null +++ b/src/locales/ro/albums.ts @@ -0,0 +1,32 @@ +export const albums = { + title: 'Toate albumele', + sortByName: 'A–Z (Album)', + sortByArtist: 'A–Z (Artist)', + sortNewest: 'Cele mai noi primele', + sortRandom: 'Aleatoriu', + yearFrom: 'De la', + yearTo: 'Până la', + yearFilterClear: 'Golește filtrul de an', + yearFilterLabel: 'An', + compilationLabel: 'Compilații', + compilationOnly: 'Doar compilații', + compilationHide: 'Ascunde compilațiile', + compilationTooltipAll: 'Toate albumele · clic: doar compilații', + compilationTooltipOnly: 'Doar compilații · clic: ascunde compilațiile', + compilationTooltipHide: 'Compilații ascunse · clic: arată toate', + select: 'Multi-selecție', + startSelect: 'Activează multi-selecția', + cancelSelect: 'Anulează', + selectionCount: '{{count}} selectate', + downloadZips: 'Descarcă ZIPuri', + addOffline: 'Adaugă Offline', + enqueueSelected_one: 'Adaugă în coadă ({{count}})', + enqueueSelected_other: 'Adaugă în coadă ({{count}})', + enqueueQueued_one: 'Adăugat {{count}} album în coadă', + enqueueQueued_other: 'Adăugat {{count}} albume în coadă', + downloadingZip: 'Se descarcă {{current}}/{{total}}: {{name}}', + downloadZipDone: '{{count}} ZIP(uri) descărcate', + downloadZipFailed: 'Nu s-a reușit descărcarea {{name}}', + offlineQueuing: 'Se adaugă în coadă {{count}} album(e) pentru offline…', + offlineFailed: 'Nu s-a reușit adăugarea {{name}} offline', +}; diff --git a/src/locales/ro/artistDetail.ts b/src/locales/ro/artistDetail.ts new file mode 100644 index 00000000..e60267e4 --- /dev/null +++ b/src/locales/ro/artistDetail.ts @@ -0,0 +1,41 @@ +export const artistDetail = { + back: 'Înapoi', + albums: 'Albume', + album: 'Album', + playAll: 'Redă tot', + shareArtist: 'Distribuie artistul', + shuffle: 'Amestecă', + radio: 'Radio', + loading: 'Se încarcă…', + noRadio: 'Nicio piesă similară găsită pentru acest artist.', + notFound: 'Artistul nu a fost găsit.', + albumsBy: 'Albume de {{name}}', + topTracks: 'Top Piese', + noAlbums: 'Niciun album găsit.', + trackTitle: 'Titlu', + trackAlbum: 'Album', + trackDuration: 'Durată', + favoriteAdd: 'Adaugă la Favorite', + favoriteRemove: 'Șterge de la Favorite', + favorite: 'Favorit', + albumCount_one: '{{count}} Album', + albumCount_other: '{{count}} Albume', + openedInBrowser: 'Deschide în browser', + featuredOn: 'Apare de asemenea în', + similarArtists: 'Artiști similari', + cacheOffline: 'Salvează discografia offline', + offlineCached: 'Discografie stocată în cache', + offlineDownloading: 'Se salvează în cache… ({{done}}/{{total}} albume)', + uploadImage: 'Încarcă imaginea artistului', + uploadImageError: 'Nu s-a reușit încărcarea imaginii', + releaseTypes: { + album: 'Album', + ep: 'EP', + single: 'Single', + compilation: 'Compilație', + live: 'Live', + soundtrack: 'Soundtrack', + remix: 'Remix', + other: 'Altul', + }, +}; diff --git a/src/locales/ro/artists.ts b/src/locales/ro/artists.ts new file mode 100644 index 00000000..d6b3259f --- /dev/null +++ b/src/locales/ro/artists.ts @@ -0,0 +1,18 @@ +export const artists = { + title: 'Artiști', + search: 'Caută…', + all: 'Tot', + gridView: 'Vizualizare grilă', + listView: 'Vizualizare listă', + imagesOn: 'Imagini artist pornit — poate mări încărcarea rețelei și a sistemului', + imagesOff: 'Imagini artist oprit — se arată doar inițialele', + loadMore: 'Încarcă mai mult', + notFound: 'Niciun artist găsit.', + albumCount_one: '{{count}} Album', + albumCount_other: '{{count}} Albume', + selectionCount: '{{count}} selectați', + select: 'Multi-selecție', + startSelect: 'Activează multi-selecția', + cancelSelect: 'Anulează', + addToPlaylist: 'Adaugă la Playlist', +}; diff --git a/src/locales/ro/changelog.ts b/src/locales/ro/changelog.ts new file mode 100644 index 00000000..5e7cc40f --- /dev/null +++ b/src/locales/ro/changelog.ts @@ -0,0 +1,5 @@ +export const changelog = { + modalTitle: "Ce este nou", + dontShowAgain: "Nu arăta din nou", + close: 'Am înțeles', +}; diff --git a/src/locales/ro/common.ts b/src/locales/ro/common.ts new file mode 100644 index 00000000..b472daf2 --- /dev/null +++ b/src/locales/ro/common.ts @@ -0,0 +1,66 @@ +export const common = { + albums: 'Albume', + album: 'Album', + loading: 'Se încarcă…', + loadingMore: 'Se încarcă…', + loadingPlaylists: 'Se încarcă Playlisturi…', + noAlbums: 'Niciun album găsit.', + downloading: 'Se descarcă…', + downloadZip: 'Descarcă (ZIP)', + back: 'Înapoi', + cancel: 'Anulează', + close: 'Închide', + save: 'Salvează', + delete: 'Șterge', + use: 'Folosește', + add: 'Adaugă', + new: 'Nou', + active: 'Activ', + download: 'Descarcă', + chooseDownloadFolder: 'Alege folderul de descărcare', + noFolderSelected: 'Niciun folder selectat', + rememberDownloadFolder: 'Ține minte acest folder', + filterGenre: 'Filtru de gen', + filterSearchGenres: 'Caută genuri…', + filterNoGenres: 'Niciun gen nu corespunde', + filterClear: 'Golește', + favorites: 'Favorite', + favoritesTooltipOff: 'Arată doar favorite', + favoritesTooltipOn: 'Arată tot', + play: 'Redă', + bulkSelected: '{{count}} selectate', + clearSelection: 'Golește selecția', + bulkAddToPlaylist: 'Adaugă la Playlist', + bulkRemoveFromPlaylist: 'Șterge din Playlist', + bulkClear: 'Golește selecția', + updaterAvailable: 'Update disponibil', + updaterVersion: 'v{{version}} este disponibil', + updaterWebsite: 'Website', + updaterModalTitle: 'Nouă versiune disponibilă', + updaterChangelog: "Ce este nou", + updaterDownloadBtn: 'Descarcă acum', + updaterSkipBtn: 'Sari peste această Versiune', + updaterRemindBtn: 'Amintește-mi mai târziu', + updaterDone: 'Descărcare finalizată', + updaterShowFolder: 'Arată în Folder', + updaterInstallHint: 'Închide Psysonic și rulează programul de instalare manual.', + updaterAurHint: 'Instalează update-ul prin AUR:', + updaterErrorMsg: 'Descărcare eșuată', + updaterRetryBtn: 'Reîncearcă', + updaterInstallNow: 'Instalează acum', + updaterMacReadyTitle: 'Pregătit de instalare', + updaterMacReady: 'Acest update descarcă, verifică și este aplicat în loc — nu este nevoie de DMG. Aplicația își dă restart automat când e gata.', + updaterTrustNotarized: 'Notarizat de Apple', + updaterTrustSignature: 'Semnătură verificată', + updaterMacDoneTitle: 'Update instalat', + updaterRestartingIn: 'Se restartează în {{n}}s…', + updaterRestarting: 'Se restartează…', + updaterRestartNow: 'Restart acum', + durationHoursMinutes: '{{hours}}h {{minutes}}m', + durationMinutesOnly: '{{minutes}}m', + updaterOpenGitHub: 'Deschide în GitHub', + filters: 'Filtre', + more: 'mai mult', + yearRange: 'Interval de an', + clearAll: 'Golește tot', +}; diff --git a/src/locales/ro/composerDetail.ts b/src/locales/ro/composerDetail.ts new file mode 100644 index 00000000..0374c30c --- /dev/null +++ b/src/locales/ro/composerDetail.ts @@ -0,0 +1,11 @@ +export const composerDetail = { + back: 'Înapoi', + notFound: 'Compozitorul nu a fost găsit.', + about: 'Despre acest compozitor', + works: 'Lucrări', + noWorks: 'Nicio lucrare găsită.', + workCount_one: '{{count}} lucrare', + workCount_other: '{{count}} lucrări', + shareComposer: 'Distribuie compozitorul', + unknownComposer: 'Compozitor', +}; diff --git a/src/locales/ro/composers.ts b/src/locales/ro/composers.ts new file mode 100644 index 00000000..9d1b6c32 --- /dev/null +++ b/src/locales/ro/composers.ts @@ -0,0 +1,10 @@ +export const composers = { + title: 'Compozitori', + search: 'Caută…', + notFound: 'Niciun compozitor găsit.', + unsupported: 'Căutarea dupa Compozitori necesită Navidrome 0.55 sau mai nou.', + loadFailed: 'Nu s-au putut încărca compozitorii.', + retry: 'Reîncearcă', + involvedIn_one: 'Implicat în {{count}} album', + involvedIn_other: 'Implicat în {{count}} albume', +}; diff --git a/src/locales/ro/connection.ts b/src/locales/ro/connection.ts new file mode 100644 index 00000000..2b12944f --- /dev/null +++ b/src/locales/ro/connection.ts @@ -0,0 +1,28 @@ +export const connection = { + connected: 'Conectat', + connectedTo: 'Conectat la {{server}}', + disconnected: 'Deconectat', + disconnectedFrom: 'Nu s-a putut ajunge la {{server}} — apasă pentru a verifica setările', + checking: 'Se conectează…', + extern: 'Extern', + offlineTitle: 'Nicio conexiune la server', + offlineSubtitle: 'Nu s-a putut ajunge la {{server}}. Verifică rețeaua sau serverul.', + offlineModeBanner: 'Modul Offline — se redă din cache-ul local', + offlineNoCacheBanner: 'Nicio conexiune la server — nu s-a putut ajunge la {{server}}', + offlineLibraryTitle: 'Librărie offline', + offlineLibraryEmpty: 'Niciun album adăugat în cache. Conectează-te, deschide un album și apasă "Fă disponibil offline".', + offlineAlbumCount: '{{n}} album', + offlineAlbumCount_plural: '{{n}} albume', + offlineFilterAll: 'Toate', + offlineFilterAlbums: 'Albume', + offlineFilterPlaylists: 'Playlisturi', + offlineFilterArtists: 'Discografii', + retry: 'Reîncearcă', + serverSettings: 'Setările serverului', + switchServerTitle: 'Schimbă serverul', + switchServerHint: 'Apasă pentru a alege alt server salvat.', + manageServers: 'Gestionează serverele…', + switchFailed: 'Nu s-a putut schimba — nu s-a putut ajunge la server.', + lastfmConnected: 'Last.fm conectat ca @{{user}}', + lastfmSessionInvalid: 'Sesiune invalidă — apasă pentru a te reconecta', +}; diff --git a/src/locales/ro/contextMenu.ts b/src/locales/ro/contextMenu.ts new file mode 100644 index 00000000..05a826cb --- /dev/null +++ b/src/locales/ro/contextMenu.ts @@ -0,0 +1,33 @@ +export const contextMenu = { + playNow: 'Redă acum', + playNext: 'Redă următorul', + addToQueue: 'Adaugă la coadă', + enqueueAlbum: 'Adaugă Albumul la coadă', + enqueueAlbums_one: 'Adaugă la coadă {{count}} Album', + enqueueAlbums_other: 'Adaugă la coadă {{count}} Albume', + startRadio: 'Pornește Radioul', + instantMix: 'Mix Instant', + instantMixFailed: 'Nu s-a putut crea Mixul Instant — eroare de server sau plugin.', + cliMixNeedsTrack: 'Nimic nu este redat — pornește redarea mai întâi, apoi rulează comanda mix din nou.', + lfmLove: 'Apreciază în Last.fm', + lfmUnlove: 'Elimină aprecierea în Last.fm', + favorite: 'Favorit', + favoriteArtist: 'Artist Favorit', + favoriteAlbum: 'Album Favorit', + unfavorite: 'Șterge din Favorite', + unfavoriteArtist: 'Șterge Artistul din Favorite', + unfavoriteAlbum: 'Șterge Albumul din Favorite', + removeFromQueue: 'Șterge din Coadă', + removeFromPlaylist: 'Șterge din Playlist', + openAlbum: 'Deschide Albumul', + goToArtist: 'Vezi Artistul', + download: 'Descarcă (ZIP)', + addToPlaylist: 'Adaugă la Playlist', + selectedPlaylists: '{{count}} playlisturi selectate', + selectedAlbums: '{{count}} albume selectate', + selectedArtists: '{{count}} artiști selectați', + songInfo: 'Informații despre Piesă', + shareLink: 'Copiază link-ul', + shareCopied: 'Link copiat în clipboard.', + shareCopyFailed: 'Nu s-a putut copia în clipboard.', +}; diff --git a/src/locales/ro/deviceSync.ts b/src/locales/ro/deviceSync.ts new file mode 100644 index 00000000..eb918f96 --- /dev/null +++ b/src/locales/ro/deviceSync.ts @@ -0,0 +1,80 @@ +export const deviceSync = { + title: 'Sincronizare Dispozitiv', + targetFolder: 'Folder Țintă', + noFolderChosen: 'Niciun folder ales', + selectDrive: 'Selectați un drive…', + refreshDrives: 'Reactualizați drive-urile', + noDrivesDetected: 'Niciun drive înlăturabil detectat', + browseManual: 'Caută manual…', + free: 'liber', + notMountedVolume: 'Ținta nu este pe un volum montat. Drive-ul este posibil deconectat.', + chooseFolder: 'Alege…', + targetDevice: 'Dispozitiv țintă', + schemaLabel: 'Schemă de numire', + schemaHint: 'Schemă fixă pentru sincronizare de încredere între sisteme de operare. Playlisturile sunt scrise ca .m3u8 care referă piesele albumului — niciun duplicat pe dispozitiv.', + migrateButton: 'Reorganizează fișiere existente…', + migrateTooltip: 'Renumește fișiere existente de pe dispozitiv în noua schemă (din șablonul numelui de fișier vechi).', + migrateTitle: 'Reorganizează fișiere existente', + migrateLoading: 'Se analizează fișiere existente…', + migrateNothingToDo: 'Toate fișierele existente corespund deja cu noua schemă — nimic de făcut.', + migrateNoTemplate: 'Niciun șablon de nume de fișier găsit pe dispozitiv. Migrarea se aplică doar când stick-ul a fost sincronizat cu o versiune de Psysonic care a suportat șabloane personalizate.', + migrateFilesToRename: 'fișiere vor fi redenumite', + migrateUnchanged: '{{n}} fișiere sunt deja în calea corectă', + migrateCollisions: '{{n}} fișiere nu au putut fi redenumite automat (mai multe piese sunt mapate către aceași țintă). Ele vor fi lăsate neatinse — următoarea sincronizare le re-descarcă în locația corectă.', + migratePreviewNote: 'Șablonul vechi: {{tpl}}', + migrateExecuting: 'Se redenumesc fișierele…', + migrateSuccess: '{{n}} fișiere redenumite cu succes', + migrateFailed: '{{n}} redenumiri au eșuat', + migrateShowErrors: 'Arată erorile', + migrateStart: 'Începe redenumirea', + onDevice: 'Manager de dispozitive', + addSources: 'Adaugă…', + colName: 'Nume', + colType: 'Tip', + colStatus: 'Status', + syncResult: '{{done}} transferate, {{skipped}} deja la zi ({{total}} total)', + deleteFromDevice: 'Marchează pentru ștergere ({{count}})', + confirmDelete: 'Șterge {{count}} element(e) din dispozitiv: {{names}}?', + deleteComplete: '{{count}} element(e) șterse din dispozitiv.', + manifestImported: '{{count}} surse importate din manifestul dispozitivului.', + selectedSources: 'Sursele selectate', + noSourcesSelected: 'Nicio sursă selectată. Apasă elementele din browser pentru a le adăuga.', + clearAll: 'Golește tot', + tabPlaylists: 'Playlisturi', + tabAlbums: 'Albume', + tabArtists: 'Artiști', + searchPlaceholder: 'Caută…', + syncButton: 'Sincronizează la Dispozitiv', + actionTransfer: 'Transferă la Dispozitiv', + actionDelete: 'Șterge din Dispozitiv', + actionApplyAll: 'Aplică toate schimbările', + cancel: 'Anulează', + noTargetDir: 'Alege un folder țintă mai întâi.', + noSources: 'Alege cel puțin o sursă.', + noTracks: 'Nicio piesă găsită în sursele selectate.', + fetchError: 'Nu s-a reușit preluarea pieselor de pe server.', + syncComplete: 'Sincronizare completă.', + dismiss: 'Îndepărtează', + cancelSync: 'Anulează', + syncCancelled: 'Sincronizare anulată ({{done}} / {{total}} transferate).', + statusSynced: 'Sincronizat', + statusPending: 'În așteptare', + statusDeletion: 'Ștergere', + markForDeletion: 'Marchează pentru Ștergere', + undoDeletion: 'Anulează ștergerea', + removeSource: 'Elimină', + syncInBackground: 'Sincronizare pornită în fundal — poți naviga în alte părți.', + syncInProgress: '{{done}} / {{total}} piese…', + scanningDevice: 'Se scanează dispozitivul…', + syncSummary: 'Sumar sincronizare', + calculating: 'Se calculează încărcătura necesară…', + filesToAdd: 'Fișiere de Adăugat:', + filesToDelete: 'Fișiere de Șterse:', + netChange: 'Schimbarea netă:', + availableSpace: 'Spațiu pe Disc disponibil:', + spaceWarning: 'Alertă: Dispozitivul țintă nu are destul spațiu raportat.', + proceed: 'Continuă cu Sincronizarea', + notEnoughSpace: 'Nu s-a detectat destul spațiu fizic pe disc!', + liveSearch: 'Live', + randomAlbumsLabel: 'Albume aleatorii', +}; diff --git a/src/locales/ro/entityRating.ts b/src/locales/ro/entityRating.ts new file mode 100644 index 00000000..2222709b --- /dev/null +++ b/src/locales/ro/entityRating.ts @@ -0,0 +1,9 @@ +export const entityRating = { + albumShort: 'Rating album', + artistShort: 'Rating artist', + albumAriaLabel: 'Rating album', + artistAriaLabel: 'Rating artist', + selectedArtistsRatingAriaLabel: 'Rating în stele pentru {{count}} artiști selectați', + selectedAlbumsRatingAriaLabel: 'Rating în stele pentru {{count}} albume selectate ', + saveFailed: 'Nu s-a putut salva rating-ul.', +}; diff --git a/src/locales/ro/favorites.ts b/src/locales/ro/favorites.ts new file mode 100644 index 00000000..1cefc877 --- /dev/null +++ b/src/locales/ro/favorites.ts @@ -0,0 +1,19 @@ +export const favorites = { + title: 'Favorite', + empty: "Nu ai salvat nimic la favorite încă.", + artists: 'Artiști', + albums: 'Albume', + songs: 'Piese', + enqueueAll: 'Adaugă tot la coadă', + playAll: 'Redă tot', + removeSong: 'Șterge de la favorite', + stations: 'Stații Radio', + showingFiltered: 'Se afișează {{filtered}} din {{total}} ({{artist}})', + showingCount: 'Se afișează {{filtered}} din {{total}}', + clearArtistFilter: 'Șterge filtrul de artist', + noFilterResults: 'Niciun rezultat cu filtrele selectate.', + allArtists: 'Toți Artiștii', + topArtists: 'Top Artiști din Favorite', + topArtistsSongCount_one: '{{count}} piesă', + topArtistsSongCount_other: '{{count}} piese', +}; diff --git a/src/locales/ro/folderBrowser.ts b/src/locales/ro/folderBrowser.ts new file mode 100644 index 00000000..c38898df --- /dev/null +++ b/src/locales/ro/folderBrowser.ts @@ -0,0 +1,4 @@ +export const folderBrowser = { + empty: 'Folder gol', + error: 'Nu s-a putut încărca', +}; diff --git a/src/locales/ro/genres.ts b/src/locales/ro/genres.ts new file mode 100644 index 00000000..5184f6d0 --- /dev/null +++ b/src/locales/ro/genres.ts @@ -0,0 +1,12 @@ +export const genres = { + title: 'Genuri', + genreCount: 'Genuri', + albumCount_one: '{{count}} album', + albumCount_other: '{{count}} albume', + loading: 'Se încarcă genuri…', + empty: 'Niciun gen găsit.', + albumsLoading: 'Se încarcă albume…', + albumsEmpty: 'Niciun album găsit pentru acest gen.', + loadMore: 'Încarcă mai mult', + back: 'Înapoi', +}; diff --git a/src/locales/ro/help.ts b/src/locales/ro/help.ts new file mode 100644 index 00000000..31c9d09d --- /dev/null +++ b/src/locales/ro/help.ts @@ -0,0 +1,115 @@ +export const help = { + title: 'Ajutor', + searchPlaceholder: 'Caută Ajutor…', + noResults: 'Niciun topic corespunzător. Încearcă un alt termen de căutare.', + // ── Section 1: Getting Started ───────────────────────────────────────── + s1: 'Pentru început', + q1: 'Ce servere sunt compatibile?', + a1: 'Psysonic este construit în principal pentru Navidrome și este complet compatibil cu serverele Subsonic - Gonic, Airsonic, LMS și alte servere pe bază de API Subsonic de asemenea funcționează. Unele funcționalități avansate (ratinguri, playlisturi inteligente, distribuirea magic strings, managementul utilizatorilor) necesită Navidrome', + q2: 'Cum adaug un server?', + a2: 'Setări → Servere → Adaugă Server. Introdu URL-ul serverului (ex. 192.168.1.100:4533), numele de utilizator, și parola. Psysonic verifică conexiunea înainte de a salva — nimic nu este stocat dacă conexiunea eșuează. Poți adăuga și schimba oricâte servere dorești în bara de sus oricând; doar unul este activ deodată', + q3: 'Tur rapid al UI?', + a3: 'Bara laterală (stâng) pentru navigare, Scena Principală / paginile din mijloc, Bara de Redare jos, și Panoul Cozii în dreapta (comută din bara de dreapta-sus lângă indicatorul Se Redă Acum). Bara de căutare de sus caută în toată librăria; "Se Redă Acum" arată ce ascultă alți utilizatori de pe același server Navidrome acum', + // ── Section 2: Playback & Queue ──────────────────────────────────────── + s2: 'Redare & Coadă', + q4: 'Cum folosesc coada?', + a4: 'Deschide Panoul Cozii din bara din dreapta-sus. Trage rândurile pentru a le reordona, lasă-le afară pentru a înlătura, sau folosește bara cozii pentru a amesteca, salva coada ca playlist, sau sări la o piesă.Trage rândurile din panou și lasă-le altundeva pentru a le transfera.', + q5: 'Gapless vs Crossfade - care este diferența?', + a5: 'Gapless preîncarcă următoarea piesă pentru a elimina liniștea dintre piese (cel mai bine pentru albume live și mixuri DJ). Crossfade estompează piesa curentă în timp ce următoarea este introdusă gradual pe parcursul a 1-10 s (cel mai bun pentru mixuri amestecate). Ele sunt opțiuni mutual exclusive - pornirea uneia o dezactivează pe cealaltă. Configurează ambele în Setări → Audio.', + q6: 'Ce este Coada Infinită?', + a6: 'Când coada se golește și Repetă este oprit, Psysonic adaugă în liniște piese aleatorii din librăria ta așa că redarea nu se oprește niciodată. Piesele auto-adăugate apar mai jos "— Adăugat automat —" divizate în coadă. Comutați-l cu iconița infinit din antetul cozii. Poți de asemenea restricționa piesele auto-adăugate către un gen specific în Setări → Coadă.', + q7: 'Selecție multiplă și interval Shift-clic?', + a7: 'Activează "Selectează" pe Albume / Lansări Noi / Albume Aleatorii / Playlisturi. Apasă pe un element pentru a-l comuta, apoi ține Shift și apasă pe alt element pentru a selecta totul dintre elementele alese în ordinea vizibilă. Shift-clicurile se extind de la cel mai recent element selectat. Bara de deasupra grilei oferă acțiuni în masă (adaugă în coadă, descarcă, șterge, etc.).', + q8: 'Scurtături ale tastaturii și taste globale?', + a8: 'Taste implicite în aplicație: Space = Redă / Pauză, Esc = închide ecranul complet / modale, F1 = cheat-sheet scurtături. În Setări → Input poți reconfigura fiecare acțiune din aplicație (chiar și combinații cum ar fi Ctrl+Shift+P) și seta scurtături globale la nivel de sistem care funcționează chiar și când Psysonic este în fundal sau minimizat. Tastele media (Redă/Pauză, Următoarea, Anterioara) funcționează pe toate platformele.', + // ── Section 3: Audio Tools ───────────────────────────────────────────── + s3: 'Unelte Audio', + q9: 'Moduri Replay Gain?', + a9: 'Setări → Audio → Replay Gain. Modul piesă normalizează fiecare piesă la un nivel țintă. Modul album păstrează curba de zgomot din album. Modul auto alege Piesă sau Album verificând dacă coada este formată dintr-un singur album. Piesele fără etichete Replay Gain ajung la o valoare preamp configurabilă', + q10: 'Ce este Normalizarea Zgomotului Inteligentă (LUFS)?', + a10: 'O alternativă modernă la Replay Gain în Setări → Audio. Psysonic analizează fiecare piesă la LUFS / EBU R128 și stochează rezultatul, ca volumul să fie consistent pe întreaga librărie - incluzând piesele fără etichete Replay Gain. Analiza cold-cache rulează în fundal și folosește în jur de 35-40 % CPU pentru ~1 minut, apoi coboară la 0. Setează nivelul de zgomot țintă (implicit -10 LUFS) o dată', + q11: 'EQ și AutoEQ?', + a11: 'Un EQ parametric pe 10 benzi se află în Setări → Audio → Egalizator cu benzi manuale și presetări. AutoEQ de lângă trage un profil de măsurătoare de corecție pentru modelul tău de căști din baza de date AutoEQ și o aplică pe benzi automat - alege-ți căștile și EQ-ul se aranjează la curba corectă', + q12: 'Cum schimb dispozitivul audio de ieșire?', + a12: 'Setări → Audio → Dispozitiv de Ieșire. Psysonic listează fiecare ieșire posibilă și se schimbă instant când alegi una. Butonul de reîmprospătare rescanează dispozitivele care au fost conectare după pornire. Numele Linux ALSA ca "sysdefault" sunt auto-curățate pentru lizibilitate', + q13: 'Ce este Hot Cache?', + a13: 'Hot Cache preîncarcă piesa curentă plus următoarele în RAM și pe disc pentru ca redarea să înceapă fără încărcare - folositor mai ales pe servere încete / îndepărtate. Piesele sunt eliminate din memorie când limita este atinsă. Configurează limita și întârzierea adăugării (pentru ca săriturile rapide să nu adauge piesele) în Setări → Audio.', + // ── Section 4: Library & Discovery ───────────────────────────────────── + s4: 'Librărie și Descoperire', + q14: 'Cum funcționează ratingurile și Sari-peste-1★?', + a14: 'Psysonic suportă ratinguri 1–5 stele prin OpenSubsonic (necesită Navidrome ≥ 0.53). Evaluează piese în lista de piese, în meniul clic-dreapta, sau în bara redării sub numele artistului; albumele pe pagina de album; artiștii pe pagina de artist. Sari-peste-1★ (Setări → Librărie → Ratinguri) auto-asignează 1 stea după un număr configurabil de sărituri consecutive. În același panou poți seta un filtru de rating minim pentru Mixul Aleatoriu sau alte mixuri generate', + q15: 'Cum răsfoiesc - Foldere, Genuri, Piese?', + a15: 'Browserul de foldere (bara laterală) parcurge prin directorul muzică al serverului tău folosind o schemă Miller-column - apasă pe un folder pentru a intra în el, apasă pe iconița de redare a unei piese pentru a o reda / adăuga în coadă. Genurile folosesc o vizualizare etichetă-nor scalată de numărul de piese; apasă pe un gen pentru a-l deschide. Piese este un hub librărie plată cu o listă virtuală cu coloane sortabile și search live.', + q16: 'Căutare și Căutare Avansată?', + a16: 'Bara de căutare rulează o căutare live rapidă prin artiști, albume și piese pe măsură ce scrii. Deschide Căutarea Avansată (bara laterală) pentru un afișaj mai amănunțit: filtrează după an, gen, rating, format, canale, sample rate, BPM, stare, și combină criterii. Clic-dreapta pe orice rezultat pentru același meniu de context folosit orinde altundeva în aplicație.', + q17: 'Ce sunt Mixurile (Aleatoriu / Gen / Super Gen / Norocos)?', + a17: 'Mixul Aleatoriu construiește un playlist din piese aleatorii din librăria ta; Filtrul Cuvinte Cheie exclude cărți audio, comedie, etc. substringuri după gen / titlu / album. Mixul Super Gen îți grupează librăria în stiluir largi (Rock, Metal, Electronic, Jazz, Clasic…) și construiește un mix focusat din unul. Mixul Norocos folosește istoricul ascultării tale, ratinguri și piese similare AudioMuse-AI pentru a asambla un playlist instant cu un clic.', + q18: 'Pagină de statistici?', + a18: 'Statistici (bara laterală) arată top artiști, top albume, top piese, detalii genuri, ascultarea în timp, și per-librărie când ai mai mult de un folder de muzică configurat. Mai multe vizualizări sunt exportabile ca o imagine card.', + q19: 'Cum descarc un album ca ZIP?', + a19: 'Pagină album → "Descarcă (ZIP)". Serverul compresează albumul prima oară — pentru albume mari sau necompresate (FLAC / WAV) bara de progres apare doar după ce arhivarea este completată și începe transferul. Acest lucru este normal.', + // ── Section 5: Lyrics ────────────────────────────────────────────────── + s5: 'Versuri', + q20: 'De unde vin versurile?', + a20: 'Trei surse, configurabile în Setări → Versuri: serverul tău Navidrome (versuri încorporate/ OpenSubsonic), LRCLIB (versuri contribuite de comunitate sincronizate), și NetEase Cloud Music (catalog larg Chinez și internațional). Poți porni sau dezactiva fiecare sursă și reordona prioritatea lor trăgând de ele.', + q21: 'Cum văd versurile în timpul redării?', + a21: 'Apasă pe iconița microfon din bara redării pentru a deschide tab-ul Versuri în panoul Cozii. Versurile sincronizate se auto-derulează și suportă clic-pentru-căutare; versurile pur text derulează ca un bloc static. Comutează Playerul pe Ecran Complet din arta barei de redare pentru o vedere imersivă de versuri cu fundal mesh-blob.', + // ── Section 6: Sharing & Social ──────────────────────────────────────── + s6: 'Distribuire & Social', + q22: 'Ce sunt Stringurile Magice?', + a22: 'Stringurile Magice sunt jetoane copy-paste care distribuie informații între utilizatorii Psysonic fără niciun server terț. Stringurile Invitație-Server permit un prieten în Navidrome-ul tău cu o lipire; Stringurile Album / Artist / Coada Magică deschid același album / artist / coadă în Psysonic-ul instalat al recipientului. Generează-le din meniul de distribuire, lipește-le în bara de căutare pentru a le folosi.', + q23: 'Ce este Orbit?', + a23: 'Orbit este o ascultare-împreună sincronizată: o gazdă redă o piesă, fiecare oaspete o aude în sincron, și oaspeții pot sugera piese pe care gazda să le accepte în coadă. Începe o sesiune din butonul Orbit de sus, distribuie link-ul de invitație, și alții pot intra oricând din orice instalare Psysonic. Gazda controlează redarea (săriri, căutări, coadă) — oaspeții primesc o vizionare în timp real și o cutie de sugestii. Sesiunile sunt efemere și se termină când sunt închise de gazdă.', + q24: 'Ce este dropdown-ul Se Redă Acum?', + a24: 'Iconița de difuzare din antetul din dreapta-sus arată ce ascultă alți utilizatori din serverul tău Navidrome, reactualizat la fiecare 10 secunde. Intrarea ta dispare în momentul în care pui pauză. Acest lucru este per-server, deci utilizatorii activi de pe alte servere nu sunt afișați.', + // ── Section 7: Personalization ───────────────────────────────────────── + s7: 'Personalizare', + q25: 'Teme și Programatorul de Teme?', + a25: 'Setări → Aparență → Temă alege din 60+ teme din 8 grupe (Psysonic, Mediaplayer, Sisteme de Operare, Jocuri, Filme, Seriale, Social Media, Clasice Open Source — Catppuccin / Nord / Gruvbox / Nightfox / Dracula). Auto-comutatorul de Teme îți permite să alegi teme zi + noapte cu timpuri de începere prin care Psysonic să comute automat.', + q26: 'Pot customiza paginile Bara laterală, Acasă și Artist?', + a26: 'Da — Setări → Personalizare. Customizatorul bării laterale îți permite tragerea elementelor de navigare în ordinea pe care o dorești și ascunde cele pe care nu le folosești. Customizatorul Acasă comută fiecare șină din Scena Principală (Promovat, Recent, Descoperă, Redat Recent, Evaluate…). Customizatorul paginii de Artist reordonează secțiunile (Top Piese, Albume, Singleuri, Compilații, Artiști Similari, etc.) și te lasă să ascunzi cele la care nu te uiți niciodată.', + q27: 'Ce este Mini Playerul?', + a27: 'O fereastră mică plutitoare cu arta coperții, controale de transport și o coadă compactă. Deschide-o din iconița mini-playerului barei de redare sau prin scurtătura ei de tastatură. Fereastra ține minte poziția ei și mărimea între sesiuni. Pe Windows webview-ul miniatură este pre-creat la pornire pentru ca deschiderea să fie instantanee; Linux / macOS aleg asta prin Setări → Aparență → Preîncarcă mini player.', + q28: 'Ce este Bara de Redare Plutitoare?', + a28: 'Un stil de bară de redare opțional (Setări → Aparență) care se detașează de marginea de jos cu un fundal tematic, margine accentuată, artă de album rotunjită și o secțiune de volum centrată. Folositor pe monitoare înalte sau teme compacte.', + q29: 'Previzualizare piesă pe hover?', + a29: 'Hover peste un rând de piesă, clic pe butonul mic de previzualizare de pe copertă, sau declanșează previzualizarea din meniul clic-dreapta — Psysonic redă primele ~15 s prin același motor audio Rust ca normalizarea zgomotului să fie aplicată. Folositor pentru filtrarea unui album pe care nu l-ai mai auzit.', + q30: 'Cronometru de somn?', + a30: 'Apasă iconița lună în bara de redare pentru a deschide cronometrul de somn. Alege o durată (sau "sfârșitul piesei curente") și Psysonic estompează și pune pe pauză la final. Butonul arată un inel circular și un cronometru în buton cât timp cronometrul rulează.', + q31: 'Scalare UI, font, stil bară de căutare?', + a31: 'Setări → Aparență — Scară Interfață (80–125 % fără a afecta mărimea fontului de sistem), Font (10 fonturi UI incluzând IBM Plex Mono, Fira Code, Geist, Golos Text…), Stil Bară de Căutare (Formă de undă analizată / pseudoundă deterministică / Linie & Punct / Bară / Bară Groasă / Segmentat / Strălucire Neon / Pulse Wave / Urmă de Particule / Lichid / Bandă Retro).', + // ── Section 8: Power User ────────────────────────────────────────────── + s8: 'Utilizatori Avansați', + q32: 'Controale player din CLI?', + a32: 'Binarul Psysonic este dublat ca o telecomandă. Exemple: psysonic --player play / pause / next / prev, --player volume 75, --player seek 15, --player shuffle, --player repeat off|all|one, --player rating 1-5. Schimbă servere, dispozitive audio, librării; declanșează Mixul Instant; caută artiști / albume / piese. Rulează psysonic --player --help pentru lista completă. Completările Shell pentru bash și zsh sunt disponibile via completări psysonic.', + q33: 'Playlisturi Inteligente (Navidrome)?', + a33: 'Playlisturile Inteligente sunt playlisturi dinamice pe partea Navidrome definite de reguli (gen = Rock ȘI an > 2020, etc.). Pagina de Playlisturi în Psysonic îți permite crearea, editarea și ștergerea lor cu un editor de reguli vizual - Psysonic comunică cu API-ul nativ Navidrome pentru asta. Ele se comportă ca playlisturi normale în restul aplicației și se actualizează pe măsură ce librăria ta se schimbă.', + q34: 'Backup și restaurarea setărilor?', + a34: 'Setări → Stocare → Backup & Restaurare exportă profilele serverului, temele, scurtăturile de tastatură și alte setări într-un singur fișier JSON. Importă fișierul pe alt calculator sau după o reinstalare pentru a restaura totul deodată. Parolele serverului sunt incluse — ține fișierul privat.', + q35: 'Unde pot vedea toate licențele open-source?', + a35: 'Setări → Sistem → Licențe Open Source. Toată lista de dependințe (cargo crates și npm packages) sunt livrate în build cu textele licențelor adunate. Apasă pe un element pentru textul complet; blocul evidențiat de sus menționează toate librăriile recunoscubile de utilizator (Tauri, React, rodio, symphonia, etc.).', + // ── Section 9: Offline & Sync ────────────────────────────────────────── + s9: 'Offline & Sincronizare', + q36: 'Modul Offline — adăugarea albumelor și playlisturilor în cache?', + a36: 'Deschide orice album sau playlist și apasă pe iconița de download din antet — Psysonic descarcă fiecare piesă local pentru a putea fi redată fără niciun apel la rețea. Pagina Librărie Offline (bara laterală) listează tot ce este în cache, afișează progresul în desfășurare, și îți permite să elimini intrări cu iconița de gunoi (care apare doar după ce descărcarea este completă).', + q37: 'Limită de stocare Offline?', + a37: 'Setări → Librărie → Offline îți permite să setezi o mărime maximă a cache. Când limita este atinsă, butonul de descărcare din pagina albumului arată un banner de avertisment. Eliberează spațiu prin eliminarea albumelor sau playlisturilor din pagina Librărie Offline.', + q38: 'Sincronizare Dispozitiv — copiază muzică la USB / SD?', + a38: 'Sincronizare Dispozitiv (bara laterală) copiază albume, playlisturi sau artiști compleți pe un dispozitiv extern pentru ascultare offline. Alege un folder țintă, sursele din tab-urile browser, apasă "Transfer la Dispozitiv". Psysonic scrie un manifest (psysonic-sync.json) pentru ca să știe ce fișiere sunt deja acolo chiar dacă deschizi Sincronizare Dispozitiv pe un alt sistem de operare cu alt șablon de nume de fișiere. Șabloanele suportă {artist} / {album} / {title} / {track_number} / {disc_number} / {year} jetoane cu / fără separatoare de folder.', + // ── Section 10: Integrations & Troubleshooting ───────────────────────── + s10: 'Integrări & Depanare', + q39: 'Scrobbling Last.fm?', + a39: 'Setări → Integrări → Last.fm. Conectează-ți contul o singură dată și Psysonic efectuează scrobble direct către Last.fm — nicio configurare Navidrome necesară. Un scrobble este trimis după ce ai ascultat 50 % dintr-o piesă. Pingurile se redă acum sunt trimise la început.', + q40: 'Prezență Discord Rich?', + a40: 'Setări → Integrări → Discord arată piesa curentă în ascultare pe profilul tău de Discord. Alege între iconița aplicației, arta de copertă a serverului (prin getAlbumInfo2 — necesită un server accesibil public), sau coperți Apple Music. Customizează stringurile de afișare (detalii, stadiu, tooltip) cu jetoane de șablon.', + q41: 'Date turneu Bandsintown?', + a41: 'Activează în Setări → Integrări → Info Se Redă Acum. Tab-ul Se Redă Acum pe pagina Se Redă Acum va afișa apoi datele turneurilor care urmează pentru artisul redat curent prin API-ul widget Bandsintown. Oprit implicit — nicio cerere nu este făcută până când nu o pornești.', + q42: 'Radio Internet — redarea streamurilor live?', + a42: 'Radio Internet (bara laterală) redă orice stream live stocat pe serverul tău Navidrome (adaugă stații prin UI admin Navidrome). Redarea rulează prin motorul audio HTML5 — cele mai multe setări EQ / Replay Gain / Zgomot nu se aplică la radio, dar metadata ICY (numele piesei curente) este arătat. Suportă MP3, AAC, OGG Vorbis și cele mai multe streamuri HLS; suportul codec depinde de platformă.', + q43: 'Testul conexiunii eșuează — ce fac acum?', + a43: 'Verifică de două ori URL-ul incluzând portul (ex. http://192.168.1.100:4533). Pe o rețea locală http:// de obicei funcționează unde https:// nu o face (niciun certificat). Asigură-te că niciun firewall nu blochează portul și că numele de utilizator și parola sunt corecte. Dacă serverul tău este în spatele unui reverse proxy, încearcă URL-ul direct prima oară pentru a izola cauza.', + q44: 'Arta copertei și imaginile artiștilor se încarcă încet.', + a44: 'Imaginile sunt preluate de pe serverul tău la prima vedere și apoi stocate în cache pentru 30 de zile. Dacă stocarea serverului tău este înceată, prima vizită către o pagină poate dura un moment; vizitele consecutive sunt instantanee. Hot Cache de asemenea ajută pentru piese dar nu pentru cache-ul imaginii.', + q45: 'Probleme pe Linux - ecran negru sau niciun audio?', + a45: 'Aceasta este de obicei o problemă de driver GPU/EGL în WebKitGTK. Pornește cu GDK_BACKEND=x11 WEBKIT_DISABLE_COMPOSITING_MODE=1 WEBKIT_DISABLE_DMABUF_RENDERER=1. Pachetul AUR și installer-ele oficiale .deb/.rpm fac asta automat.', +}; diff --git a/src/locales/ro/hero.ts b/src/locales/ro/hero.ts new file mode 100644 index 00000000..534ccf4a --- /dev/null +++ b/src/locales/ro/hero.ts @@ -0,0 +1,6 @@ +export const hero = { + eyebrow: 'Album Promovat', + playAlbum: 'Redă Album', + enqueue: 'Pune în coadă', + enqueueTooltip: 'Adaugă întregul album în coadă', +}; diff --git a/src/locales/ro/home.ts b/src/locales/ro/home.ts new file mode 100644 index 00000000..25ef742c --- /dev/null +++ b/src/locales/ro/home.ts @@ -0,0 +1,19 @@ +export const home = { + hero: 'Promovat', + starred: 'Evaluate', + recent: 'Adăugate Recent', + mostPlayed: 'Cele mai Redate', + recentlyPlayed: 'Redate Recent', + losslessAlbums: 'Albume Lossless', + discover: 'Descoperă', + discoverSongs: 'Descoperă Piese', + loadMore: 'Încarcă mai Mult', + discoverMore: 'Descoperă mai Mult', + discoverArtists: 'Descoperă Artiști', + discoverArtistsMore: 'Toți Artiștii', + becauseYouLike: 'Deoarece ai ascultat…', + becauseYouLikeFor: 'Deoarece ai ascultat {{artist}}', + similarTo: 'Similar cu {{artist}}', + becauseYouLikeTracks_one: '{{count}} piesă', + becauseYouLikeTracks_other: '{{count}} piese' +}; diff --git a/src/locales/ro/index.ts b/src/locales/ro/index.ts new file mode 100644 index 00000000..a4fd1487 --- /dev/null +++ b/src/locales/ro/index.ts @@ -0,0 +1,91 @@ +import { sidebar } from './sidebar'; +import { home } from './home'; +import { hero } from './hero'; +import { search } from './search'; +import { nowPlaying } from './nowPlaying'; +import { contextMenu } from './contextMenu'; +import { sharePaste } from './sharePaste'; +import { albumDetail } from './albumDetail'; +import { entityRating } from './entityRating'; +import { artistDetail } from './artistDetail'; +import { favorites } from './favorites'; +import { randomLanding } from './randomLanding'; +import { randomAlbums } from './randomAlbums'; +import { genres } from './genres'; +import { randomMix } from './randomMix'; +import { luckyMix } from './luckyMix'; +import { albums } from './albums'; +import { tracks } from './tracks'; +import { artists } from './artists'; +import { composers } from './composers'; +import { composerDetail } from './composerDetail'; +import { login } from './login'; +import { connection } from './connection'; +import { common } from './common'; +import { settings } from './settings'; +import { changelog } from './changelog'; +import { whatsNew } from './whatsNew'; +import { help } from './help'; +import { queue } from './queue'; +import { miniPlayer } from './miniPlayer'; +import { statistics } from './statistics'; +import { player } from './player'; +import { nowPlayingInfo } from './nowPlayingInfo'; +import { songInfo } from './songInfo'; +import { playlists } from './playlists'; +import { smartPlaylists } from './smartPlaylists'; +import { mostPlayed } from './mostPlayed'; +import { losslessAlbums } from './losslessAlbums'; +import { radio } from './radio'; +import { folderBrowser } from './folderBrowser'; +import { deviceSync } from './deviceSync'; +import { orbit } from './orbit'; +import { tray } from './tray'; +import { licenses } from './licenses'; + +export const roTranslation = { + sidebar, + home, + hero, + search, + nowPlaying, + contextMenu, + sharePaste, + albumDetail, + entityRating, + artistDetail, + favorites, + randomLanding, + randomAlbums, + genres, + randomMix, + luckyMix, + albums, + tracks, + artists, + composers, + composerDetail, + login, + connection, + common, + settings, + changelog, + whatsNew, + help, + queue, + miniPlayer, + statistics, + player, + nowPlayingInfo, + songInfo, + playlists, + smartPlaylists, + mostPlayed, + losslessAlbums, + radio, + folderBrowser, + deviceSync, + orbit, + tray, + licenses, +}; diff --git a/src/locales/ro/licenses.ts b/src/locales/ro/licenses.ts new file mode 100644 index 00000000..6e572743 --- /dev/null +++ b/src/locales/ro/licenses.ts @@ -0,0 +1,13 @@ +export const licenses = { + title: 'Licențe Open Source', + intro: 'Psysonic este construit pe software open-source. Lista de mai jos arată fiecare dependință a aplicației, cu versiunea, licența și textul complet al licenței ei.', + highlights: 'Dependințe cheie', + searchPlaceholder: 'Caută după nume, versiune sau licență…', + noResults: 'Nicio potrivire.', + loading: 'Se încarcă licențele…', + loadError: 'Nu s-au putut încărca datele licenței.', + noLicenseText: 'Niciun text de licență inclus pentru această dependință.', + viewSource: 'Vezi sursa', + totalLine: '{{total}} dependințe — {{cargo}} cargo, {{npm}} npm', + generatedAt: 'Ultima dată a generării {{date}}', +}; diff --git a/src/locales/ro/login.ts b/src/locales/ro/login.ts new file mode 100644 index 00000000..bc059699 --- /dev/null +++ b/src/locales/ro/login.ts @@ -0,0 +1,22 @@ +export const login = { + subtitle: 'Playerul tău Navidrome Desktop', + serverName: 'Numele Serverului (opțional)', + serverNamePlaceholder: 'Navidrome-ul meu', + serverUrl: 'URL Server', + serverUrlPlaceholder: '192.168.1.100:4533 sau https://music.example.com', + username: 'Nume utilizator', + usernamePlaceholder: 'admin', + password: 'Parolă', + showPassword: 'Arată parola', + hidePassword: 'Ascunde parola', + connect: 'Conectează-te', + connecting: 'Se conectează…', + connected: 'Conectat!', + error: 'Conexiunea a eșuat – verifică detaliile.', + urlRequired: 'Introdu un server URL.', + savedServers: 'Servere salvate', + addNew: 'Sau adaugă un nou server', + orMagicString: 'Sau un string magic', + magicStringPlaceholder: 'Lipește un string distribuit (psysonic1-…)', + magicStringInvalid: 'String magic invalid sau ilizibil.', +}; diff --git a/src/locales/ro/losslessAlbums.ts b/src/locales/ro/losslessAlbums.ts new file mode 100644 index 00000000..5a106c47 --- /dev/null +++ b/src/locales/ro/losslessAlbums.ts @@ -0,0 +1,5 @@ +export const losslessAlbums = { + empty: 'Niciun album lossless în această librărie încă.', + unsupported: 'Acest server nu expune metadata necesară pentru a găsi albumele lossless.', + slowFetchHint: 'Se încarcă mai încet decât alte pagini de album — Psysonic parcurge prin tot catalogul pieselor după calitate.', +}; diff --git a/src/locales/ro/luckyMix.ts b/src/locales/ro/luckyMix.ts new file mode 100644 index 00000000..9518499c --- /dev/null +++ b/src/locales/ro/luckyMix.ts @@ -0,0 +1,6 @@ +export const luckyMix = { + done: 'Mix Norocos pregătit: {{count}} piese', + failed: 'Nu s-a putut crea Mixul Norocos. Încercați din nou.', + unavailable: 'Mixul Norocos nu este disponibil pentru acest server.', + cancelTooltip: 'Anulează crearea Mixului Norocos', +}; diff --git a/src/locales/ro/miniPlayer.ts b/src/locales/ro/miniPlayer.ts new file mode 100644 index 00000000..5a5edb1c --- /dev/null +++ b/src/locales/ro/miniPlayer.ts @@ -0,0 +1,9 @@ +export const miniPlayer = { + showQueue: 'Arată coada', + hideQueue: 'Ascunde coada', + pinOnTop: 'Fixează sus', + pinOff: 'Anulează fixarea', + openMainWindow: 'Deschide fereastra principală', + close: 'Închide', + emptyQueue: 'Coada este goală', +}; diff --git a/src/locales/ro/mostPlayed.ts b/src/locales/ro/mostPlayed.ts new file mode 100644 index 00000000..042f2d1a --- /dev/null +++ b/src/locales/ro/mostPlayed.ts @@ -0,0 +1,13 @@ +export const mostPlayed = { + title: 'Cele mai Redate', + topArtists: 'Top Artiști', + topAlbums: 'Top Albume', + plays: '{{n}} redări', + sortMost: 'Cele mai multe redări primele', + sortLeast: 'Cele mai puține redări primele', + loadMore: 'Încarcă mai multe albume', + noData: 'Nu există date de redare încă. Începe ascultarea!', + noArtists: 'Toți artiștii sunt filtrați.', + filterCompilations: 'Ascunde artiștii din compilații (Artiști variați, Coloane sonore, etc.)', + filterCompilationsShort: 'Ascunde compilațiile', +}; diff --git a/src/locales/ro/nowPlaying.ts b/src/locales/ro/nowPlaying.ts new file mode 100644 index 00000000..802ca41b --- /dev/null +++ b/src/locales/ro/nowPlaying.ts @@ -0,0 +1,47 @@ +export const nowPlaying = { + tooltip: 'Cine ascultă?', + title: 'Cine ascultă?', + loading: 'Se încarcă…', + nobody: 'Nimeni nu ascultă momentan.', + minutesAgo: 'acum {{n}}m', + nothingPlaying: 'Nu se redă nimic încă. Începe o piesă!', + aboutArtist: 'Despre Artist', + fromAlbum: 'Din acest Album', + viewAlbum: 'Vezi Albumul', + goToArtist: 'Către Artist', + readMore: 'Mai mult', + showLess: 'Mai puțin', + genreInfo: 'Gen', + trackInfo: 'Informații despre Piesă', + topSongs: 'Cele mai redate din acest artist', + topSongsCredit: 'Top piese de la {{name}}', + trackPosition: 'Piesa {{pos}}', + playsCount_one: '{{count}} redare', + playsCount_other: '{{count}} redări', + releasedYearsAgo_one: 'acum {{count}} an', + releasedYearsAgo_other: 'acum {{count}} ani', + discography: 'Discografie', + lastfmStats: 'Statistici Last.fm', + thisTrack: 'Această piesă', + thisArtist: 'Acest artist', + listeners: 'ascultători', + scrobbles: 'scrobble-uri', + yourScrobbles: 'de tine', + listenersN: '{{n}} ascultători', + scrobblesN: '{{n}} scrobble-uri', + playsByYouN: 'redate {{n}}× de tine', + openTrackOnLastfm: 'Piesă în Last.fm', + openArtistOnLastfm: 'Artist în Last.fm', + rgTrackTooltip: 'ReplayGain (piesă)', + rgAlbumTooltip: 'ReplayGain (album)', + rgAutoTooltip: 'ReplayGain (auto)', + showMoreTracks: 'Arată încă {{count}}', + showLessTracks: 'Arată mai puțin', + hideCard: 'Ascunde cardul', + layoutMenu: 'Layout', + visibleCards: 'Carduri vizibile', + hiddenCards: 'Carduri ascunse', + noHiddenCards: 'Niciun card ascuns', + resetLayout: 'Resetează layout-ul', + emptyColumn: 'Lasă cardurile aici', +}; diff --git a/src/locales/ro/nowPlayingInfo.ts b/src/locales/ro/nowPlayingInfo.ts new file mode 100644 index 00000000..4288d9ab --- /dev/null +++ b/src/locales/ro/nowPlayingInfo.ts @@ -0,0 +1,24 @@ +export const nowPlayingInfo = { + tab: 'Informații', + empty: 'Redă ceva pentru a vedea informații', + artist: 'Artist', + songInfo: 'Informații piesă', + onTour: 'În turneu', + noTourEvents: 'Niciun show următor', + tourLoading: 'Se încarcă…', + poweredByBandsintown: 'Date turneu prin Bandsintown', + bioReadMore: 'Citește mai multe', + bioReadLess: 'Arată mai puțin', + showMoreTours_one: 'Arată cu {{count}} mai mult', + showMoreTours_other: 'Arată cu {{count}} mai mult', + showLessTours: 'Arată mai puțin', + enableBandsintownPrompt: 'Vezi date următoare de turnee?', + enableBandsintownPromptDesc: 'Opțional. Încarcă concertele pentru artistul curent prin API-ul public Bandsintown.', + enableBandsintownPrivacy: 'Când este pornit, numele artistului piesei curente redate este trimis către API-ul Bandsintown pentru a prelua datele turneelor. Nimic din datele personale sau ale contului nu părăsesc dispozitivul.', + enableBandsintownAction: 'Pornește', + role: { + artist: 'Artist', + albumArtist: 'Artist album', + composer: 'Compozitor', + }, +}; diff --git a/src/locales/ro/orbit.ts b/src/locales/ro/orbit.ts new file mode 100644 index 00000000..deec6dc6 --- /dev/null +++ b/src/locales/ro/orbit.ts @@ -0,0 +1,200 @@ +export const orbit = { + triggerLabel: 'Orbit', + triggerTooltip: 'Pornește sau intră în o sesiune de ascultare distribuită', + launchCreate: 'Crează o sesiune', + launchJoin: 'Intră într-o sesiune', + launchHelp: 'Cum funcționează asta?', + launchHelpSoon: 'În curând', + joinModalTitle: 'Intră într-o sesiune Orbit', + joinModalSub: 'Lipește link-ul de invitație pe care organizatorul ți l-a trimis.', + joinModalLinkLabel: 'Link-ul de invitație', + joinModalLinkPlaceholder: 'psysonic2-…', + joinModalLinkHelper: 'Funcționează cu orice link valid Orbit. Trebuie să arate spre serverul în care ești conectat acum.', + joinModalPasteTooltip: 'Lipește din clipboard', + joinModalSubmit: 'Intră', + joinModalBusy: 'Se intră…', + joinErrEmpty: 'Lipește un link de invitație.', + joinErrInvalid: 'Asta nu arată ca un link de invitație Orbit.', + closeAria: 'Închide', + heroTitlePrefix: 'Ascultă împreună cu', + heroTitleBrand: 'Orbit', + heroSub: 'Pornește o sesiune — alți utilizatori de pe {{server}} vor asculta deodată și pot sugera piese.', + fallbackServer: 'acest server', + tipLan: "Ești conectat acum printr-o adresă de rețea locală. Invitații din afara rețelei tale nu pot intra — schimbă pe o adresă publică de server în setări înainte de a începe.", + tipRemote: 'Pentru ca oaspeții din afara rețelei să poată intra, serverul tău trebuie să fie accesibil public. Dacă serverul tău este doar intern, schimbă înainte de a începe.', + labelName: 'Numele sesiunii', + namePlaceholder: 'Velvet Orbit', + reshuffleTooltip: 'Nouă sugestie', + reshuffleAria: 'Sugerează un nou nume', + helperName: 'Cum apare sesiunea către oaspeții tăi — păstrează-l sau folosește-l pe al tău.', + labelMax: 'Max oaspeți', + helperMax: "Tu nu ești numărat — se ține cont doar de oaspeții care intră.", + labelLink: 'Link-ul de invitație', + tooltipCopied: 'Copiat', + tooltipCopy: 'Copiază', + ariaCopyLink: 'Copiază link-ul de invitație', + helperLink: 'Trimite acest link către invitații tăi. Ei îl pot lipi oriunde în Psysonic cu Ctrl+V.', + labelClearQueue: 'Golește-mi coada mai întâi', + helperClearQueue: 'Începe sesiunea cu o coadă proaspătă goală. Oprit: piesele pe care le ai deja în coadă rămân și sunt distribuite cu oaspeții.', + btnCancel: 'Anulează', + btnStarting: 'Se începe…', + btnStart: 'Începe Orbit', + btnCopyAndStart: 'Copiază acest link & începe', + errNameRequired: 'Dă un nume sesiunii tale.', + errStartFailed: "Nu s-a putut începe.", + hostLabel: 'Gazdă: {{name}}', + participantsTooltip: 'Participanți', + settingsTooltip: 'Setările sesiunii', + shareTooltip: 'Distribuie link-ul de invitație', + shuffleLabel: 'Coada se re-amestecă în', + catchUpLabel: 'ajunge din urmă', + catchUpTooltip: "Sari către poziția curentă a gazdei", + hostAway: 'Gazdă offline', + hostOnline: 'Gazdă online', + endTooltip: 'Termină sesiunea', + leaveTooltip: 'Părăsește sesiunea', + helpTooltip: 'Cum funcționează Orbit', + diag: { + openTooltip: 'Diagnostice — log-uri evenimente copiabile', + title: 'Diagnostice Orbit', + role: 'Rol', + hostTrack: 'Id piesă gazdă', + hostPos: 'Poziție gazdă', + guestTrack: 'Id-ul piesei mele', + guestPos: 'Id-ul poziției mele', + drift: 'Drift', + stateAge: 'Status vârstă', + eventLog: 'Log-uri evenimente ({{count}})', + copyLabel: 'Copiază', + copyTooltip: 'Copiază log-urile în clipboard', + clearLabel: 'Golește', + clearTooltip: 'Șterge buffer-ul', + empty: 'Niciun eveniment deocamdată — evenimentele apar ca sincronizare Orbit.', + hint: 'Deschide asta înainte de a reproduce o problemă, apoi apasă Copiază și lipește în raportul problemei.', + copied: 'S-au copiat {{count}} linii de eveniment', + copyFailed: 'Nu s-a putut copia în clipboard', + cleared: 'Buffer curățat', + }, + helpTitle: 'Cum funcționează Orbit', + helpIntro: 'Orbit transformă Psysonic într-o cameră distribuită de ascultare. O gazdă alege muzica; oaspeții ascultă în sincron și pot sugera piese.', + helpHostOnly: '(gazdă)', + helpSec1Title: 'Ce este Orbit?', + helpSec1Body: "Un mod \"ascultă împreună\" — gazda controlează redarea, oaspeții se alătură. Totul rulează prin playlisturile de pe serverul tău Navidrome; nicio infrastructură externă.", + helpSec2Title: 'Gazdă și oaspeți', + helpSec2Body: 'Gazda controlează redarea (redă / pauză / sari / caută) și decide când sesiunea se termină. Oaspeții urmează redarea gazdei, pot sugera piese, și pot ieși și re-intra oricând. Doar gazda poate da afară sau bana permanent un participant.', + helpSec2WarnHead: 'Important: conturi separate.', + helpSec2WarnBody: "Fiecare participant are nevoie de contul său Navidrome. Dacă gazda și oaspetele se conectează cu același utilizator propunerile lor se ciocnesc și gazda nu va vedea propunerile oaspetului.", + helpSec3Title: 'Pornirea și invitarea', + helpSec3Body: 'Apasă pe butonul "Orbit" → Crează o sesiune → modalul de pornire arată un link de invitație gata de copiat și te lasă opțional să golești coada curentă. Împarte acel link oricum dorești. Cât timp o sesiune este în derulare, butonul de distribuire din bara sesiunii de sus copiază link-ul din nou oricând.', + helpSec4Title: 'Intrare', + helpSec4Body: 'Lipește link-ul de invitație oriunde în Psysonic cu Ctrl+V / Cmd+V — prompt-ul de alăturare se deschide automat. Alternativă: "Orbit" → Intră într-o sesiune → lipește în câmpul prezentat. Dacă link-ul arată către un server pe care ai un cont, Psysonic îl schimbă pentru tine. Când ai mai mult de un cont pe acel server, un alegător mic te va întreba pe care să îl folosești.', + helpSec5Title: 'Sugerarea pieselor', + helpSec5Body: 'În orice listă de piese: dublu-clic pe un rând, sau clic-dreapta → "Adaugă la sesiunea Orbit". Un clic singular arată o sugestie în loc de a pune tot albumul în coada distribuită — asta este intenționat. Acțiunile explicite în masă cum ar fi "Redă Tot" sau "Redă Album" întreabă pentru confirmare mai întâi și după adaugă (niciodată schimbă).', + helpSec6Title: 'Coadă distribuită', + helpSec6Body: "Coada afișează piesele următoare ale gazdei — vizibile către toți. Adăugările în masă care sosesc sunt mereu adăugate, deci sugestiile oaspeților nu sunt pierdute. Auto-amestecarea reordonează coada periodic (configrabil: 1 / 5 / 10 / 15 / 30 min). Dacă redarea se Îndepărtează de gazdă, butonul de \"Ajunge din urmă\" în bara sesiunii sare înapoi către poziția live a gazdei.", + helpSec7Title: 'Aprobări', + helpSec7Body: 'Implicit, sugestiile oaspeților au nevoie de aprobare manuală — apar în banda "Aprobări" în vârful panoului cozii cu butoane de acceptă / respinge. Auto-aprobarea poate fi pornită în setările sesiunii pentru ca toate sugestiile să intre din prima.', + helpSec8Title: 'Participanți și setări', + helpSec8Body: 'Deschide iconița de setări din bara sesiunii pentru cadența amestecării, auto-aprobare, și scurtătura "Amestecă acum". Apasă pe numărul de participanți pentru a vedea cine este conectat — dă afară (se poate reconecta cu link-ul) sau ban (blocat din sesiune). Oaspeții pot vedea de asemenea lista de participanți, doar nu o pot modifica.', + helpSec9Title: 'Sfârșirea sesiunii', + helpSec9Body: "Gazdă X → dialog confirmare → sesiunea se închide pentru toată lumea și playlisturile serverului sunt curățate automat. Oaspete X → oaspetele pleacă, sesiunea continuă să ruleze. Dacă gazda nu răspunde pentru 5 minute oaspetele iese automat cu o notificare; reconectările scurte din acel interval sunt invizibile.", + participantsInviteLabel: 'Link-ul de invitație', + participantsCountLabel: '{{count}} în sesiune', + participantsHost: 'gazdă', + participantsEmpty: 'Niciun oaspete deocamdată', + participantsKickTooltip: 'Înlătură din sesiune', + participantsKickAria: 'Înlătură {{user}}', + participantsRemoveTooltip: 'Înlătură din sesiune', + participantsRemoveAria: 'Înlătură {{user}} din această sesiune', + participantsBanTooltip: 'Banează permanent', + participantsBanAria: 'Banează permanent {{user}}', + participantsMuteTooltip: 'Dezactivează sugestiile', + participantsUnmuteTooltip: 'Permite sugestiile', + participantsMuteAria: 'Dezactivează sugestii de la {{user}}', + participantsUnmuteAria: 'Permite sugestii de la {{user}}', + confirmRemoveTitle: 'Înlătură din sesiune?', + confirmRemoveBody: '{{user}} va fi dat afară din sesiune, dar poate reintra prin link-ul tău de invitație.', + confirmRemoveConfirm: 'Înlătură', + confirmBanTitle: 'Banezi permanent?', + confirmBanBody: '{{user}} va fi înlăturat și blocat din reintrarea în această sesiune. Acest lucru nu poate fi anulat pe durata sesiunii.', + confirmBanConfirm: 'Ban', + confirmCancel: 'Anulează', + confirmJoinTitle: 'Te alături sesiunii Orbit?', + confirmJoinBody: '{{host}} te-a invitat în "{{name}}". Intri în sesiune?', + confirmJoinConfirm: 'Intră', + confirmLeaveTitle: 'Părăsești sesiunea?', + confirmLeaveBody: 'Părăsești "{{name}}"? Poți reintra prin link-ul de invitație al {{host}} oricând.', + confirmLeaveConfirm: 'Pleacă', + confirmEndTitle: 'Termini sesiunea pentru toți?', + confirmEndBody: '"{{name}}" va închide pentru toți participanții. Playlisturile sesiunii sunt curățate automat.', + confirmEndConfirm: 'Termină sesiunea', + invalidLinkTitle: 'Link-ul de invitație nu mai este valid', + invalidLinkBody: 'Această sesiune Orbit nu mai există sau s-a terminat deja. Roagă gazda pentru un link de invitație proaspăt.', + settingsTitle: 'Setările sesiunii', + settingAutoApprove: 'Auto-aprobă sugestiile', + settingAutoApproveHint: "Sugestiile oaspeților intră în coadă instant. Oprit: ele rămân în lista sesiunii pentru ca tu să le revizuiești mai târziu.", + settingAutoShuffle: 'Reamestecare automată', + settingAutoShuffleHint: "Amestecare periodică Fisher–Yates a cozii care urmează. Oprit: ordinea se schimbă doar când o rearanjezi.", + settingShuffleInterval: 'Reamestecă la fiecare', + settingShuffleIntervalHint: 'Cât de des se reamestecă coada în timp ce sesiunea rulează.', + suggestBlockedMuted: 'Gazda te-a oprit din a trimite sugestii pentru această sesiune — sugestiile sunt oprite.', + settingShuffleIntervalValue_one: '{{count}} min', + settingShuffleIntervalValue_other: '{{count}} min', + settingShuffleNow: 'Amestecă acum', + toastSuggested: '{{user}} a sugerat "{{title}}"', + toastSuggestedMany: '{{count}} noi sugestii în coadă', + toastShuffled: 'Coadă amestecată', + toastJoined: 'A intrat în sesiune', + toastLoginFirst: 'Log in before joining a session', + toastSwitchServer: 'Schimbă la {{url}} mai întâi, apoi lipește din nou', + toastNoAccountForServer: "Nu ai acces la {{url}}. Cere o invitație gazdei.", + toastSwitchFailed: "Nu s-a putut schimba la {{url}}", + accountPickerTitle: 'Ce cont?', + accountPickerSub: 'Ai mai mult de un cont pentru {{url}}. Alege unul cu care să intri în sesiune.', + toastJoinFail: "Nu s-a putut alătura sesiunii", + joinErrNotFound: 'Sesiunea nu a fost găsită', + joinErrEnded: 'Sesiunea s-a terminat', + joinErrFull: 'Sesiunea este plină', + joinErrKicked: "Nu poți reintra în această sesiune", + joinErrNoUser: 'Niciun server activ', + joinErrServerError: "Nu s-a putut intra", + ctxAddToSession: 'Adaugă la sesiunea Orbit', + ctxSuggestedToast: 'Sugerat la sesiune', + ctxSuggestFailed: "Nu s-a putut sugera — neintrat", + ctxAddToSessionHost: 'Adaugă la sesiunea Orbit', + ctxAddedHostToast: 'Adăugat la sesiune', + ctxAddHostFailed: "Nu s-a putut adăuga la sesiune", + bulkConfirmTitle: 'Adaugi tot în coada Orbit?', + bulkConfirmBody: "Asta va lăsa {{count}} piese în coada distribuită deodată. Asta este mult pentru toți oaspeții să remarce. Continui?", + bulkConfirmYes: 'Adaugă tot', + bulkConfirmNo: 'Anulează', + guestLive: 'Live', + guestPlaying: 'Se redă acum', + guestPaused: 'Pauză', + guestLoading: 'Se încarcă…', + guestSuggestions: 'Sugestii', + guestUpNext: 'Urmează', + guestUpNextEmpty: 'Nimic în coadă. Deschide meniul de context a unei piese și alege "Adaugă la sesiunea Orbit" pentru a sugera una.', + guestPendingTitle: 'Se așteaptă gazda', + guestPendingHint: 'Sugerat — va apărea în coadă când gazda o va alege.', + approvalTitle: 'Aprobări în așteptare', + approvalFrom: 'Sugerat de{{user}}', + approvalAccept: 'Accept', + approvalDecline: 'Respinge', + guestUpNextMore: '+ {{count}} mai multe în coada gazdei', + guestSubmitter: 'de {{user}}', + queueAddedByHost: 'Adăugat de gazdă', + queueAddedByYou: 'Adăugat de tine', + queueAddedByUser: 'Adăugat de {{user}}', + guestEmpty: 'Nicio sugestie încă. Deschide meniul de context a unei piese și alege "Adaugă la sesiunea Orbit".', + guestFooter: "Gazda controlează redarea — nu poți schimba lista.", + exitKickedTitle: 'Ai fost banat din sesiune', + exitRemovedTitle: 'Ai fost înlăturat din sesiune', + exitEndedTitle: 'Gazda a încheiat sesiunea', + exitHostTimeoutTitle: 'Gazda n-a mai răspuns', + exitHostTimeoutBody: "{{host}} nu a mai trimis un update de ceva timp, așa că \"{{name}}\" a fost închis pe partea ta. Poți reintra oricând cu link-ul de invitație.", + exitKickedBody: '{{host}} te-a banat din "{{name}}". Nu poți reintra', + exitRemovedBody: '{{host}} te-a înlăturat din "{{name}}". Poți reintra oricând cu link-ul de invitație.', + exitEndedBody: '"{{name}}" s-a terminat. Sper că te-ai distrat.', + exitOk: 'OK', +}; diff --git a/src/locales/ro/player.ts b/src/locales/ro/player.ts new file mode 100644 index 00000000..49ad7f77 --- /dev/null +++ b/src/locales/ro/player.ts @@ -0,0 +1,56 @@ +export const player = { + regionLabel: 'Player Muzică', + openFullscreen: 'Deschide Playerul pe ecran complet', + fullscreen: 'Player pe ecran complet', + closeFullscreen: 'Închide ecranul complet', + closeTooltip: 'Închide (Esc)', + noTitle: 'Fără Titlu', + stop: 'Stop', + prev: 'Piesa anterioară', + play: 'Redă', + pause: 'Pauză', + previewActive: 'Previzualizează redarea', + previewLabel: 'Previzualizare', + delayModalTitle: 'Temporizator', + delayPauseSection: 'Pune pauză după', + delayStartSection: 'Începe după', + delayPreviewPause: 'Se pune pauză la', + delayPreviewStart: 'Începe la', + delaySchedulePause: 'Programează pauza', + delayScheduleStart: 'Programează pornirea', + delayCancelPause: 'Anulează temporizatorul de pauză', + delayCancelStart: 'Anulează temporizatorul de start', + delayInactivePause: 'Disponibil până când ceva este redat.', + delayInactiveStart: 'Disponibil când o piesă sau un radio încărcat este în pauză.', + delayCustomMinutes: 'Întârziere personalizată (minute)', + delayCustomPlaceholder: 'ex. 2.5', + closeDelayModal: 'Închide', + delayIn: 'în', + delayFmtSec: '{{n}}s', + delayFmtMin: '{{n}} min', + delayFmtHr: '{{n}} h', + delayCancel: 'Anulează', + delayApply: 'Aplică', + next: 'Următoarea Piesă', + repeat: 'Repetă', + repeatOff: 'Oprit', + repeatAll: 'Tot', + repeatOne: 'Unul', + progress: 'Progresul Piesei', + volume: 'Volum', + toggleQueue: 'Comutați Coada', + collapseQueueResize: 'Strânge coada, redimensionează', + moreOptions: 'Mai multe opțiuni', + equalizer: 'Egalizator', + miniPlayer: 'Player Mini', + lyrics: 'Versuri', + fsLyricsToggle: 'Versuri în ecran complet', + lyricsLoading: 'Se încarcă versurile…', + lyricsNotFound: 'Niciun vers găsit pentru această piesă', + lyricsSourceServer: 'Sursa: Server', + lyricsSourceLrclib: 'Sursa: LRCLIB', + lyricsSourceNetease: 'Sursa: Netease', + lyricsSourceLyricsplus: 'Sursa: YouLyPlus', + showDuration: 'Arată durata', + showRemainingTime: 'Arată timpul rămas', +}; diff --git a/src/locales/ro/playlists.ts b/src/locales/ro/playlists.ts new file mode 100644 index 00000000..d1734d63 --- /dev/null +++ b/src/locales/ro/playlists.ts @@ -0,0 +1,101 @@ +export const playlists = { + title: 'Playlisturi', + newPlaylist: 'Playlist nou', + unnamed: 'Playlist fără nume', + createName: 'Nume Playlist…', + create: 'Crează', + cancel: 'Anulează', + empty: 'Niciun playlist deocamdată.', + emptyPlaylist: 'Acest playlist este gol.', + addFirstSong: 'Adaugă prima ta piesă', + notFound: 'Playlistul nu a fost găsit.', + songs: '{{n}} piese', + playAll: 'Redă tot', + shuffle: 'Amestecă', + addToQueue: 'Adaugă la Coadă', + back: 'Înapoi la Playlisturi', + deletePlaylist: 'Șterge', + confirmDelete: 'Apasă din nou pentru a confirma', + removeSong: 'Șterge din playlist', + addSongs: 'Adaugă Piese', + searchPlaceholder: 'Caută în librărie…', + noResults: 'Niciun rezultat.', + suggestions: 'Piese sugerate', + noSuggestions: 'Nicio sugestie disponibilă.', + titleBadge: 'Playlist', + refreshSuggestions: 'Sugestii noi', + addSong: 'Adaugă la playlist', + preview: 'Previzualizare (30s)', + previewStop: 'Oprește previzualiarea', + playNextSuggestion: 'Redă următorul', + suggestionsHint: 'Dublu-clic pe un rând pentru a-l adăuga în playlist', + addSelected: 'Adaugă selectate', + cacheOffline: 'Adaugă playlistul în memoria cache offline', + offlineCached: 'Playlist adăugat în cache', + removeOffline: 'Șterge din cache-ul offline', + offlineDownloading: 'Se descarcă… ({{done}}/{{total}} albume)', + publicLabel: 'Public', + privateLabel: 'Privat', + editMeta: 'Editează playlist', + editNamePlaceholder: 'Nume playlist…', + editCommentPlaceholder: 'Adaugă o descriere…', + editPublic: 'Playlist public', + editSave: 'Salvează', + editCancel: 'Anulează', + changeCover: 'Schimbă imaginea de copertă', + changeCoverLabel: 'Schimbă poza', + removeCover: 'Șterge poza', + coverUpdated: 'Copertă actualizată', + metaSaved: 'Playlist actualizat', + downloadZip: 'Descarcă (ZIP)', + // Toast notifications for multi-select + addSuccess: '{{count}} piese adăugate la {{playlist}}', + addPartial: '{{added}} adăugate, {{skipped}} sărite (duplicate)', + addAllSkipped: 'Toate sărite ({{count}} duplicate)', + addedAsDuplicates: '{{count}} piese adăugate la {{playlist}} (ca duplicate)', + duplicateConfirmTitle: 'Deja în playlist', + duplicateConfirmMessage: 'Toate {{count}} piese sunt deja în "{{playlist}}". Adaugă-le din nou ca duplicate?', + duplicateConfirmAction: 'Adaugă oricum', + addError: 'Eroare la adăugarea pieselor', + createAndAddSuccess: 'Playlist "{{playlist}}" creat cu {{count}} piese', + createError: 'Eroare la crearea playlistului', + deleteSuccess: '{{count}} playlisturi șterse', + deleteFailed: 'Eroare la ștergerea {{name}}', + deleteSelected: 'Șterge selectate', + deleteSelectedPartial: 'Doar {{n}} din {{total}} playlisturi selectate pot fi șterse (celelalte aparțin altcuiva).', + mergeSuccess: '{{count}} piese comasate în {{playlist}}', + mergeNoNewSongs: 'Nicio piesă nouă de adăugat', + mergeError: 'Eroare la comasarea playlisturilor', + mergeInto: 'Comasează în', + selectionCount: '{{count}} selectate', + select: 'Selectează', + startSelect: 'Pornește selecția', + cancelSelect: 'Anulează', + loadingAlbums: 'Se rezolvă {{count}} albume…', + loadingArtists: 'Se rezolvă {{count}} artiști…', + myPlaylists: 'Playlisturile mele', + noOtherPlaylists: 'Niciun alt playlist disponibil', + addToPlaylistSuccess: '{{count}} piese adăugate în {{playlist}}', + addToPlaylistNoNew: 'Nicio piesă nouă adăugată în {{playlist}}', + addToPlaylistError: 'Eroare la adăugarea în playlist', + removeSuccess: 'Piesă ștearsă din playlist', + removeError: 'Eroare la ștergerea piesei din playlist', + importCSV: 'Import CSV', + importCSVTooltip: 'Import din CSV Spotify', + csvImportReport: 'Raport Import CSV', + csvImportTotal: 'Total', + csvImportAdded: 'Adăugate', + csvImportDuplicates: 'Duplicate', + csvImportNotFound: 'Negăsite', + csvImportNetworkErrors: 'Erori de rețea', + csvImportDuplicatesTitle: 'Piese duplicate (Deja în Playlist):', + csvImportNotFoundTitle: 'Piese negăsite:', + csvImportNetworkErrorsTitle: 'Erori de rețea (se poate reîncerca importul):', + csvImportDownloadReport: 'Descarcă Raport', + csvImportClose: 'Închide', + csvImportNoValidTracks: 'Nicio piesă validă găsită în fișierul CSV', + csvImportFailed: 'Nu s-a reușit importul fișierului CSV', + csvImportToast: '{{added}} adăugate, {{notFound}} negăsite, {{duplicates}} duplicate', + csvImportDownloadSuccess: 'Pagina de raport descărcată cu succes', + csvImportDownloadError: 'Nu s-a putut descărca raportul', +}; diff --git a/src/locales/ro/queue.ts b/src/locales/ro/queue.ts new file mode 100644 index 00000000..88ef57fb --- /dev/null +++ b/src/locales/ro/queue.ts @@ -0,0 +1,45 @@ +export const queue = { + title: 'Coadă', + savePlaylist: 'Salvează Playlist', + updatePlaylist: 'Actualizează Playlist', + filterPlaylists: 'Filtrează playlisturi…', + playlistName: 'Nume Playlist', + cancel: 'Anulează', + save: 'Salvează', + loadPlaylist: 'Încarcă Playlist', + loading: 'Se încarcă…', + noPlaylists: 'Niciun playlist găsit.', + load: 'Înlocuiește coadă & redare', + appendToQueue: 'Adaugă la coadă', + delete: 'Șterge', + deleteConfirm: 'Șterge playlist "{{name}}"?', + clear: 'Golește', + shuffle: 'Amestecă coada', + gapless: 'Gapless', + crossfade: 'Crossfade', + infiniteQueue: 'Coadă infinită', + autoAdded: '— Adăugat automat—', + radioAdded: '— Radio —', + hide: 'Ascunde', + hideNowPlaying: 'Ascunde informația now playing', + showNowPlaying: 'Arată informația now playing', + close: 'Închide', + nextTracks: 'Următoarele Piese', + shareQueue: 'Copiază link-ul distribuirii cozii', + shareQueueEmpty: 'Coada este goală — nimic de distribuit.', + emptyQueue: 'Coada este goală.', + trackSingular: 'piesă', + trackPlural: 'piese', + showRemaining: 'Arată timpul rămas', + showTotal: 'Arată timpul total', + showEta: 'Arată timpul estimativ până la final', + replayGain: 'ReplayGain', + rgTrack: 'P {{db}} dB', + rgAlbum: 'A {{db}} dB', + rgPeak: 'Vârf {{pk}}', + sourceOffline: 'Se redă din librăria offline', + sourceHot: 'Se redă din cache', + sourceStream: 'Se redă din stream-ul de rețea', + clearCachedLoudnessWaveform: 'Golește zgomotul si formele de undă din cache, apoi reanalizează piesa', + recalculatingLoudnessWaveform: 'Se recalculează zgomotul și formele de undă pentru această piesă…', +}; diff --git a/src/locales/ro/radio.ts b/src/locales/ro/radio.ts new file mode 100644 index 00000000..45be79c8 --- /dev/null +++ b/src/locales/ro/radio.ts @@ -0,0 +1,35 @@ +export const radio = { + title: 'Radio Internet', + empty: 'Nicio stație radio configurată.', + addStation: 'Adaugă Stație', + editStation: 'Editează', + deleteStation: 'Șterge stație', + confirmDelete: 'Apasă din nou pentru a confirma', + stationName: 'Numele stației…', + streamUrl: 'URL-ul streamului…', + homepageUrl: 'URL-ul paginii principale (opțional)', + save: 'Salvează', + cancel: 'Anulează', + live: 'LIVE', + liveStream: 'Radio Internet', + openHomepage: 'Deschide pagina principală', + changeCoverLabel: 'Schimbă coperta', + removeCover: 'Șterge coperta', + browseDirectory: 'Caută Director', + directoryPlaceholder: 'Caută stații…', + noResults: 'Nicio stație găsită.', + stationAdded: 'Stație adăugată', + filterAll: 'Toate', + filterFavorites: 'Favorite', + sortManual: 'Manual', + sortAZ: 'A → Z', + sortZA: 'Z → A', + sortNewest: 'Cele mai noi', + favorite: 'Adaugă la favorite', + unfavorite: 'Șterge din favorites', + noFavorites: 'Nicio stație favorită.', + listenerCount_one: '{{count}} ascultător', + listenerCount_other: '{{count}} ascultători', + recentlyPlayed: 'Redate recent', + upNext: 'Urmează', +}; diff --git a/src/locales/ro/randomAlbums.ts b/src/locales/ro/randomAlbums.ts new file mode 100644 index 00000000..3eb36b32 --- /dev/null +++ b/src/locales/ro/randomAlbums.ts @@ -0,0 +1,4 @@ +export const randomAlbums = { + title: 'Albume aleatorii', + refresh: 'Reîmprospătează', +}; diff --git a/src/locales/ro/randomLanding.ts b/src/locales/ro/randomLanding.ts new file mode 100644 index 00000000..f4cb8064 --- /dev/null +++ b/src/locales/ro/randomLanding.ts @@ -0,0 +1,9 @@ +export const randomLanding = { + title: 'Crează un Mix', + mixByTracks: 'Mix după Piese', + mixByTracksDesc: 'Selecție aleatorie de piese din întreaga librărie', + mixByAlbums: 'Mix după Albume', + mixByAlbumsDesc: 'Selecție aleatorie de albume pentru următoarea ta descoperire', + mixByLucky: 'Mix Norocos', + mixByLuckyDesc: 'Mix instant inteligent din artiștii, albumele și ratingurile tale de top', +}; diff --git a/src/locales/ro/randomMix.ts b/src/locales/ro/randomMix.ts new file mode 100644 index 00000000..e962d04c --- /dev/null +++ b/src/locales/ro/randomMix.ts @@ -0,0 +1,39 @@ +export const randomMix = { + title: 'Mix Aleatoriu', + remix: 'Remix', + remixTooltip: 'Încarcă noi piese aleatorii', + remixGenre: 'Remix {{genre}}', + remixTooltipGenre: 'Încarcă piese {{genre}} noi', + playAll: 'Redă tot', + trackTitle: 'Titlu', + trackArtist: 'Artist', + trackAlbum: 'Album', + trackFavorite: 'Favorit', + trackDuration: 'Durată', + favoriteAdd: 'Adaugă la Favorites', + favoriteRemove: 'Șterge din Favorite', + play: 'Redă', + trackGenre: 'Gen', + mixSettingsHeader: 'Setări Mix', + exclusionsHeader: 'Excluderi', + filterPanelInexactSizeNote: 'Mărimea mixului este o țintă — cererile mari pot returna mai puține piese dacă colecția serverului este mai mică.', + mixSize: 'Mărimea playlistului', + excludeAudiobooks: 'Exclude audiobookuri & redări radio', + excludeAudiobooksDesc: 'Potrivește cuvinte cheie cu gen, titlu, album și artist - ex. Hörbuch, Audiobook, Spoken Word, …', + genreBlocked: 'Cuvânt cheie blocat', + genreAddedToBlacklist: 'Adăugat la lista de filtre', + genreAlreadyBlocked: 'Deja blocat', + artistBlocked: 'Artist blocat', + artistAddedToBlacklist: 'Artist adăugat la lista de filtre', + artistClickHint: 'Clic pentru a bloca acest artist', + blacklistToggle: 'Filtru de cuvinte cheie', + genreMixTitle: 'Mix de Genuri', + genreMixDesc: 'Top 20 genuri după numărul de piese - clic pentru a încărca un mix aleatoriu', + genreMixAll: 'Toate piesele', + genreMixLoadMore: 'Încarcă încă 10', + genreMixNoGenres: 'Niciun gen găsit pe server.', + shuffleGenres: 'Arată genuri diferite', + filterPanelTitle: 'Filtre', + filterPanelDesc: 'Apasă pe un tag de gen sau nume de artist în lista de piese de mai jos pentru a o bloca din mixuri viitoare.', + genreClickHint: 'Apasă pe un tag de gen pentru a-l adăuga\nca un filtru de cuvânt cheie.\nFiltrul corespunde cu gen, titlu, album & artist.', +}; diff --git a/src/locales/ro/search.ts b/src/locales/ro/search.ts new file mode 100644 index 00000000..25c6e6d1 --- /dev/null +++ b/src/locales/ro/search.ts @@ -0,0 +1,29 @@ +export const search = { + placeholder: 'Caută un artist, album sau piesă…', + noResults: 'Niciun rezultat pentru "{{query}}"', + artists: 'Artiști', + albums: 'Albume', + songs: 'Piese', + clearLabel: 'Șterge căutarea', + addedToQueueToast: 'Adăugat "{{title}}" în coadă', + title: 'Caută', + resultsFor: 'Rezultate pentru "{{query}}"', + album: 'Album', + advanced: 'Căutare avansată', + advancedSearchTerm: 'Termen de căutare', + advancedSearchPlaceholder: 'Titlu, album, artist…', + advancedGenre: 'Gen', + advancedAllGenres: 'Toate genurile', + advancedYear: 'An', + advancedYearFrom: 'de la', + advancedYearTo: 'până la', + advancedAll: 'Toate', + advancedSearch: 'Căutare', + advancedEmpty: 'Introdu un termen de căutare sau alege un filtru pentru a începe', + advancedNoResults: 'Niciun rezultat găsit.', + advancedGenreNote: 'Piesele sunt alese aleatoriu din acest gen', + recentSearches: 'Căutări Recente', + browse: 'Răsfoiește', + emptyHint: 'Ce vrei să auzi?', + genres: 'Genuri', +}; diff --git a/src/locales/ro/settings.ts b/src/locales/ro/settings.ts new file mode 100644 index 00000000..28b9362a --- /dev/null +++ b/src/locales/ro/settings.ts @@ -0,0 +1,445 @@ +export const settings = { + title: 'Setări', + language: 'Limbă', + languageEn: 'Engleză', + languageDe: 'Germană', + languageFr: 'Franceză', + languageNl: 'Olandeză', + languageZh: 'Chineză', + languageNb: 'Norvegiană', + languageRu: 'Rusă', + languageEs: 'Spaniolă', + languageRo: 'Română', + font: 'Font', + fontHintOpenDyslexic: 'Prietenos cu dislexia · Chineza nu este suportată', + theme: 'Temă', + appearance: 'Aparență', + servers: 'Servere', + serverName: 'Nume Server', + serverUrl: 'URL Server', + serverUrlPlaceholder: '192.168.1.100:4533 sau https://music.example.com', + serverUsername: 'Nume utilizator', + serverPassword: 'Parolă', + addServer: 'Adaugă Server', + addServerTitle: 'Adaugă Server nou', + useServer: 'Folosește', + deleteServer: 'Șterge', + noServers: 'Niciun server salvat.', + serverActive: 'Activ', + confirmDeleteServer: 'Șterge server "{{name}}"?', + serverConnecting: 'Se conectează…', + serverConnected: 'Conectat!', + serverFailed: 'Conexiune eșuată.', + testBtn: 'Testează Conexiunea', + testingBtn: 'Se testează…', + serverCompatible: 'Făcut pentru Navidrome. Alte servere compatibile cu Subsonic (Gonic, Airsonic, …) pot rula cu funcționalitate redusă, deoarece Psysonic folosește multe endpointuri API specifice Navidrome.', + userMgmtTitle: 'Gestionarea Utilizatorilor', + userMgmtDesc: 'Gestionează utilizatorii de pe acest server. Necesită privilegii admin.', + userMgmtNoAdmin: 'Ai nevoie de privilegii de admin pentru a gestiona utilizatorii de pe acest server.', + userMgmtLoadError: 'Eroare la încărcarea utilizatorilor.', + userMgmtLoadFriendly: 'Serverul nu a răspuns — acesta este de obicei un caz singular.', + userMgmtRetry: 'Reîncearcă', + userMgmtEmpty: 'Niciun utilizator găsit.', + userMgmtYouBadge: 'Tu', + userMgmtAdminBadge: 'Admin', + userMgmtAddUser: 'Adaugă Utilizator', + userMgmtAddUserTitle: 'Adaugă Nou Utilizator', + userMgmtEditUserTitle: 'Editează Utilizatorul', + userMgmtUsername: 'Nume utilizator', + userMgmtName: 'Nume afișaj', + userMgmtEmail: 'Email', + userMgmtPassword: 'Parolă', + userMgmtPasswordEditHint: 'Introdu o parolă nouă pentru a o actualiza.', + userMgmtRoleAdmin: 'Admin', + userMgmtLibraries: 'Librării', + userMgmtLibrariesAdminHint: 'Utilizatorii Admin au acces automat la toate librăriile.', + userMgmtLibrariesEmpty: 'Nicio librărie disponibilă pe acest server.', + userMgmtLibrariesValidation: 'Alege cel puțin o librărie.', + userMgmtLibrariesUpdateError: 'Utilizator salvat, dar atribuirea librăriilor a eșuat', + userMgmtNoLibraries: 'Nicio librărie asignată', + userMgmtNeverSeen: 'Niciodată', + userMgmtSave: 'Salvează', + userMgmtCancel: 'Anulează', + userMgmtDelete: 'Șterge', + userMgmtEdit: 'Editează', + userMgmtConfirmDelete: 'Șterge utilizatorul "{{username}}"? Acestă acțiune nu poate fi anulată.', + userMgmtCreateError: 'Nu s-a putut crea utilizatorul.', + userMgmtUpdateError: 'Nu s-a putut actualiza utilizatorul.', + userMgmtDeleteError: 'Nu s-a putut șterge utilizatorul.', + userMgmtCreated: 'Utilizator creat.', + userMgmtUpdated: 'Utilizator actualizat.', + userMgmtDeleted: 'Utilizator șters.', + userMgmtValidationMissing: 'Numele de utilizator, numele de afișaj și parola sunt necesare.', + userMgmtValidationMissingIdentity: 'Numele de utilizator și numele de afișaj sunt necesare.', + userMgmtMagicStringGenerate: 'Generează string-ul magic', + userMgmtSaveAndMagicString: 'Salvează și obține string-ul magic', + userMgmtMagicStringPasswordNavHint: + 'Navidrome va salva această parolă pentru utilizator. Dacă diferă de cea curentă, serverul va actualiza parola de login.', + userMgmtMagicStringPlaintextWarning: + 'Distribuie string-ul magic cu grijă: conține o parolă necriptată (codificarea nu este criptare). Oricine cu string-ul complet se poate conecta ca acest utilizator.', + userMgmtMagicStringCopied: 'String-ul magic copiat în clipboard.', + userMgmtMagicStringCopyFailed: 'Nu s-a putut copia în clipboard.', + userMgmtMagicStringLoginFailed: 'Verificarea parolei a eșuat — credențialele nu au putut fi verificate.', + userMgmtMagicStringModalTitle: 'Generează string-ul magic', + userMgmtMagicStringModalDesc: 'Introdu parola Subsonic pentru "{{username}}". Este inclusă în string-ul magic copiat.', + userMgmtMagicStringModalConfirm: 'Copiază string-ul', + audiomuseTitle: 'AudioMuse-AI (Navidrome)', + audiomuseDesc: + 'Pornește dacă acest server are AudioMuse-AI Navidrome plugin configurat. Activează Mixul Instant din piese si folosește artiști similari de pe partea de server în loc de Last.fm pe paginile de artiști.', + audiomuseIssueHint: + 'Mixul Instant a eșuat recent — verifică plugin-ul Navidrome și API-ul AudioMuse. Artiștii similari sunt bazați pe Last.fm când serverul nu returnează nimic.', + connected: 'Conectat', + failed: 'Eșuat', + eqTitle: 'Egalizator', + eqEnabled: 'Activează Egalizatorul', + eqPreset: 'Preset', + eqPresetCustom: 'Personalizat', + eqPresetBuiltin: 'Preseturi încorporate', + eqPresetCustomGroup: 'Preseturile mele', + eqSavePreset: 'Salvează ca Preset', + eqPresetName: 'Nume preset…', + eqDeletePreset: 'Șterge preset', + eqResetBands: 'Resetează la Plat', + eqPreGain: 'Pre-gain', + eqResetPreGain: 'Resetează pre-gain', + eqAutoEqTitle: 'Căutare Căști AutoEQ', + eqAutoEqPlaceholder: 'Caută model căști / IEM…', + eqAutoEqSearching: 'Se caută…', + eqAutoEqNoResults: 'Niciun rezultat găsit', + eqAutoEqError: 'Căutarea a eșuat', + eqAutoEqRateLimit: 'Limita ratei GitHub a fost atinsă — încearcă din nou într-un minut', + eqAutoEqFetchError: 'Nu s-a putut lua profilul EQ', + lfmTitle: 'Last.fm', + lfmConnect: 'Conectează-te cu Last.fm', + lfmConnecting: 'Se așteaptă autorizarea…', + lfmConfirm: 'Am autorizat aplicația', + lfmConnected: 'Conectat ca', + lfmDisconnect: 'Deconectează-te', + lfmConnectDesc: 'Conectează contul tău Last.fm pentru a pornit scrobbling și update-uri Now Playing direct din Psysonic — nicio nevoie configurare Navidrome necesară.', + lfmOpenBrowser: 'O fereastră browser se va deschide. Autorizează Psysonic în Last.fm, apoi apasă pe butonul de mai jos.', + lfmScrobbles: '{{n}} scrobble-uri', + lfmMemberSince: 'Membru din {{year}}', + scrobbleEnabled: 'Scrobbling dezactivat', + scrobbleDesc: 'Trimite piese la Last.fm după 50% timp de redare', + behavior: 'Comportamentul Aplicației', + cacheTitle: 'Spațiu de stocare maxim', + cacheDesc: 'Artă copertă și imagini artist. Când este plin, cele mai vechi intrări sunt șterse automat. Albumele offline nu sunt șterse automat, dar vor fi șterse când memoria cache este curățată manual.', + cacheUsedImages: 'Imagini:', + cacheUsedOffline: 'Piese offline:', + cacheUsedHot: 'Mărimea pe disc:', + hotCacheTrackCount: 'Piese în memoria cache:', + cacheMaxLabel: 'Mărimea maximă', + cacheClearBtn: 'Golește memoria cache', + waveformCacheClearBtn: 'Golește cache-ul formelor de undă', + cacheClearWarning: 'Aceasta va înlătura de asemenea toate albumele offline din librărie.', + cacheClearConfirm: 'Golește totul', + cacheClearCancel: 'Anulează', + waveformCacheCleared: 'Cache-ul formelor de undă golit ({{count}} rows).', + waveformCacheClearFailed: 'Golirea cache-ului formelor de undă a eșuat.', + offlineDirTitle: 'Librărie offline (În Aplicație)', + offlineDirDesc: 'Locația stocării pieselor pe care le faci disponibile offline în Psysonic.', + offlineDirDefault: 'Implicit (App Data)', + offlineDirChange: 'Schimbă directorul', + offlineDirClear: 'Resetează la implicit', + offlineDirHint: 'Noile descărcări vor folosi această locație. Descărcările existente rămân la adresa originală.', + hotCacheTitle: 'Cache-ul hot playback', + hotCacheDisclaimer: 'Preîncarcă piesele ce urmează din coadă și păstrează anterioarele. Când este pornit, folosește spațiu pe disc și rețea.', + hotCacheDirDefault: 'Implicit (App Data)', + hotCacheDirChange: 'Schimbă folderul', + hotCacheDirClear: 'Resetează la implicit', + hotCacheDirHint: 'Schimbarea folderului resetează indexul din aplicație; fișierele aflate deja pe disc stau unde sunt până când le ștergi.', + hotCacheEnabled: 'Activează cache-ul hot playback cache', + hotCacheMaxMb: 'Mărimea maximă cache', + hotCacheDebounce: 'Debounce la schimbarea cozii', + hotCacheDebounceImmediate: 'Imediat', + hotCacheDebounceSeconds: '{{n}} s', + hotCacheClearBtn: 'Golește hot cache', + audioOutputDevice: 'Dispozitiv de ieșire audio', + audioOutputDeviceDesc: 'Alege prin ce dispozitiv audio să redea Psysonic. Schimbările au efect imediat și re-încep piesa curentă.', + audioOutputDeviceDefault: 'Implicit sistem', + audioOutputDeviceRefresh: 'Reîmprospătează lista dispozitivelor', + audioOutputDeviceOsDefaultNow: 'ieșirea curentă a sistemului', + audioOutputDeviceListError: 'Nu s-a putut încărca lista dispozitivelor audio', + audioOutputDeviceNotInCurrentList: 'nu există în lista curentă', + audioOutputDeviceMacNotice: 'În macOS, redarea urmărește mereu dispozitivul audio de ieșire al sistemului din motive tehnice. Schimbă ținta în Setări → Sunet sau iconița difuzor din bara de meniu. Fundal: CoreAudio declanșează un prompt de permisiune de microfon când se deschide un stream non-implicit — îl evităm folosind opțiunea implicită a sistemului mereu.', + hiResTitle: 'Playback Hi-Res nativ', + hiResEnabled: 'Pornește playback-ul hi-res nativ', + hiResDesc: "Forțează ieșire implicită de 44.1 kHz pentru stabilitate maximă. Pornește doar dacă sistemul hardware și rețeaua suport fiabil rate mari de eșantionare (88.2 kHz+).", + showArtistImages: 'Afișează Imagini Artist', + showArtistImagesDesc: 'Încarcă și afișează imagini artist în Prezentarea generală a Artiștilor. Oprit implicit pentru a reduce I/O pe server și încărcarea rețelei pe librării mari.', + showOrbitTrigger: 'Afișează "Orbit" în antet', + showOrbitTriggerDesc: 'Declanșatorul din bara de sus pentru a începe sau intra într-o sesiune de ascultare distribuită. Ascunde-l dacă nu folosești Orbit - îl poți porni înapoi aici.', + showTrayIcon: 'Afișează Iconița Tavă', + showTrayIconDesc: 'Afișează iconița Psysonic în zona notificărilor de sistem / bara de meniu.', + minimizeToTray: 'Minimizează în Tavă', + minimizeToTrayDesc: 'La închiderea ferestrei, continuă rularea Psysonic în tava de sistem în loc de ieșire', + preloadMiniPlayer: 'Preîncarcă mini player', + preloadMiniPlayerDesc: 'Crează fereastra mini player în fundal la deschiderea aplicației pentru a arăta conținut instantaneu la prima deschidere. Folosește puțină extra memorie.', + discordRichPresence: 'Prezență Discord Rich', + discordRichPresenceDesc: 'Arată piesa redată curent pe profilul tău de Discord. Necesită Discord să ruleze.', + useCustomTitlebar: 'Bară de titlu personalizată', + useCustomTitlebarDesc: 'Înlocuiește bara de titlu a sistemului cu una care corespunde cu tema aplicației. Dezactivează pentru a folosi bara de titlu nativ GNOME/GTK.', + linuxWebkitSmoothScroll: 'Rotiță lină (Linux)', + linuxWebkitSmoothScrollDesc: 'Pornit: scroll inert. Oprit: linie cu linie, în stil GTK.', + discordCoverSource: 'Sursa artei de copertă', + discordCoverSourceDesc: 'De unde să fie preluată arta de album afișată pe profilul tău de Discord.', + discordCoverNone: 'Niciuna (doar iconița aplicației)', + discordCoverServer: 'Server (prin informații album)', + discordCoverApple: 'Apple Music', + discordOptions: 'Opțiuni avansate Discord', + discordTemplates: 'Șablon text personalizat', + discordTemplatesDesc: 'Personalizează ce informații sunt afișate pe profilul tău de Discord. Variabile: {title}, {artist}, {album}', + discordTemplateDetails: 'Linia principală (detalii)', + discordTemplateState: 'Linia secundară (status)', + discordTemplateLargeText: 'Tooltip album (largeText)', + nowPlayingEnabled: 'Se afișează în Now Playing', + nowPlayingEnabledDesc: 'Difuzează piesa redată curent către vizualizatorul de ascultare live a serverului. Dezactivează pentru a opri trimiterea datelor de redare.', + enableBandsintown: 'Date de turneu Bandsintown', + enableBandsintownDesc: 'Arată concertele următoare pentru artisul curent în tab-ul Informații. Datele sunt preluate din API-ul public Bandsintown.', + lyricsServerFirst: 'Preferă versurile de pe server', + lyricsServerFirstDesc: 'Verifică versurile furnizate de server (tag-uri încorporate, fișiere sidecar) înainte de interogarea LRCLIB. Dezactivează pentru a folosi LRCLIB primul.', + enableNeteaselyrics: 'Versuri Netease Cloud Music', + enableNeteaselyricsDesc: 'Folosește Netease Cloud Music ca ultimă soluție pentru versuri când serverul și LRCLIB nu returnează nimic. Cea mai bună acoperire pentru muzică Asiatică și internațională.', + lyricsSourcesTitle: 'Sursă versuri', + lyricsSourcesDesc: 'Alege ce surse se interoghează pentru versuri și în ce ordine. Trage pentru a reordona. Sursele dezactivate sunt ignorate complet.', + lyricsSourceServer: 'Server', + lyricsSourceLrclib: 'LRCLIB', + lyricsSourceNetease: 'Netease Cloud Music', + lyricsModeStandard: 'Standard', + lyricsModeStandardDesc: 'Trei surse în o listă ordonabilă: tag-uri server, LRCLIB, Netease.', + lyricsModeLyricsplus: 'YouLyPlus (Karaoke)', + lyricsModeLyricsplusDesc: 'Sincronizare cuvânt-cu-cuvânt preluată din Apple Music, Spotify, Musixmatch & QQ (backend comunitate). Recurge în tăcere la sursele standard când nimic nu este găsit.', + lyricsStaticOnly: 'Afișează versurile doar ca text static', + lyricsStaticOnlyDesc: 'Redă versurile sincronizate fără scroll automat și fără evidențierea cuvintelor.', + downloadsTitle: 'Export ZIP & Arhivare', + downloadsFolderDesc: 'Folder destinație pentru albumele pe care le descarci ca fișiere ZIP în calculator.', + downloadsDefault: 'Folderul Download Implicit', + pickFolder: 'Selectează', + pickFolderTitle: 'Selectează Folderul de Download', + clearFolder: 'Golește folderul de download', + logout: 'Deconectare', + aboutTitle: 'Despre Psysonic', + aboutDesc: 'Un player muzical desktop modern făcut pentru Navidrome. Folosește API-ul Subsonic plus extensiile specifice Navidrome. Construit cu Tauri v2 cu un motor audio nativ Rust — ușor și rapid, dar împachetat cu funcționalități: bară de redare cu forme de undă, versuri sincronizate, integrare Last.fm, EQ 10 benzi, crossfade, redare fără spațiu între piese, Replay Gain, navigarea pe gen, și o librărie largă de teme.', + aboutLicense: 'Licență', + aboutLicenseText: 'GNU GPL v3 — liber de utilizat, modificat, și distribuit sub aceeași licență.', + aboutRepo: 'Cod Sursă pe GitHub', + aboutVersion: 'Versiune', + aboutBuiltWith: 'Construit cu Tauri · React · TypeScript · Rust/rodio', + aboutMaintainersLabel: 'Dezvoltatori', + aboutReleaseNotesLabel: 'Notițe lansare', + aboutReleaseNotesLink: "Deschide ce e nou pentru această versiune", + aboutContributorsLabel: 'Contribuabili', + showChangelogOnUpdate: "Arată 'Ce este nou' în update", + showChangelogOnUpdateDesc: "Arată un banner discret cu lista modificărilor deasupra Now Playing după un update. Apasă pentru a deschide lista modificărilor; X îl respinge.", + randomMixTitle: 'Lista neagră Mix Aleatoriu', + luckyMixMenuTitle: 'Arată Mixul Norocos în meniu', + luckyMixMenuDesc: 'Activează Mixul Norocos în Construiește un Mix și ca un element separat în meniu când navigarea împărțită este pornită. Vizibil doar când AudioMuse este activat pe serverul activ.', + randomMixBlacklistTitle: 'Cuvinte cheie personalizate pentru filtre', + randomMixBlacklistDesc: 'Piesele sunt excluse când orice cuvânt cheie corespunde cu genul, titlul, albumul sau artistul lor (activ când checkbox-ul de deasupra este pornit).', + randomMixBlacklistPlaceholder: 'Adaugă cuvânt cheie…', + randomMixBlacklistAdd: 'Adaugă', + randomMixBlacklistEmpty: 'Niciun cuvânt cheie adăugat încă.', + randomMixHardcodedTitle: 'Cuvinte cheie predefinite (activ când checkbox-ul este pornit)', + tabAudio: 'Audio', + tabStorage: 'Offline & Cache', + tabAppearance: 'Aparență', + tabLibrary: 'Librărie', + tabServers: 'Servere', + tabLyrics: 'Versuri', + tabPersonalisation: 'Personalizare', + tabIntegrations: 'Integrări', + inputKeybindingsTitle: 'Scurtături tastatură', + aboutContributorsCount_one: '{{count}} contribuție', + aboutContributorsCount_other: '{{count}} contribuții', + searchPlaceholder: 'Caută setări…', + searchNoResults: 'Nicio setare nu corespunde cu ce ai căutat.', + integrationsPrivacyTitle: 'Notificare de confidențialitate', + integrationsPrivacyBody: 'Toate integrările din acest tab sunt opționale și trimit date către servicii externe sau server-ul tău Navidrome când sunt activate. Last.fm primește istoricul ascultărilor tale, Discord arată piesa redată curent în profilul tău, Bandsintown e interogat per artist pentru a aduce date de turnee, și distribuirea Now-Playing publică piesa curentă către alți useri din server-ul tău Navidrome. Dacă nu vrei vreo opțiune, doar lasă secțiunea corespunzătoare dezactivată', + homeCustomizerTitle: 'Pagina Principală', + queueToolbarTitle: 'Toolbar Coadă', + queueToolbarReset: 'Resetează la implicit', + queueToolbarSeparator: 'Separator', + sidebarTitle: 'Bara laterală', + sidebarReset: 'Resetează la implicit', + artistLayoutTitle: 'Secțiunile paginii artistului', + artistLayoutDesc: 'Trage pentru a reordona, comutați pentru a ascunde secțiuni individuale ale paginii de artist. Secțiunile fără date sunt ignorate automat.', + artistLayoutReset: 'Resetează la implicit', + artistLayoutBio: 'Biografie artist', + artistLayoutTopTracks: 'Top piese', + artistLayoutSimilar: 'Artiști similari', + artistLayoutAlbums: 'Albume', + artistLayoutFeatured: 'Prezentat și pe', + sidebarDrag: 'Trage pentru a reordona', + sidebarFixed: 'Mereu vizibil', + randomNavSplitTitle: 'Navigare Mix împărțită', + randomNavSplitDesc: 'Arată "Mix Aleatoriu", "Albume Aleatorii", și "Mix Norocos" ca intrări separate în bara laterală în loc de hub-ul "Construiește un Mix".', + tabInput: 'Input', + tabUsers: 'Useri', + tabSystem: 'Sistem', + loggingTitle: 'Logging', + loggingModeDesc: 'Controlează verbozitatea log-urilor din backend în terminal.', + loggingModeOff: 'Oprit', + loggingModeNormal: 'Normal', + loggingModeDebug: 'Debug', + loggingExport: 'Exportă log-uri', + loggingExportSuccess: 'Log-uri exportate ({{count}} linii).', + loggingExportError: 'Nu s-au putut exporta log-urile.', + ratingsSectionTitle: 'Ratinguri', + ratingsSkipStarTitle: 'Sari peste 1 stea', + ratingsSkipStarDesc: + 'După mai multe salturi la rând, setează ratingul piesei la 1★. Doar pentru piesele care nu au fost deja evaluate.', + ratingsSkipStarThresholdLabel: 'Salturi', + ratingsMixFilterTitle: 'Filtrează după rating', + ratingsMixFilterDesc: + 'Filtrează elementele cu scor mic în {{mix}} și {{albums}}. Apasă pe steaua selectată din nou pentru a opri limita.', + ratingsMixMinSong: 'Piese', + ratingsMixMinAlbum: 'Albume', + ratingsMixMinArtist: 'Artiști', + ratingsMixMinThresholdAria: 'Stele minime: {{label}}', + backupTitle: 'Backup & Restaurare', + backupExport: 'Setări de export', + backupExportDesc: 'Salvează toate setările, profilele de server, configurări Last.fm, teme, EQ și combinații de taste către un fișier .psybkp. Parolele sunt stocate ca text — păstrează fișierul în siguranță.', + backupImport: 'Setări de Import', + backupImportDesc: 'Restaurează setări dintr-in fișier .psybkp. Aplicația se va reîncărca după import.', + backupImportConfirm: 'Aceasta va suprascrie toate setările curente. Continuați?', + backupSuccess: 'Backup salvat', + backupImportSuccess: 'Setări restaurate — se reîncarcă…', + backupImportError: 'Fișier de backup invalid sau corupt.', + shortcutsReset: 'Resetează la implicite', + shortcutListening: 'Apasă o tastă…', + shortcutUnbound: '—', + globalShortcutsTitle: 'Scurtături globale', + globalShortcutsNote: 'Funcționează la nivel de sistem și când Psysonic este în fundal. Necesită Ctrl, Alt, sau Super ca un modificator.', + shortcutClear: 'Golește', + shortcutPlayPause: 'Redă / Pauză', + shortcutNext: 'Următoarea piesă', + shortcutPrev: 'Piesa anterioară', + shortcutVolumeUp: 'Ridică volumul', + shortcutVolumeDown: 'Coboară volumul', + shortcutSeekForward: 'Dă înainte 10s', + shortcutSeekBackward: 'Dă înapoi 10s', + shortcutToggleQueue: 'Comutați coada', + shortcutOpenFolderBrowser: 'Deschide {{folderBrowser}}', + shortcutFullscreenPlayer: 'Player pe ecran complet', + shortcutNativeFullscreen: 'Ecran complet nativ', + shortcutOpenMiniPlayer: 'Deschide mini player', + shortcutStartSearch: 'Începe o căutare', + shortcutStartAdvancedSearch: 'Începe o căutare avansată', + shortcutToggleSidebar: 'Comutați bara laterală', + shortcutMuteSound: 'Opriți sunetul', + shortcutToggleEqualizer: 'Porniți / Comutați Egalizatorul', + shortcutToggleRepeat: 'Comutați repetarea', + shortcutOpenNowPlaying: 'Deschide "Now Playing"', + shortcutShowLyrics: 'Arată Versurile', + shortcutFavoriteCurrentTrack: 'Adaugă piesa curentă la favorite', + shortcutOpenHelp: 'Ajutor', + playbackTitle: 'Redare', + replayGain: 'Replay Gain', + replayGainDesc: 'Normalizează volumul pieselor folosind metadata ReplayGain', + replayGainMode: 'Mod', + replayGainAuto: 'Auto', + replayGainAutoDesc: 'Alege volumul albumului când piesele vecine din coadă sunt din același album, altfel volumul piesei.', + replayGainTrack: 'Piesă', + replayGainAlbum: 'Album', + replayGainPreGain: 'Pre-Gain (fișiere etichetate)', + replayGainPreGainDesc: 'Boost universal adăugat peste fiecare calculare ReplayGain. Folosește pentru a compensa dacă librăria ta se simte prea liniștită per total.', + replayGainFallback: 'Rezervă (neetichetat / radio)', + replayGainFallbackDesc: 'Aplicat la piesele (și stream-urile radio) care nu au tag-uri ReplayGain deloc, pentru ca conținutul neetichetat să nu se audă mai gălăgios decât restul.', + normalization: 'Normalizare', + normalizationDesc: 'Aliniază volumul perceput peste piese, albume și radio.', + normalizationOff: 'Oprit', + normalizationReplayGain: 'ReplayGain', + normalizationLufs: 'LUFS', + loudnessTargetLufs: 'Țintă LUFS', + loudnessTargetLufsDesc: 'Volumul de referință la care toate piesele sunt ajustate. Numere mai mici = volum mai mare. Serviciile de streaming sunt setate în mod obișnuit la -14 LUFS.', + loudnessPreAnalysisAttenuation: 'Atenuare pre-analiză', + loudnessPreAnalysisAttenuationDesc: + 'Extra coborâre a volumului până când nivelul pentru această piesă este salvat. Streaming apoi folosește presupuneri aproximative, nu o măsurătoare completă. 0 dB = oprit; mai jos = mai încet. Numărul din dreapta este nivelul dB efectif pentru ținta curentă.', + loudnessPreAnalysisAttenuationRef: '{{eff}} dB efectiv cu ținta {{tgt}} LUFS.', + loudnessPreAnalysisAttenuationReset: 'Resetează la implicit', + loudnessFirstPlayNote: + 'Prima redate a unei piese noi își poate schimba brusc volumul cât este măsurată. Următoarea redare folosește măsurătoarea stocată și este stabilă. Piesele următoare din coadă sunt de obicei pre-analizate în timpul piesei anterioare, deci acest fenomen se întâmplă rar în practică.', + crossfade: 'Crossfade', + crossfadeDesc: 'Estompează între piese', + crossfadeSecs: '{{n}} s', + notWithGapless: 'Nu este valabil cât Gapless este activ', + notWithCrossfade: 'Nu este valabil cât Crossfade este activ', + gapless: 'Playback Gapless', + gaplessDesc: 'Pre-încarcă următoarea piesă pentru a elimina spațiile dintre piese', + preservePlayNextOrder: 'Prezervă ordinea "Redă următoarea"', + preservePlayNextOrderDesc: 'Elementele Redă Următoarea noi adăugate sunt puse după cele adăugate mai devreme în loc să sară în față.', + trackPreviewsTitle: 'Previzualizări Piese', + trackPreviewsToggle: 'Pornește previzualizările pieselor', + trackPreviewsDesc: 'Arată butoanele de Redare și Pre-vizualizare în rând în listele de piese pentru o mostră rapidă din mijlocul piesei.', + trackPreviewStart: 'Poziția de începere', + trackPreviewStartDesc: 'Cât de departe în piesă să înceapă pre-vizualizarea (% din lungimea piesei).', + trackPreviewDuration: 'Durată', + trackPreviewDurationDesc: 'Cât de mult se redă fiecare pre-vizualizare până se oprește.', + trackPreviewDurationSecs: '{{n}} s', + trackPreviewLocationsTitle: 'Unde apar pre-vizualizările', + trackPreviewLocationsDesc: 'Alege ce liste arată butoanele de pre-vizualizare în linie.', + trackPreviewLocation_suggestions: 'Sugestii în playlist', + trackPreviewLocation_albums: 'Liste de piese în album', + trackPreviewLocation_playlists: 'În playlist-uri', + trackPreviewLocation_favorites: 'În favorite', + trackPreviewLocation_artist: 'În top piese ale artistului', + trackPreviewLocation_randomMix: 'În Mixul Aleatoriu', + preloadMode: 'Preîncarcă Următoarea Piesă', + preloadModeDesc: 'Când să înceapă preîncărcarea următoarei piese din coadă', + nextTrackBufferingTitle: 'Preîncarcă', + preloadHotCacheMutualExclusive: 'Preîncarcarea și Hot Cache au același scop — doar una poate fi activată deodată. Pornirea unei opțiuni o dezactivează pe cealaltă.', + preloadOff: 'Oprit', + preloadBalanced: 'Balansat (30 s înainte de sfârșit)', + preloadEarly: 'Devreme (după 5 s de redare)', + preloadCustom: 'Personalizat', + preloadCustomSeconds: 'Secunde înainte de sfârșit: {{n}}', + infiniteQueue: 'Coadă Infinită', + infiniteQueueDesc: 'Adaugă automat piese aleatorii când coada se golește', + experimental: 'Experimental', + fsPlayerSection: 'Player pe ecran complet', + fsLyricsStyle: 'Stilul versurilor', + fsLyricsStyleRail: 'Șină', + fsLyricsStyleRailDesc: 'Șină clasica pe 5 linii.', + fsLyricsStyleApple: 'Derulare', + fsLyricsStyleAppleDesc: 'Listă în derulare pe ecran complet.', + sidebarLyricsStyle: 'Stilul derulării versurilor', + sidebarLyricsStyleClassic: 'Clasic', + sidebarLyricsStyleClassicDesc: 'Derulează linia activă în centru.', + sidebarLyricsStyleApple: 'Ca Apple Music', + sidebarLyricsStyleAppleDesc: 'Linia activă este ancorată aproape de vârf cu animații netede.', + fsShowArtistPortrait: 'Arată poza artisului', + fsShowArtistPortraitDesc: 'Arată poza artistului (sau arta albumului) în partea dreaptă a playerului pe ecran complet.', + fsPortraitDim: 'Estomparea fotografiei', + seekbarStyle: 'Stilul barei de redare', + seekbarStyleDesc: 'Alege aspectul barei de redare a playerului', + seekbarTruewave: 'Truewave', + seekbarPseudowave: 'Pseudowave', + seekbarLinedot: 'Linie & Punct', + seekbarBar: 'Bară', + seekbarThick: 'Bară groasă', + seekbarSegmented: 'Segmentat', + seekbarNeon: 'Strălucire Neon', + seekbarPulsewave: 'Undă de Puls', + seekbarParticletrail: 'Urmă de Particule', + seekbarLiquidfill: 'Lichid', + seekbarRetrotape: 'Bandă Retro', + themeSchedulerTitle: 'Schimbă Tema automat', + themeSchedulerEnable: 'Pornește temele programate', + themeSchedulerEnableSub: 'Schimbă automat între două teme pe baza orei din zi', + themeSchedulerDayTheme: 'Temă de zi', + themeSchedulerDayStart: 'Ziua începe la', + themeSchedulerNightTheme: 'Temă de noapte', + themeSchedulerNightStart: 'Noaptea începe la', + themeSchedulerActiveHint: 'Temele programate sunt active - aceste schimbări de teme sunt gestionate automat.', + visualOptionsTitle: 'Opțiuni vizuale', + coverArtBackground: 'Arta de fundal a copertei', + coverArtBackgroundSub: 'Arată arta de copertă blurată ca fundal în antetele albumelor/playlisturilor', + playlistCoverPhoto: 'Poza de copertă a playlistului', + playlistCoverPhotoSub: 'Arată poza grilă de copertă în afișajul de detalii al playlistului', + showBitrate: 'Arată Bitrate', + showBitrateSub: 'Arată bitrate-ul audio în listările de piese', + floatingPlayerBar: 'Bară Player plutitoare', + floatingPlayerBarSub: 'Păstrează bara playerului plutind deasupra conținutului', + uiScaleTitle: 'Scara interfaței', + uiScaleLabel: 'Zoom', +}; diff --git a/src/locales/ro/sharePaste.ts b/src/locales/ro/sharePaste.ts new file mode 100644 index 00000000..9e959683 --- /dev/null +++ b/src/locales/ro/sharePaste.ts @@ -0,0 +1,18 @@ +export const sharePaste = { + notLoggedIn: 'Loghează-te și adaugă serverul înainte de a lipi link-ul distribuit.', + noMatchingServer: 'Niciun server nu corespunde cu acest link. Adaugă un server cu această adresă: {{url}}', + trackUnavailable: 'Această piesă nu a fost găsită în server.', + albumUnavailable: 'Acest album nu a fost găsit în server.', + artistUnavailable: 'Acest artist nu a fost găsit în server.', + composerUnavailable: 'Acest compozitor nu a fost găsit pe server.', + openedTrack: 'Se redă piesa distribuită.', + openedAlbum: 'Se deschide albumul distribuit.', + openedArtist: 'Se deschide artistul distribuit.', + openedComposer: 'Se deschide compozitorul distribuit.', + openedQueue_one: 'Se redă {{count}} piesă din link-ul distribuit.', + openedQueue_other: 'Se redau {{count}} piese din link-ul distribuit.', + openedQueuePartial: + 'Se redau {{played}} din {{total}} piese din link ({{skipped}} nu au fost găsite în server).', + queueAllUnavailable: 'Nicio piesă din acest link nu a fost găsită în server.', + genericError: 'Nu s-a putut deschide link-ul distribuit.', +}; diff --git a/src/locales/ro/sidebar.ts b/src/locales/ro/sidebar.ts new file mode 100644 index 00000000..d8109741 --- /dev/null +++ b/src/locales/ro/sidebar.ts @@ -0,0 +1,39 @@ +export const sidebar = { + library: 'Librărie', + mainstage: 'Scena Principală', + newReleases: 'Lansări Noi', + allAlbums: 'Toate Albumele', + randomAlbums: 'Albume Aleatorii', + randomPicker: 'Construiește un Mix', + artists: 'Artiști', + composers: 'Compozitori', + randomMix: 'Mix Aleatoriu', + favorites: 'Favorite', + nowPlaying: 'Se Redă Acum', + system: 'Sistem', + statistics: 'Statistici', + settings: 'Setări', + help: 'Ajutor', + expand: 'Extinde bara laterală', + collapse: 'Restrânge bara laterală', + + downloadingTracks: 'Se descarcă {{n}} piese…', + syncingTracks: 'Se sincronizează {{done}}/{{total}}…', + cancelDownload: 'Anulează descărcarea', + offlineLibrary: 'Librărie Offline', + genres: 'Genuri', + tracks: 'Piese', + playlists: 'Playlisturi', + smartPlaylists: 'Playlisturi Smart', + mostPlayed: 'Cele mai Redate', + losslessAlbums: 'Lossless', + radio: 'Radio Internet', + folderBrowser: 'Browser de foldere', + deviceSync: 'Sincronizare Dispozitive', + libraryScope: 'Domeniul bibliotecii', + allLibraries: 'Toate librăriile', + expandPlaylists: 'Extinde playlisturi', + collapsePlaylists: 'Restrânge playlisturi', + more: 'Mai mult', + feelingLucky: 'Mix Norocos', +}; diff --git a/src/locales/ro/smartPlaylists.ts b/src/locales/ro/smartPlaylists.ts new file mode 100644 index 00000000..f2c0a42e --- /dev/null +++ b/src/locales/ro/smartPlaylists.ts @@ -0,0 +1,41 @@ +export const smartPlaylists = { + sectionBasic: '1. De bază', + sectionGenres: '2. Genuri', + sectionYearsAndFilters: '3. Ani și filtre', + genreMode: 'Mod gen', + genreModeInclude: 'Include genuri', + genreModeExclude: 'Exclude genuri', + genreSearchPlaceholder: 'Filtrează genuri...', + availableGenres: 'Disponibil', + selectedGenres: 'Selectat', + yearMode: 'Mod an', + yearModeInclude: 'Include distanță', + yearModeExclude: 'Exclude distanță', + name: 'Nume (fără prefix)', + limit: 'Limită', + limitHint: 'Cât de multe piese să fie incluse în playlist (1-{{max}}, de obicei 50).', + artistContains: 'Artistul conține…', + albumContains: 'Albumul conține…', + titleContains: 'Titlul conține…', + minRating: 'Rating minim', + minRatingAria: 'Rating minim pentru playlist inteligent', + minRatingHint: '0 dezactivează limita minimă; 1-5 păstrează piesele cu rating peste valoarea selectată.', + fromYear: 'Din anul', + toYear: 'Până la anul', + excludeUnrated: 'Exclude piesele fără rating', + compilationOnly: 'Doar compilații', + create: 'Nou Playlist Inteligent', + save: 'Salvează Playlist Inteligent', + created: 'Creat {{name}}', + updated: 'Actualizat {{name}}', + createFailed: 'Nu s-a putut crea playlistul inteligent.', + updateFailed: 'Nu s-a putut actualiza playlistul inteligent.', + navidromeOnly: 'Playlisturile inteligente pot fi create doar pe servere Navidrome.', + loadFailed: 'Nu s-a putut încărca playlistul inteligent din Navidrome.', + sortRandom: 'Sortează: aleatoriu', + sortTitleAsc: 'Sortează: titlu A-Z', + sortTitleDesc: 'Sortează: titlu Z-A', + sortYearDesc: 'Sortează: an desc', + sortYearAsc: 'Sortează: an asc', + sortPlayCountDesc: 'Sortează: număr de redări desc', +}; diff --git a/src/locales/ro/songInfo.ts b/src/locales/ro/songInfo.ts new file mode 100644 index 00000000..3bf88a51 --- /dev/null +++ b/src/locales/ro/songInfo.ts @@ -0,0 +1,23 @@ +export const songInfo = { + title: 'Informație piesă', + songTitle: 'Titlu', + artist: 'Artist', + album: 'Album', + albumArtist: 'Artist Album', + year: 'An', + genre: 'Gen', + duration: 'Durată', + track: 'Piesă', + format: 'Format', + bitrate: 'Bitrate', + sampleRate: 'Rată de Sample', + bitDepth: 'Adâncimea Biților', + channels: 'Canale', + fileSize: 'Mărime fișier', + path: 'Cale', + replayGainTrack: 'RG Gain Piesă', + replayGainAlbum: 'RG Gain Album', + replayGainPeak: 'RG Vârf Piesă', + mono: 'Mono', + stereo: 'Stereo', +}; diff --git a/src/locales/ro/statistics.ts b/src/locales/ro/statistics.ts new file mode 100644 index 00000000..890a6e65 --- /dev/null +++ b/src/locales/ro/statistics.ts @@ -0,0 +1,65 @@ +export const statistics = { + title: 'Statistici', + recentlyPlayed: 'Redate recent', + mostPlayed: 'Cele mai Redate Albume', + highestRated: 'Cele mai Votate Albume', + genreDistribution: 'Distribuția de Genuri (Top 20)', + loadMore: 'Încearcă mai mult', + statArtists: 'Artiști', + statArtistsTooltip: 'Doar albume de artiști — artiștii care apar doar ca un artist la nivel de piesă (prezentate, oaspete, etc.) fără albumul lor nu sunt incluși.', + statAlbums: 'Albume', + statSongs: 'Piese', + statGenres: 'Genuri', + statPlaytime: 'Timpul total de redare', + genreInsights: 'Perspectivele Genurilor', + formatDistribution: 'Distribuția Formatului', + formatSample: 'Eșantion de {{n}} piese', + computing: 'Se calculează…', + genreSongs: '{{count}} Piese', + genreAlbums: '{{count}} Albume', + recentlyAdded: 'Adăugate recent', + decadeDistribution: 'Albume după Deceniu', + decadeAlbums_one: '{{count}} Album', + decadeAlbums_other: '{{count}} Albume', + decadeUnknown: 'Necunoscut', + lfmTitle: 'Statistici Last.fm', + lfmTopArtists: 'Artiști de top', + lfmTopAlbums: 'Albume de top', + lfmTopTracks: 'Piese de top', + lfmPlays: '{{count}} redări', + lfmPeriodOverall: 'Din tot timpul', + lfmPeriod7day: '7 Zile', + lfmPeriod1month: '1 Lună', + lfmPeriod3month: '3 Luni', + lfmPeriod6month: '6 Luni', + lfmPeriod12month: '12 Luni', + lfmNotConnected: 'Conectează Last.fm în Setări pentru a îți vedea statisticile.', + lfmRecentTracks: 'Scrobble-uri Recente', + lfmNowPlaying: 'Now Playing', + lfmJustNow: 'tocmai acum', + lfmMinutesAgo: 'acum {{n}}m', + lfmHoursAgo: 'acum {{n}}h', + lfmDaysAgo: 'acum {{n}}d', + topRatedSongs: 'Cele mai bine cotate Piese', + topRatedArtists: 'Cei mai bine cotați Artiști', + noRatedSongs: 'Nicio piesă evaluată încă. Evaluează piese în afișajul de album sau playlist.', + noRatedArtists: 'Niciun artist evaluat încă.', + exportShare: 'Distribuie', + exportTitle: 'Distribuie Albumele din Top', + exportSubtitle: 'Generează o imagine distribuibilă cu cele mai redate albume ale tale.', + exportFormat: 'Format', + exportFormatStory: 'Poveste', + exportFormatSquare: 'Pătrat', + exportFormatTwitter: 'Card Twitter', + exportGrid: 'Grilă', + exportGridLabel: '{{n}}×{{n}}', + exportPreview: 'Previzualizare', + exportGenerate: 'Generează', + exportSave: 'Salvează imaginea…', + exportCancel: 'Anulează', + exportFooterLabel: 'Top Albume', + exportNotEnough: 'Ai nevoie de cel puțin {{count}} albume în librăria ta pentru o grilă {{n}}×{{n}}.', + exportSaving: 'Se salvează…', + exportSaved: 'Salvat.', + exportSaveFailed: 'Nu s-a putut salva imaginea.', +}; diff --git a/src/locales/ro/tracks.ts b/src/locales/ro/tracks.ts new file mode 100644 index 00000000..250896b1 --- /dev/null +++ b/src/locales/ro/tracks.ts @@ -0,0 +1,15 @@ +export const tracks = { + title: 'Piese', + subtitle: 'Răsfoiește. Caută. Descoperă.', + heroEyebrow: 'Piesa momentului', + heroReroll: 'Alege alta', + playSong: 'Redă', + enqueueSong: 'Adaugă în coadă', + railRandom: 'Alegere aleatorie', + railHighlyRated: 'Foarte apreciate', + browseTitle: 'Caută toate piesele', + browseUnsupported: "Acest server nu afișează toată librăria deodată. Folosește căutarea de mai sus pentru a găsi piese specifice.", + searchPlaceholder: 'Găsește o piesă după titlu, artist sau album…', + count_one: '{{count}} piesă', + count_other: '{{count}} piese', +}; diff --git a/src/locales/ro/tray.ts b/src/locales/ro/tray.ts new file mode 100644 index 00000000..47ea083a --- /dev/null +++ b/src/locales/ro/tray.ts @@ -0,0 +1,8 @@ +export const tray = { + playPause: 'Redă / Pauză', + nextTrack: 'Următoarea Piesă', + previousTrack: 'Piesa Anterioară', + showHide: 'Arată / Ascunde', + exitPsysonic: 'Ieși din Psysonic', + nothingPlaying: 'Nimic nu este redat', +}; diff --git a/src/locales/ro/whatsNew.ts b/src/locales/ro/whatsNew.ts new file mode 100644 index 00000000..376cb71c --- /dev/null +++ b/src/locales/ro/whatsNew.ts @@ -0,0 +1,8 @@ +export const whatsNew = { + title: "Ce este nou", + empty: 'Nicio intrare în lista de schimbări pentru această versiune încă.', + bannerTitle: 'Lista de schimbări', + bannerCollapsed: "Ce este nou în v{{version}}", + dismiss: 'Respinge', + close: 'Închide', +}; diff --git a/src/locales/ru.ts b/src/locales/ru.ts deleted file mode 100644 index f14b078c..00000000 --- a/src/locales/ru.ts +++ /dev/null @@ -1,1888 +0,0 @@ -/** Russian UI strings — natural phrasing for a music desktop app */ -export const ruTranslation = { - sidebar: { - library: 'Медиатека', - mainstage: 'Для вас', - newReleases: 'Новинки', - allAlbums: 'Все альбомы', - randomAlbums: 'Случайные альбомы', - randomPicker: 'Собрать микс', - artists: 'Исполнители', - composers: 'Композиторы', - randomMix: 'Случайный микс', - favorites: 'Избранное', - nowPlaying: 'Сейчас играет', - system: 'Система', - statistics: 'Статистика', - settings: 'Настройки', - help: 'Справка', - expand: 'Развернуть боковую панель', - collapse: 'Свернуть боковую панель', - downloadingTracks: 'Кэширование {{n}} треков…', - syncingTracks: 'Синхронизация {{done}}/{{total}}…', - cancelDownload: 'Отменить загрузку', - offlineLibrary: 'Офлайн-библиотека', - genres: 'Жанры', - tracks: 'Треки', - playlists: 'Плейлисты', - smartPlaylists: 'Смарт-плейлисты', - mostPlayed: 'Популярное', - losslessAlbums: 'Lossless', - radio: 'Онлайн-радио', - folderBrowser: 'Браузер папок', - deviceSync: 'Синхронизация устройства', - libraryScope: 'Область медиатеки', - allLibraries: 'Все библиотеки', - expandPlaylists: 'Развернуть плейлисты', - collapsePlaylists: 'Свернуть плейлисты', - more: 'Ещё', - feelingLucky: 'Мне повезёт', - }, - home: { - hero: 'Подборка', - starred: 'Личное избранное', - recent: 'Недавно добавлено', - mostPlayed: 'Популярное', - recentlyPlayed: 'Недавно проиграно', - losslessAlbums: 'Lossless-альбомы', - discover: 'Обзор', - discoverSongs: 'Открыть треки', - loadMore: 'Ещё', - discoverMore: 'Смотреть ещё', - discoverArtists: 'Исполнители', - discoverArtistsMore: 'Все исполнители', - becauseYouLike: 'Потому что вы слушали…', - becauseYouLikeFor: 'Потому что вы слушали {{artist}}', - similarTo: 'Похоже на {{artist}}', - becauseYouLikeTracks_one: '{{count}} трек', - becauseYouLikeTracks_few: '{{count}} трека', - becauseYouLikeTracks_many: '{{count}} треков', - becauseYouLikeTracks_other: '{{count}} треков', - }, - hero: { - eyebrow: 'Альбом дня', - playAlbum: 'Воспроизвести альбом', - enqueue: 'В очередь', - enqueueTooltip: 'Добавить весь альбом в очередь', - }, - search: { - placeholder: 'Исполнитель, альбом или трек…', - noResults: 'Ничего не найдено по запросу «{{query}}»', - artists: 'Исполнители', - albums: 'Альбомы', - songs: 'Треки', - clearLabel: 'Очистить поиск', - addedToQueueToast: '«{{title}}» добавлен в очередь', - title: 'Поиск', - resultsFor: 'Результаты по «{{query}}»', - album: 'Альбом', - advanced: 'Расширенный поиск', - advancedSearchTerm: 'Поисковый запрос', - advancedSearchPlaceholder: 'Название, альбом, исполнитель…', - advancedGenre: 'Жанр', - advancedAllGenres: 'Все жанры', - advancedYear: 'Год', - advancedYearFrom: 'от', - advancedYearTo: 'до', - advancedAll: 'Все', - advancedSearch: 'Найти', - advancedEmpty: 'Введите запрос или выберите фильтр.', - advancedNoResults: 'Ничего не найдено.', - advancedGenreNote: 'Треки выбираются случайно в рамках жанра.', - recentSearches: 'Недавние запросы', - browse: 'Обзор', - emptyHint: 'Что хочешь послушать?', - genres: 'Жанры', - }, - nowPlaying: { - tooltip: 'Кто сейчас слушает?', - title: 'Кто сейчас слушает?', - loading: 'Загрузка…', - nobody: 'Сейчас никто не слушает.', - minutesAgo: '{{n}} мин назад', - nothingPlaying: 'Пока ничего не играет — включите трек.', - aboutArtist: 'Об исполнителе', - fromAlbum: 'Из этого альбома', - viewAlbum: 'Просмотр альбома', - goToArtist: 'Перейти к исполнителю', - readMore: 'Читать далее', - showLess: 'Свернуть', - genreInfo: 'Жанр', - trackInfo: 'О треке', - topSongs: 'Самое популярное у этого исполнителя', - topSongsCredit: 'Топ-треки исполнителя {{name}}', - trackPosition: 'Трек {{pos}}', - playsCount_one: '{{count}} прослушивание', - playsCount_few: '{{count}} прослушивания', - playsCount_many: '{{count}} прослушиваний', - playsCount_other: '{{count}} прослушиваний', - releasedYearsAgo_one: '{{count}} год назад', - releasedYearsAgo_few: '{{count}} года назад', - releasedYearsAgo_many: '{{count}} лет назад', - releasedYearsAgo_other: '{{count}} лет назад', - discography: 'Дискография', - lastfmStats: 'Статистика Last.fm', - thisTrack: 'Этот трек', - thisArtist: 'Этот исполнитель', - listeners: 'слушателей', - scrobbles: 'прослушиваний', - yourScrobbles: 'вами', - listenersN: '{{n}} слушателей', - scrobblesN: '{{n}} прослушиваний', - playsByYouN: 'прослушано вами {{n}}×', - openTrackOnLastfm: 'Трек на Last.fm', - openArtistOnLastfm: 'Исполнитель на Last.fm', - rgTrackTooltip: 'ReplayGain (трек)', - rgAlbumTooltip: 'ReplayGain (альбом)', - rgAutoTooltip: 'ReplayGain (авто)', - showMoreTracks: 'Показать ещё {{count}}', - showLessTracks: 'Свернуть', - hideCard: 'Скрыть карточку', - layoutMenu: 'Макет', - visibleCards: 'Видимые карточки', - hiddenCards: 'Скрытые карточки', - noHiddenCards: 'Нет скрытых карточек', - resetLayout: 'Сбросить макет', - emptyColumn: 'Перетащите карточки сюда', - }, - contextMenu: { - playNow: 'Играть сейчас', - playNext: 'Играть следующим', - addToQueue: 'В конец очереди', - enqueueAlbum: 'Альбом в очередь', - enqueueAlbums_one: '{{count}} альбом в очередь', - enqueueAlbums_few: '{{count}} альбома в очередь', - enqueueAlbums_many: '{{count}} альбомов в очередь', - enqueueAlbums_other: '{{count}} альбомов в очередь', - startRadio: 'Радио по похожим', - instantMix: 'Instant Mix', - instantMixFailed: 'Не удалось собрать Instant Mix — ошибка сервера или плагина.', - cliMixNeedsTrack: 'Ничего не играет — сначала начните воспроизведение, затем снова выполните команду микса.', - lfmLove: 'Любимое на Last.fm', - lfmUnlove: 'Убрать с Last.fm', - favorite: 'В избранное', - favoriteArtist: 'Исполнитель в избранное', - favoriteAlbum: 'Альбом в избранное', - unfavorite: 'Убрать из избранного', - unfavoriteArtist: 'Убрать исполнителя из избранного', - unfavoriteAlbum: 'Убрать альбом из избранного', - removeFromQueue: 'Убрать из очереди', - removeFromPlaylist: 'Убрать из плейлиста', - openAlbum: 'Открыть альбом', - goToArtist: 'К исполнителю', - download: 'Скачать (ZIP)', - addToPlaylist: 'В плейлист', - selectedPlaylists: '{{count}} плейлистов выбрано', - selectedAlbums: '{{count}} альбомов выбрано', - selectedArtists: '{{count}} исполнителей выбрано', - songInfo: 'Сведения о треке', - shareLink: 'Копировать ссылку для обмена', - shareCopied: 'Ссылка для обмена скопирована в буфер.', - shareCopyFailed: 'Не удалось скопировать в буфер.', - }, - sharePaste: { - notLoggedIn: 'Войдите и добавьте сервер, затем вставьте ссылку.', - noMatchingServer: 'Ни один сохранённый сервер не совпадает с адресом из ссылки. Добавьте сервер: {{url}}', - trackUnavailable: 'Трек на сервере не найден.', - albumUnavailable: 'Альбом на сервере не найден.', - artistUnavailable: 'Исполнитель на сервере не найден.', - composerUnavailable: 'Композитор на сервере не найден.', - openedTrack: 'Воспроизводится присланный трек.', - openedAlbum: 'Открывается присланный альбом.', - openedArtist: 'Открывается присланный исполнитель.', - openedComposer: 'Открывается присланный композитор.', - openedQueue_one: 'Воспроизводится присланная очередь: {{count}} трек.', - openedQueue_few: 'Воспроизводится присланная очередь: {{count}} трека.', - openedQueue_many: 'Воспроизводится присланная очередь: {{count}} треков.', - openedQueue_other: 'Воспроизводится присланная очередь: {{count}} треков.', - openedQueuePartial: - 'Воспроизводится {{played}} из {{total}} треков по ссылке ({{skipped}} на этом сервере не найдены).', - queueAllUnavailable: 'Ни один из треков по ссылке не найден на сервере.', - genericError: 'Не удалось открыть ссылку для обмена.', - }, - albumDetail: { - back: 'Назад', - orbitDoubleClickHint: 'Двойной клик, чтобы добавить этот трек в очередь Orbit', - playAll: 'Воспроизвести всё', - shareAlbum: 'Поделиться альбомом', - enqueue: 'В очередь', - enqueueTooltip: 'Добавить весь альбом в очередь', - artistBio: 'Биография', - download: 'Скачать (ZIP)', - downloading: 'Загрузка…', - cacheOffline: 'Сохранить офлайн', - offlineCached: 'Доступно офлайн', - offlineDownloading: 'Кэширование… ({{n}} из {{total}})', - removeOffline: 'Удалить офлайн-копию', - offlineStorageFull: - 'Место для офлайн закончилось (лимит {{mb}} МБ). Освободите место в офлайн-библиотеке или увеличьте лимит в настройках.', - offlineStorageGoToLibrary: 'Офлайн-библиотека', - offlineStorageGoToSettings: 'Настройки', - favoriteAdd: 'В избранное', - favoriteRemove: 'Убрать из избранного', - favorite: 'Избранное', - noBio: 'Биография недоступна.', - moreByArtist: 'Ещё от {{artist}}', - tracksCount: 'Композиций: {{n}}', - goToArtist: 'Перейти к {{artist}}', - moreLabelAlbums: 'Другие альбомы на {{label}}', - trackTitle: 'Название', - trackAlbum: 'Альбом', - trackArtist: 'Исполнитель', - trackGenre: 'Жанр', - trackFormat: 'Формат', - trackFavorite: 'Избранное', - trackRating: 'Оценка', - trackDuration: 'Длительность', - trackTotal: 'Итого', - columns: 'Колонки', - resetColumns: 'Сбросить', - notFound: 'Альбом не найден.', - bioModal: 'Биография исполнителя', - bioClose: 'Закрыть', - ratingLabel: 'Оценка', - enlargeCover: 'Увеличить обложку', - filterSongs: 'Фильтр треков…', - sortNatural: 'По умолчанию', - sortByTitle: 'А–Я (название)', - sortByArtist: 'А–Я (исполнитель)', - sortByAlbum: 'А–Я (альбом)', - }, - entityRating: { - albumShort: 'Оценка альбома', - artistShort: 'Оценка исполнителя', - albumAriaLabel: 'Оценка альбома', - artistAriaLabel: 'Оценка исполнителя', - selectedArtistsRatingAriaLabel: 'Звёздная оценка для выбранных исполнителей ({{count}})', - selectedAlbumsRatingAriaLabel: 'Звёздная оценка для выбранных альбомов ({{count}})', - saveFailed: 'Не удалось сохранить оценку.', - }, - artistDetail: { - back: 'Назад', - albums: 'Альбомы', - album: 'Альбом', - playAll: 'Воспроизвести всё', - shareArtist: 'Поделиться исполнителем', - shuffle: 'Перемешать', - radio: 'Радио', - loading: 'Загрузка…', - noRadio: 'Похожие треки для этого исполнителя не найдены.', - notFound: 'Исполнитель не найден.', - albumsBy: 'Альбомы — {{name}}', - topTracks: 'Популярные треки', - noAlbums: 'Альбомов нет.', - trackTitle: 'Название', - trackAlbum: 'Альбом', - trackDuration: 'Длительность', - favoriteAdd: 'В избранное', - favoriteRemove: 'Убрать из избранного', - favorite: 'Избранное', - albumCount_one: '{{count}} альбом', - albumCount_few: '{{count}} альбома', - albumCount_many: '{{count}} альбомов', - albumCount_other: '{{count}} альбомов', - openedInBrowser: 'Открыто в браузере', - featuredOn: 'Также участвует в', - similarArtists: 'Похожие исполнители', - cacheOffline: 'Сохранить дискографию офлайн', - offlineCached: 'Дискография сохранена', - offlineDownloading: 'Кэширование… ({{done}} из {{total}} альбомов)', - uploadImage: 'Загрузить фото исполнителя', - uploadImageError: 'Не удалось загрузить изображение', - releaseTypes: { - album: 'Альбом', - ep: 'EP', - single: 'Сингл', - compilation: 'Сборник', - live: 'Концерт', - soundtrack: 'Саундтрек', - remix: 'Ремикс', - other: 'Другое', - }, - }, - favorites: { - title: 'Избранное', - empty: 'Пока ничего не отмечено звёздочкой.', - artists: 'Исполнители', - albums: 'Альбомы', - songs: 'Треки', - enqueueAll: 'Всё в очередь', - playAll: 'Воспроизвести всё', - removeSong: 'Убрать из избранного', - stations: 'Радиостанции', - showingFiltered: 'Показано {{filtered}} из {{total}} ({{artist}})', - showingCount: 'Показано {{filtered}} из {{total}}', - clearArtistFilter: 'Сбросить фильтр исполнителя', - noFilterResults: 'Нет результатов с выбранными фильтрами.', - allArtists: 'Все исполнители', - topArtists: 'Топ исполнителей по избранному', - topArtistsSongCount_one: '{{count}} трек', - topArtistsSongCount_few: '{{count}} трека', - topArtistsSongCount_many: '{{count}} треков', - topArtistsSongCount_other: '{{count}} трека', - }, - randomLanding: { - title: 'Собрать микс', - mixByTracks: 'Микс по трекам', - mixByTracksDesc: 'Случайная подборка треков со всей медиатеки', - mixByAlbums: 'Микс по альбомам', - mixByAlbumsDesc: 'Случайная подборка альбомов для открытий', - mixByLucky: 'Мне повезёт', - mixByLuckyDesc: 'Умный Instant Mix из топ-артистов, альбомов и высоких оценок', - }, - randomAlbums: { - title: 'Случайные альбомы', - refresh: 'Обновить', - }, - genres: { - title: 'Жанры', - genreCount: 'Жанры', - albumCount_one: '{{count}} альбом', - albumCount_few: '{{count}} альбома', - albumCount_many: '{{count}} альбомов', - albumCount_other: '{{count}} альбомов', - loading: 'Загрузка жанров…', - empty: 'Жанры не найдены.', - albumsLoading: 'Загрузка альбомов…', - albumsEmpty: 'В этом жанре альбомов нет.', - loadMore: 'Ещё', - back: 'Назад', - }, - randomMix: { - title: 'Случайный микс', - remix: 'Новый микс', - remixTooltip: 'Подобрать другие случайные треки', - remixGenre: 'Новый микс: {{genre}}', - remixTooltipGenre: 'Подобрать другие треки жанра {{genre}}', - playAll: 'Воспроизвести всё', - trackTitle: 'Название', - trackArtist: 'Исполнитель', - trackAlbum: 'Альбом', - trackFavorite: 'Избранное', - trackDuration: 'Длительность', - favoriteAdd: 'В избранное', - favoriteRemove: 'Убрать из избранного', - play: 'Играть', - trackGenre: 'Жанр', - mixSettingsHeader: 'Настройки микса', - exclusionsHeader: 'Исключения', - filterPanelInexactSizeNote: 'Размер микса — это цель. При больших запросах сервер может вернуть меньше уникальных треков, если его случайный пул иссякает.', - mixSize: 'Размер списка', - excludeAudiobooks: 'Исключать аудиокниги и радиоспектакли', - excludeAudiobooksDesc: - 'По ключевым словам в жанре, названии, альбоме и исполнителе — например Hörbuch, Audiobook, Spoken Word и т. п.', - genreBlocked: 'Слово отфильтровано', - genreAddedToBlacklist: 'Добавлено в список фильтра', - genreAlreadyBlocked: 'Уже в списке', - artistBlocked: 'Исполнитель отфильтрован', - artistAddedToBlacklist: 'Исполнитель добавлен в фильтр', - artistClickHint: 'Нажмите, чтобы скрыть этого исполнителя', - blacklistToggle: 'Фильтр по словам', - genreMixTitle: 'Микс по жанру', - genreMixDesc: 'Топ-20 жанров по числу треков — нажмите, чтобы собрать микс', - genreMixAll: 'Все треки', - genreMixLoadMore: 'Ещё 10 жанров', - genreMixNoGenres: 'На сервере нет данных о жанрах.', - shuffleGenres: 'Другие жанры', - filterPanelTitle: 'Фильтры', - filterPanelDesc: - 'Нажмите на тег жанра или имя исполнителя в списке ниже, чтобы исключить их из будущих миксов.', - genreClickHint: - 'Нажмите на тег жанра — слово попадёт в фильтр.\nУчитываются жанр, название, альбом и исполнитель.', - }, - luckyMix: { - done: '«Мне повезёт» готово: {{count}} треков', - failed: 'Не удалось собрать микс «Мне повезёт». Попробуйте ещё раз.', - unavailable: '«Мне повезёт» недоступен на этом сервере.', - cancelTooltip: 'Отменить сборку микса «Мне повезёт»', - }, - albums: { - title: 'Все альбомы', - sortByName: 'А–Я (альбом)', - sortByArtist: 'А–Я (исполнитель)', - sortNewest: 'Сначала новые', - sortRandom: 'Случайно', - yearFrom: 'С', - yearTo: 'По', - yearFilterClear: 'Сбросить год', - yearFilterLabel: 'Год', - compilationLabel: 'Сборники', - compilationOnly: 'Только сборники', - compilationHide: 'Скрыть сборники', - compilationTooltipAll: 'Все альбомы · клик: только сборники', - compilationTooltipOnly: 'Только сборники · клик: скрыть сборники', - compilationTooltipHide: 'Сборники скрыты · клик: показать всё', - select: 'Множественный выбор', - startSelect: 'Включить множественный выбор', - cancelSelect: 'Отмена', - selectionCount: '{{count}} выбрано', - downloadZips: 'Скачать ZIP-архивы', - addOffline: 'Добавить офлайн', - enqueueSelected_one: 'В очередь ({{count}})', - enqueueSelected_few: 'В очередь ({{count}})', - enqueueSelected_many: 'В очередь ({{count}})', - enqueueSelected_other: 'В очередь ({{count}})', - enqueueQueued_one: '{{count}} альбом добавлен в очередь', - enqueueQueued_few: '{{count}} альбома добавлены в очередь', - enqueueQueued_many: '{{count}} альбомов добавлены в очередь', - enqueueQueued_other: '{{count}} альбомов добавлены в очередь', - downloadingZip: 'Загрузка {{current}}/{{total}}: {{name}}', - downloadZipDone: '{{count}} ZIP-архив(ов) загружено', - downloadZipFailed: 'Не удалось скачать {{name}}', - offlineQueuing: 'Добавление {{count}} альбом(ов) в офлайн…', - offlineFailed: 'Не удалось добавить {{name}} офлайн', - }, - tracks: { - title: 'Треки', - subtitle: 'Листать. Искать. Открывать.', - heroEyebrow: 'Трек момента', - heroReroll: 'Выбрать другой', - playSong: 'Воспроизвести', - enqueueSong: 'В очередь', - railRandom: 'Случайная подборка', - railHighlyRated: 'Высоко оценённые', - browseTitle: 'Просмотреть все треки', - browseUnsupported: 'Этот сервер не возвращает всю библиотеку сразу. Воспользуйтесь поиском выше, чтобы найти конкретные треки.', - searchPlaceholder: 'Найти трек по названию, исполнителю или альбому…', - count_one: '{{count}} трек', - count_few: '{{count}} трека', - count_many: '{{count}} треков', - count_other: '{{count}} треков', - }, - artists: { - title: 'Исполнители', - search: 'Поиск…', - all: 'Все', - gridView: 'Сетка', - listView: 'Список', - imagesOn: 'Фото исполнителей — больше трафика и нагрузка на систему', - imagesOff: 'Только инициалы — экономнее по трафику', - loadMore: 'Ещё', - notFound: 'Исполнители не найдены.', - albumCount_one: '{{count}} альбом', - albumCount_few: '{{count}} альбома', - albumCount_many: '{{count}} альбомов', - albumCount_other: '{{count}} альбомов', - selectionCount: '{{count}} выбрано', - select: 'Множественный выбор', - startSelect: 'Включить множественный выбор', - cancelSelect: 'Отмена', - addToPlaylist: 'В плейлист', - }, - composers: { - title: 'Композиторы', - search: 'Поиск…', - notFound: 'Композиторы не найдены.', - unsupported: 'Просмотр по композиторам требует Navidrome 0.55 или новее.', - loadFailed: 'Не удалось загрузить композиторов.', - retry: 'Повторить', - involvedIn_one: 'Участие в {{count}} альбоме', - involvedIn_other: 'Участие в {{count}} альбомах', - }, - composerDetail: { - back: 'Назад', - notFound: 'Композитор не найден.', - about: 'Об этом композиторе', - works: 'Произведения', - noWorks: 'Произведения не найдены.', - workCount_one: '{{count}} произведение', - workCount_other: '{{count}} произведений', - shareComposer: 'Поделиться композитором', - unknownComposer: 'Композитор', - }, - login: { - subtitle: 'Десктопный клиент для Navidrome', - serverName: 'Название сервера (необязательно)', - serverNamePlaceholder: 'Мой Navidrome', - serverUrl: 'Адрес сервера', - serverUrlPlaceholder: '192.168.1.100:4533 или https://music.example.com', - username: 'Логин', - usernamePlaceholder: 'admin', - password: 'Пароль', - showPassword: 'Показать пароль', - hidePassword: 'Скрыть пароль', - connect: 'Подключиться', - connecting: 'Подключение…', - connected: 'Готово!', - error: 'Не удалось подключиться — проверьте данные.', - urlRequired: 'Укажите адрес сервера.', - savedServers: 'Сохранённые серверы', - addNew: 'Или добавить новый сервер', - orMagicString: 'Или magic string', - magicStringPlaceholder: 'Вставьте строку приглашения (psysonic1-…)', - magicStringInvalid: 'Неверная или нечитаемая magic string.', - }, - connection: { - connected: 'Подключено', - connectedTo: 'Сервер: {{server}}', - disconnected: 'Нет связи', - disconnectedFrom: 'Сервер {{server}} недоступен — нажмите для настроек', - checking: 'Подключение…', - extern: 'Внешний', - offlineTitle: 'Нет связи с сервером', - offlineSubtitle: 'Сервер {{server}} недоступен. Проверьте сеть и адрес.', - offlineModeBanner: 'Офлайн — воспроизведение из локального кэша', - offlineNoCacheBanner: 'Нет соединения с сервером — {{server}} недоступен', - offlineLibraryTitle: 'Офлайн-библиотека', - offlineLibraryEmpty: - 'Пока ничего не сохранено. Подключитесь к сети, откройте альбом и нажмите «Сохранить офлайн».', - offlineAlbumCount_one: '{{n}} альбом', - offlineAlbumCount_few: '{{n}} альбома', - offlineAlbumCount_many: '{{n}} альбомов', - offlineAlbumCount_other: '{{n}} альбомов', - offlineFilterAll: 'Всё', - offlineFilterAlbums: 'Альбомы', - offlineFilterPlaylists: 'Плейлисты', - offlineFilterArtists: 'Дискографии', - retry: 'Повторить', - serverSettings: 'Настройки сервера', - switchServerTitle: 'Сменить сервер', - switchServerHint: 'Нажмите, чтобы выбрать другой сохранённый сервер.', - manageServers: 'Управление серверами…', - switchFailed: 'Не удалось переключиться — сервер недоступен.', - lastfmConnected: 'Last.fm: @{{user}}', - lastfmSessionInvalid: 'Сессия недействительна — подключите снова', - }, - common: { - albums: 'Альбомы', - album: 'Альбом', - loading: 'Загрузка…', - loadingMore: 'Загрузка…', - loadingPlaylists: 'Загрузка плейлистов…', - noAlbums: 'Альбомов нет.', - downloading: 'Скачивание…', - downloadZip: 'Скачать (ZIP)', - back: 'Назад', - cancel: 'Отмена', - save: 'Сохранить', - delete: 'Удалить', - use: 'Использовать', - add: 'Добавить', - new: 'Новое', - active: 'Активен', - download: 'Скачать', - chooseDownloadFolder: 'Выбрать папку', - noFolderSelected: 'Папка не выбрана', - rememberDownloadFolder: 'Запомнить папку', - filterGenre: 'Фильтр по жанру', - filterSearchGenres: 'Поиск жанров…', - filterNoGenres: 'Нет совпадений', - filterClear: 'Сбросить', - favorites: 'Избранное', - favoritesTooltipOff: 'Показывать только избранное', - favoritesTooltipOn: 'Показать всё', - play: 'Воспроизвести', - bulkSelected: 'Выбрано: {{count}}', - clearSelection: 'Сбросить выбор', - bulkAddToPlaylist: 'В плейлист', - bulkRemoveFromPlaylist: 'Убрать из плейлиста', - bulkClear: 'Снять выделение', - updaterAvailable: 'Доступно обновление', - updaterVersion: 'Версия {{version}} доступна', - updaterWebsite: 'Сайт', - updaterModalTitle: 'Доступна новая версия', - updaterChangelog: 'Что нового', - updaterDownloadBtn: 'Скачать сейчас', - updaterSkipBtn: 'Пропустить эту версию', - updaterRemindBtn: 'Напомнить позже', - updaterDone: 'Загрузка завершена', - updaterShowFolder: 'Показать в папке', - updaterInstallHint: 'Закройте Psysonic и запустите установщик вручную.', - updaterAurHint: 'Установить обновление через AUR:', - updaterErrorMsg: 'Ошибка загрузки', - updaterRetryBtn: 'Повторить', - durationHoursMinutes: '{{hours}}ч {{minutes}}мин', - durationMinutesOnly: '{{minutes}}мин', - updaterOpenGitHub: 'Открыть на GitHub', - filters: 'Фильтры', - more: 'еще', - yearRange: 'Диапазон лет', - clearAll: 'Очистить всё', - }, - settings: { - title: 'Настройки', - language: 'Язык', - languageEn: 'English', - languageDe: 'Deutsch', - languageEs: 'Español', - languageFr: 'Français', - languageNl: 'Nederlands', - languageNb: 'Norsk', - languageRu: 'Русский', - languageZh: '中文', - languageRo: 'Română', - font: 'Шрифт', - fontHintOpenDyslexic: 'Подходит для дислексии · без поддержки китайского', - theme: 'Тема', - appearance: 'Оформление', - servers: 'Серверы', - serverName: 'Название', - serverUrl: 'Адрес', - serverUrlPlaceholder: '192.168.1.100:4533 или https://music.example.com', - serverUsername: 'Логин', - serverPassword: 'Пароль', - addServer: 'Добавить сервер', - addServerTitle: 'Новый сервер', - useServer: 'Выбрать', - deleteServer: 'Удалить', - noServers: 'Нет сохранённых серверов.', - serverActive: 'Активен', - confirmDeleteServer: 'Удалить сервер «{{name}}»?', - serverConnecting: 'Подключение…', - serverConnected: 'Подключено!', - serverFailed: 'Ошибка подключения.', - testBtn: 'Проверить', - testingBtn: 'Проверка…', - serverCompatible: 'Разработано для Navidrome. Другие Subsonic-совместимые серверы (Gonic, Airsonic, …) могут работать с ограничениями, так как Psysonic использует много специфичных для Navidrome API-эндпоинтов.', - userMgmtTitle: 'Управление пользователями', - userMgmtDesc: 'Управляйте пользователями этого сервера. Требуются права администратора.', - userMgmtNoAdmin: 'Для управления пользователями на этом сервере нужны права администратора.', - userMgmtLoadError: 'Не удалось загрузить пользователей.', - userMgmtLoadFriendly: 'Сервер не ответил — обычно разовая ошибка.', - userMgmtRetry: 'Повторить', - userMgmtEmpty: 'Пользователи не найдены.', - userMgmtYouBadge: 'Вы', - userMgmtAdminBadge: 'Админ', - userMgmtAddUser: 'Добавить пользователя', - userMgmtAddUserTitle: 'Новый пользователь', - userMgmtEditUserTitle: 'Изменить пользователя', - userMgmtUsername: 'Имя пользователя', - userMgmtName: 'Отображаемое имя', - userMgmtEmail: 'E-mail', - userMgmtPassword: 'Пароль', - userMgmtPasswordEditHint: 'Введите новый пароль, чтобы изменить его.', - userMgmtRoleAdmin: 'Админ', - userMgmtLibraries: 'Библиотеки', - userMgmtLibrariesAdminHint: 'Администраторы автоматически имеют доступ ко всем библиотекам.', - userMgmtLibrariesEmpty: 'На этом сервере нет доступных библиотек.', - userMgmtLibrariesValidation: 'Выберите хотя бы одну библиотеку.', - userMgmtLibrariesUpdateError: 'Пользователь сохранён, но не удалось назначить библиотеки', - userMgmtNoLibraries: 'Библиотеки не назначены', - userMgmtNeverSeen: 'Никогда', - userMgmtSave: 'Сохранить', - userMgmtCancel: 'Отмена', - userMgmtDelete: 'Удалить', - userMgmtEdit: 'Изменить', - userMgmtConfirmDelete: 'Удалить пользователя «{{username}}»? Действие нельзя отменить.', - userMgmtCreateError: 'Не удалось создать пользователя.', - userMgmtUpdateError: 'Не удалось обновить пользователя.', - userMgmtDeleteError: 'Не удалось удалить пользователя.', - userMgmtCreated: 'Пользователь создан.', - userMgmtUpdated: 'Пользователь обновлён.', - userMgmtDeleted: 'Пользователь удалён.', - userMgmtValidationMissing: 'Требуются имя пользователя, отображаемое имя и пароль.', - userMgmtValidationMissingIdentity: 'Укажите имя пользователя и отображаемое имя.', - userMgmtMagicStringGenerate: 'Сгенерировать magic string', - userMgmtSaveAndMagicString: 'Сохранить и получить magic string', - userMgmtMagicStringPasswordNavHint: - 'Navidrome сохранит этот пароль для пользователя. Если он не совпадает с текущим, на сервере будет установлен новый пароль входа.', - userMgmtMagicStringPlaintextWarning: - 'Передавайте magic string осторожно: в ней пароль в открытом виде (кодирование — не шифрование). У кого есть полная строка, тот может войти под этим пользователем.', - userMgmtMagicStringCopied: 'Magic string скопирован в буфер обмена.', - userMgmtMagicStringCopyFailed: 'Не удалось скопировать в буфер обмена.', - userMgmtMagicStringLoginFailed: 'Пароль не подошёл — не удалось проверить учётные данные.', - userMgmtMagicStringModalTitle: 'Сгенерировать magic string', - userMgmtMagicStringModalDesc: 'Введите пароль Subsonic для «{{username}}» — он попадёт в копируемую magic string.', - userMgmtMagicStringModalConfirm: 'Скопировать строку', - audiomuseTitle: 'AudioMuse-AI (Navidrome)', - audiomuseDesc: - 'Включите, если на этом сервере настроен плагин AudioMuse-AI для Navidrome. Появится Instant Mix для треков, а на странице исполнителя похожие будут браться с сервера вместо Last.fm.', - audiomuseIssueHint: - 'Недавно не удалось собрать Instant Mix — проверьте плагин Navidrome и API AudioMuse. Похожие исполнители подтянутся с Last.fm, если сервер ничего не вернёт.', - connected: 'Подключено', - failed: 'Ошибка', - eqTitle: 'Эквалайзер', - eqEnabled: 'Включить эквалайзер', - eqPreset: 'Пресет', - eqPresetCustom: 'Свой', - eqPresetBuiltin: 'Встроенные', - eqPresetCustomGroup: 'Мои пресеты', - eqSavePreset: 'Сохранить как пресет', - eqPresetName: 'Название пресета…', - eqDeletePreset: 'Удалить пресет', - eqResetBands: 'Сбросить полосы', - eqPreGain: 'Предусиление', - eqResetPreGain: 'Сбросить предусиление', - eqAutoEqTitle: 'AutoEQ — поиск профиля наушников', - eqAutoEqPlaceholder: 'Модель наушников или IEM…', - eqAutoEqSearching: 'Поиск…', - eqAutoEqNoResults: 'Ничего не найдено', - eqAutoEqError: 'Ошибка поиска', - eqAutoEqRateLimit: 'Лимит GitHub — попробуйте через минуту', - eqAutoEqFetchError: 'Не удалось загрузить профиль EQ', - lfmTitle: 'Last.fm', - lfmConnect: 'Подключить Last.fm', - lfmConnecting: 'Ожидание авторизации…', - lfmConfirm: 'Я разрешил доступ', - lfmConnected: 'Аккаунт', - lfmDisconnect: 'Отключить', - lfmConnectDesc: - 'Привяжите Last.fm для скробблинга и статуса «Сейчас слушаю» прямо из Psysonic — настраивать Navidrome не нужно.', - lfmOpenBrowser: 'Откроется браузер. Разрешите доступ на Last.fm, затем нажмите кнопку ниже.', - lfmScrobbles: 'Скробблов: {{n}}', - lfmMemberSince: 'С {{year}} года', - scrobbleEnabled: 'Скробблинг включён', - scrobbleDesc: 'Отправлять прослушивания на Last.fm после 50% трека', - behavior: 'Поведение', - cacheTitle: 'Макс. размер кэша', - cacheDesc: - 'Обложки и фото исполнителей. При переполнении старые записи удаляются. Офлайн-альбомы не трогаются автоматически, но сотрутся при полной очистке кэша.', - cacheUsedImages: 'Изображения:', - cacheUsedOffline: 'Офлайн-треки:', - cacheUsedHot: 'На диске:', - hotCacheTrackCount: 'Треков в кэше:', - cacheMaxLabel: 'Лимит', - cacheClearBtn: 'Очистить кэш', - waveformCacheClearBtn: 'Очистить кэш waveform', - cacheClearWarning: 'Будут удалены и все офлайн-альбомы.', - cacheClearConfirm: 'Очистить всё', - cacheClearCancel: 'Отмена', - waveformCacheCleared: 'Кэш waveform очищен ({{count}} строк).', - waveformCacheClearFailed: 'Не удалось очистить кэш waveform.', - offlineDirTitle: 'Офлайн-библиотека (в приложении)', - offlineDirDesc: 'Папка для треков, сохранённых для офлайн-прослушивания.', - offlineDirDefault: 'По умолчанию (данные приложения)', - offlineDirChange: 'Сменить папку', - offlineDirClear: 'Сбросить по умолчанию', - offlineDirHint: 'Новые загрузки пойдут в выбранную папку. Старые останутся на прежнем месте.', - hotCacheTitle: 'Горячий кэш воспроизведения', - hotCacheDisclaimer: 'Заранее подгружает следующие треки из очереди и сохраняет предыдущие. При включении использует место на диске и сеть.', - hotCacheDirDefault: 'По умолчанию (данные приложения)', - hotCacheDirChange: 'Сменить папку', - hotCacheDirClear: 'Сбросить по умолчанию', - hotCacheDirHint: 'При смене папки сбрасывается список в приложении; уже скачанные файлы остаются на старом пути, пока вы их не удалите.', - hotCacheEnabled: 'Включить горячий кэш воспроизведения', - hotCacheMaxMb: 'Максимальный размер кэша', - hotCacheDebounce: 'Задержка после изменения очереди', - hotCacheDebounceImmediate: 'Сразу', - hotCacheDebounceSeconds: '{{n}} с', - hotCacheClearBtn: 'Очистить горячий кэш', - audioOutputDevice: 'Устройство вывода звука', - audioOutputDeviceDesc: 'Выберите аудиоустройство для воспроизведения. Изменения применяются немедленно и перезапускают текущий трек.', - audioOutputDeviceDefault: 'Системное по умолчанию', - audioOutputDeviceRefresh: 'Обновить список устройств', - audioOutputDeviceOsDefaultNow: 'текущий системный вывод', - audioOutputDeviceListError: 'Не удалось загрузить список аудиоустройств.', - audioOutputDeviceNotInCurrentList: 'нет в текущем списке', - audioOutputDeviceMacNotice: 'В macOS воспроизведение в настоящее время всегда следует за системным устройством вывода по техническим причинам. Измените цель через Системные настройки → Звук или значок динамика в строке меню. Причина: CoreAudio запрашивает разрешение на использование микрофона при открытии не-стандартного потока — мы избегаем этого, всегда используя системный вывод по умолчанию.', - hiResTitle: 'Нативное воспроизведение Hi-Res', - hiResEnabled: 'Включить нативное Hi-Res воспроизведение', - hiResDesc: "По умолчанию вывод ограничен до 44,1 кГц для максимальной стабильности. Включайте только если оборудование и сеть надёжно поддерживают высокие частоты (88,2 кГц+).", - showArtistImages: 'Фото исполнителей', - showArtistImagesDesc: - 'Показывать обложки в разделе «Исполнители». По умолчанию выключено — меньше нагрузки на диск и сеть.', - showOrbitTrigger: 'Показывать «Orbit» в шапке', - showOrbitTriggerDesc: 'Кнопка в шапке для запуска или присоединения к совместной сессии. Скрой, если не используешь Orbit — здесь же можно включить обратно.', - showTrayIcon: 'Иконка в трее', - showTrayIconDesc: 'Показывать Psysonic в области уведомлений / строке меню.', - minimizeToTray: 'Сворачивать в трей', - minimizeToTrayDesc: 'При закрытии окна не выходить из приложения, а оставаться в трее.', - preloadMiniPlayer: 'Предзагрузка мини-плеера', - preloadMiniPlayerDesc: 'Создаёт окно мини-плеера в фоне при запуске приложения, чтобы при первом открытии содержимое отображалось мгновенно. Использует немного больше памяти.', - useCustomTitlebar: 'Своя строка заголовка', - useCustomTitlebarDesc: - 'Заменить системную строку заголовка встроенной, в стиле темы приложения. Отключите, чтобы использовать родную строку GNOME/GTK и т.д.', - linuxWebkitSmoothScroll: 'Плавное колесо (Linux)', - linuxWebkitSmoothScrollDesc: 'Вкл — инерция. Выкл — по шагам, как в GTK.', - discordRichPresence: 'Статус в Discord', - discordRichPresenceDesc: - 'Показывать текущий трек в профиле и статусе Discord. Нужен запущенный клиент Discord.', - discordCoverSource: 'Источник обложки', - discordCoverSourceDesc: 'Откуда загружать обложку альбома для профиля Discord.', - discordCoverNone: 'Нет (только иконка приложения)', - discordCoverServer: 'Сервер (через информацию об альбоме)', - discordCoverApple: 'Apple Music', - discordOptions: 'Расширенные параметры Discord', - discordTemplates: 'Пользовательские шаблоны текста', - discordTemplatesDesc: 'Настройте, какая информация отображается в профиле Discord. Переменные: {title}, {artist}, {album}', - discordTemplateDetails: 'Основная строка (details)', - discordTemplateState: 'Вторичная строка (state)', - discordTemplateLargeText: 'Подсказка альбома (largeText)', - nowPlayingEnabled: 'Показывать в «Сейчас играет»', - nowPlayingEnabledDesc: - 'Отправлять на сервер, что вы сейчас слушаете. Отключите, чтобы не делиться этим.', - enableBandsintown: 'Даты туров Bandsintown', - enableBandsintownDesc: 'Показывает предстоящие концерты текущего исполнителя на вкладке «Инфо». Данные берутся из публичного API Bandsintown.', - lyricsServerFirst: 'Предпочитать тексты с сервера', - lyricsServerFirstDesc: 'Проверять тексты песен, предоставленные сервером (встроенные теги, sidecar-файлы) перед запросом LRCLIB. Отключите, чтобы сначала использовать LRCLIB.', - enableNeteaselyrics: 'Тексты из Netease Cloud Music', - enableNeteaselyricsDesc: 'Использовать Netease Cloud Music как последний источник текстов, когда остальные способы не находят ничего. Лучшее покрытие для азиатской и международной музыки.', - lyricsSourcesTitle: 'Источники текстов', - lyricsSourcesDesc: 'Выберите источники для поиска текстов и их порядок. Перетаскивайте для сортировки. Отключённые источники пропускаются.', - lyricsSourceServer: 'Сервер', - lyricsSourceLrclib: 'LRCLIB', - lyricsSourceNetease: 'Netease Cloud Music', - lyricsModeStandard: 'Стандарт', - lyricsModeStandardDesc: 'Три источника в свободно настраиваемом порядке: серверные теги, LRCLIB, Netease.', - lyricsModeLyricsplus: 'YouLyPlus (Караоке)', - lyricsModeLyricsplusDesc: 'Синхронизация слово-в-слово из Apple Music, Spotify, Musixmatch и QQ (общественный бэкенд). При отсутствии результата незаметно возвращается к стандартным источникам.', - lyricsStaticOnly: 'Показывать текст статично', - lyricsStaticOnlyDesc: 'Синхронизированный текст отображается без авто-прокрутки и подсветки слов.', - downloadsTitle: 'Экспорт ZIP и архивов', - downloadsFolderDesc: 'Куда сохранять альбомы в ZIP архиве на диск.', - downloadsDefault: 'Папка «Загрузки» по умолчанию', - pickFolder: 'Выбрать', - pickFolderTitle: 'Папка для загрузок', - clearFolder: 'Сбросить папку', - logout: 'Выйти', - aboutTitle: 'О Psysonic', - aboutDesc: - 'Современный десктопный плеер, созданный для Navidrome. Использует API Subsonic плюс специфичные для Navidrome расширения. На Tauri v2 и нативном аудиодвижке на Rust — лёгкий и быстрый: волновая шкала, синхронные тексты, Last.fm, 10-полосный EQ, кроссфейд, воспроизведение без пауз, Replay Gain, жанры и много тем оформления.', - aboutLicense: 'Лицензия', - aboutLicenseText: 'GNU GPL v3 — свободное использование и изменение на тех же условиях.', - aboutRepo: 'Исходный код на GitHub', - aboutVersion: 'Версия', - aboutBuiltWith: 'Tauri · React · TypeScript · Rust/rodio', - aboutReleaseNotesLabel: 'Примечания к выпуску', - aboutReleaseNotesLink: 'Открыть «Что нового» этой версии', - aboutContributorsLabel: 'Участники', - showChangelogOnUpdate: 'Показывать «Что нового» после обновления', - showChangelogOnUpdateDesc: 'После обновления над «Сейчас играет» появится ненавязчивый баннер журнала изменений. Клик открывает заметки о выпуске, X скрывает.', - randomMixTitle: 'Чёрный список случайного микса', - luckyMixMenuTitle: 'Показывать «Мне повезёт» в меню', - luckyMixMenuDesc: - 'Включает «Мне повезёт» в «Собрать микс», а при раздельной навигации — отдельным пунктом меню. Видно только при включённом AudioMuse на активном сервере.', - randomMixBlacklistTitle: 'Свои слова-фильтры', - randomMixBlacklistDesc: - 'Треки скрываются, если слово встречается в жанре, названии, альбоме или исполнителе (когда включён фильтр выше).', - randomMixBlacklistPlaceholder: 'Добавить слово…', - randomMixBlacklistAdd: 'Добавить', - randomMixBlacklistEmpty: 'Пока пусто.', - randomMixHardcodedTitle: 'Встроенные слова (при включённом фильтре)', - tabAudio: 'Звук', - tabStorage: 'Офлайн и кэш', - tabAppearance: 'Внешний вид', - tabLibrary: 'Библиотека', - tabServers: 'Серверы', - tabLyrics: 'Тексты песен', - tabPersonalisation: 'Персонализация', - tabIntegrations: 'Интеграции', - inputKeybindingsTitle: 'Горячие клавиши', - aboutContributorsCount_one: '{{count}} вклад', - aboutContributorsCount_few: '{{count}} вклада', - aboutContributorsCount_many: '{{count}} вкладов', - aboutContributorsCount_other: '{{count}} вклада', - searchPlaceholder: 'Поиск в настройках…', - searchNoResults: 'Ничего не найдено по вашему запросу.', - aboutMaintainersLabel: 'Сопровождающие', - integrationsPrivacyTitle: 'Уведомление о конфиденциальности', - integrationsPrivacyBody: 'Все интеграции на этой вкладке включаются по желанию и при активации отправляют данные во внешние сервисы или на ваш сервер Navidrome. Last.fm получает вашу историю прослушивания, Discord показывает текущую композицию в вашем профиле, Bandsintown опрашивается по артисту для получения дат гастролей, а «Сейчас играет» делится текущей композицией с другими пользователями вашего сервера Navidrome. Если вы не хотите ничего из этого, просто оставьте соответствующий раздел отключённым.', - homeCustomizerTitle: 'Главная', - queueToolbarTitle: 'Панель инструментов очереди', - queueToolbarReset: 'Сбросить', - queueToolbarSeparator: 'Разделитель', - sidebarTitle: 'Боковая панель', - sidebarReset: 'Сбросить порядок', - artistLayoutTitle: 'Разделы страницы исполнителя', - artistLayoutDesc: 'Перетаскивайте, чтобы изменить порядок, переключайте, чтобы скрыть отдельные разделы страницы исполнителя. Разделы без данных пропускаются автоматически.', - artistLayoutReset: 'Сбросить', - artistLayoutBio: 'Биография исполнителя', - artistLayoutTopTracks: 'Топ-треки', - artistLayoutSimilar: 'Похожие исполнители', - artistLayoutAlbums: 'Альбомы', - artistLayoutFeatured: 'Также участвует в', - sidebarDrag: 'Перетащите для порядка', - sidebarFixed: 'Всегда показывать', - randomNavSplitTitle: 'Разделить навигацию микса', - randomNavSplitDesc: - 'Показывать «Случайный микс», «Случайные альбомы» и «Мне повезёт» как отдельные пункты боковой панели вместо хаба «Собрать микс».', - tabInput: 'Ввод', - tabUsers: 'Пользователи', - tabSystem: 'Система', - loggingTitle: 'Логирование', - loggingModeDesc: 'Управляет подробностью логов backend в терминале.', - loggingModeOff: 'Выключено', - loggingModeNormal: 'Обычное', - loggingModeDebug: 'Дебаг', - loggingExport: 'Экспорт логов', - loggingExportSuccess: 'Логи экспортированы ({{count}} строк).', - loggingExportError: 'Не удалось экспортировать логи.', - ratingsSectionTitle: 'Рейтинги', - ratingsSkipStarTitle: 'Скипнуть для 1 звезды', - ratingsSkipStarDesc: - 'При N скипов подряд ставить 1★ треку. Только для не оцененных ранее.', - ratingsSkipStarThresholdLabel: 'Скипов', - ratingsMixFilterTitle: 'Фильтрация по рейтингу', - ratingsMixFilterDesc: - 'Фильтровать с низким рейтингом в «{{mix}}» и «{{albums}}». Повторный клик по выбранной звезде отключает порог.', - ratingsMixMinSong: 'Песни', - ratingsMixMinAlbum: 'Альбомы', - ratingsMixMinArtist: 'Исполнители', - ratingsMixMinThresholdAria: 'Минимум звёзд: {{label}}', - backupTitle: 'Резервная копия', - backupExport: 'Экспорт настроек', - backupExportDesc: - 'Сохраняет настройки, серверы, Last.fm, тему, EQ и горячие клавиши в файл .psybkp. Пароли в открытом виде — храните файл в безопасности.', - backupImport: 'Импорт настроек', - backupImportDesc: 'Восстановить из .psybkp. Приложение перезапустится.', - backupImportConfirm: 'Текущие настройки будут заменены. Продолжить?', - backupSuccess: 'Копия сохранена', - backupImportSuccess: 'Настройки восстановлены — перезапуск…', - backupImportError: 'Файл повреждён или не подходит.', - shortcutsReset: 'Сбросить', - shortcutListening: 'Нажмите клавишу…', - shortcutUnbound: '—', - globalShortcutsTitle: 'Глобальные сочетания', - globalShortcutsNote: - 'Работают, когда окно не в фокусе. Нужен модификатор: Ctrl, Alt или Super.', - shortcutClear: 'Сбросить', - shortcutPlayPause: 'Пауза / воспроизведение', - shortcutNext: 'Следующий трек', - shortcutPrev: 'Предыдущий трек', - shortcutVolumeUp: 'Громче', - shortcutVolumeDown: 'Тише', - shortcutSeekForward: 'Вперёд на 10 с', - shortcutSeekBackward: 'Назад на 10 с', - shortcutToggleQueue: 'Показать / скрыть очередь', - shortcutOpenFolderBrowser: 'Открыть {{folderBrowser}}', - shortcutFullscreenPlayer: 'Полноэкранный плеер', - shortcutNativeFullscreen: 'Системный полный экран', - shortcutOpenMiniPlayer: 'Открыть мини-плеер', - shortcutStartSearch: 'Начать поиск', - shortcutStartAdvancedSearch: 'Начать расширенный поиск', - shortcutToggleSidebar: 'Переключить боковую панель', - shortcutMuteSound: 'Без звука', - shortcutToggleEqualizer: 'Открыть / переключить эквалайзер', - shortcutToggleRepeat: 'Переключить повтор', - shortcutOpenNowPlaying: 'Открыть «Сейчас играет»', - shortcutShowLyrics: 'Показать текст песни', - shortcutFavoriteCurrentTrack: 'Добавить текущий трек в избранное', - shortcutOpenHelp: 'Справка', - playbackTitle: 'Воспроизведение', - replayGain: 'Replay Gain', - replayGainDesc: 'Выравнивание громкости по метаданным ReplayGain', - replayGainMode: 'Режим', - replayGainAuto: 'Авто', - replayGainAutoDesc: 'Использует громкость альбома, когда соседние треки в очереди из того же альбома, иначе громкость трека.', - replayGainTrack: 'По треку', - replayGainAlbum: 'По альбому', - replayGainPreGain: 'Предусиление (файлы с тегами)', - replayGainPreGainDesc: 'Общая прибавка, добавляемая к каждому расчёту ReplayGain. Удобно, если библиотека в целом кажется тихой.', - replayGainFallback: 'Резерв (без тегов / радио)', - replayGainFallbackDesc: 'Применяется к трекам (и радиопотокам) без тегов ReplayGain, чтобы непомеченный контент не звучал громче остального.', - normalization: 'Нормализация', - normalizationDesc: 'Выровнять воспринимаемую громкость между треками, альбомами и радио.', - normalizationOff: 'Выкл.', - normalizationReplayGain: 'ReplayGain', - normalizationLufs: 'LUFS', - loudnessTargetLufs: 'Целевой LUFS', - loudnessTargetLufsDesc: 'Опорная громкость, к которой подгоняются все треки. Меньше число = громче на выходе. Стриминг-сервисы обычно держат около -14 LUFS.', - loudnessPreAnalysisAttenuation: 'Ослабление до измерения', - loudnessPreAnalysisAttenuationDesc: - 'Насколько приглушить звук, пока для трека нет сохранённого измерения громкости. При стриме дальше идут лишь грубые оценки, не полный LUFS. 0 dB — без дополнительного приглушения; ниже — тише. Справа показывается фактическая поправка для текущей цели.', - loudnessPreAnalysisAttenuationRef: 'Фактически {{eff}} dB при цели {{tgt}} LUFS.', - loudnessPreAnalysisAttenuationReset: 'По умолчанию', - loudnessFirstPlayNote: - 'При первом прослушивании нового трека громкость может ненадолго колебаться, пока идёт измерение. Со второго раза применяется уже сохранённое значение и всё стабильно. Следующие треки в очереди обычно анализируются во время предыдущей композиции, поэтому на практике это случается редко.', - crossfade: 'Кроссфейд', - crossfadeDesc: 'Плавный переход между треками', - crossfadeSecs: '{{n}} с', - notWithGapless: 'Недоступно при включённом режиме без пауз', - notWithCrossfade: 'Недоступно при включённом кроссфейде', - gapless: 'Без пауз между треками', - gaplessDesc: 'Заранее подгружать следующий трек, чтобы не было тишины', - preservePlayNextOrder: 'Сохранять порядок «Играть следующим»', - preservePlayNextOrderDesc: 'Новые элементы «Играть следующим» становятся в конец очереди, а не лезут вперёд.', - trackPreviewsTitle: 'Превью треков', - trackPreviewsToggle: 'Включить превью треков', - trackPreviewsDesc: 'Показывать встроенные кнопки воспроизведения и превью в списках треков для быстрого прослушивания фрагмента.', - trackPreviewStart: 'Начальная позиция', - trackPreviewStartDesc: 'С какого момента трека начинается превью (% от длительности).', - trackPreviewDuration: 'Длительность', - trackPreviewDurationDesc: 'Сколько играет каждое превью до автоматической остановки.', - trackPreviewDurationSecs: '{{n}} с', - trackPreviewLocationsTitle: 'Где показывать превью', - trackPreviewLocationsDesc: 'Выберите, в каких списках показывать кнопки превью.', - trackPreviewLocation_suggestions: 'В предложениях плейлиста', - trackPreviewLocation_albums: 'В списках треков альбома', - trackPreviewLocation_playlists: 'В плейлистах', - trackPreviewLocation_favorites: 'В избранном', - trackPreviewLocation_artist: 'В топ-треках исполнителя', - trackPreviewLocation_randomMix: 'В Random Mix', - preloadMode: 'Предзагрузка следующего трека', - preloadModeDesc: 'Когда начинать буферизацию следующего в очереди', - nextTrackBufferingTitle: 'Буферизация', - preloadHotCacheMutualExclusive: 'Предзагрузка и Hot Cache выполняют одну функцию — одновременно может быть активна только одна. Включение одной автоматически отключает другую.', - preloadOff: 'Выкл.', - preloadBalanced: 'Умеренно (за 30 с до конца)', - preloadEarly: 'Рано (через 5 с после старта)', - preloadCustom: 'Свой интервал', - preloadCustomSeconds: 'Секунд до конца: {{n}}', - infiniteQueue: 'Бесконечная очередь', - infiniteQueueDesc: 'Подмешивать случайные треки, когда очередь закончится', - experimental: 'Экспериментально', - fsPlayerSection: 'Полноэкранный плеер', - fsShowArtistPortrait: 'Отображать фото артиста', - fsShowArtistPortraitDesc: 'Показывать фото артиста (или обложку альбома) в правой части полноэкранного плеера.', - fsPortraitDim: 'Затемнение фото', - fsLyricsStyle: 'Стиль отображения текста', - fsLyricsStyleRail: 'Рельс', - fsLyricsStyleRailDesc: 'Классическая рамка из 5 строк.', - fsLyricsStyleApple: 'Прокрутка', - fsLyricsStyleAppleDesc: 'Полноэкранный список с прокруткой.', - sidebarLyricsStyle: 'Стиль прокрутки текста', - sidebarLyricsStyleClassic: 'Классический', - sidebarLyricsStyleClassicDesc: 'Активная строка центрируется.', - sidebarLyricsStyleApple: 'Apple Music-like', - sidebarLyricsStyleAppleDesc: 'Активная строка фиксируется сверху с плавной анимацией.', - seekbarStyle: 'Стиль прогресс-бара', - seekbarStyleDesc: 'Выбор внешнего вида полосы воспроизведения', - seekbarTruewave: 'Реальная форма волны', - seekbarPseudowave: 'Псевдо форма волны', - seekbarLinedot: 'Линия и точка', - seekbarBar: 'Полоса', - seekbarThick: 'Толстая полоса', - seekbarSegmented: 'Сегменты', - seekbarNeon: 'Неон', - seekbarPulsewave: 'Пульс-волна', - seekbarParticletrail: 'Частицы', - seekbarLiquidfill: 'Жидкость', - seekbarRetrotape: 'Ретро-лента', - themeSchedulerTitle: 'Расписание тем', - themeSchedulerEnable: 'Включить расписание тем', - themeSchedulerEnableSub: 'Автоматически переключается между двумя темами в зависимости от времени суток', - themeSchedulerDayTheme: 'Дневная тема', - themeSchedulerDayStart: 'День начинается в', - themeSchedulerNightTheme: 'Ночная тема', - themeSchedulerNightStart: 'Ночь начинается в', - themeSchedulerActiveHint: 'Расписание тем активно - темы переключаются автоматически.', - visualOptionsTitle: 'Визуальные Настройки', - coverArtBackground: 'Фон Обложки', - coverArtBackgroundSub: 'Показывать размытую обложку как фон в заголовках альбомов и плейлистов', - playlistCoverPhoto: 'Обложка Плейлиста', - playlistCoverPhotoSub: 'Показывать сетку обложек в детальном виде плейлиста', - showBitrate: 'Показывать Битрейт', - showBitrateSub: 'Отображать битрейт аудио в списках треков', - floatingPlayerBar: 'Плавающая панель плеера', - floatingPlayerBarSub: 'Держать панель плеера плавающей над содержимым', - uiScaleTitle: 'Масштаб интерфейса', - uiScaleLabel: 'Масштаб', - }, - changelog: { - modalTitle: 'Что нового', - dontShowAgain: 'Больше не показывать', - close: 'Понятно', - }, - whatsNew: { - title: 'Что нового', - empty: 'Для этой версии пока нет записи в журнале изменений.', - bannerTitle: 'Журнал изменений', - bannerCollapsed: 'Что нового в v{{version}}', - dismiss: 'Скрыть', - close: 'Закрыть', - }, - help: { - title: 'Справка', - searchPlaceholder: 'Поиск по справке…', - noResults: 'Ничего не найдено. Попробуйте другой запрос.', - s1: 'С чего начать', - q1: 'Какие серверы поддерживаются?', - a1: 'Psysonic в первую очередь сделан для Navidrome и полностью совместим с Subsonic — Gonic, Airsonic, LMS и другие серверы Subsonic-API тоже работают. Некоторые расширенные функции (рейтинги, умные плейлисты, обмен Magic String, управление пользователями) требуют Navidrome.', - q2: 'Как добавить сервер?', - a2: 'Настройки → Серверы → Добавить сервер. Введите URL (например, http://192.168.1.100:4533), имя пользователя и пароль. Psysonic проверяет соединение перед сохранением — при ошибке ничего не сохраняется. Можно добавить сколько угодно серверов и переключаться между ними в шапке; одновременно активен только один.', - q3: 'Краткий обзор интерфейса?', - a3: 'Боковая панель (слева) для навигации, Mainstage / страницы по центру, плеер внизу, панель Очереди справа (открывается через иконку справа вверху рядом с индикатором Now Playing). Поиск вверху работает по всей библиотеке; «Now Playing» показывает, что слушают другие пользователи на том же сервере Navidrome.', - s2: 'Воспроизведение и Очередь', - q4: 'Как пользоваться очередью?', - a4: 'Откройте панель Очереди справа вверху. Перетаскивайте строки, чтобы менять порядок, выносите их за пределы для удаления, или используйте панель инструментов для перемешивания, сохранения очереди как плейлиста или перехода к треку. Перетаскивайте строки из панели в другие места как способ переноса.', - q5: 'Gapless и Crossfade — в чём разница?', - a5: 'Gapless преднабуферизирует следующий трек, чтобы между песнями не было тишины (идеально для концертных альбомов и DJ-миксов). Crossfade плавно затухает текущий трек, пока следующий нарастает (1–10 с — для перемешанных миксов). Они взаимоисключающи — включение одного отключает другое. Настройте оба в Настройки → Аудио.', - q6: 'Что такое Бесконечная очередь?', - a6: 'Когда очередь заканчивается и Повтор выключен, Psysonic тихо добавляет похожие/случайные треки из вашей библиотеки, чтобы воспроизведение не останавливалось. Авто-добавленные треки появляются под разделителем «— Добавлено автоматически —». Включается иконкой бесконечности в шапке очереди; ограничьте автодобавление жанром в Настройки → Очередь.', - q7: 'Множественный выбор и Shift+клик диапазона?', - a7: 'Включите «Выбор» на Альбомах / Новинках / Random Albums / Плейлистах. Клик переключает элемент, затем удерживайте Shift и кликните другой элемент — всё между ними в видимом порядке выделится. Shift+клики расширяют от последнего кликнутого якоря. Панель инструментов сверху предлагает массовые действия (очередь, скачивание, удаление и т. д.).', - q8: 'Сочетания клавиш и глобальные хоткеи?', - a8: 'По умолчанию: Пробел = Воспроизведение / Пауза, Esc = выйти из полного экрана / закрыть модалки, F1 = памятка по сочетаниям. Настройки → Ввод позволяет переназначить любое внутри-приложенческое действие (включая аккорды вроде Ctrl+Shift+P) и задать системные глобальные сочетания, работающие даже когда Psysonic в фоне или свёрнут. Медиа-клавиши (Воспр./Пауза, Далее, Назад) работают на всех платформах.', - s3: 'Аудио-инструменты', - q9: 'Режимы Replay Gain?', - a9: 'Настройки → Аудио → Replay Gain. Режим Трек нормализует каждую песню к целевому уровню. Режим Альбом сохраняет кривую громкости внутри альбома. Режим Авто выбирает Трек или Альбом в зависимости от того, происходит ли очередь из одного альбома. Треки без тегов Replay Gain используют настраиваемый предусилитель.', - q10: 'Что такое Smart Loudness Normalization (LUFS)?', - a10: 'Современная альтернатива Replay Gain в Настройки → Аудио. Psysonic анализирует каждый трек по LUFS / EBU R128 и сохраняет результат, чтобы громкость была единой по всей библиотеке — включая треки без Replay Gain тегов. Холодный анализ работает в фоне и использует 35–40 % CPU около 1 минуты, потом 0. Установите целевую громкость (по умолчанию −10 LUFS) один раз.', - q11: 'EQ и AutoEQ?', - a11: '10-полосный параметрический EQ в Настройки → Аудио → Эквалайзер с ручными полосами и пресетами. AutoEQ рядом подгружает измеренный профиль коррекции для модели ваших наушников из базы AutoEQ и применяет его к полосам автоматически — выберите наушники, EQ настроится на правильную кривую.', - q12: 'Как переключить устройство вывода аудио?', - a12: 'Настройки → Аудио → Устройство вывода. Psysonic перечисляет все доступные выходы и переключается мгновенно при выборе. Кнопка обновления находит устройства, подключённые после запуска. На Linux ALSA-имена вроде «sysdefault» автоматически очищаются для удобства чтения.', - q13: 'Что такое Hot Cache?', - a13: 'Hot Cache предзагружает текущий трек и следующие в RAM и на диск, чтобы воспроизведение начиналось без задержек буферизации — особенно полезно на медленных / удалённых серверах. Вытеснение срабатывает при достижении лимита размера. Настройте размер и задержку дебаунса (чтобы быстрые скипы не приводили к лишним загрузкам) в Настройки → Аудио.', - s4: 'Библиотека и Открытие', - q14: 'Как работают рейтинги и Skip-to-1★?', - a14: 'Psysonic поддерживает рейтинг 1–5 звёзд через OpenSubsonic (Navidrome ≥ 0.53). Оценивайте треки в списках, в контекстном меню или в плеере под именем исполнителя; альбомы — на странице альбома; исполнителей — на странице исполнителя. Skip-to-1★ (Настройки → Библиотека → Рейтинги) автоматически ставит 1 звезду после настраиваемого числа последовательных скипов. Та же панель позволяет задать минимальный рейтинг как фильтр для генерируемых миксов.', - q15: 'Как просматривать — Папки, Жанры, Треки?', - a15: 'Просмотр папок (боковая панель) ходит по дереву музыкальной директории сервера в Miller-column раскладке — клик по папке для входа, клик по треку или иконке воспроизведения папки для проигрывания / добавления. Жанры используют tag-cloud вид с размером по числу треков; клик по жанру открывает его. Треки — это плоский хаб библиотеки с виртуальным списком, сортируемым по столбцам, и живым поиском.', - q16: 'Поиск и расширенный поиск?', - a16: 'Поиск в шапке выполняет живой поиск по исполнителям, альбомам и трекам по мере набора. Откройте Расширенный поиск (боковая панель) для более богатого вида: фильтры по году, жанру, рейтингу, формату, каналам, частоте дискретизации, BPM, настроению — комбинируемые. Правый клик по любому результату открывает то же контекстное меню, что и в других местах.', - q17: 'Что такое Миксы (Random / Genre / Super Genre / Lucky)?', - a17: 'Random Mix строит плейлист случайных треков из библиотеки; фильтр ключевых слов исключает аудиокниги, комедию и т. д. по подстрокам жанра / названия / альбома. Super Genre Mix группирует библиотеку в широкие стили (Рок, Метал, Электронная, Джаз, Классика…) и строит сфокусированный микс. Lucky Mix использует историю прослушивания, рейтинги и похожие треки AudioMuse-AI для составления мгновенного плейлиста по одному клику.', - q18: 'Страница статистики?', - a18: 'Статистика (боковая панель) показывает топ исполнителей, топ альбомов, топ треков, разбивку по жанрам, время прослушивания со временем и охват по библиотеке, если настроено несколько музыкальных папок. Несколько видов экспортируются как изображение-карточка для шаринга.', - q19: 'Как скачать альбом как ZIP?', - a19: 'Страница альбома → «Скачать (ZIP)». Сервер сначала упаковывает альбом — для больших или lossless альбомов (FLAC / WAV) индикатор прогресса появляется только после завершения упаковки и начала передачи. Это нормально.', - s5: 'Тексты', - q20: 'Откуда берутся тексты?', - a20: 'Три источника, настраиваемые в Настройки → Тексты: ваш сервер Navidrome (встроенные / OpenSubsonic тексты), LRCLIB (синхронизированные тексты от сообщества) и NetEase Cloud Music (большой азиатский + международный каталог). Каждый источник можно включить / выключить и переставить перетаскиванием.', - q21: 'Как смотреть тексты во время воспроизведения?', - a21: 'Кликните на иконку микрофона в плеере, чтобы открыть вкладку Тексты в панели очереди. Синхронизированные тексты автоматически прокручиваются и поддерживают клик-для-перехода; обычный текст прокручивается как статический блок. Включите Полноэкранный плеер через обложку плеера для иммерсивного вида текстов с mesh-blob фоном.', - s6: 'Шаринг и Социальные функции', - q22: 'Что такое Magic Strings?', - a22: 'Magic Strings — это короткие копи-паст токены для шаринга вещей между пользователями Psysonic без сторонних серверов. Server-Invite строки позволяют другу присоединиться к вашему Navidrome одной вставкой; Magic Strings альбомов / исполнителей / очередей открывают тот же альбом / исполнителя / очередь у получателя. Создавайте через меню «Поделиться», вставляйте в строку поиска для использования.', - q23: 'Что такое Orbit?', - a23: 'Orbit — это синхронное совместное прослушивание: хост проигрывает трек, каждый гость слышит его синхронно, и гости могут предлагать песни, которые хост может принять в очередь. Запустите сессию через кнопку Orbit в шапке, поделитесь ссылкой-приглашением, и другие могут присоединиться с любой установки Psysonic. Хост контролирует воспроизведение (скип, перемотка, очередь) — гости получают вид в реальном времени и поле для предложений. Сессии эфемерные и завершаются, когда хост их закрывает.', - q24: 'Что такое выпадающее меню Now Playing?', - a24: 'Иконка трансляции справа вверху показывает, что слушают другие пользователи на вашем сервере Navidrome прямо сейчас, обновляется каждые 10 секунд. Ваша запись исчезает в момент паузы. По серверам — пользователи на другом активном сервере не показываются.', - s7: 'Персонализация', - q25: 'Темы и планировщик тем?', - a25: 'Настройки → Внешний вид → Тема выбирает из 60+ тем в 8 группах (Psysonic, Mediaplayer, Операционные системы, Игры, Фильмы, Сериалы, Соцсети, Open Source Classics — Catppuccin / Nord / Gruvbox / Nightfox / Dracula). Auto-Switch Theme позволяет задать дневную и ночную тему со временем переключения, чтобы Psysonic переключался автоматически.', - q26: 'Можно настроить боковую панель, Главную и страницу исполнителя?', - a26: 'Да — Настройки → Персонализация. Кастомизатор боковой панели позволяет перетаскивать nav-элементы в нужном порядке и скрывать те, что не используются. Кастомизатор Главной включает/выключает каждый ряд Mainstage (Hero, Recent, Discover, Recently Played, Starred…). Кастомизатор страницы исполнителя меняет порядок секций (Top Songs, Альбомы, Синглы, Сборники, Похожие исполнители и т. д.) и позволяет скрывать те, на которые вы не смотрите.', - q27: 'Что такое Mini Player?', - a27: 'Маленькое плавающее окно с обложкой, элементами управления воспроизведением и компактной очередью. Открывается из иконки mini-player в плеере или сочетанием клавиш. Окно запоминает позицию и размер между сессиями. На Windows mini-webview предсоздаётся при запуске для мгновенного открытия; Linux / macOS включают это опционально через Настройки → Внешний вид → Предзагружать mini player.', - q28: 'Что такое Floating Player Bar?', - a28: 'Опциональный стиль плеера (Настройки → Внешний вид), который отделяется от нижней границы с тематическим фоном, акцентной рамкой, скруглённой обложкой и центрированной секцией громкости. Полезно на высоких мониторах или с компактными темами.', - q29: 'Превью трека по наведению?', - a29: 'Наведите мышь на строку трека, кликните маленькую кнопку превью на обложке или вызовите превью из контекстного меню — Psysonic стримит первые ~15 с через тот же Rust-аудио-движок, чтобы применилась нормализация громкости. Полезно для быстрого знакомства с альбомом, который вы ещё не слушали.', - q30: 'Таймер сна?', - a30: 'Кликните иконку луны в плеере, чтобы открыть таймер сна. Выберите длительность (или «конец текущего трека») и Psysonic плавно затухнет и поставит на паузу в конце. На кнопке отображается круговое кольцо и обратный отсчёт во время работы таймера.', - q31: 'Масштаб UI, шрифт, стиль seekbar?', - a31: 'Настройки → Внешний вид — Масштаб интерфейса (80–125 % без влияния на системный размер шрифта), Шрифт (10 UI шрифтов, включая IBM Plex Mono, Fira Code, Geist, Golos Text…), Стиль Seekbar (Волна анализированная / pseudowave детерминированная / Линия и Точка / Полоса / Толстая полоса / Сегментированный / Неон / Импульсная волна / Шлейф частиц / Жидкое заполнение / Ретро-плёнка).', - s8: 'Опытный пользователь', - q32: 'Управление плеером из командной строки?', - a32: 'Бинарь Psysonic также служит пультом дистанционного управления. Примеры: psysonic --player play / pause / next / prev, --player volume 75, --player seek 15, --player shuffle, --player repeat off|all|one, --player rating 1-5. Переключайте серверы, аудиоустройства, библиотеки; запускайте Instant Mix; ищите исполнителей / альбомы / треки. Полный список через psysonic --player --help. Shell-автодополнение для bash и zsh через psysonic completions.', - q33: 'Умные плейлисты (Navidrome)?', - a33: 'Умные плейлисты — это динамические плейлисты на стороне Navidrome, определяемые правилами (жанр = Рок И год > 2020 и т. д.). Страница Плейлисты в Psysonic позволяет создавать, редактировать и удалять их с визуальным редактором правил — Psysonic общается с Navidrome native API для этого. Они ведут себя как обычные плейлисты в остальной части приложения и обновляются автоматически при изменении библиотеки.', - q34: 'Резервная копия и восстановление настроек?', - a34: 'Настройки → Хранилище → Резервное копирование экспортирует профили серверов, темы, сочетания клавиш и другие настройки в один JSON файл. Импортируйте файл на другой машине или после переустановки, чтобы восстановить всё сразу. Пароли серверов включены — храните файл в надёжном месте.', - q35: 'Где смотреть все open-source лицензии?', - a35: 'Настройки → Система → Open Source Licenses. Полный список зависимостей (cargo crates и npm пакеты) поставляется со встроенными текстами лицензий. Кликните на запись для полного текста; выделенный блок сверху подсвечивает узнаваемые библиотеки (Tauri, React, rodio, symphonia и т. д.).', - s9: 'Офлайн и Sync', - q36: 'Офлайн-режим — кэширование альбомов и плейлистов?', - a36: 'Откройте любой альбом или плейлист и кликните иконку загрузки в шапке — Psysonic кэширует каждый трек локально, чтобы он играл с диска без сетевого вызова. Страница Офлайн-библиотека (боковая панель) показывает всё кэшированное, прогресс текущих загрузок и позволяет удалять записи иконкой корзины (появляется после завершения загрузки).', - q37: 'Лимит офлайн-хранилища?', - a37: 'Настройки → Библиотека → Офлайн позволяет задать максимальный размер кэша. При достижении лимита кнопка загрузки на странице альбома показывает предупреждающий баннер. Освободите место, удалив альбомы или плейлисты со страницы Офлайн-библиотека.', - q38: 'Device Sync — копирование музыки на USB / SD?', - a38: 'Device Sync (боковая панель) копирует альбомы, плейлисты или целых исполнителей на внешний диск для офлайн-прослушивания на других устройствах. Выберите целевую папку, выберите источники из вкладок браузера, нажмите «Перенести на устройство». Psysonic пишет манифест (psysonic-sync.json), чтобы знать, какие файлы уже там, даже если переоткрыть Device Sync на другой ОС с другим шаблоном имени файла. Шаблоны поддерживают токены {artist} / {album} / {title} / {track_number} / {disc_number} / {year} с / как разделителем папок.', - s10: 'Интеграции и Устранение неполадок', - q39: 'Скробблинг Last.fm?', - a39: 'Настройки → Интеграции → Last.fm. Подключите аккаунт один раз, и Psysonic скробблит напрямую в Last.fm — настройка Navidrome не нужна. Скроббл отправляется после прослушивания 50 % трека. Now-playing пинги отправляются в начале.', - q40: 'Discord Rich Presence?', - a40: 'Настройки → Интеграции → Discord показывает текущий трек в вашем профиле Discord. Выберите между иконкой приложения, обложками с вашего сервера (через getAlbumInfo2 — нужен публично доступный сервер) или обложками Apple Music. Кастомизируйте отображаемые строки (детали, состояние, тултип) с помощью токен-шаблонов.', - q41: 'Даты туров Bandsintown?', - a41: 'Включается в Настройки → Интеграции → Now-Playing Info. Вкладка Now Playing на странице Now Playing затем показывает предстоящие даты туров для играющего исполнителя через Bandsintown widget API. По умолчанию выключено — никаких запросов до включения.', - q42: 'Internet Radio — воспроизведение живых стримов?', - a42: 'Internet Radio (боковая панель) проигрывает любой live-стрим, сохранённый на вашем сервере Navidrome (добавляйте станции через Navidrome admin UI). Воспроизведение работает через HTML5 audio движок браузера — большинство настроек EQ / Replay Gain / Loudness не применяются к радио, но ICY-метаданные (текущее имя песни) отображаются. Поддерживает MP3, AAC, OGG Vorbis и большинство HLS стримов; поддержка кодеков зависит от платформы.', - q43: 'Тест соединения не проходит — что делать?', - a43: 'Дважды проверьте URL включая порт (например, http://192.168.1.100:4533). В локальной сети http:// часто работает там, где https:// не работает (нет сертификата). Убедитесь, что firewall не блокирует порт и что имя пользователя и пароль правильные. Если сервер за reverse proxy, попробуйте сначала прямой URL для изоляции причины.', - q44: 'Обложки и изображения исполнителей загружаются медленно.', - a44: 'Изображения подгружаются с сервера при первом просмотре, затем кэшируются локально на 30 дней. Если хранилище сервера медленное, первый визит на страницу может занять момент; последующие визиты мгновенные. Hot Cache также помогает с треками, но кэш изображений независим.', - q45: 'Проблемы Linux — чёрный экран или нет звука?', - a45: 'Чёрный экран обычно проблема GPU / EGL драйвера в WebKitGTK — запускайте с GDK_BACKEND=x11 WEBKIT_DISABLE_COMPOSITING_MODE=1 WEBKIT_DISABLE_DMABUF_RENDERER=1 (AUR / .deb / .rpm установщики устанавливают это автоматически). Для аудио убедитесь, что PipeWire или PulseAudio запущены. Пропадание звука после спящего режима / пробуждения теперь обрабатывается автоматически post-sleep recovery hook.', - }, - queue: { - title: 'Очередь', - savePlaylist: 'Сохранить как плейлист', - updatePlaylist: 'Обновить плейлист', - filterPlaylists: 'Фильтр плейлистов…', - playlistName: 'Название плейлиста', - cancel: 'Отмена', - save: 'Сохранить', - loadPlaylist: 'Загрузить плейлист', - loading: 'Загрузка…', - noPlaylists: 'Плейлистов нет.', - load: 'Заменить очередь и играть', - appendToQueue: 'Добавить в очередь', - delete: 'Удалить', - deleteConfirm: 'Удалить плейлист «{{name}}»?', - clear: 'Очистить', - shuffle: 'Перемешать', - gapless: 'Без пауз', - crossfade: 'Кроссфейд', - infiniteQueue: 'Бесконечная очередь', - autoAdded: '— Добавлено автоматически —', - radioAdded: '— Радио —', - hide: 'Скрыть', - hideNowPlaying: 'Скрыть информацию о воспроизведении', - showNowPlaying: 'Показать информацию о воспроизведении', - close: 'Закрыть', - nextTracks: 'Дальше', - shareQueue: 'Копировать ссылку на очередь', - shareQueueEmpty: 'Очередь пуста — нечем поделиться.', - emptyQueue: 'Очередь пуста.', - trackSingular: 'трек', - trackPlural: 'треков', - showRemaining: 'Осталось', - showTotal: 'Всего', - showEta: 'Показать ориентировочное окончание', - replayGain: 'ReplayGain', - rgTrack: 'Т {{db}} дБ', - rgAlbum: 'А {{db}} дБ', - rgPeak: 'Пик {{pk}}', - sourceOffline: 'Играет из офлайн-библиотеки', - sourceHot: 'Играет из кэша', - sourceStream: 'Играет из сетевого потока', - clearCachedLoudnessWaveform: 'Сбросить кэш громкости (LUFS) и формы волны и заново проанализировать трек', - recalculatingLoudnessWaveform: 'Пересчёт громкости и формы волны для этого трека…', - }, - miniPlayer: { - showQueue: 'Показать очередь', - hideQueue: 'Скрыть очередь', - pinOnTop: 'Поверх окон', - pinOff: 'Открепить', - openMainWindow: 'Открыть главное окно', - close: 'Закрыть', - emptyQueue: 'Очередь пуста', - }, - statistics: { - title: 'Статистика', - recentlyPlayed: 'Недавно проиграно', - mostPlayed: 'Самые проигранные альбомы', - highestRated: 'С высоким рейтингом', - genreDistribution: 'Жанры (топ-20)', - loadMore: 'Ещё', - statArtists: 'Исполнители', - statArtistsTooltip: 'Только исполнители альбомов — артисты, присутствующие лишь в треках (фичеринг, гость и т. д.) без собственного альбома, не учитываются.', - statAlbums: 'Альбомы', - statSongs: 'Треки', - statGenres: 'Жанры', - statPlaytime: 'Время звучания', - genreInsights: 'По жанрам', - formatDistribution: 'Форматы', - formatSample: 'Выборка {{n}} треков', - computing: 'Считаем…', - genreSongs_one: '{{count}} композиция', - genreSongs_few: '{{count}} композиции', - genreSongs_many: '{{count}} композиций', - genreSongs_other: '{{count}} композиций', - genreAlbums_one: '{{count}} альбом', - genreAlbums_few: '{{count}} альбома', - genreAlbums_many: '{{count}} альбомов', - genreAlbums_other: '{{count}} альбомов', - recentlyAdded: 'Недавно добавлено', - decadeDistribution: 'Альбомы по десятилетиям', - decadeAlbums_one: '{{count}} альбом', - decadeAlbums_few: '{{count}} альбома', - decadeAlbums_many: '{{count}} альбомов', - decadeAlbums_other: '{{count}} альбомов', - decadeUnknown: 'Неизвестно', - lfmTitle: 'Статистика Last.fm', - lfmTopArtists: 'Топ исполнителей', - lfmTopAlbums: 'Топ альбомов', - lfmTopTracks: 'Топ треков', - lfmPlays_one: '{{count}} прослушивание', - lfmPlays_few: '{{count}} прослушивания', - lfmPlays_many: '{{count}} прослушиваний', - lfmPlays_other: '{{count}} прослушиваний', - lfmPeriodOverall: 'За всё время', - lfmPeriod7day: '7 дней', - lfmPeriod1month: 'Месяц', - lfmPeriod3month: '3 месяца', - lfmPeriod6month: '6 месяцев', - lfmPeriod12month: 'Год', - lfmNotConnected: 'Подключите Last.fm в настройках.', - lfmRecentTracks: 'Последние скробблы', - lfmNowPlaying: 'Сейчас играет', - lfmJustNow: 'только что', - lfmMinutesAgo: '{{n}} мин назад', - lfmHoursAgo: '{{n}} ч назад', - lfmDaysAgo: '{{n}} дн. назад', - topRatedSongs: 'Лучшие по рейтингу треки', - topRatedArtists: 'Лучшие по рейтингу исполнители', - noRatedSongs: 'Нет оценённых треков. Ставьте оценки в альбомах или плейлистах.', - noRatedArtists: 'Нет оценённых исполнителей.', - }, - player: { - regionLabel: 'Плеер', - openFullscreen: 'Полноэкранный плеер', - fullscreen: 'Полноэкранный режим', - closeFullscreen: 'Выйти из полноэкранного', - closeTooltip: 'Закрыть (Esc)', - noTitle: 'Без названия', - stop: 'Стоп', - prev: 'Предыдущий трек', - play: 'Играть', - pause: 'Пауза', - previewActive: 'Превью воспроизводится', - previewLabel: 'Превью', - delayModalTitle: 'Таймер', - delayPauseSection: 'Пауза через', - delayStartSection: 'Старт через', - delayPreviewPause: 'Пауза в', - delayPreviewStart: 'Старт в', - delaySchedulePause: 'Запланировать паузу', - delayScheduleStart: 'Запланировать старт', - delayCancelPause: 'Отменить таймер паузы', - delayCancelStart: 'Отменить таймер старта', - delayInactivePause: 'Доступно только во время воспроизведения.', - delayInactiveStart: 'Доступно на паузе при загруженном треке или радио.', - delayCustomMinutes: 'Своя задержка (минуты)', - delayCustomPlaceholder: 'напр. 2.5', - closeDelayModal: 'Закрыть', - delayIn: 'через', - delayFmtSec: '{{n}} с', - delayFmtMin: '{{n}} мин', - delayFmtHr: '{{n}} ч', - delayCancel: 'Отмена', - delayApply: 'Применить', - next: 'Следующий трек', - repeat: 'Повтор', - repeatOff: 'Выкл.', - repeatAll: 'Все', - repeatOne: 'Один', - progress: 'Прогресс', - volume: 'Громкость', - toggleQueue: 'Очередь', - collapseQueueResize: 'Свернуть очередь, изменить ширину', - moreOptions: 'Дополнительно', - equalizer: 'Эквалайзер', - miniPlayer: 'Мини-плеер', - lyrics: 'Текст', - lyricsLoading: 'Загрузка текста…', - lyricsNotFound: 'Текст не найден', - lyricsSourceNetease: 'Источник: Netease', - lyricsSourceLyricsplus: 'Источник: YouLyPlus', - showDuration: 'Показать длительность', - showRemainingTime: 'Показать оставшееся время', - }, - nowPlayingInfo: { - tab: 'Инфо', - empty: 'Включите воспроизведение, чтобы увидеть информацию', - artist: 'Исполнитель', - songInfo: 'О треке', - onTour: 'В туре', - noTourEvents: 'Нет предстоящих концертов', - tourLoading: 'Загрузка…', - poweredByBandsintown: 'Данные о туре через Bandsintown', - bioReadMore: 'Читать дальше', - bioReadLess: 'Свернуть', - showMoreTours_one: 'Показать ещё {{count}}', - showMoreTours_few: 'Показать ещё {{count}}', - showMoreTours_many: 'Показать ещё {{count}}', - showMoreTours_other: 'Показать ещё {{count}}', - showLessTours: 'Свернуть', - enableBandsintownPrompt: 'Показать предстоящие концерты?', - enableBandsintownPromptDesc: 'Опционально. Загружает концерты текущего исполнителя через публичный API Bandsintown.', - enableBandsintownPrivacy: 'При включении имя текущего исполнителя отправляется в API Bandsintown для получения дат концертов. Аккаунт и личные данные не передаются.', - enableBandsintownAction: 'Включить', - role: { - artist: 'Исполнитель', - albumArtist: 'Исполнитель альбома', - composer: 'Композитор', - }, - }, - songInfo: { - title: 'О треке', - songTitle: 'Название', - artist: 'Исполнитель', - album: 'Альбом', - albumArtist: 'Альбомный исполнитель', - year: 'Год', - genre: 'Жанр', - duration: 'Длительность', - track: 'Номер', - format: 'Формат', - bitrate: 'Битрейт', - sampleRate: 'Частота', - bitDepth: 'Разрядность', - channels: 'Каналы', - fileSize: 'Размер файла', - path: 'Путь', - replayGainTrack: 'RG по треку', - replayGainAlbum: 'RG по альбому', - replayGainPeak: 'Пик RG', - mono: 'Моно', - stereo: 'Стерео', - }, - playlists: { - title: 'Плейлисты', - newPlaylist: 'Новый плейлист', - unnamed: 'Без названия', - createName: 'Название…', - create: 'Создать', - cancel: 'Отмена', - empty: 'Плейлистов пока нет.', - emptyPlaylist: 'Плейлист пуст.', - addFirstSong: 'Добавьте первый трек', - notFound: 'Плейлист не найден.', - songs: 'Треков: {{n}}', - playAll: 'Воспроизвести всё', - shuffle: 'Перемешать', - addToQueue: 'В очередь', - back: 'К списку плейлистов', - deletePlaylist: 'Удалить', - confirmDelete: 'Нажмите ещё раз для подтверждения', - removeSong: 'Убрать из плейлиста', - addSongs: 'Добавить треки', - searchPlaceholder: 'Поиск по библиотеке…', - noResults: 'Ничего не найдено.', - suggestions: 'Рекомендации', - noSuggestions: 'Пока нет рекомендаций.', - titleBadge: 'Плейлист', - refreshSuggestions: 'Обновить подборку', - addSong: 'В плейлист', - preview: 'Превью (30 с)', - previewStop: 'Остановить превью', - playNextSuggestion: 'Играть следующим', - suggestionsHint: 'Двойной клик по строке — добавить в плейлист', - addSelected: 'Добавить выбранные', - cacheOffline: 'Сохранить плейлист офлайн', - offlineCached: 'Плейлист сохранён', - removeOffline: 'Удалить из офлайн-кэша', - offlineDownloading: 'Кэширование… ({{done}} из {{total}} альбомов)', - publicLabel: 'Публичный', - privateLabel: 'Личный', - editMeta: 'Изменить плейлист', - editNamePlaceholder: 'Название…', - editCommentPlaceholder: 'Описание…', - editPublic: 'Публичный плейлист', - editSave: 'Сохранить', - editCancel: 'Отмена', - changeCover: 'Сменить обложку', - changeCoverLabel: 'Сменить фото', - removeCover: 'Убрать фото', - coverUpdated: 'Обложка обновлена', - metaSaved: 'Плейлист сохранён', - downloadZip: 'Скачать (ZIP)', - // Toast notifications for multi-select - addSuccess: '{{count}} треков добавлено в {{playlist}}', - addPartial: '{{added}} добавлено, {{skipped}} пропущено (дубликаты)', - addAllSkipped: 'Все пропущены ({{count}} дубликатов)', - addedAsDuplicates: '{{count}} треков добавлено в {{playlist}} (как дубликаты)', - duplicateConfirmTitle: 'Уже в плейлисте', - duplicateConfirmMessage: 'Все {{count}} треков уже есть в «{{playlist}}». Всё равно добавить их как дубликаты?', - duplicateConfirmAction: 'Всё равно добавить', - addError: 'Ошибка при добавлении треков', - createAndAddSuccess: 'Плейлист "{{playlist}}" создан с {{count}} треками', - createError: 'Ошибка при создании плейлиста', - deleteSuccess: '{{count}} плейлистов удалено', - deleteFailed: 'Ошибка при удалении {{name}}', - deleteSelected: 'Удалить выбранные', - deleteSelectedPartial: 'Можно удалить только {{n}} из {{total}} выбранных плейлистов (остальные принадлежат другим пользователям).', - mergeSuccess: '{{count}} треков объединено в {{playlist}}', - mergeNoNewSongs: 'Нет новых треков для добавления', - mergeError: 'Ошибка при объединении плейлистов', - mergeInto: 'Объединить в', - selectionCount: '{{count}} выбрано', - select: 'Выбрать', - startSelect: 'Включить выбор', - cancelSelect: 'Отмена', - loadingAlbums: 'Загрузка {{count}} альбомов…', - loadingArtists: 'Загрузка {{count}} исполнителей…', - myPlaylists: 'Мои плейлисты', - noOtherPlaylists: 'Нет других доступных плейлистов', - addToPlaylistSuccess: '{{count}} треков добавлено в {{playlist}}', - addToPlaylistNoNew: 'Нет новых треков для {{playlist}}', - addToPlaylistError: 'Ошибка при добавлении в плейлист', - removeSuccess: 'Трек убран из плейлиста', - removeError: 'Ошибка при удалении из плейлиста', - importCSV: 'Импорт CSV', - importCSVTooltip: 'Импорт из CSV Spotify', - csvImportReport: 'Отчёт об импорте CSV', - csvImportTotal: 'Всего', - csvImportAdded: 'Добавлено', - csvImportDuplicates: 'Дубликаты', - csvImportNotFound: 'Не найдено', - csvImportNetworkErrors: 'Ошибки сети', - csvImportDuplicatesTitle: 'Дубликаты (уже в плейлисте):', - csvImportNotFoundTitle: 'Не найденные треки:', - csvImportNetworkErrorsTitle: 'Ошибки сети (можно повторить импорт):', - csvImportDownloadReport: 'Скачать отчёт', - csvImportClose: 'Закрыть', - csvImportNoValidTracks: 'В CSV-файле не найдено действительных треков', - csvImportFailed: 'Не удалось импортировать CSV-файл', - csvImportToast: '{{added}} добавлено, {{notFound}} не найдено, {{duplicates}} дубликатов', - csvImportDownloadSuccess: 'Отчёт успешно скачан', - csvImportDownloadError: 'Не удалось скачать отчёт', - }, - smartPlaylists: { - sectionBasic: '1. База', - sectionGenres: '2. Жанры', - sectionYearsAndFilters: '3. Годы и фильтры', - genreMode: 'Режим жанров', - genreModeInclude: 'Включить жанры', - genreModeExclude: 'Исключить жанры', - genreSearchPlaceholder: 'Фильтр жанров...', - availableGenres: 'Доступные', - selectedGenres: 'Выбранные', - yearMode: 'Режим годов', - yearModeInclude: 'Включить диапазон', - yearModeExclude: 'Исключить диапазон', - name: 'Название (без префикса)', - limit: 'Лимит', - limitHint: 'Сколько треков включать в плейлист (1-{{max}}, обычно 50).', - artistContains: 'Исполнитель содержит…', - albumContains: 'Альбом содержит…', - titleContains: 'Название содержит…', - minRating: 'Мин. рейтинг', - minRatingAria: 'Минимальный рейтинг для смарт-плейлиста', - minRatingHint: '0 — без минимального порога; 1-5 — оставить треки с рейтингом выше выбранного.', - fromYear: 'Год от', - toYear: 'Год до', - excludeUnrated: 'Исключить треки без рейтинга', - compilationOnly: 'Только сборники', - create: 'Создать смарт-плейлист', - save: 'Сохранить смарт-плейлист', - created: 'Создан {{name}}', - updated: 'Обновлён {{name}}', - createFailed: 'Не удалось создать смарт-плейлист.', - updateFailed: 'Не удалось обновить смарт-плейлист.', - navidromeOnly: 'Смарт-плейлисты можно создавать только на серверах Navidrome.', - loadFailed: 'Не удалось загрузить смарт-плейлисты из Navidrome.', - sortRandom: 'Сортировка: случайно', - sortTitleAsc: 'Сортировка: название А-Я', - sortTitleDesc: 'Сортировка: название Я-А', - sortYearDesc: 'Сортировка: год по убыванию', - sortYearAsc: 'Сортировка: год по возрастанию', - sortPlayCountDesc: 'Сортировка: прослушивания по убыванию', - }, - mostPlayed: { - title: 'Популярное', - topArtists: 'Топ исполнителей', - topAlbums: 'Топ альбомов', - plays: '{{n}} прослушиваний', - sortMost: 'Сначала популярные', - sortLeast: 'Сначала малоизвестные', - loadMore: 'Загрузить больше альбомов', - noData: 'Пока нет данных о прослушивании. Начните слушать!', - noArtists: 'Все исполнители отфильтрованы.', - filterCompilations: 'Скрыть исполнителей сборников (Various Artists, Soundtracks и др.)', - filterCompilationsShort: 'Скрыть сборники', - }, - losslessAlbums: { - empty: 'В этой библиотеке пока нет lossless-альбомов.', - unsupported: 'Этот сервер не предоставляет метаданные, необходимые для поиска lossless-альбомов.', - slowFetchHint: 'Загружается медленнее других страниц альбомов — Psysonic проходит весь каталог песен по качеству.', - }, - radio: { - title: 'Онлайн-радио', - empty: 'Радиостанции не настроены.', - addStation: 'Добавить станцию', - editStation: 'Изменить', - deleteStation: 'Удалить станцию', - confirmDelete: 'Нажмите ещё раз для подтверждения', - stationName: 'Название станции…', - streamUrl: 'URL потока…', - homepageUrl: 'Сайт станции (необязательно)', - save: 'Сохранить', - cancel: 'Отмена', - live: 'ЭФИР', - liveStream: 'Онлайн-радио', - openHomepage: 'Открыть сайт', - changeCoverLabel: 'Сменить обложку', - removeCover: 'Убрать обложку', - browseDirectory: 'Каталог станций', - directoryPlaceholder: 'Поиск станций…', - noResults: 'Станции не найдены.', - stationAdded: 'Станция добавлена', - filterAll: 'Все', - filterFavorites: 'Избранное', - sortManual: 'Вручную', - sortAZ: 'А → Я', - sortZA: 'Я → А', - sortNewest: 'Сначала новые', - favorite: 'В избранное', - unfavorite: 'Убрать из избранного', - noFavorites: 'Избранных станций нет.', - listenerCount_one: '{{count}} слушатель', - listenerCount_other: '{{count}} слушателей', - recentlyPlayed: 'Недавно сыгранное', - upNext: 'Следующий', - }, - folderBrowser: { - empty: 'Папка пуста', - error: 'Ошибка загрузки', - }, - deviceSync: { - title: 'Синхронизация устройства', - targetFolder: 'Папка назначения', - noFolderChosen: 'Папка не выбрана', - selectDrive: 'Выберите диск…', - refreshDrives: 'Обновить диски', - noDrivesDetected: 'Съёмные диски не обнаружены', - browseManual: 'Обзор вручную…', - free: 'свободно', - notMountedVolume: 'Цель не находится на смонтированном томе. Диск мог быть отключён.', - chooseFolder: 'Выбрать…', - filenameTemplate: 'Шаблон имени файла', - targetDevice: 'Целевое устройство', - templateHint: 'Переменные: {artist}, {album}, {title}, {track_number}, {disc_number}, {year}', - cleanupButton: 'Удалить файлы вне выборки', - cleanupNothingToDelete: 'Нечего удалять — устройство уже синхронизировано.', - confirmCleanup: 'Удалить {{count}} файл(ов) с устройства, не входящих в текущую выборку. Продолжить?', - cleanupComplete: '{{count}} файл(ов) удалено с устройства.', - selectedSources: 'Выбранные источники', - noSourcesSelected: 'Источники не выбраны. Нажмите на элементы в браузере, чтобы добавить их.', - clearAll: 'Очистить всё', - tabPlaylists: 'Плейлисты', - tabAlbums: 'Альбомы', - tabArtists: 'Исполнители', - searchPlaceholder: 'Поиск…', - syncButton: 'Синхронизировать на устройство', - actionTransfer: 'Перенести на устройство', - actionDelete: 'Удалить с устройства', - actionApplyAll: 'Применить все изменения', - templatePreview: 'Предпросмотр', - templatePresetStandard: 'Стандарт', - templatePresetMultiDisc: 'Мульти-диск', - templatePresetAltFolder: 'Альт. папка', - tokenSlashHint: '/ = разделитель папок', - cancel: 'Отмена', - noTargetDir: 'Сначала выберите папку назначения.', - noSources: 'Выберите хотя бы один источник.', - noTracks: 'В выбранных источниках не найдено треков.', - fetchError: 'Ошибка загрузки треков с сервера.', - syncComplete: 'Синхронизация завершена.', - dismiss: 'Закрыть', - cancelSync: 'Отмена', - syncCancelled: 'Синхронизация отменена ({{done}} / {{total}} перенесено).', - colName: 'Название', - colType: 'Тип', - colStatus: 'Статус', - onDevice: 'Управление устройством', - addSources: 'Добавить…', - syncResult: '{{done}} перенесено, {{skipped}} уже актуально ({{total}} всего)', - deleteFromDevice: 'Пометить для удаления ({{count}})', - confirmDelete: 'Удалить {{count}} запись(ей) с устройства: {{names}}?', - deleteComplete: '{{count}} запись(ей) удалено с устройства.', - manifestImported: 'Импортировано {{count}} источник(ов) из манифеста устройства.', - statusSynced: 'Синхронизировано', - statusPending: 'Ожидает', - statusDeletion: 'Удаление', - markForDeletion: 'Пометить для удаления', - removeSource: 'Удалить', - undoDeletion: 'Отменить удаление', - syncInBackground: 'Синхронизация запущена в фоне — можно перейти в другой раздел.', - syncInProgress: '{{done}} / {{total}} треков…', - syncSummary: 'Сводка синхронизации', - calculating: 'Вычисление необходимых данных…', - filesToAdd: 'Файлы для добавления:', - filesToDelete: 'Файлы для удаления:', - netChange: 'Чистое изменение:', - availableSpace: 'Доступное место на диске:', - spaceWarning: 'Предупреждение: на целевом устройстве недостаточно сообщаемого места.', - proceed: 'Продолжить синхронизацию', - notEnoughSpace: 'Обнаружено недостаточно физического места на диске!', - liveSearch: 'Live', - randomAlbumsLabel: 'Случайные альбомы', - }, - orbit: { - triggerLabel: 'Orbit', - triggerTooltip: 'Начать или присоединиться к совместной сессии прослушивания', - launchCreate: 'Создать сессию', - launchJoin: 'Присоединиться к сессии', - launchHelp: 'Как это работает?', - launchHelpSoon: 'Скоро будет', - joinModalTitle: 'Присоединиться к сессии Orbit', - joinModalSub: 'Вставь ссылку-приглашение от хоста.', - joinModalLinkLabel: 'Ссылка-приглашение', - joinModalLinkPlaceholder: 'psysonic2-…', - joinModalLinkHelper: 'Работает с любой действительной ссылкой Orbit. Должна указывать на сервер, на котором ты сейчас авторизован.', - joinModalPasteTooltip: 'Вставить из буфера обмена', - joinModalSubmit: 'Присоединиться', - joinModalBusy: 'Подключение…', - joinErrEmpty: 'Вставь ссылку-приглашение.', - joinErrInvalid: 'Это не похоже на ссылку-приглашение Orbit.', - closeAria: 'Закрыть', - heroTitlePrefix: 'Слушай вместе с', - heroTitleBrand: 'Orbit', - heroSub: 'Начни сессию — другие пользователи на {{server}} будут слушать вместе и смогут предлагать треки.', - fallbackServer: 'этот сервер', - tipLan: 'Ты сейчас подключён через адрес домашней сети. Гости вне твоей сети не смогут присоединиться — переключись на публичный адрес сервера в настройках перед стартом.', - tipRemote: 'Чтобы гости вне домашней сети могли присоединиться, адрес сервера должен быть публично доступен. Если сервер только внутренний, переключись перед стартом.', - labelName: 'Название сессии', - namePlaceholder: 'Velvet Orbit', - reshuffleTooltip: 'Новое предложение', - reshuffleAria: 'Предложить новое название', - helperName: 'Как сессия будет отображаться у гостей — оставь или введи своё.', - labelMax: 'Макс. гостей', - helperMax: 'Ты не считаешься — это только ограничивает входящих гостей.', - labelLink: 'Ссылка-приглашение', - tooltipCopied: 'Скопировано', - tooltipCopy: 'Копировать', - ariaCopyLink: 'Копировать ссылку-приглашение', - helperLink: 'Отправь эту ссылку гостям. Они могут вставить её в Psysonic в любом месте с помощью Ctrl+V.', - labelClearQueue: 'Сначала очистить мою очередь', - helperClearQueue: 'Начать сессию с пустой очередью. Выкл.: уже поставленные треки остаются и делятся с гостями.', - btnCancel: 'Отмена', - btnStarting: 'Запуск…', - btnStart: 'Запустить Orbit', - btnCopyAndStart: 'Копировать ссылку и запустить', - errNameRequired: 'Пожалуйста, дай сессии название.', - errStartFailed: 'Не удалось запустить.', - hostLabel: 'Хост: {{name}}', - participantsTooltip: 'Участники', - settingsTooltip: 'Настройки сессии', - shareTooltip: 'Поделиться ссылкой-приглашением', - shuffleLabel: 'Следующее перемешивание через', - catchUpLabel: 'догнать', - catchUpTooltip: 'Перейти к текущей позиции хоста', - hostAway: 'Хост оффлайн', - hostOnline: 'Хост онлайн', - endTooltip: 'Завершить сессию', - leaveTooltip: 'Покинуть сессию', - helpTooltip: 'Как работает Orbit', - diag: { - openTooltip: 'Диагностика — копируемый журнал событий', - title: 'Диагностика Orbit', - role: 'Роль', - hostTrack: 'ID трека хоста', - hostPos: 'Позиция хоста', - guestTrack: 'Мой ID трека', - guestPos: 'Моя позиция', - drift: 'Расхождение', - stateAge: 'Возраст состояния', - eventLog: 'Журнал событий ({{count}})', - copyLabel: 'Копировать', - copyTooltip: 'Скопировать журнал в буфер обмена', - clearLabel: 'Очистить', - clearTooltip: 'Очистить буфер', - empty: 'Пока нет событий — они появятся когда Orbit начнёт синхронизацию.', - hint: 'Открой это перед воспроизведением проблемы, затем нажми Копировать и вставь в баг-репорт.', - copied: 'Скопировано строк: {{count}}', - copyFailed: 'Не удалось скопировать в буфер обмена', - cleared: 'Буфер очищен', - }, - helpTitle: 'Как работает Orbit', - helpIntro: 'Orbit превращает Psysonic в общую комнату прослушивания. Хост выбирает музыку; гости слушают синхронно и могут предлагать треки.', - helpHostOnly: '(хост)', - helpSec1Title: 'Что такое Orbit?', - helpSec1Body: 'Режим «слушать вместе» — хост управляет воспроизведением, гости подключаются. Всё идёт через плейлисты на твоём собственном сервере Navidrome; никакой внешней инфраструктуры.', - helpSec2Title: 'Хост и гости', - helpSec2Body: 'Хост управляет воспроизведением (play / pause / skip / seek) и решает, когда завершить сессию. Гости следуют за воспроизведением хоста, могут предлагать треки и выходить или присоединяться в любое время. Только хост может исключать или навсегда банить участников.', - helpSec2WarnHead: 'Важно: отдельные аккаунты.', - helpSec2WarnBody: 'У каждого участника должен быть свой аккаунт Navidrome. Если хост и гость входят под одним и тем же пользователем, их отправки конфликтуют, и хост никогда не увидит предложения гостя.', - helpSec3Title: 'Запуск и приглашение', - helpSec3Body: 'Нажми кнопку «Orbit» → Создать сессию → стартовое окно покажет готовую ссылку для копирования и опционально позволит очистить текущую очередь. Делись ссылкой как угодно. Пока сессия активна, кнопка «Поделиться» в верхней панели сессии копирует ссылку в любой момент.', - helpSec4Title: 'Присоединение', - helpSec4Body: 'Вставь ссылку-приглашение в любом месте Psysonic с помощью Ctrl+V / Cmd+V — запрос на присоединение появится автоматически. Альтернатива: «Orbit» → Присоединиться к сессии → вставь в поле. Если ссылка указывает на сервер, где у тебя есть аккаунт, Psysonic переключит тебя автоматически. Если у тебя несколько аккаунтов на этом сервере, небольшой выбор спросит, какой использовать.', - helpSec5Title: 'Предложение треков', - helpSec5Body: 'В любом списке треков: двойной клик по строке или правый клик → «Добавить в сессию Orbit». Одиночный клик показывает подсказку вместо того, чтобы забрасывать весь альбом в общую очередь — это намеренно. Явные массовые действия вроде «Воспроизвести всё» или «Воспроизвести альбом» сначала запрашивают подтверждение, потом добавляют (никогда не заменяют).', - helpSec6Title: 'Общая очередь', - helpSec6Body: 'Очередь показывает предстоящие треки хоста — видно всем. Входящие массовые добавления всегда идут в конец, чтобы не потерять предложения гостей. Автоперемешивание периодически переупорядочивает очередь (настраивается: 1 / 5 / 10 / 15 / 30 мин). Если твоё воспроизведение отклоняется от хоста, кнопка «Догнать» в панели сессии возвращает тебя к live-позиции хоста.', - helpSec7Title: 'Подтверждения', - helpSec7Body: 'По умолчанию предложения гостей требуют ручного подтверждения — они появляются в полосе «Подтверждения» вверху панели очереди с кнопками принять / отклонить. В настройках сессии можно включить автоматическое подтверждение, и всё будет попадать сразу.', - helpSec8Title: 'Участники и настройки', - helpSec8Body: 'Открой иконку настроек в панели сессии для частоты перемешивания, автоподтверждения и быстрого «Перемешать сейчас». Нажми на количество участников, чтобы увидеть, кто подключён — исключить (может присоединиться снова по ссылке) или забанить (заблокирован для этой сессии). Гости тоже видят список участников, но только для чтения.', - helpSec9Title: 'Завершение сессии', - helpSec9Body: 'X хоста → диалог подтверждения → сессия закрывается для всех, серверные плейлисты очищаются автоматически. X гостя → гость выходит, сессия продолжается. Если хост молчит 5 минут, гость автоматически выходит с уведомлением; короткие переподключения в этом окне невидимы.', - participantsInviteLabel: 'Ссылка-приглашение', - participantsCountLabel: '{{count}} в сессии', - participantsHost: 'хост', - participantsEmpty: 'Пока нет гостей', - participantsKickTooltip: 'Удалить из сессии', - participantsKickAria: 'Удалить {{user}}', - participantsRemoveTooltip: 'Удалить из сессии', - participantsRemoveAria: 'Удалить {{user}} из этой сессии', - participantsBanTooltip: 'Забанить навсегда', - participantsBanAria: 'Забанить {{user}} навсегда', - participantsMuteTooltip: 'Запретить предлагать треки', - participantsUnmuteTooltip: 'Разрешить предлагать треки', - participantsMuteAria: 'Запретить {{user}} предлагать треки', - participantsUnmuteAria: 'Снова разрешить {{user}} предлагать треки', - confirmRemoveTitle: 'Удалить из сессии?', - confirmRemoveBody: '{{user}} будет удалён из сессии, но может присоединиться снова по твоей ссылке-приглашению.', - confirmRemoveConfirm: 'Удалить', - confirmBanTitle: 'Забанить навсегда?', - confirmBanBody: '{{user}} будет удалён и заблокирован от повторного присоединения к этой сессии. Отменить нельзя на время сессии.', - confirmBanConfirm: 'Забанить', - confirmCancel: 'Отмена', - confirmJoinTitle: 'Присоединиться к сессии Orbit?', - confirmJoinBody: '{{host}} пригласил тебя в «{{name}}». Присоединиться к сессии?', - confirmJoinConfirm: 'Присоединиться', - confirmLeaveTitle: 'Покинуть сессию?', - confirmLeaveBody: 'Покинуть «{{name}}»? Ты можешь присоединиться снова в любое время по ссылке-приглашению от {{host}}.', - confirmLeaveConfirm: 'Покинуть', - confirmEndTitle: 'Завершить сессию для всех?', - confirmEndBody: '«{{name}}» закроется для всех участников. Плейлисты сессии очищаются автоматически.', - confirmEndConfirm: 'Завершить сессию', - invalidLinkTitle: 'Ссылка-приглашение больше недействительна', - invalidLinkBody: 'Эта сессия Orbit больше не существует или уже завершена. Попроси хоста прислать новую ссылку.', - settingsTitle: 'Настройки сессии', - settingAutoApprove: 'Автоматически принимать предложения', - settingAutoApproveHint: 'Предложения гостей сразу попадают в твою очередь. Выкл.: они остаются в списке сессии для последующего просмотра.', - settingAutoShuffle: 'Автоперемешивание', - settingAutoShuffleHint: 'Периодическое Fisher-Yates перемешивание предстоящей очереди. Выкл.: порядок меняется только при ручной перестановке.', - settingShuffleInterval: 'Перемешивать каждые', - settingShuffleIntervalHint: 'Как часто предстоящая очередь перемешивается во время сессии.', - suggestBlockedMuted: 'Хост отключил тебе предложение треков на этой сессии.', - settingShuffleIntervalValue_one: '{{count}} мин', - settingShuffleIntervalValue_few: '{{count}} мин', - settingShuffleIntervalValue_many: '{{count}} мин', - settingShuffleIntervalValue_other: '{{count}} мин', - settingShuffleNow: 'Перемешать сейчас', - toastSuggested: '{{user}} предложил «{{title}}»', - toastSuggestedMany: '{{count}} новых предложений в очереди', - toastShuffled: 'Очередь перемешана', - toastJoined: 'Присоединился к сессии', - toastLoginFirst: 'Войди, прежде чем присоединяться к сессии', - toastSwitchServer: 'Сначала переключись на {{url}}, потом вставь снова', - toastNoAccountForServer: 'У тебя нет доступа к {{url}}. Попроси хоста прислать приглашение.', - toastSwitchFailed: 'Не удалось переключиться на {{url}}', - accountPickerTitle: 'Какой аккаунт?', - accountPickerSub: 'У тебя несколько аккаунтов для {{url}}. Выбери тот, под которым хочешь присоединиться.', - toastJoinFail: 'Не удалось присоединиться к сессии', - joinErrNotFound: 'Сессия не найдена', - joinErrEnded: 'Сессия завершена', - joinErrFull: 'Сессия заполнена', - joinErrKicked: 'Ты не можешь присоединиться к этой сессии', - joinErrNoUser: 'Нет активного сервера', - joinErrServerError: 'Не удалось присоединиться', - ctxAddToSession: 'Добавить в сессию Orbit', - ctxSuggestedToast: 'Предложено в сессию', - ctxSuggestFailed: 'Не удалось предложить — не присоединён', - ctxAddToSessionHost: 'Добавить в сессию Orbit', - ctxAddedHostToast: 'Добавлено в сессию', - ctxAddHostFailed: 'Не удалось добавить в сессию', - bulkConfirmTitle: 'Добавить всё в очередь Orbit?', - bulkConfirmBody: 'Это сбросит {{count}} треков в общую очередь за раз. Это много для твоих гостей. Продолжить?', - bulkConfirmYes: 'Добавить всё', - bulkConfirmNo: 'Отмена', - guestLive: 'Live', - guestPlaying: 'Сейчас играет', - guestPaused: 'Пауза', - guestLoading: 'Загрузка…', - guestSuggestions: 'Предложения', - guestUpNext: 'Далее', - guestUpNextEmpty: 'В очереди пусто. Открой контекстное меню трека и выбери «Добавить в сессию Orbit», чтобы предложить что-то.', - guestPendingTitle: 'Ожидание хоста', - guestPendingHint: 'Предложено — появится в очереди, когда хост примет.', - approvalTitle: 'Ожидают подтверждения', - approvalFrom: 'Предложено {{user}}', - approvalAccept: 'Принять', - approvalDecline: 'Отклонить', - guestUpNextMore: '+ ещё {{count}} в очереди хоста', - guestSubmitter: 'от {{user}}', - queueAddedByHost: 'Добавил хост', - queueAddedByYou: 'Добавил(а) ты', - queueAddedByUser: 'Добавил {{user}}', - guestEmpty: 'Предложений пока нет. Открой контекстное меню трека и выбери «Добавить в сессию Orbit».', - guestFooter: 'Хост управляет воспроизведением — ты не можешь изменять список.', - exitKickedTitle: 'Тебя забанили в сессии', - exitRemovedTitle: 'Тебя удалили из сессии', - exitEndedTitle: 'Хост завершил сессию', - exitHostTimeoutTitle: 'Хост недоступен', - exitHostTimeoutBody: '{{host}} давно не присылал обновления, поэтому «{{name}}» закрыта на твоей стороне. Ты можешь присоединиться снова в любое время по ссылке.', - exitKickedBody: '{{host}} забанил тебя в «{{name}}». Ты не можешь присоединиться снова.', - exitRemovedBody: '{{host}} удалил тебя из «{{name}}». Ты можешь присоединиться снова в любое время по ссылке.', - exitEndedBody: '«{{name}}» завершена. Надеюсь, тебе понравилось.', - exitOk: 'ОК', - }, - tray: { - playPause: 'Воспроизвести / Пауза', - nextTrack: 'Следующий трек', - previousTrack: 'Предыдущий трек', - showHide: 'Показать / Скрыть', - exitPsysonic: 'Закрыть Psysonic', - nothingPlaying: 'Ничего не воспроизводится', - }, - licenses: { - title: 'Лицензии открытого кода', - intro: 'Psysonic построен на программном обеспечении с открытым исходным кодом. Список ниже показывает каждую зависимость, поставляемую с приложением, с версией, лицензией и полным текстом лицензии.', - highlights: 'Ключевые зависимости', - searchPlaceholder: 'Поиск по имени, версии или лицензии…', - noResults: 'Нет совпадений.', - loading: 'Загрузка лицензий…', - loadError: 'Не удалось загрузить данные о лицензиях.', - noLicenseText: 'Текст лицензии для этой зависимости не включён.', - viewSource: 'Открыть исходник', - totalLine: '{{total}} зависимостей — {{cargo}} cargo, {{npm}} npm', - generatedAt: 'Последняя генерация {{date}}', - }, -}; diff --git a/src/locales/ru/albumDetail.ts b/src/locales/ru/albumDetail.ts new file mode 100644 index 00000000..67596d29 --- /dev/null +++ b/src/locales/ru/albumDetail.ts @@ -0,0 +1,48 @@ +export const albumDetail = { + back: 'Назад', + orbitDoubleClickHint: 'Двойной клик, чтобы добавить этот трек в очередь Orbit', + playAll: 'Воспроизвести всё', + shareAlbum: 'Поделиться альбомом', + enqueue: 'В очередь', + enqueueTooltip: 'Добавить весь альбом в очередь', + artistBio: 'Биография', + download: 'Скачать (ZIP)', + downloading: 'Загрузка…', + cacheOffline: 'Сохранить офлайн', + offlineCached: 'Доступно офлайн', + offlineDownloading: 'Кэширование… ({{n}} из {{total}})', + removeOffline: 'Удалить офлайн-копию', + offlineStorageFull: + 'Место для офлайн закончилось (лимит {{mb}} МБ). Освободите место в офлайн-библиотеке или увеличьте лимит в настройках.', + offlineStorageGoToLibrary: 'Офлайн-библиотека', + offlineStorageGoToSettings: 'Настройки', + favoriteAdd: 'В избранное', + favoriteRemove: 'Убрать из избранного', + favorite: 'Избранное', + noBio: 'Биография недоступна.', + moreByArtist: 'Ещё от {{artist}}', + tracksCount: 'Композиций: {{n}}', + goToArtist: 'Перейти к {{artist}}', + moreLabelAlbums: 'Другие альбомы на {{label}}', + trackTitle: 'Название', + trackAlbum: 'Альбом', + trackArtist: 'Исполнитель', + trackGenre: 'Жанр', + trackFormat: 'Формат', + trackFavorite: 'Избранное', + trackRating: 'Оценка', + trackDuration: 'Длительность', + trackTotal: 'Итого', + columns: 'Колонки', + resetColumns: 'Сбросить', + notFound: 'Альбом не найден.', + bioModal: 'Биография исполнителя', + bioClose: 'Закрыть', + ratingLabel: 'Оценка', + enlargeCover: 'Увеличить обложку', + filterSongs: 'Фильтр треков…', + sortNatural: 'По умолчанию', + sortByTitle: 'А–Я (название)', + sortByArtist: 'А–Я (исполнитель)', + sortByAlbum: 'А–Я (альбом)', +}; diff --git a/src/locales/ru/albums.ts b/src/locales/ru/albums.ts new file mode 100644 index 00000000..e50b0342 --- /dev/null +++ b/src/locales/ru/albums.ts @@ -0,0 +1,36 @@ +export const albums = { + title: 'Все альбомы', + sortByName: 'А–Я (альбом)', + sortByArtist: 'А–Я (исполнитель)', + sortNewest: 'Сначала новые', + sortRandom: 'Случайно', + yearFrom: 'С', + yearTo: 'По', + yearFilterClear: 'Сбросить год', + yearFilterLabel: 'Год', + compilationLabel: 'Сборники', + compilationOnly: 'Только сборники', + compilationHide: 'Скрыть сборники', + compilationTooltipAll: 'Все альбомы · клик: только сборники', + compilationTooltipOnly: 'Только сборники · клик: скрыть сборники', + compilationTooltipHide: 'Сборники скрыты · клик: показать всё', + select: 'Множественный выбор', + startSelect: 'Включить множественный выбор', + cancelSelect: 'Отмена', + selectionCount: '{{count}} выбрано', + downloadZips: 'Скачать ZIP-архивы', + addOffline: 'Добавить офлайн', + enqueueSelected_one: 'В очередь ({{count}})', + enqueueSelected_few: 'В очередь ({{count}})', + enqueueSelected_many: 'В очередь ({{count}})', + enqueueSelected_other: 'В очередь ({{count}})', + enqueueQueued_one: '{{count}} альбом добавлен в очередь', + enqueueQueued_few: '{{count}} альбома добавлены в очередь', + enqueueQueued_many: '{{count}} альбомов добавлены в очередь', + enqueueQueued_other: '{{count}} альбомов добавлены в очередь', + downloadingZip: 'Загрузка {{current}}/{{total}}: {{name}}', + downloadZipDone: '{{count}} ZIP-архив(ов) загружено', + downloadZipFailed: 'Не удалось скачать {{name}}', + offlineQueuing: 'Добавление {{count}} альбом(ов) в офлайн…', + offlineFailed: 'Не удалось добавить {{name}} офлайн', +}; diff --git a/src/locales/ru/artistDetail.ts b/src/locales/ru/artistDetail.ts new file mode 100644 index 00000000..03e7441b --- /dev/null +++ b/src/locales/ru/artistDetail.ts @@ -0,0 +1,43 @@ +export const artistDetail = { + back: 'Назад', + albums: 'Альбомы', + album: 'Альбом', + playAll: 'Воспроизвести всё', + shareArtist: 'Поделиться исполнителем', + shuffle: 'Перемешать', + radio: 'Радио', + loading: 'Загрузка…', + noRadio: 'Похожие треки для этого исполнителя не найдены.', + notFound: 'Исполнитель не найден.', + albumsBy: 'Альбомы — {{name}}', + topTracks: 'Популярные треки', + noAlbums: 'Альбомов нет.', + trackTitle: 'Название', + trackAlbum: 'Альбом', + trackDuration: 'Длительность', + favoriteAdd: 'В избранное', + favoriteRemove: 'Убрать из избранного', + favorite: 'Избранное', + albumCount_one: '{{count}} альбом', + albumCount_few: '{{count}} альбома', + albumCount_many: '{{count}} альбомов', + albumCount_other: '{{count}} альбомов', + openedInBrowser: 'Открыто в браузере', + featuredOn: 'Также участвует в', + similarArtists: 'Похожие исполнители', + cacheOffline: 'Сохранить дискографию офлайн', + offlineCached: 'Дискография сохранена', + offlineDownloading: 'Кэширование… ({{done}} из {{total}} альбомов)', + uploadImage: 'Загрузить фото исполнителя', + uploadImageError: 'Не удалось загрузить изображение', + releaseTypes: { + album: 'Альбом', + ep: 'EP', + single: 'Сингл', + compilation: 'Сборник', + live: 'Концерт', + soundtrack: 'Саундтрек', + remix: 'Ремикс', + other: 'Другое', + }, +}; diff --git a/src/locales/ru/artists.ts b/src/locales/ru/artists.ts new file mode 100644 index 00000000..a29d1bdb --- /dev/null +++ b/src/locales/ru/artists.ts @@ -0,0 +1,20 @@ +export const artists = { + title: 'Исполнители', + search: 'Поиск…', + all: 'Все', + gridView: 'Сетка', + listView: 'Список', + imagesOn: 'Фото исполнителей — больше трафика и нагрузка на систему', + imagesOff: 'Только инициалы — экономнее по трафику', + loadMore: 'Ещё', + notFound: 'Исполнители не найдены.', + albumCount_one: '{{count}} альбом', + albumCount_few: '{{count}} альбома', + albumCount_many: '{{count}} альбомов', + albumCount_other: '{{count}} альбомов', + selectionCount: '{{count}} выбрано', + select: 'Множественный выбор', + startSelect: 'Включить множественный выбор', + cancelSelect: 'Отмена', + addToPlaylist: 'В плейлист', +}; diff --git a/src/locales/ru/changelog.ts b/src/locales/ru/changelog.ts new file mode 100644 index 00000000..1ccb605f --- /dev/null +++ b/src/locales/ru/changelog.ts @@ -0,0 +1,5 @@ +export const changelog = { + modalTitle: 'Что нового', + dontShowAgain: 'Больше не показывать', + close: 'Понятно', +}; diff --git a/src/locales/ru/common.ts b/src/locales/ru/common.ts new file mode 100644 index 00000000..24dc0474 --- /dev/null +++ b/src/locales/ru/common.ts @@ -0,0 +1,56 @@ +export const common = { + albums: 'Альбомы', + album: 'Альбом', + loading: 'Загрузка…', + loadingMore: 'Загрузка…', + loadingPlaylists: 'Загрузка плейлистов…', + noAlbums: 'Альбомов нет.', + downloading: 'Скачивание…', + downloadZip: 'Скачать (ZIP)', + back: 'Назад', + cancel: 'Отмена', + save: 'Сохранить', + delete: 'Удалить', + use: 'Использовать', + add: 'Добавить', + new: 'Новое', + active: 'Активен', + download: 'Скачать', + chooseDownloadFolder: 'Выбрать папку', + noFolderSelected: 'Папка не выбрана', + rememberDownloadFolder: 'Запомнить папку', + filterGenre: 'Фильтр по жанру', + filterSearchGenres: 'Поиск жанров…', + filterNoGenres: 'Нет совпадений', + filterClear: 'Сбросить', + favorites: 'Избранное', + favoritesTooltipOff: 'Показывать только избранное', + favoritesTooltipOn: 'Показать всё', + play: 'Воспроизвести', + bulkSelected: 'Выбрано: {{count}}', + clearSelection: 'Сбросить выбор', + bulkAddToPlaylist: 'В плейлист', + bulkRemoveFromPlaylist: 'Убрать из плейлиста', + bulkClear: 'Снять выделение', + updaterAvailable: 'Доступно обновление', + updaterVersion: 'Версия {{version}} доступна', + updaterWebsite: 'Сайт', + updaterModalTitle: 'Доступна новая версия', + updaterChangelog: 'Что нового', + updaterDownloadBtn: 'Скачать сейчас', + updaterSkipBtn: 'Пропустить эту версию', + updaterRemindBtn: 'Напомнить позже', + updaterDone: 'Загрузка завершена', + updaterShowFolder: 'Показать в папке', + updaterInstallHint: 'Закройте Psysonic и запустите установщик вручную.', + updaterAurHint: 'Установить обновление через AUR:', + updaterErrorMsg: 'Ошибка загрузки', + updaterRetryBtn: 'Повторить', + durationHoursMinutes: '{{hours}}ч {{minutes}}мин', + durationMinutesOnly: '{{minutes}}мин', + updaterOpenGitHub: 'Открыть на GitHub', + filters: 'Фильтры', + more: 'еще', + yearRange: 'Диапазон лет', + clearAll: 'Очистить всё', +}; diff --git a/src/locales/ru/composerDetail.ts b/src/locales/ru/composerDetail.ts new file mode 100644 index 00000000..3760871a --- /dev/null +++ b/src/locales/ru/composerDetail.ts @@ -0,0 +1,11 @@ +export const composerDetail = { + back: 'Назад', + notFound: 'Композитор не найден.', + about: 'Об этом композиторе', + works: 'Произведения', + noWorks: 'Произведения не найдены.', + workCount_one: '{{count}} произведение', + workCount_other: '{{count}} произведений', + shareComposer: 'Поделиться композитором', + unknownComposer: 'Композитор', +}; diff --git a/src/locales/ru/composers.ts b/src/locales/ru/composers.ts new file mode 100644 index 00000000..a7ae59ea --- /dev/null +++ b/src/locales/ru/composers.ts @@ -0,0 +1,10 @@ +export const composers = { + title: 'Композиторы', + search: 'Поиск…', + notFound: 'Композиторы не найдены.', + unsupported: 'Просмотр по композиторам требует Navidrome 0.55 или новее.', + loadFailed: 'Не удалось загрузить композиторов.', + retry: 'Повторить', + involvedIn_one: 'Участие в {{count}} альбоме', + involvedIn_other: 'Участие в {{count}} альбомах', +}; diff --git a/src/locales/ru/connection.ts b/src/locales/ru/connection.ts new file mode 100644 index 00000000..a1b7ce56 --- /dev/null +++ b/src/locales/ru/connection.ts @@ -0,0 +1,31 @@ +export const connection = { + connected: 'Подключено', + connectedTo: 'Сервер: {{server}}', + disconnected: 'Нет связи', + disconnectedFrom: 'Сервер {{server}} недоступен — нажмите для настроек', + checking: 'Подключение…', + extern: 'Внешний', + offlineTitle: 'Нет связи с сервером', + offlineSubtitle: 'Сервер {{server}} недоступен. Проверьте сеть и адрес.', + offlineModeBanner: 'Офлайн — воспроизведение из локального кэша', + offlineNoCacheBanner: 'Нет соединения с сервером — {{server}} недоступен', + offlineLibraryTitle: 'Офлайн-библиотека', + offlineLibraryEmpty: + 'Пока ничего не сохранено. Подключитесь к сети, откройте альбом и нажмите «Сохранить офлайн».', + offlineAlbumCount_one: '{{n}} альбом', + offlineAlbumCount_few: '{{n}} альбома', + offlineAlbumCount_many: '{{n}} альбомов', + offlineAlbumCount_other: '{{n}} альбомов', + offlineFilterAll: 'Всё', + offlineFilterAlbums: 'Альбомы', + offlineFilterPlaylists: 'Плейлисты', + offlineFilterArtists: 'Дискографии', + retry: 'Повторить', + serverSettings: 'Настройки сервера', + switchServerTitle: 'Сменить сервер', + switchServerHint: 'Нажмите, чтобы выбрать другой сохранённый сервер.', + manageServers: 'Управление серверами…', + switchFailed: 'Не удалось переключиться — сервер недоступен.', + lastfmConnected: 'Last.fm: @{{user}}', + lastfmSessionInvalid: 'Сессия недействительна — подключите снова', +}; diff --git a/src/locales/ru/contextMenu.ts b/src/locales/ru/contextMenu.ts new file mode 100644 index 00000000..9da16aa2 --- /dev/null +++ b/src/locales/ru/contextMenu.ts @@ -0,0 +1,35 @@ +export const contextMenu = { + playNow: 'Играть сейчас', + playNext: 'Играть следующим', + addToQueue: 'В конец очереди', + enqueueAlbum: 'Альбом в очередь', + enqueueAlbums_one: '{{count}} альбом в очередь', + enqueueAlbums_few: '{{count}} альбома в очередь', + enqueueAlbums_many: '{{count}} альбомов в очередь', + enqueueAlbums_other: '{{count}} альбомов в очередь', + startRadio: 'Радио по похожим', + instantMix: 'Instant Mix', + instantMixFailed: 'Не удалось собрать Instant Mix — ошибка сервера или плагина.', + cliMixNeedsTrack: 'Ничего не играет — сначала начните воспроизведение, затем снова выполните команду микса.', + lfmLove: 'Любимое на Last.fm', + lfmUnlove: 'Убрать с Last.fm', + favorite: 'В избранное', + favoriteArtist: 'Исполнитель в избранное', + favoriteAlbum: 'Альбом в избранное', + unfavorite: 'Убрать из избранного', + unfavoriteArtist: 'Убрать исполнителя из избранного', + unfavoriteAlbum: 'Убрать альбом из избранного', + removeFromQueue: 'Убрать из очереди', + removeFromPlaylist: 'Убрать из плейлиста', + openAlbum: 'Открыть альбом', + goToArtist: 'К исполнителю', + download: 'Скачать (ZIP)', + addToPlaylist: 'В плейлист', + selectedPlaylists: '{{count}} плейлистов выбрано', + selectedAlbums: '{{count}} альбомов выбрано', + selectedArtists: '{{count}} исполнителей выбрано', + songInfo: 'Сведения о треке', + shareLink: 'Копировать ссылку для обмена', + shareCopied: 'Ссылка для обмена скопирована в буфер.', + shareCopyFailed: 'Не удалось скопировать в буфер.', +}; diff --git a/src/locales/ru/deviceSync.ts b/src/locales/ru/deviceSync.ts new file mode 100644 index 00000000..12400ecb --- /dev/null +++ b/src/locales/ru/deviceSync.ts @@ -0,0 +1,73 @@ +export const deviceSync = { + title: 'Синхронизация устройства', + targetFolder: 'Папка назначения', + noFolderChosen: 'Папка не выбрана', + selectDrive: 'Выберите диск…', + refreshDrives: 'Обновить диски', + noDrivesDetected: 'Съёмные диски не обнаружены', + browseManual: 'Обзор вручную…', + free: 'свободно', + notMountedVolume: 'Цель не находится на смонтированном томе. Диск мог быть отключён.', + chooseFolder: 'Выбрать…', + filenameTemplate: 'Шаблон имени файла', + targetDevice: 'Целевое устройство', + templateHint: 'Переменные: {artist}, {album}, {title}, {track_number}, {disc_number}, {year}', + cleanupButton: 'Удалить файлы вне выборки', + cleanupNothingToDelete: 'Нечего удалять — устройство уже синхронизировано.', + confirmCleanup: 'Удалить {{count}} файл(ов) с устройства, не входящих в текущую выборку. Продолжить?', + cleanupComplete: '{{count}} файл(ов) удалено с устройства.', + selectedSources: 'Выбранные источники', + noSourcesSelected: 'Источники не выбраны. Нажмите на элементы в браузере, чтобы добавить их.', + clearAll: 'Очистить всё', + tabPlaylists: 'Плейлисты', + tabAlbums: 'Альбомы', + tabArtists: 'Исполнители', + searchPlaceholder: 'Поиск…', + syncButton: 'Синхронизировать на устройство', + actionTransfer: 'Перенести на устройство', + actionDelete: 'Удалить с устройства', + actionApplyAll: 'Применить все изменения', + templatePreview: 'Предпросмотр', + templatePresetStandard: 'Стандарт', + templatePresetMultiDisc: 'Мульти-диск', + templatePresetAltFolder: 'Альт. папка', + tokenSlashHint: '/ = разделитель папок', + cancel: 'Отмена', + noTargetDir: 'Сначала выберите папку назначения.', + noSources: 'Выберите хотя бы один источник.', + noTracks: 'В выбранных источниках не найдено треков.', + fetchError: 'Ошибка загрузки треков с сервера.', + syncComplete: 'Синхронизация завершена.', + dismiss: 'Закрыть', + cancelSync: 'Отмена', + syncCancelled: 'Синхронизация отменена ({{done}} / {{total}} перенесено).', + colName: 'Название', + colType: 'Тип', + colStatus: 'Статус', + onDevice: 'Управление устройством', + addSources: 'Добавить…', + syncResult: '{{done}} перенесено, {{skipped}} уже актуально ({{total}} всего)', + deleteFromDevice: 'Пометить для удаления ({{count}})', + confirmDelete: 'Удалить {{count}} запись(ей) с устройства: {{names}}?', + deleteComplete: '{{count}} запись(ей) удалено с устройства.', + manifestImported: 'Импортировано {{count}} источник(ов) из манифеста устройства.', + statusSynced: 'Синхронизировано', + statusPending: 'Ожидает', + statusDeletion: 'Удаление', + markForDeletion: 'Пометить для удаления', + removeSource: 'Удалить', + undoDeletion: 'Отменить удаление', + syncInBackground: 'Синхронизация запущена в фоне — можно перейти в другой раздел.', + syncInProgress: '{{done}} / {{total}} треков…', + syncSummary: 'Сводка синхронизации', + calculating: 'Вычисление необходимых данных…', + filesToAdd: 'Файлы для добавления:', + filesToDelete: 'Файлы для удаления:', + netChange: 'Чистое изменение:', + availableSpace: 'Доступное место на диске:', + spaceWarning: 'Предупреждение: на целевом устройстве недостаточно сообщаемого места.', + proceed: 'Продолжить синхронизацию', + notEnoughSpace: 'Обнаружено недостаточно физического места на диске!', + liveSearch: 'Live', + randomAlbumsLabel: 'Случайные альбомы', +}; diff --git a/src/locales/ru/entityRating.ts b/src/locales/ru/entityRating.ts new file mode 100644 index 00000000..d6ebad33 --- /dev/null +++ b/src/locales/ru/entityRating.ts @@ -0,0 +1,9 @@ +export const entityRating = { + albumShort: 'Оценка альбома', + artistShort: 'Оценка исполнителя', + albumAriaLabel: 'Оценка альбома', + artistAriaLabel: 'Оценка исполнителя', + selectedArtistsRatingAriaLabel: 'Звёздная оценка для выбранных исполнителей ({{count}})', + selectedAlbumsRatingAriaLabel: 'Звёздная оценка для выбранных альбомов ({{count}})', + saveFailed: 'Не удалось сохранить оценку.', +}; diff --git a/src/locales/ru/favorites.ts b/src/locales/ru/favorites.ts new file mode 100644 index 00000000..e975e695 --- /dev/null +++ b/src/locales/ru/favorites.ts @@ -0,0 +1,21 @@ +export const favorites = { + title: 'Избранное', + empty: 'Пока ничего не отмечено звёздочкой.', + artists: 'Исполнители', + albums: 'Альбомы', + songs: 'Треки', + enqueueAll: 'Всё в очередь', + playAll: 'Воспроизвести всё', + removeSong: 'Убрать из избранного', + stations: 'Радиостанции', + showingFiltered: 'Показано {{filtered}} из {{total}} ({{artist}})', + showingCount: 'Показано {{filtered}} из {{total}}', + clearArtistFilter: 'Сбросить фильтр исполнителя', + noFilterResults: 'Нет результатов с выбранными фильтрами.', + allArtists: 'Все исполнители', + topArtists: 'Топ исполнителей по избранному', + topArtistsSongCount_one: '{{count}} трек', + topArtistsSongCount_few: '{{count}} трека', + topArtistsSongCount_many: '{{count}} треков', + topArtistsSongCount_other: '{{count}} трека', +}; diff --git a/src/locales/ru/folderBrowser.ts b/src/locales/ru/folderBrowser.ts new file mode 100644 index 00000000..077da41f --- /dev/null +++ b/src/locales/ru/folderBrowser.ts @@ -0,0 +1,4 @@ +export const folderBrowser = { + empty: 'Папка пуста', + error: 'Ошибка загрузки', +}; diff --git a/src/locales/ru/genres.ts b/src/locales/ru/genres.ts new file mode 100644 index 00000000..04104556 --- /dev/null +++ b/src/locales/ru/genres.ts @@ -0,0 +1,14 @@ +export const genres = { + title: 'Жанры', + genreCount: 'Жанры', + albumCount_one: '{{count}} альбом', + albumCount_few: '{{count}} альбома', + albumCount_many: '{{count}} альбомов', + albumCount_other: '{{count}} альбомов', + loading: 'Загрузка жанров…', + empty: 'Жанры не найдены.', + albumsLoading: 'Загрузка альбомов…', + albumsEmpty: 'В этом жанре альбомов нет.', + loadMore: 'Ещё', + back: 'Назад', +}; diff --git a/src/locales/ru/help.ts b/src/locales/ru/help.ts new file mode 100644 index 00000000..28db0e4c --- /dev/null +++ b/src/locales/ru/help.ts @@ -0,0 +1,105 @@ +export const help = { + title: 'Справка', + searchPlaceholder: 'Поиск по справке…', + noResults: 'Ничего не найдено. Попробуйте другой запрос.', + s1: 'С чего начать', + q1: 'Какие серверы поддерживаются?', + a1: 'Psysonic в первую очередь сделан для Navidrome и полностью совместим с Subsonic — Gonic, Airsonic, LMS и другие серверы Subsonic-API тоже работают. Некоторые расширенные функции (рейтинги, умные плейлисты, обмен Magic String, управление пользователями) требуют Navidrome.', + q2: 'Как добавить сервер?', + a2: 'Настройки → Серверы → Добавить сервер. Введите URL (например, http://192.168.1.100:4533), имя пользователя и пароль. Psysonic проверяет соединение перед сохранением — при ошибке ничего не сохраняется. Можно добавить сколько угодно серверов и переключаться между ними в шапке; одновременно активен только один.', + q3: 'Краткий обзор интерфейса?', + a3: 'Боковая панель (слева) для навигации, Mainstage / страницы по центру, плеер внизу, панель Очереди справа (открывается через иконку справа вверху рядом с индикатором Now Playing). Поиск вверху работает по всей библиотеке; «Now Playing» показывает, что слушают другие пользователи на том же сервере Navidrome.', + s2: 'Воспроизведение и Очередь', + q4: 'Как пользоваться очередью?', + a4: 'Откройте панель Очереди справа вверху. Перетаскивайте строки, чтобы менять порядок, выносите их за пределы для удаления, или используйте панель инструментов для перемешивания, сохранения очереди как плейлиста или перехода к треку. Перетаскивайте строки из панели в другие места как способ переноса.', + q5: 'Gapless и Crossfade — в чём разница?', + a5: 'Gapless преднабуферизирует следующий трек, чтобы между песнями не было тишины (идеально для концертных альбомов и DJ-миксов). Crossfade плавно затухает текущий трек, пока следующий нарастает (1–10 с — для перемешанных миксов). Они взаимоисключающи — включение одного отключает другое. Настройте оба в Настройки → Аудио.', + q6: 'Что такое Бесконечная очередь?', + a6: 'Когда очередь заканчивается и Повтор выключен, Psysonic тихо добавляет похожие/случайные треки из вашей библиотеки, чтобы воспроизведение не останавливалось. Авто-добавленные треки появляются под разделителем «— Добавлено автоматически —». Включается иконкой бесконечности в шапке очереди; ограничьте автодобавление жанром в Настройки → Очередь.', + q7: 'Множественный выбор и Shift+клик диапазона?', + a7: 'Включите «Выбор» на Альбомах / Новинках / Random Albums / Плейлистах. Клик переключает элемент, затем удерживайте Shift и кликните другой элемент — всё между ними в видимом порядке выделится. Shift+клики расширяют от последнего кликнутого якоря. Панель инструментов сверху предлагает массовые действия (очередь, скачивание, удаление и т. д.).', + q8: 'Сочетания клавиш и глобальные хоткеи?', + a8: 'По умолчанию: Пробел = Воспроизведение / Пауза, Esc = выйти из полного экрана / закрыть модалки, F1 = памятка по сочетаниям. Настройки → Ввод позволяет переназначить любое внутри-приложенческое действие (включая аккорды вроде Ctrl+Shift+P) и задать системные глобальные сочетания, работающие даже когда Psysonic в фоне или свёрнут. Медиа-клавиши (Воспр./Пауза, Далее, Назад) работают на всех платформах.', + s3: 'Аудио-инструменты', + q9: 'Режимы Replay Gain?', + a9: 'Настройки → Аудио → Replay Gain. Режим Трек нормализует каждую песню к целевому уровню. Режим Альбом сохраняет кривую громкости внутри альбома. Режим Авто выбирает Трек или Альбом в зависимости от того, происходит ли очередь из одного альбома. Треки без тегов Replay Gain используют настраиваемый предусилитель.', + q10: 'Что такое Smart Loudness Normalization (LUFS)?', + a10: 'Современная альтернатива Replay Gain в Настройки → Аудио. Psysonic анализирует каждый трек по LUFS / EBU R128 и сохраняет результат, чтобы громкость была единой по всей библиотеке — включая треки без Replay Gain тегов. Холодный анализ работает в фоне и использует 35–40 % CPU около 1 минуты, потом 0. Установите целевую громкость (по умолчанию −10 LUFS) один раз.', + q11: 'EQ и AutoEQ?', + a11: '10-полосный параметрический EQ в Настройки → Аудио → Эквалайзер с ручными полосами и пресетами. AutoEQ рядом подгружает измеренный профиль коррекции для модели ваших наушников из базы AutoEQ и применяет его к полосам автоматически — выберите наушники, EQ настроится на правильную кривую.', + q12: 'Как переключить устройство вывода аудио?', + a12: 'Настройки → Аудио → Устройство вывода. Psysonic перечисляет все доступные выходы и переключается мгновенно при выборе. Кнопка обновления находит устройства, подключённые после запуска. На Linux ALSA-имена вроде «sysdefault» автоматически очищаются для удобства чтения.', + q13: 'Что такое Hot Cache?', + a13: 'Hot Cache предзагружает текущий трек и следующие в RAM и на диск, чтобы воспроизведение начиналось без задержек буферизации — особенно полезно на медленных / удалённых серверах. Вытеснение срабатывает при достижении лимита размера. Настройте размер и задержку дебаунса (чтобы быстрые скипы не приводили к лишним загрузкам) в Настройки → Аудио.', + s4: 'Библиотека и Открытие', + q14: 'Как работают рейтинги и Skip-to-1★?', + a14: 'Psysonic поддерживает рейтинг 1–5 звёзд через OpenSubsonic (Navidrome ≥ 0.53). Оценивайте треки в списках, в контекстном меню или в плеере под именем исполнителя; альбомы — на странице альбома; исполнителей — на странице исполнителя. Skip-to-1★ (Настройки → Библиотека → Рейтинги) автоматически ставит 1 звезду после настраиваемого числа последовательных скипов. Та же панель позволяет задать минимальный рейтинг как фильтр для генерируемых миксов.', + q15: 'Как просматривать — Папки, Жанры, Треки?', + a15: 'Просмотр папок (боковая панель) ходит по дереву музыкальной директории сервера в Miller-column раскладке — клик по папке для входа, клик по треку или иконке воспроизведения папки для проигрывания / добавления. Жанры используют tag-cloud вид с размером по числу треков; клик по жанру открывает его. Треки — это плоский хаб библиотеки с виртуальным списком, сортируемым по столбцам, и живым поиском.', + q16: 'Поиск и расширенный поиск?', + a16: 'Поиск в шапке выполняет живой поиск по исполнителям, альбомам и трекам по мере набора. Откройте Расширенный поиск (боковая панель) для более богатого вида: фильтры по году, жанру, рейтингу, формату, каналам, частоте дискретизации, BPM, настроению — комбинируемые. Правый клик по любому результату открывает то же контекстное меню, что и в других местах.', + q17: 'Что такое Миксы (Random / Genre / Super Genre / Lucky)?', + a17: 'Random Mix строит плейлист случайных треков из библиотеки; фильтр ключевых слов исключает аудиокниги, комедию и т. д. по подстрокам жанра / названия / альбома. Super Genre Mix группирует библиотеку в широкие стили (Рок, Метал, Электронная, Джаз, Классика…) и строит сфокусированный микс. Lucky Mix использует историю прослушивания, рейтинги и похожие треки AudioMuse-AI для составления мгновенного плейлиста по одному клику.', + q18: 'Страница статистики?', + a18: 'Статистика (боковая панель) показывает топ исполнителей, топ альбомов, топ треков, разбивку по жанрам, время прослушивания со временем и охват по библиотеке, если настроено несколько музыкальных папок. Несколько видов экспортируются как изображение-карточка для шаринга.', + q19: 'Как скачать альбом как ZIP?', + a19: 'Страница альбома → «Скачать (ZIP)». Сервер сначала упаковывает альбом — для больших или lossless альбомов (FLAC / WAV) индикатор прогресса появляется только после завершения упаковки и начала передачи. Это нормально.', + s5: 'Тексты', + q20: 'Откуда берутся тексты?', + a20: 'Три источника, настраиваемые в Настройки → Тексты: ваш сервер Navidrome (встроенные / OpenSubsonic тексты), LRCLIB (синхронизированные тексты от сообщества) и NetEase Cloud Music (большой азиатский + международный каталог). Каждый источник можно включить / выключить и переставить перетаскиванием.', + q21: 'Как смотреть тексты во время воспроизведения?', + a21: 'Кликните на иконку микрофона в плеере, чтобы открыть вкладку Тексты в панели очереди. Синхронизированные тексты автоматически прокручиваются и поддерживают клик-для-перехода; обычный текст прокручивается как статический блок. Включите Полноэкранный плеер через обложку плеера для иммерсивного вида текстов с mesh-blob фоном.', + s6: 'Шаринг и Социальные функции', + q22: 'Что такое Magic Strings?', + a22: 'Magic Strings — это короткие копи-паст токены для шаринга вещей между пользователями Psysonic без сторонних серверов. Server-Invite строки позволяют другу присоединиться к вашему Navidrome одной вставкой; Magic Strings альбомов / исполнителей / очередей открывают тот же альбом / исполнителя / очередь у получателя. Создавайте через меню «Поделиться», вставляйте в строку поиска для использования.', + q23: 'Что такое Orbit?', + a23: 'Orbit — это синхронное совместное прослушивание: хост проигрывает трек, каждый гость слышит его синхронно, и гости могут предлагать песни, которые хост может принять в очередь. Запустите сессию через кнопку Orbit в шапке, поделитесь ссылкой-приглашением, и другие могут присоединиться с любой установки Psysonic. Хост контролирует воспроизведение (скип, перемотка, очередь) — гости получают вид в реальном времени и поле для предложений. Сессии эфемерные и завершаются, когда хост их закрывает.', + q24: 'Что такое выпадающее меню Now Playing?', + a24: 'Иконка трансляции справа вверху показывает, что слушают другие пользователи на вашем сервере Navidrome прямо сейчас, обновляется каждые 10 секунд. Ваша запись исчезает в момент паузы. По серверам — пользователи на другом активном сервере не показываются.', + s7: 'Персонализация', + q25: 'Темы и планировщик тем?', + a25: 'Настройки → Внешний вид → Тема выбирает из 60+ тем в 8 группах (Psysonic, Mediaplayer, Операционные системы, Игры, Фильмы, Сериалы, Соцсети, Open Source Classics — Catppuccin / Nord / Gruvbox / Nightfox / Dracula). Auto-Switch Theme позволяет задать дневную и ночную тему со временем переключения, чтобы Psysonic переключался автоматически.', + q26: 'Можно настроить боковую панель, Главную и страницу исполнителя?', + a26: 'Да — Настройки → Персонализация. Кастомизатор боковой панели позволяет перетаскивать nav-элементы в нужном порядке и скрывать те, что не используются. Кастомизатор Главной включает/выключает каждый ряд Mainstage (Hero, Recent, Discover, Recently Played, Starred…). Кастомизатор страницы исполнителя меняет порядок секций (Top Songs, Альбомы, Синглы, Сборники, Похожие исполнители и т. д.) и позволяет скрывать те, на которые вы не смотрите.', + q27: 'Что такое Mini Player?', + a27: 'Маленькое плавающее окно с обложкой, элементами управления воспроизведением и компактной очередью. Открывается из иконки mini-player в плеере или сочетанием клавиш. Окно запоминает позицию и размер между сессиями. На Windows mini-webview предсоздаётся при запуске для мгновенного открытия; Linux / macOS включают это опционально через Настройки → Внешний вид → Предзагружать mini player.', + q28: 'Что такое Floating Player Bar?', + a28: 'Опциональный стиль плеера (Настройки → Внешний вид), который отделяется от нижней границы с тематическим фоном, акцентной рамкой, скруглённой обложкой и центрированной секцией громкости. Полезно на высоких мониторах или с компактными темами.', + q29: 'Превью трека по наведению?', + a29: 'Наведите мышь на строку трека, кликните маленькую кнопку превью на обложке или вызовите превью из контекстного меню — Psysonic стримит первые ~15 с через тот же Rust-аудио-движок, чтобы применилась нормализация громкости. Полезно для быстрого знакомства с альбомом, который вы ещё не слушали.', + q30: 'Таймер сна?', + a30: 'Кликните иконку луны в плеере, чтобы открыть таймер сна. Выберите длительность (или «конец текущего трека») и Psysonic плавно затухнет и поставит на паузу в конце. На кнопке отображается круговое кольцо и обратный отсчёт во время работы таймера.', + q31: 'Масштаб UI, шрифт, стиль seekbar?', + a31: 'Настройки → Внешний вид — Масштаб интерфейса (80–125 % без влияния на системный размер шрифта), Шрифт (10 UI шрифтов, включая IBM Plex Mono, Fira Code, Geist, Golos Text…), Стиль Seekbar (Волна анализированная / pseudowave детерминированная / Линия и Точка / Полоса / Толстая полоса / Сегментированный / Неон / Импульсная волна / Шлейф частиц / Жидкое заполнение / Ретро-плёнка).', + s8: 'Опытный пользователь', + q32: 'Управление плеером из командной строки?', + a32: 'Бинарь Psysonic также служит пультом дистанционного управления. Примеры: psysonic --player play / pause / next / prev, --player volume 75, --player seek 15, --player shuffle, --player repeat off|all|one, --player rating 1-5. Переключайте серверы, аудиоустройства, библиотеки; запускайте Instant Mix; ищите исполнителей / альбомы / треки. Полный список через psysonic --player --help. Shell-автодополнение для bash и zsh через psysonic completions.', + q33: 'Умные плейлисты (Navidrome)?', + a33: 'Умные плейлисты — это динамические плейлисты на стороне Navidrome, определяемые правилами (жанр = Рок И год > 2020 и т. д.). Страница Плейлисты в Psysonic позволяет создавать, редактировать и удалять их с визуальным редактором правил — Psysonic общается с Navidrome native API для этого. Они ведут себя как обычные плейлисты в остальной части приложения и обновляются автоматически при изменении библиотеки.', + q34: 'Резервная копия и восстановление настроек?', + a34: 'Настройки → Хранилище → Резервное копирование экспортирует профили серверов, темы, сочетания клавиш и другие настройки в один JSON файл. Импортируйте файл на другой машине или после переустановки, чтобы восстановить всё сразу. Пароли серверов включены — храните файл в надёжном месте.', + q35: 'Где смотреть все open-source лицензии?', + a35: 'Настройки → Система → Open Source Licenses. Полный список зависимостей (cargo crates и npm пакеты) поставляется со встроенными текстами лицензий. Кликните на запись для полного текста; выделенный блок сверху подсвечивает узнаваемые библиотеки (Tauri, React, rodio, symphonia и т. д.).', + s9: 'Офлайн и Sync', + q36: 'Офлайн-режим — кэширование альбомов и плейлистов?', + a36: 'Откройте любой альбом или плейлист и кликните иконку загрузки в шапке — Psysonic кэширует каждый трек локально, чтобы он играл с диска без сетевого вызова. Страница Офлайн-библиотека (боковая панель) показывает всё кэшированное, прогресс текущих загрузок и позволяет удалять записи иконкой корзины (появляется после завершения загрузки).', + q37: 'Лимит офлайн-хранилища?', + a37: 'Настройки → Библиотека → Офлайн позволяет задать максимальный размер кэша. При достижении лимита кнопка загрузки на странице альбома показывает предупреждающий баннер. Освободите место, удалив альбомы или плейлисты со страницы Офлайн-библиотека.', + q38: 'Device Sync — копирование музыки на USB / SD?', + a38: 'Device Sync (боковая панель) копирует альбомы, плейлисты или целых исполнителей на внешний диск для офлайн-прослушивания на других устройствах. Выберите целевую папку, выберите источники из вкладок браузера, нажмите «Перенести на устройство». Psysonic пишет манифест (psysonic-sync.json), чтобы знать, какие файлы уже там, даже если переоткрыть Device Sync на другой ОС с другим шаблоном имени файла. Шаблоны поддерживают токены {artist} / {album} / {title} / {track_number} / {disc_number} / {year} с / как разделителем папок.', + s10: 'Интеграции и Устранение неполадок', + q39: 'Скробблинг Last.fm?', + a39: 'Настройки → Интеграции → Last.fm. Подключите аккаунт один раз, и Psysonic скробблит напрямую в Last.fm — настройка Navidrome не нужна. Скроббл отправляется после прослушивания 50 % трека. Now-playing пинги отправляются в начале.', + q40: 'Discord Rich Presence?', + a40: 'Настройки → Интеграции → Discord показывает текущий трек в вашем профиле Discord. Выберите между иконкой приложения, обложками с вашего сервера (через getAlbumInfo2 — нужен публично доступный сервер) или обложками Apple Music. Кастомизируйте отображаемые строки (детали, состояние, тултип) с помощью токен-шаблонов.', + q41: 'Даты туров Bandsintown?', + a41: 'Включается в Настройки → Интеграции → Now-Playing Info. Вкладка Now Playing на странице Now Playing затем показывает предстоящие даты туров для играющего исполнителя через Bandsintown widget API. По умолчанию выключено — никаких запросов до включения.', + q42: 'Internet Radio — воспроизведение живых стримов?', + a42: 'Internet Radio (боковая панель) проигрывает любой live-стрим, сохранённый на вашем сервере Navidrome (добавляйте станции через Navidrome admin UI). Воспроизведение работает через HTML5 audio движок браузера — большинство настроек EQ / Replay Gain / Loudness не применяются к радио, но ICY-метаданные (текущее имя песни) отображаются. Поддерживает MP3, AAC, OGG Vorbis и большинство HLS стримов; поддержка кодеков зависит от платформы.', + q43: 'Тест соединения не проходит — что делать?', + a43: 'Дважды проверьте URL включая порт (например, http://192.168.1.100:4533). В локальной сети http:// часто работает там, где https:// не работает (нет сертификата). Убедитесь, что firewall не блокирует порт и что имя пользователя и пароль правильные. Если сервер за reverse proxy, попробуйте сначала прямой URL для изоляции причины.', + q44: 'Обложки и изображения исполнителей загружаются медленно.', + a44: 'Изображения подгружаются с сервера при первом просмотре, затем кэшируются локально на 30 дней. Если хранилище сервера медленное, первый визит на страницу может занять момент; последующие визиты мгновенные. Hot Cache также помогает с треками, но кэш изображений независим.', + q45: 'Проблемы Linux — чёрный экран или нет звука?', + a45: 'Чёрный экран обычно проблема GPU / EGL драйвера в WebKitGTK — запускайте с GDK_BACKEND=x11 WEBKIT_DISABLE_COMPOSITING_MODE=1 WEBKIT_DISABLE_DMABUF_RENDERER=1 (AUR / .deb / .rpm установщики устанавливают это автоматически). Для аудио убедитесь, что PipeWire или PulseAudio запущены. Пропадание звука после спящего режима / пробуждения теперь обрабатывается автоматически post-sleep recovery hook.', +}; diff --git a/src/locales/ru/hero.ts b/src/locales/ru/hero.ts new file mode 100644 index 00000000..fb0ec2e8 --- /dev/null +++ b/src/locales/ru/hero.ts @@ -0,0 +1,6 @@ +export const hero = { + eyebrow: 'Альбом дня', + playAlbum: 'Воспроизвести альбом', + enqueue: 'В очередь', + enqueueTooltip: 'Добавить весь альбом в очередь', +}; diff --git a/src/locales/ru/home.ts b/src/locales/ru/home.ts new file mode 100644 index 00000000..087aa1b8 --- /dev/null +++ b/src/locales/ru/home.ts @@ -0,0 +1,21 @@ +export const home = { + hero: 'Подборка', + starred: 'Личное избранное', + recent: 'Недавно добавлено', + mostPlayed: 'Популярное', + recentlyPlayed: 'Недавно проиграно', + losslessAlbums: 'Lossless-альбомы', + discover: 'Обзор', + discoverSongs: 'Открыть треки', + loadMore: 'Ещё', + discoverMore: 'Смотреть ещё', + discoverArtists: 'Исполнители', + discoverArtistsMore: 'Все исполнители', + becauseYouLike: 'Потому что вы слушали…', + becauseYouLikeFor: 'Потому что вы слушали {{artist}}', + similarTo: 'Похоже на {{artist}}', + becauseYouLikeTracks_one: '{{count}} трек', + becauseYouLikeTracks_few: '{{count}} трека', + becauseYouLikeTracks_many: '{{count}} треков', + becauseYouLikeTracks_other: '{{count}} треков', +}; diff --git a/src/locales/ru/index.ts b/src/locales/ru/index.ts new file mode 100644 index 00000000..3d7059ac --- /dev/null +++ b/src/locales/ru/index.ts @@ -0,0 +1,91 @@ +import { sidebar } from './sidebar'; +import { home } from './home'; +import { hero } from './hero'; +import { search } from './search'; +import { nowPlaying } from './nowPlaying'; +import { contextMenu } from './contextMenu'; +import { sharePaste } from './sharePaste'; +import { albumDetail } from './albumDetail'; +import { entityRating } from './entityRating'; +import { artistDetail } from './artistDetail'; +import { favorites } from './favorites'; +import { randomLanding } from './randomLanding'; +import { randomAlbums } from './randomAlbums'; +import { genres } from './genres'; +import { randomMix } from './randomMix'; +import { luckyMix } from './luckyMix'; +import { albums } from './albums'; +import { tracks } from './tracks'; +import { artists } from './artists'; +import { composers } from './composers'; +import { composerDetail } from './composerDetail'; +import { login } from './login'; +import { connection } from './connection'; +import { common } from './common'; +import { settings } from './settings'; +import { changelog } from './changelog'; +import { whatsNew } from './whatsNew'; +import { help } from './help'; +import { queue } from './queue'; +import { miniPlayer } from './miniPlayer'; +import { statistics } from './statistics'; +import { player } from './player'; +import { nowPlayingInfo } from './nowPlayingInfo'; +import { songInfo } from './songInfo'; +import { playlists } from './playlists'; +import { smartPlaylists } from './smartPlaylists'; +import { mostPlayed } from './mostPlayed'; +import { losslessAlbums } from './losslessAlbums'; +import { radio } from './radio'; +import { folderBrowser } from './folderBrowser'; +import { deviceSync } from './deviceSync'; +import { orbit } from './orbit'; +import { tray } from './tray'; +import { licenses } from './licenses'; + +export const ruTranslation = { + sidebar, + home, + hero, + search, + nowPlaying, + contextMenu, + sharePaste, + albumDetail, + entityRating, + artistDetail, + favorites, + randomLanding, + randomAlbums, + genres, + randomMix, + luckyMix, + albums, + tracks, + artists, + composers, + composerDetail, + login, + connection, + common, + settings, + changelog, + whatsNew, + help, + queue, + miniPlayer, + statistics, + player, + nowPlayingInfo, + songInfo, + playlists, + smartPlaylists, + mostPlayed, + losslessAlbums, + radio, + folderBrowser, + deviceSync, + orbit, + tray, + licenses, +}; diff --git a/src/locales/ru/licenses.ts b/src/locales/ru/licenses.ts new file mode 100644 index 00000000..09e6b31b --- /dev/null +++ b/src/locales/ru/licenses.ts @@ -0,0 +1,13 @@ +export const licenses = { + title: 'Лицензии открытого кода', + intro: 'Psysonic построен на программном обеспечении с открытым исходным кодом. Список ниже показывает каждую зависимость, поставляемую с приложением, с версией, лицензией и полным текстом лицензии.', + highlights: 'Ключевые зависимости', + searchPlaceholder: 'Поиск по имени, версии или лицензии…', + noResults: 'Нет совпадений.', + loading: 'Загрузка лицензий…', + loadError: 'Не удалось загрузить данные о лицензиях.', + noLicenseText: 'Текст лицензии для этой зависимости не включён.', + viewSource: 'Открыть исходник', + totalLine: '{{total}} зависимостей — {{cargo}} cargo, {{npm}} npm', + generatedAt: 'Последняя генерация {{date}}', +}; diff --git a/src/locales/ru/login.ts b/src/locales/ru/login.ts new file mode 100644 index 00000000..f42a05cb --- /dev/null +++ b/src/locales/ru/login.ts @@ -0,0 +1,22 @@ +export const login = { + subtitle: 'Десктопный клиент для Navidrome', + serverName: 'Название сервера (необязательно)', + serverNamePlaceholder: 'Мой Navidrome', + serverUrl: 'Адрес сервера', + serverUrlPlaceholder: '192.168.1.100:4533 или https://music.example.com', + username: 'Логин', + usernamePlaceholder: 'admin', + password: 'Пароль', + showPassword: 'Показать пароль', + hidePassword: 'Скрыть пароль', + connect: 'Подключиться', + connecting: 'Подключение…', + connected: 'Готово!', + error: 'Не удалось подключиться — проверьте данные.', + urlRequired: 'Укажите адрес сервера.', + savedServers: 'Сохранённые серверы', + addNew: 'Или добавить новый сервер', + orMagicString: 'Или magic string', + magicStringPlaceholder: 'Вставьте строку приглашения (psysonic1-…)', + magicStringInvalid: 'Неверная или нечитаемая magic string.', +}; diff --git a/src/locales/ru/losslessAlbums.ts b/src/locales/ru/losslessAlbums.ts new file mode 100644 index 00000000..297acb3f --- /dev/null +++ b/src/locales/ru/losslessAlbums.ts @@ -0,0 +1,5 @@ +export const losslessAlbums = { + empty: 'В этой библиотеке пока нет lossless-альбомов.', + unsupported: 'Этот сервер не предоставляет метаданные, необходимые для поиска lossless-альбомов.', + slowFetchHint: 'Загружается медленнее других страниц альбомов — Psysonic проходит весь каталог песен по качеству.', +}; diff --git a/src/locales/ru/luckyMix.ts b/src/locales/ru/luckyMix.ts new file mode 100644 index 00000000..3ae71027 --- /dev/null +++ b/src/locales/ru/luckyMix.ts @@ -0,0 +1,6 @@ +export const luckyMix = { + done: '«Мне повезёт» готово: {{count}} треков', + failed: 'Не удалось собрать микс «Мне повезёт». Попробуйте ещё раз.', + unavailable: '«Мне повезёт» недоступен на этом сервере.', + cancelTooltip: 'Отменить сборку микса «Мне повезёт»', +}; diff --git a/src/locales/ru/miniPlayer.ts b/src/locales/ru/miniPlayer.ts new file mode 100644 index 00000000..1cf37cd9 --- /dev/null +++ b/src/locales/ru/miniPlayer.ts @@ -0,0 +1,9 @@ +export const miniPlayer = { + showQueue: 'Показать очередь', + hideQueue: 'Скрыть очередь', + pinOnTop: 'Поверх окон', + pinOff: 'Открепить', + openMainWindow: 'Открыть главное окно', + close: 'Закрыть', + emptyQueue: 'Очередь пуста', +}; diff --git a/src/locales/ru/mostPlayed.ts b/src/locales/ru/mostPlayed.ts new file mode 100644 index 00000000..5fe4b450 --- /dev/null +++ b/src/locales/ru/mostPlayed.ts @@ -0,0 +1,13 @@ +export const mostPlayed = { + title: 'Популярное', + topArtists: 'Топ исполнителей', + topAlbums: 'Топ альбомов', + plays: '{{n}} прослушиваний', + sortMost: 'Сначала популярные', + sortLeast: 'Сначала малоизвестные', + loadMore: 'Загрузить больше альбомов', + noData: 'Пока нет данных о прослушивании. Начните слушать!', + noArtists: 'Все исполнители отфильтрованы.', + filterCompilations: 'Скрыть исполнителей сборников (Various Artists, Soundtracks и др.)', + filterCompilationsShort: 'Скрыть сборники', +}; diff --git a/src/locales/ru/nowPlaying.ts b/src/locales/ru/nowPlaying.ts new file mode 100644 index 00000000..50360155 --- /dev/null +++ b/src/locales/ru/nowPlaying.ts @@ -0,0 +1,51 @@ +export const nowPlaying = { + tooltip: 'Кто сейчас слушает?', + title: 'Кто сейчас слушает?', + loading: 'Загрузка…', + nobody: 'Сейчас никто не слушает.', + minutesAgo: '{{n}} мин назад', + nothingPlaying: 'Пока ничего не играет — включите трек.', + aboutArtist: 'Об исполнителе', + fromAlbum: 'Из этого альбома', + viewAlbum: 'Просмотр альбома', + goToArtist: 'Перейти к исполнителю', + readMore: 'Читать далее', + showLess: 'Свернуть', + genreInfo: 'Жанр', + trackInfo: 'О треке', + topSongs: 'Самое популярное у этого исполнителя', + topSongsCredit: 'Топ-треки исполнителя {{name}}', + trackPosition: 'Трек {{pos}}', + playsCount_one: '{{count}} прослушивание', + playsCount_few: '{{count}} прослушивания', + playsCount_many: '{{count}} прослушиваний', + playsCount_other: '{{count}} прослушиваний', + releasedYearsAgo_one: '{{count}} год назад', + releasedYearsAgo_few: '{{count}} года назад', + releasedYearsAgo_many: '{{count}} лет назад', + releasedYearsAgo_other: '{{count}} лет назад', + discography: 'Дискография', + lastfmStats: 'Статистика Last.fm', + thisTrack: 'Этот трек', + thisArtist: 'Этот исполнитель', + listeners: 'слушателей', + scrobbles: 'прослушиваний', + yourScrobbles: 'вами', + listenersN: '{{n}} слушателей', + scrobblesN: '{{n}} прослушиваний', + playsByYouN: 'прослушано вами {{n}}×', + openTrackOnLastfm: 'Трек на Last.fm', + openArtistOnLastfm: 'Исполнитель на Last.fm', + rgTrackTooltip: 'ReplayGain (трек)', + rgAlbumTooltip: 'ReplayGain (альбом)', + rgAutoTooltip: 'ReplayGain (авто)', + showMoreTracks: 'Показать ещё {{count}}', + showLessTracks: 'Свернуть', + hideCard: 'Скрыть карточку', + layoutMenu: 'Макет', + visibleCards: 'Видимые карточки', + hiddenCards: 'Скрытые карточки', + noHiddenCards: 'Нет скрытых карточек', + resetLayout: 'Сбросить макет', + emptyColumn: 'Перетащите карточки сюда', +}; diff --git a/src/locales/ru/nowPlayingInfo.ts b/src/locales/ru/nowPlayingInfo.ts new file mode 100644 index 00000000..9662e12a --- /dev/null +++ b/src/locales/ru/nowPlayingInfo.ts @@ -0,0 +1,26 @@ +export const nowPlayingInfo = { + tab: 'Инфо', + empty: 'Включите воспроизведение, чтобы увидеть информацию', + artist: 'Исполнитель', + songInfo: 'О треке', + onTour: 'В туре', + noTourEvents: 'Нет предстоящих концертов', + tourLoading: 'Загрузка…', + poweredByBandsintown: 'Данные о туре через Bandsintown', + bioReadMore: 'Читать дальше', + bioReadLess: 'Свернуть', + showMoreTours_one: 'Показать ещё {{count}}', + showMoreTours_few: 'Показать ещё {{count}}', + showMoreTours_many: 'Показать ещё {{count}}', + showMoreTours_other: 'Показать ещё {{count}}', + showLessTours: 'Свернуть', + enableBandsintownPrompt: 'Показать предстоящие концерты?', + enableBandsintownPromptDesc: 'Опционально. Загружает концерты текущего исполнителя через публичный API Bandsintown.', + enableBandsintownPrivacy: 'При включении имя текущего исполнителя отправляется в API Bandsintown для получения дат концертов. Аккаунт и личные данные не передаются.', + enableBandsintownAction: 'Включить', + role: { + artist: 'Исполнитель', + albumArtist: 'Исполнитель альбома', + composer: 'Композитор', + }, +}; diff --git a/src/locales/ru/orbit.ts b/src/locales/ru/orbit.ts new file mode 100644 index 00000000..20b5c6ca --- /dev/null +++ b/src/locales/ru/orbit.ts @@ -0,0 +1,202 @@ +export const orbit = { + triggerLabel: 'Orbit', + triggerTooltip: 'Начать или присоединиться к совместной сессии прослушивания', + launchCreate: 'Создать сессию', + launchJoin: 'Присоединиться к сессии', + launchHelp: 'Как это работает?', + launchHelpSoon: 'Скоро будет', + joinModalTitle: 'Присоединиться к сессии Orbit', + joinModalSub: 'Вставь ссылку-приглашение от хоста.', + joinModalLinkLabel: 'Ссылка-приглашение', + joinModalLinkPlaceholder: 'psysonic2-…', + joinModalLinkHelper: 'Работает с любой действительной ссылкой Orbit. Должна указывать на сервер, на котором ты сейчас авторизован.', + joinModalPasteTooltip: 'Вставить из буфера обмена', + joinModalSubmit: 'Присоединиться', + joinModalBusy: 'Подключение…', + joinErrEmpty: 'Вставь ссылку-приглашение.', + joinErrInvalid: 'Это не похоже на ссылку-приглашение Orbit.', + closeAria: 'Закрыть', + heroTitlePrefix: 'Слушай вместе с', + heroTitleBrand: 'Orbit', + heroSub: 'Начни сессию — другие пользователи на {{server}} будут слушать вместе и смогут предлагать треки.', + fallbackServer: 'этот сервер', + tipLan: 'Ты сейчас подключён через адрес домашней сети. Гости вне твоей сети не смогут присоединиться — переключись на публичный адрес сервера в настройках перед стартом.', + tipRemote: 'Чтобы гости вне домашней сети могли присоединиться, адрес сервера должен быть публично доступен. Если сервер только внутренний, переключись перед стартом.', + labelName: 'Название сессии', + namePlaceholder: 'Velvet Orbit', + reshuffleTooltip: 'Новое предложение', + reshuffleAria: 'Предложить новое название', + helperName: 'Как сессия будет отображаться у гостей — оставь или введи своё.', + labelMax: 'Макс. гостей', + helperMax: 'Ты не считаешься — это только ограничивает входящих гостей.', + labelLink: 'Ссылка-приглашение', + tooltipCopied: 'Скопировано', + tooltipCopy: 'Копировать', + ariaCopyLink: 'Копировать ссылку-приглашение', + helperLink: 'Отправь эту ссылку гостям. Они могут вставить её в Psysonic в любом месте с помощью Ctrl+V.', + labelClearQueue: 'Сначала очистить мою очередь', + helperClearQueue: 'Начать сессию с пустой очередью. Выкл.: уже поставленные треки остаются и делятся с гостями.', + btnCancel: 'Отмена', + btnStarting: 'Запуск…', + btnStart: 'Запустить Orbit', + btnCopyAndStart: 'Копировать ссылку и запустить', + errNameRequired: 'Пожалуйста, дай сессии название.', + errStartFailed: 'Не удалось запустить.', + hostLabel: 'Хост: {{name}}', + participantsTooltip: 'Участники', + settingsTooltip: 'Настройки сессии', + shareTooltip: 'Поделиться ссылкой-приглашением', + shuffleLabel: 'Следующее перемешивание через', + catchUpLabel: 'догнать', + catchUpTooltip: 'Перейти к текущей позиции хоста', + hostAway: 'Хост оффлайн', + hostOnline: 'Хост онлайн', + endTooltip: 'Завершить сессию', + leaveTooltip: 'Покинуть сессию', + helpTooltip: 'Как работает Orbit', + diag: { + openTooltip: 'Диагностика — копируемый журнал событий', + title: 'Диагностика Orbit', + role: 'Роль', + hostTrack: 'ID трека хоста', + hostPos: 'Позиция хоста', + guestTrack: 'Мой ID трека', + guestPos: 'Моя позиция', + drift: 'Расхождение', + stateAge: 'Возраст состояния', + eventLog: 'Журнал событий ({{count}})', + copyLabel: 'Копировать', + copyTooltip: 'Скопировать журнал в буфер обмена', + clearLabel: 'Очистить', + clearTooltip: 'Очистить буфер', + empty: 'Пока нет событий — они появятся когда Orbit начнёт синхронизацию.', + hint: 'Открой это перед воспроизведением проблемы, затем нажми Копировать и вставь в баг-репорт.', + copied: 'Скопировано строк: {{count}}', + copyFailed: 'Не удалось скопировать в буфер обмена', + cleared: 'Буфер очищен', + }, + helpTitle: 'Как работает Orbit', + helpIntro: 'Orbit превращает Psysonic в общую комнату прослушивания. Хост выбирает музыку; гости слушают синхронно и могут предлагать треки.', + helpHostOnly: '(хост)', + helpSec1Title: 'Что такое Orbit?', + helpSec1Body: 'Режим «слушать вместе» — хост управляет воспроизведением, гости подключаются. Всё идёт через плейлисты на твоём собственном сервере Navidrome; никакой внешней инфраструктуры.', + helpSec2Title: 'Хост и гости', + helpSec2Body: 'Хост управляет воспроизведением (play / pause / skip / seek) и решает, когда завершить сессию. Гости следуют за воспроизведением хоста, могут предлагать треки и выходить или присоединяться в любое время. Только хост может исключать или навсегда банить участников.', + helpSec2WarnHead: 'Важно: отдельные аккаунты.', + helpSec2WarnBody: 'У каждого участника должен быть свой аккаунт Navidrome. Если хост и гость входят под одним и тем же пользователем, их отправки конфликтуют, и хост никогда не увидит предложения гостя.', + helpSec3Title: 'Запуск и приглашение', + helpSec3Body: 'Нажми кнопку «Orbit» → Создать сессию → стартовое окно покажет готовую ссылку для копирования и опционально позволит очистить текущую очередь. Делись ссылкой как угодно. Пока сессия активна, кнопка «Поделиться» в верхней панели сессии копирует ссылку в любой момент.', + helpSec4Title: 'Присоединение', + helpSec4Body: 'Вставь ссылку-приглашение в любом месте Psysonic с помощью Ctrl+V / Cmd+V — запрос на присоединение появится автоматически. Альтернатива: «Orbit» → Присоединиться к сессии → вставь в поле. Если ссылка указывает на сервер, где у тебя есть аккаунт, Psysonic переключит тебя автоматически. Если у тебя несколько аккаунтов на этом сервере, небольшой выбор спросит, какой использовать.', + helpSec5Title: 'Предложение треков', + helpSec5Body: 'В любом списке треков: двойной клик по строке или правый клик → «Добавить в сессию Orbit». Одиночный клик показывает подсказку вместо того, чтобы забрасывать весь альбом в общую очередь — это намеренно. Явные массовые действия вроде «Воспроизвести всё» или «Воспроизвести альбом» сначала запрашивают подтверждение, потом добавляют (никогда не заменяют).', + helpSec6Title: 'Общая очередь', + helpSec6Body: 'Очередь показывает предстоящие треки хоста — видно всем. Входящие массовые добавления всегда идут в конец, чтобы не потерять предложения гостей. Автоперемешивание периодически переупорядочивает очередь (настраивается: 1 / 5 / 10 / 15 / 30 мин). Если твоё воспроизведение отклоняется от хоста, кнопка «Догнать» в панели сессии возвращает тебя к live-позиции хоста.', + helpSec7Title: 'Подтверждения', + helpSec7Body: 'По умолчанию предложения гостей требуют ручного подтверждения — они появляются в полосе «Подтверждения» вверху панели очереди с кнопками принять / отклонить. В настройках сессии можно включить автоматическое подтверждение, и всё будет попадать сразу.', + helpSec8Title: 'Участники и настройки', + helpSec8Body: 'Открой иконку настроек в панели сессии для частоты перемешивания, автоподтверждения и быстрого «Перемешать сейчас». Нажми на количество участников, чтобы увидеть, кто подключён — исключить (может присоединиться снова по ссылке) или забанить (заблокирован для этой сессии). Гости тоже видят список участников, но только для чтения.', + helpSec9Title: 'Завершение сессии', + helpSec9Body: 'X хоста → диалог подтверждения → сессия закрывается для всех, серверные плейлисты очищаются автоматически. X гостя → гость выходит, сессия продолжается. Если хост молчит 5 минут, гость автоматически выходит с уведомлением; короткие переподключения в этом окне невидимы.', + participantsInviteLabel: 'Ссылка-приглашение', + participantsCountLabel: '{{count}} в сессии', + participantsHost: 'хост', + participantsEmpty: 'Пока нет гостей', + participantsKickTooltip: 'Удалить из сессии', + participantsKickAria: 'Удалить {{user}}', + participantsRemoveTooltip: 'Удалить из сессии', + participantsRemoveAria: 'Удалить {{user}} из этой сессии', + participantsBanTooltip: 'Забанить навсегда', + participantsBanAria: 'Забанить {{user}} навсегда', + participantsMuteTooltip: 'Запретить предлагать треки', + participantsUnmuteTooltip: 'Разрешить предлагать треки', + participantsMuteAria: 'Запретить {{user}} предлагать треки', + participantsUnmuteAria: 'Снова разрешить {{user}} предлагать треки', + confirmRemoveTitle: 'Удалить из сессии?', + confirmRemoveBody: '{{user}} будет удалён из сессии, но может присоединиться снова по твоей ссылке-приглашению.', + confirmRemoveConfirm: 'Удалить', + confirmBanTitle: 'Забанить навсегда?', + confirmBanBody: '{{user}} будет удалён и заблокирован от повторного присоединения к этой сессии. Отменить нельзя на время сессии.', + confirmBanConfirm: 'Забанить', + confirmCancel: 'Отмена', + confirmJoinTitle: 'Присоединиться к сессии Orbit?', + confirmJoinBody: '{{host}} пригласил тебя в «{{name}}». Присоединиться к сессии?', + confirmJoinConfirm: 'Присоединиться', + confirmLeaveTitle: 'Покинуть сессию?', + confirmLeaveBody: 'Покинуть «{{name}}»? Ты можешь присоединиться снова в любое время по ссылке-приглашению от {{host}}.', + confirmLeaveConfirm: 'Покинуть', + confirmEndTitle: 'Завершить сессию для всех?', + confirmEndBody: '«{{name}}» закроется для всех участников. Плейлисты сессии очищаются автоматически.', + confirmEndConfirm: 'Завершить сессию', + invalidLinkTitle: 'Ссылка-приглашение больше недействительна', + invalidLinkBody: 'Эта сессия Orbit больше не существует или уже завершена. Попроси хоста прислать новую ссылку.', + settingsTitle: 'Настройки сессии', + settingAutoApprove: 'Автоматически принимать предложения', + settingAutoApproveHint: 'Предложения гостей сразу попадают в твою очередь. Выкл.: они остаются в списке сессии для последующего просмотра.', + settingAutoShuffle: 'Автоперемешивание', + settingAutoShuffleHint: 'Периодическое Fisher-Yates перемешивание предстоящей очереди. Выкл.: порядок меняется только при ручной перестановке.', + settingShuffleInterval: 'Перемешивать каждые', + settingShuffleIntervalHint: 'Как часто предстоящая очередь перемешивается во время сессии.', + suggestBlockedMuted: 'Хост отключил тебе предложение треков на этой сессии.', + settingShuffleIntervalValue_one: '{{count}} мин', + settingShuffleIntervalValue_few: '{{count}} мин', + settingShuffleIntervalValue_many: '{{count}} мин', + settingShuffleIntervalValue_other: '{{count}} мин', + settingShuffleNow: 'Перемешать сейчас', + toastSuggested: '{{user}} предложил «{{title}}»', + toastSuggestedMany: '{{count}} новых предложений в очереди', + toastShuffled: 'Очередь перемешана', + toastJoined: 'Присоединился к сессии', + toastLoginFirst: 'Войди, прежде чем присоединяться к сессии', + toastSwitchServer: 'Сначала переключись на {{url}}, потом вставь снова', + toastNoAccountForServer: 'У тебя нет доступа к {{url}}. Попроси хоста прислать приглашение.', + toastSwitchFailed: 'Не удалось переключиться на {{url}}', + accountPickerTitle: 'Какой аккаунт?', + accountPickerSub: 'У тебя несколько аккаунтов для {{url}}. Выбери тот, под которым хочешь присоединиться.', + toastJoinFail: 'Не удалось присоединиться к сессии', + joinErrNotFound: 'Сессия не найдена', + joinErrEnded: 'Сессия завершена', + joinErrFull: 'Сессия заполнена', + joinErrKicked: 'Ты не можешь присоединиться к этой сессии', + joinErrNoUser: 'Нет активного сервера', + joinErrServerError: 'Не удалось присоединиться', + ctxAddToSession: 'Добавить в сессию Orbit', + ctxSuggestedToast: 'Предложено в сессию', + ctxSuggestFailed: 'Не удалось предложить — не присоединён', + ctxAddToSessionHost: 'Добавить в сессию Orbit', + ctxAddedHostToast: 'Добавлено в сессию', + ctxAddHostFailed: 'Не удалось добавить в сессию', + bulkConfirmTitle: 'Добавить всё в очередь Orbit?', + bulkConfirmBody: 'Это сбросит {{count}} треков в общую очередь за раз. Это много для твоих гостей. Продолжить?', + bulkConfirmYes: 'Добавить всё', + bulkConfirmNo: 'Отмена', + guestLive: 'Live', + guestPlaying: 'Сейчас играет', + guestPaused: 'Пауза', + guestLoading: 'Загрузка…', + guestSuggestions: 'Предложения', + guestUpNext: 'Далее', + guestUpNextEmpty: 'В очереди пусто. Открой контекстное меню трека и выбери «Добавить в сессию Orbit», чтобы предложить что-то.', + guestPendingTitle: 'Ожидание хоста', + guestPendingHint: 'Предложено — появится в очереди, когда хост примет.', + approvalTitle: 'Ожидают подтверждения', + approvalFrom: 'Предложено {{user}}', + approvalAccept: 'Принять', + approvalDecline: 'Отклонить', + guestUpNextMore: '+ ещё {{count}} в очереди хоста', + guestSubmitter: 'от {{user}}', + queueAddedByHost: 'Добавил хост', + queueAddedByYou: 'Добавил(а) ты', + queueAddedByUser: 'Добавил {{user}}', + guestEmpty: 'Предложений пока нет. Открой контекстное меню трека и выбери «Добавить в сессию Orbit».', + guestFooter: 'Хост управляет воспроизведением — ты не можешь изменять список.', + exitKickedTitle: 'Тебя забанили в сессии', + exitRemovedTitle: 'Тебя удалили из сессии', + exitEndedTitle: 'Хост завершил сессию', + exitHostTimeoutTitle: 'Хост недоступен', + exitHostTimeoutBody: '{{host}} давно не присылал обновления, поэтому «{{name}}» закрыта на твоей стороне. Ты можешь присоединиться снова в любое время по ссылке.', + exitKickedBody: '{{host}} забанил тебя в «{{name}}». Ты не можешь присоединиться снова.', + exitRemovedBody: '{{host}} удалил тебя из «{{name}}». Ты можешь присоединиться снова в любое время по ссылке.', + exitEndedBody: '«{{name}}» завершена. Надеюсь, тебе понравилось.', + exitOk: 'ОК', +}; diff --git a/src/locales/ru/player.ts b/src/locales/ru/player.ts new file mode 100644 index 00000000..532bf8ee --- /dev/null +++ b/src/locales/ru/player.ts @@ -0,0 +1,53 @@ +export const player = { + regionLabel: 'Плеер', + openFullscreen: 'Полноэкранный плеер', + fullscreen: 'Полноэкранный режим', + closeFullscreen: 'Выйти из полноэкранного', + closeTooltip: 'Закрыть (Esc)', + noTitle: 'Без названия', + stop: 'Стоп', + prev: 'Предыдущий трек', + play: 'Играть', + pause: 'Пауза', + previewActive: 'Превью воспроизводится', + previewLabel: 'Превью', + delayModalTitle: 'Таймер', + delayPauseSection: 'Пауза через', + delayStartSection: 'Старт через', + delayPreviewPause: 'Пауза в', + delayPreviewStart: 'Старт в', + delaySchedulePause: 'Запланировать паузу', + delayScheduleStart: 'Запланировать старт', + delayCancelPause: 'Отменить таймер паузы', + delayCancelStart: 'Отменить таймер старта', + delayInactivePause: 'Доступно только во время воспроизведения.', + delayInactiveStart: 'Доступно на паузе при загруженном треке или радио.', + delayCustomMinutes: 'Своя задержка (минуты)', + delayCustomPlaceholder: 'напр. 2.5', + closeDelayModal: 'Закрыть', + delayIn: 'через', + delayFmtSec: '{{n}} с', + delayFmtMin: '{{n}} мин', + delayFmtHr: '{{n}} ч', + delayCancel: 'Отмена', + delayApply: 'Применить', + next: 'Следующий трек', + repeat: 'Повтор', + repeatOff: 'Выкл.', + repeatAll: 'Все', + repeatOne: 'Один', + progress: 'Прогресс', + volume: 'Громкость', + toggleQueue: 'Очередь', + collapseQueueResize: 'Свернуть очередь, изменить ширину', + moreOptions: 'Дополнительно', + equalizer: 'Эквалайзер', + miniPlayer: 'Мини-плеер', + lyrics: 'Текст', + lyricsLoading: 'Загрузка текста…', + lyricsNotFound: 'Текст не найден', + lyricsSourceNetease: 'Источник: Netease', + lyricsSourceLyricsplus: 'Источник: YouLyPlus', + showDuration: 'Показать длительность', + showRemainingTime: 'Показать оставшееся время', +}; diff --git a/src/locales/ru/playlists.ts b/src/locales/ru/playlists.ts new file mode 100644 index 00000000..7aee0d16 --- /dev/null +++ b/src/locales/ru/playlists.ts @@ -0,0 +1,101 @@ +export const playlists = { + title: 'Плейлисты', + newPlaylist: 'Новый плейлист', + unnamed: 'Без названия', + createName: 'Название…', + create: 'Создать', + cancel: 'Отмена', + empty: 'Плейлистов пока нет.', + emptyPlaylist: 'Плейлист пуст.', + addFirstSong: 'Добавьте первый трек', + notFound: 'Плейлист не найден.', + songs: 'Треков: {{n}}', + playAll: 'Воспроизвести всё', + shuffle: 'Перемешать', + addToQueue: 'В очередь', + back: 'К списку плейлистов', + deletePlaylist: 'Удалить', + confirmDelete: 'Нажмите ещё раз для подтверждения', + removeSong: 'Убрать из плейлиста', + addSongs: 'Добавить треки', + searchPlaceholder: 'Поиск по библиотеке…', + noResults: 'Ничего не найдено.', + suggestions: 'Рекомендации', + noSuggestions: 'Пока нет рекомендаций.', + titleBadge: 'Плейлист', + refreshSuggestions: 'Обновить подборку', + addSong: 'В плейлист', + preview: 'Превью (30 с)', + previewStop: 'Остановить превью', + playNextSuggestion: 'Играть следующим', + suggestionsHint: 'Двойной клик по строке — добавить в плейлист', + addSelected: 'Добавить выбранные', + cacheOffline: 'Сохранить плейлист офлайн', + offlineCached: 'Плейлист сохранён', + removeOffline: 'Удалить из офлайн-кэша', + offlineDownloading: 'Кэширование… ({{done}} из {{total}} альбомов)', + publicLabel: 'Публичный', + privateLabel: 'Личный', + editMeta: 'Изменить плейлист', + editNamePlaceholder: 'Название…', + editCommentPlaceholder: 'Описание…', + editPublic: 'Публичный плейлист', + editSave: 'Сохранить', + editCancel: 'Отмена', + changeCover: 'Сменить обложку', + changeCoverLabel: 'Сменить фото', + removeCover: 'Убрать фото', + coverUpdated: 'Обложка обновлена', + metaSaved: 'Плейлист сохранён', + downloadZip: 'Скачать (ZIP)', + // Toast notifications for multi-select + addSuccess: '{{count}} треков добавлено в {{playlist}}', + addPartial: '{{added}} добавлено, {{skipped}} пропущено (дубликаты)', + addAllSkipped: 'Все пропущены ({{count}} дубликатов)', + addedAsDuplicates: '{{count}} треков добавлено в {{playlist}} (как дубликаты)', + duplicateConfirmTitle: 'Уже в плейлисте', + duplicateConfirmMessage: 'Все {{count}} треков уже есть в «{{playlist}}». Всё равно добавить их как дубликаты?', + duplicateConfirmAction: 'Всё равно добавить', + addError: 'Ошибка при добавлении треков', + createAndAddSuccess: 'Плейлист "{{playlist}}" создан с {{count}} треками', + createError: 'Ошибка при создании плейлиста', + deleteSuccess: '{{count}} плейлистов удалено', + deleteFailed: 'Ошибка при удалении {{name}}', + deleteSelected: 'Удалить выбранные', + deleteSelectedPartial: 'Можно удалить только {{n}} из {{total}} выбранных плейлистов (остальные принадлежат другим пользователям).', + mergeSuccess: '{{count}} треков объединено в {{playlist}}', + mergeNoNewSongs: 'Нет новых треков для добавления', + mergeError: 'Ошибка при объединении плейлистов', + mergeInto: 'Объединить в', + selectionCount: '{{count}} выбрано', + select: 'Выбрать', + startSelect: 'Включить выбор', + cancelSelect: 'Отмена', + loadingAlbums: 'Загрузка {{count}} альбомов…', + loadingArtists: 'Загрузка {{count}} исполнителей…', + myPlaylists: 'Мои плейлисты', + noOtherPlaylists: 'Нет других доступных плейлистов', + addToPlaylistSuccess: '{{count}} треков добавлено в {{playlist}}', + addToPlaylistNoNew: 'Нет новых треков для {{playlist}}', + addToPlaylistError: 'Ошибка при добавлении в плейлист', + removeSuccess: 'Трек убран из плейлиста', + removeError: 'Ошибка при удалении из плейлиста', + importCSV: 'Импорт CSV', + importCSVTooltip: 'Импорт из CSV Spotify', + csvImportReport: 'Отчёт об импорте CSV', + csvImportTotal: 'Всего', + csvImportAdded: 'Добавлено', + csvImportDuplicates: 'Дубликаты', + csvImportNotFound: 'Не найдено', + csvImportNetworkErrors: 'Ошибки сети', + csvImportDuplicatesTitle: 'Дубликаты (уже в плейлисте):', + csvImportNotFoundTitle: 'Не найденные треки:', + csvImportNetworkErrorsTitle: 'Ошибки сети (можно повторить импорт):', + csvImportDownloadReport: 'Скачать отчёт', + csvImportClose: 'Закрыть', + csvImportNoValidTracks: 'В CSV-файле не найдено действительных треков', + csvImportFailed: 'Не удалось импортировать CSV-файл', + csvImportToast: '{{added}} добавлено, {{notFound}} не найдено, {{duplicates}} дубликатов', + csvImportDownloadSuccess: 'Отчёт успешно скачан', + csvImportDownloadError: 'Не удалось скачать отчёт', +}; diff --git a/src/locales/ru/queue.ts b/src/locales/ru/queue.ts new file mode 100644 index 00000000..2caf22ce --- /dev/null +++ b/src/locales/ru/queue.ts @@ -0,0 +1,45 @@ +export const queue = { + title: 'Очередь', + savePlaylist: 'Сохранить как плейлист', + updatePlaylist: 'Обновить плейлист', + filterPlaylists: 'Фильтр плейлистов…', + playlistName: 'Название плейлиста', + cancel: 'Отмена', + save: 'Сохранить', + loadPlaylist: 'Загрузить плейлист', + loading: 'Загрузка…', + noPlaylists: 'Плейлистов нет.', + load: 'Заменить очередь и играть', + appendToQueue: 'Добавить в очередь', + delete: 'Удалить', + deleteConfirm: 'Удалить плейлист «{{name}}»?', + clear: 'Очистить', + shuffle: 'Перемешать', + gapless: 'Без пауз', + crossfade: 'Кроссфейд', + infiniteQueue: 'Бесконечная очередь', + autoAdded: '— Добавлено автоматически —', + radioAdded: '— Радио —', + hide: 'Скрыть', + hideNowPlaying: 'Скрыть информацию о воспроизведении', + showNowPlaying: 'Показать информацию о воспроизведении', + close: 'Закрыть', + nextTracks: 'Дальше', + shareQueue: 'Копировать ссылку на очередь', + shareQueueEmpty: 'Очередь пуста — нечем поделиться.', + emptyQueue: 'Очередь пуста.', + trackSingular: 'трек', + trackPlural: 'треков', + showRemaining: 'Осталось', + showTotal: 'Всего', + showEta: 'Показать ориентировочное окончание', + replayGain: 'ReplayGain', + rgTrack: 'Т {{db}} дБ', + rgAlbum: 'А {{db}} дБ', + rgPeak: 'Пик {{pk}}', + sourceOffline: 'Играет из офлайн-библиотеки', + sourceHot: 'Играет из кэша', + sourceStream: 'Играет из сетевого потока', + clearCachedLoudnessWaveform: 'Сбросить кэш громкости (LUFS) и формы волны и заново проанализировать трек', + recalculatingLoudnessWaveform: 'Пересчёт громкости и формы волны для этого трека…', +}; diff --git a/src/locales/ru/radio.ts b/src/locales/ru/radio.ts new file mode 100644 index 00000000..a2e32e8e --- /dev/null +++ b/src/locales/ru/radio.ts @@ -0,0 +1,35 @@ +export const radio = { + title: 'Онлайн-радио', + empty: 'Радиостанции не настроены.', + addStation: 'Добавить станцию', + editStation: 'Изменить', + deleteStation: 'Удалить станцию', + confirmDelete: 'Нажмите ещё раз для подтверждения', + stationName: 'Название станции…', + streamUrl: 'URL потока…', + homepageUrl: 'Сайт станции (необязательно)', + save: 'Сохранить', + cancel: 'Отмена', + live: 'ЭФИР', + liveStream: 'Онлайн-радио', + openHomepage: 'Открыть сайт', + changeCoverLabel: 'Сменить обложку', + removeCover: 'Убрать обложку', + browseDirectory: 'Каталог станций', + directoryPlaceholder: 'Поиск станций…', + noResults: 'Станции не найдены.', + stationAdded: 'Станция добавлена', + filterAll: 'Все', + filterFavorites: 'Избранное', + sortManual: 'Вручную', + sortAZ: 'А → Я', + sortZA: 'Я → А', + sortNewest: 'Сначала новые', + favorite: 'В избранное', + unfavorite: 'Убрать из избранного', + noFavorites: 'Избранных станций нет.', + listenerCount_one: '{{count}} слушатель', + listenerCount_other: '{{count}} слушателей', + recentlyPlayed: 'Недавно сыгранное', + upNext: 'Следующий', +}; diff --git a/src/locales/ru/randomAlbums.ts b/src/locales/ru/randomAlbums.ts new file mode 100644 index 00000000..1e7c3807 --- /dev/null +++ b/src/locales/ru/randomAlbums.ts @@ -0,0 +1,4 @@ +export const randomAlbums = { + title: 'Случайные альбомы', + refresh: 'Обновить', +}; diff --git a/src/locales/ru/randomLanding.ts b/src/locales/ru/randomLanding.ts new file mode 100644 index 00000000..689a6d65 --- /dev/null +++ b/src/locales/ru/randomLanding.ts @@ -0,0 +1,9 @@ +export const randomLanding = { + title: 'Собрать микс', + mixByTracks: 'Микс по трекам', + mixByTracksDesc: 'Случайная подборка треков со всей медиатеки', + mixByAlbums: 'Микс по альбомам', + mixByAlbumsDesc: 'Случайная подборка альбомов для открытий', + mixByLucky: 'Мне повезёт', + mixByLuckyDesc: 'Умный Instant Mix из топ-артистов, альбомов и высоких оценок', +}; diff --git a/src/locales/ru/randomMix.ts b/src/locales/ru/randomMix.ts new file mode 100644 index 00000000..38a91773 --- /dev/null +++ b/src/locales/ru/randomMix.ts @@ -0,0 +1,42 @@ +export const randomMix = { + title: 'Случайный микс', + remix: 'Новый микс', + remixTooltip: 'Подобрать другие случайные треки', + remixGenre: 'Новый микс: {{genre}}', + remixTooltipGenre: 'Подобрать другие треки жанра {{genre}}', + playAll: 'Воспроизвести всё', + trackTitle: 'Название', + trackArtist: 'Исполнитель', + trackAlbum: 'Альбом', + trackFavorite: 'Избранное', + trackDuration: 'Длительность', + favoriteAdd: 'В избранное', + favoriteRemove: 'Убрать из избранного', + play: 'Играть', + trackGenre: 'Жанр', + mixSettingsHeader: 'Настройки микса', + exclusionsHeader: 'Исключения', + filterPanelInexactSizeNote: 'Размер микса — это цель. При больших запросах сервер может вернуть меньше уникальных треков, если его случайный пул иссякает.', + mixSize: 'Размер списка', + excludeAudiobooks: 'Исключать аудиокниги и радиоспектакли', + excludeAudiobooksDesc: + 'По ключевым словам в жанре, названии, альбоме и исполнителе — например Hörbuch, Audiobook, Spoken Word и т. п.', + genreBlocked: 'Слово отфильтровано', + genreAddedToBlacklist: 'Добавлено в список фильтра', + genreAlreadyBlocked: 'Уже в списке', + artistBlocked: 'Исполнитель отфильтрован', + artistAddedToBlacklist: 'Исполнитель добавлен в фильтр', + artistClickHint: 'Нажмите, чтобы скрыть этого исполнителя', + blacklistToggle: 'Фильтр по словам', + genreMixTitle: 'Микс по жанру', + genreMixDesc: 'Топ-20 жанров по числу треков — нажмите, чтобы собрать микс', + genreMixAll: 'Все треки', + genreMixLoadMore: 'Ещё 10 жанров', + genreMixNoGenres: 'На сервере нет данных о жанрах.', + shuffleGenres: 'Другие жанры', + filterPanelTitle: 'Фильтры', + filterPanelDesc: + 'Нажмите на тег жанра или имя исполнителя в списке ниже, чтобы исключить их из будущих миксов.', + genreClickHint: + 'Нажмите на тег жанра — слово попадёт в фильтр.\nУчитываются жанр, название, альбом и исполнитель.', +}; diff --git a/src/locales/ru/search.ts b/src/locales/ru/search.ts new file mode 100644 index 00000000..bd8bc2d2 --- /dev/null +++ b/src/locales/ru/search.ts @@ -0,0 +1,29 @@ +export const search = { + placeholder: 'Исполнитель, альбом или трек…', + noResults: 'Ничего не найдено по запросу «{{query}}»', + artists: 'Исполнители', + albums: 'Альбомы', + songs: 'Треки', + clearLabel: 'Очистить поиск', + addedToQueueToast: '«{{title}}» добавлен в очередь', + title: 'Поиск', + resultsFor: 'Результаты по «{{query}}»', + album: 'Альбом', + advanced: 'Расширенный поиск', + advancedSearchTerm: 'Поисковый запрос', + advancedSearchPlaceholder: 'Название, альбом, исполнитель…', + advancedGenre: 'Жанр', + advancedAllGenres: 'Все жанры', + advancedYear: 'Год', + advancedYearFrom: 'от', + advancedYearTo: 'до', + advancedAll: 'Все', + advancedSearch: 'Найти', + advancedEmpty: 'Введите запрос или выберите фильтр.', + advancedNoResults: 'Ничего не найдено.', + advancedGenreNote: 'Треки выбираются случайно в рамках жанра.', + recentSearches: 'Недавние запросы', + browse: 'Обзор', + emptyHint: 'Что хочешь послушать?', + genres: 'Жанры', +}; diff --git a/src/locales/ru/settings.ts b/src/locales/ru/settings.ts new file mode 100644 index 00000000..e7920bb6 --- /dev/null +++ b/src/locales/ru/settings.ts @@ -0,0 +1,459 @@ +export const settings = { + title: 'Настройки', + language: 'Язык', + languageEn: 'English', + languageDe: 'Deutsch', + languageEs: 'Español', + languageFr: 'Français', + languageNl: 'Nederlands', + languageNb: 'Norsk', + languageRu: 'Русский', + languageZh: '中文', + languageRo: 'Română', + font: 'Шрифт', + fontHintOpenDyslexic: 'Подходит для дислексии · без поддержки китайского', + theme: 'Тема', + appearance: 'Оформление', + servers: 'Серверы', + serverName: 'Название', + serverUrl: 'Адрес', + serverUrlPlaceholder: '192.168.1.100:4533 или https://music.example.com', + serverUsername: 'Логин', + serverPassword: 'Пароль', + addServer: 'Добавить сервер', + addServerTitle: 'Новый сервер', + useServer: 'Выбрать', + deleteServer: 'Удалить', + noServers: 'Нет сохранённых серверов.', + serverActive: 'Активен', + confirmDeleteServer: 'Удалить сервер «{{name}}»?', + serverConnecting: 'Подключение…', + serverConnected: 'Подключено!', + serverFailed: 'Ошибка подключения.', + testBtn: 'Проверить', + testingBtn: 'Проверка…', + serverCompatible: 'Разработано для Navidrome. Другие Subsonic-совместимые серверы (Gonic, Airsonic, …) могут работать с ограничениями, так как Psysonic использует много специфичных для Navidrome API-эндпоинтов.', + userMgmtTitle: 'Управление пользователями', + userMgmtDesc: 'Управляйте пользователями этого сервера. Требуются права администратора.', + userMgmtNoAdmin: 'Для управления пользователями на этом сервере нужны права администратора.', + userMgmtLoadError: 'Не удалось загрузить пользователей.', + userMgmtLoadFriendly: 'Сервер не ответил — обычно разовая ошибка.', + userMgmtRetry: 'Повторить', + userMgmtEmpty: 'Пользователи не найдены.', + userMgmtYouBadge: 'Вы', + userMgmtAdminBadge: 'Админ', + userMgmtAddUser: 'Добавить пользователя', + userMgmtAddUserTitle: 'Новый пользователь', + userMgmtEditUserTitle: 'Изменить пользователя', + userMgmtUsername: 'Имя пользователя', + userMgmtName: 'Отображаемое имя', + userMgmtEmail: 'E-mail', + userMgmtPassword: 'Пароль', + userMgmtPasswordEditHint: 'Введите новый пароль, чтобы изменить его.', + userMgmtRoleAdmin: 'Админ', + userMgmtLibraries: 'Библиотеки', + userMgmtLibrariesAdminHint: 'Администраторы автоматически имеют доступ ко всем библиотекам.', + userMgmtLibrariesEmpty: 'На этом сервере нет доступных библиотек.', + userMgmtLibrariesValidation: 'Выберите хотя бы одну библиотеку.', + userMgmtLibrariesUpdateError: 'Пользователь сохранён, но не удалось назначить библиотеки', + userMgmtNoLibraries: 'Библиотеки не назначены', + userMgmtNeverSeen: 'Никогда', + userMgmtSave: 'Сохранить', + userMgmtCancel: 'Отмена', + userMgmtDelete: 'Удалить', + userMgmtEdit: 'Изменить', + userMgmtConfirmDelete: 'Удалить пользователя «{{username}}»? Действие нельзя отменить.', + userMgmtCreateError: 'Не удалось создать пользователя.', + userMgmtUpdateError: 'Не удалось обновить пользователя.', + userMgmtDeleteError: 'Не удалось удалить пользователя.', + userMgmtCreated: 'Пользователь создан.', + userMgmtUpdated: 'Пользователь обновлён.', + userMgmtDeleted: 'Пользователь удалён.', + userMgmtValidationMissing: 'Требуются имя пользователя, отображаемое имя и пароль.', + userMgmtValidationMissingIdentity: 'Укажите имя пользователя и отображаемое имя.', + userMgmtMagicStringGenerate: 'Сгенерировать magic string', + userMgmtSaveAndMagicString: 'Сохранить и получить magic string', + userMgmtMagicStringPasswordNavHint: + 'Navidrome сохранит этот пароль для пользователя. Если он не совпадает с текущим, на сервере будет установлен новый пароль входа.', + userMgmtMagicStringPlaintextWarning: + 'Передавайте magic string осторожно: в ней пароль в открытом виде (кодирование — не шифрование). У кого есть полная строка, тот может войти под этим пользователем.', + userMgmtMagicStringCopied: 'Magic string скопирован в буфер обмена.', + userMgmtMagicStringCopyFailed: 'Не удалось скопировать в буфер обмена.', + userMgmtMagicStringLoginFailed: 'Пароль не подошёл — не удалось проверить учётные данные.', + userMgmtMagicStringModalTitle: 'Сгенерировать magic string', + userMgmtMagicStringModalDesc: 'Введите пароль Subsonic для «{{username}}» — он попадёт в копируемую magic string.', + userMgmtMagicStringModalConfirm: 'Скопировать строку', + audiomuseTitle: 'AudioMuse-AI (Navidrome)', + audiomuseDesc: + 'Включите, если на этом сервере настроен плагин AudioMuse-AI для Navidrome. Появится Instant Mix для треков, а на странице исполнителя похожие будут браться с сервера вместо Last.fm.', + audiomuseIssueHint: + 'Недавно не удалось собрать Instant Mix — проверьте плагин Navidrome и API AudioMuse. Похожие исполнители подтянутся с Last.fm, если сервер ничего не вернёт.', + connected: 'Подключено', + failed: 'Ошибка', + eqTitle: 'Эквалайзер', + eqEnabled: 'Включить эквалайзер', + eqPreset: 'Пресет', + eqPresetCustom: 'Свой', + eqPresetBuiltin: 'Встроенные', + eqPresetCustomGroup: 'Мои пресеты', + eqSavePreset: 'Сохранить как пресет', + eqPresetName: 'Название пресета…', + eqDeletePreset: 'Удалить пресет', + eqResetBands: 'Сбросить полосы', + eqPreGain: 'Предусиление', + eqResetPreGain: 'Сбросить предусиление', + eqAutoEqTitle: 'AutoEQ — поиск профиля наушников', + eqAutoEqPlaceholder: 'Модель наушников или IEM…', + eqAutoEqSearching: 'Поиск…', + eqAutoEqNoResults: 'Ничего не найдено', + eqAutoEqError: 'Ошибка поиска', + eqAutoEqRateLimit: 'Лимит GitHub — попробуйте через минуту', + eqAutoEqFetchError: 'Не удалось загрузить профиль EQ', + lfmTitle: 'Last.fm', + lfmConnect: 'Подключить Last.fm', + lfmConnecting: 'Ожидание авторизации…', + lfmConfirm: 'Я разрешил доступ', + lfmConnected: 'Аккаунт', + lfmDisconnect: 'Отключить', + lfmConnectDesc: + 'Привяжите Last.fm для скробблинга и статуса «Сейчас слушаю» прямо из Psysonic — настраивать Navidrome не нужно.', + lfmOpenBrowser: 'Откроется браузер. Разрешите доступ на Last.fm, затем нажмите кнопку ниже.', + lfmScrobbles: 'Скробблов: {{n}}', + lfmMemberSince: 'С {{year}} года', + scrobbleEnabled: 'Скробблинг включён', + scrobbleDesc: 'Отправлять прослушивания на Last.fm после 50% трека', + behavior: 'Поведение', + cacheTitle: 'Макс. размер кэша', + cacheDesc: + 'Обложки и фото исполнителей. При переполнении старые записи удаляются. Офлайн-альбомы не трогаются автоматически, но сотрутся при полной очистке кэша.', + cacheUsedImages: 'Изображения:', + cacheUsedOffline: 'Офлайн-треки:', + cacheUsedHot: 'На диске:', + hotCacheTrackCount: 'Треков в кэше:', + cacheMaxLabel: 'Лимит', + cacheClearBtn: 'Очистить кэш', + waveformCacheClearBtn: 'Очистить кэш waveform', + cacheClearWarning: 'Будут удалены и все офлайн-альбомы.', + cacheClearConfirm: 'Очистить всё', + cacheClearCancel: 'Отмена', + waveformCacheCleared: 'Кэш waveform очищен ({{count}} строк).', + waveformCacheClearFailed: 'Не удалось очистить кэш waveform.', + offlineDirTitle: 'Офлайн-библиотека (в приложении)', + offlineDirDesc: 'Папка для треков, сохранённых для офлайн-прослушивания.', + offlineDirDefault: 'По умолчанию (данные приложения)', + offlineDirChange: 'Сменить папку', + offlineDirClear: 'Сбросить по умолчанию', + offlineDirHint: 'Новые загрузки пойдут в выбранную папку. Старые останутся на прежнем месте.', + hotCacheTitle: 'Горячий кэш воспроизведения', + hotCacheDisclaimer: 'Заранее подгружает следующие треки из очереди и сохраняет предыдущие. При включении использует место на диске и сеть.', + hotCacheDirDefault: 'По умолчанию (данные приложения)', + hotCacheDirChange: 'Сменить папку', + hotCacheDirClear: 'Сбросить по умолчанию', + hotCacheDirHint: 'При смене папки сбрасывается список в приложении; уже скачанные файлы остаются на старом пути, пока вы их не удалите.', + hotCacheEnabled: 'Включить горячий кэш воспроизведения', + hotCacheMaxMb: 'Максимальный размер кэша', + hotCacheDebounce: 'Задержка после изменения очереди', + hotCacheDebounceImmediate: 'Сразу', + hotCacheDebounceSeconds: '{{n}} с', + hotCacheClearBtn: 'Очистить горячий кэш', + audioOutputDevice: 'Устройство вывода звука', + audioOutputDeviceDesc: 'Выберите аудиоустройство для воспроизведения. Изменения применяются немедленно и перезапускают текущий трек.', + audioOutputDeviceDefault: 'Системное по умолчанию', + audioOutputDeviceRefresh: 'Обновить список устройств', + audioOutputDeviceOsDefaultNow: 'текущий системный вывод', + audioOutputDeviceListError: 'Не удалось загрузить список аудиоустройств.', + audioOutputDeviceNotInCurrentList: 'нет в текущем списке', + audioOutputDeviceMacNotice: 'В macOS воспроизведение в настоящее время всегда следует за системным устройством вывода по техническим причинам. Измените цель через Системные настройки → Звук или значок динамика в строке меню. Причина: CoreAudio запрашивает разрешение на использование микрофона при открытии не-стандартного потока — мы избегаем этого, всегда используя системный вывод по умолчанию.', + hiResTitle: 'Нативное воспроизведение Hi-Res', + hiResEnabled: 'Включить нативное Hi-Res воспроизведение', + hiResDesc: "По умолчанию вывод ограничен до 44,1 кГц для максимальной стабильности. Включайте только если оборудование и сеть надёжно поддерживают высокие частоты (88,2 кГц+).", + showArtistImages: 'Фото исполнителей', + showArtistImagesDesc: + 'Показывать обложки в разделе «Исполнители». По умолчанию выключено — меньше нагрузки на диск и сеть.', + showOrbitTrigger: 'Показывать «Orbit» в шапке', + showOrbitTriggerDesc: 'Кнопка в шапке для запуска или присоединения к совместной сессии. Скрой, если не используешь Orbit — здесь же можно включить обратно.', + showTrayIcon: 'Иконка в трее', + showTrayIconDesc: 'Показывать Psysonic в области уведомлений / строке меню.', + minimizeToTray: 'Сворачивать в трей', + minimizeToTrayDesc: 'При закрытии окна не выходить из приложения, а оставаться в трее.', + preloadMiniPlayer: 'Предзагрузка мини-плеера', + preloadMiniPlayerDesc: 'Создаёт окно мини-плеера в фоне при запуске приложения, чтобы при первом открытии содержимое отображалось мгновенно. Использует немного больше памяти.', + useCustomTitlebar: 'Своя строка заголовка', + useCustomTitlebarDesc: + 'Заменить системную строку заголовка встроенной, в стиле темы приложения. Отключите, чтобы использовать родную строку GNOME/GTK и т.д.', + linuxWebkitSmoothScroll: 'Плавное колесо (Linux)', + linuxWebkitSmoothScrollDesc: 'Вкл — инерция. Выкл — по шагам, как в GTK.', + discordRichPresence: 'Статус в Discord', + discordRichPresenceDesc: + 'Показывать текущий трек в профиле и статусе Discord. Нужен запущенный клиент Discord.', + discordCoverSource: 'Источник обложки', + discordCoverSourceDesc: 'Откуда загружать обложку альбома для профиля Discord.', + discordCoverNone: 'Нет (только иконка приложения)', + discordCoverServer: 'Сервер (через информацию об альбоме)', + discordCoverApple: 'Apple Music', + discordOptions: 'Расширенные параметры Discord', + discordTemplates: 'Пользовательские шаблоны текста', + discordTemplatesDesc: 'Настройте, какая информация отображается в профиле Discord. Переменные: {title}, {artist}, {album}', + discordTemplateDetails: 'Основная строка (details)', + discordTemplateState: 'Вторичная строка (state)', + discordTemplateLargeText: 'Подсказка альбома (largeText)', + nowPlayingEnabled: 'Показывать в «Сейчас играет»', + nowPlayingEnabledDesc: + 'Отправлять на сервер, что вы сейчас слушаете. Отключите, чтобы не делиться этим.', + enableBandsintown: 'Даты туров Bandsintown', + enableBandsintownDesc: 'Показывает предстоящие концерты текущего исполнителя на вкладке «Инфо». Данные берутся из публичного API Bandsintown.', + lyricsServerFirst: 'Предпочитать тексты с сервера', + lyricsServerFirstDesc: 'Проверять тексты песен, предоставленные сервером (встроенные теги, sidecar-файлы) перед запросом LRCLIB. Отключите, чтобы сначала использовать LRCLIB.', + enableNeteaselyrics: 'Тексты из Netease Cloud Music', + enableNeteaselyricsDesc: 'Использовать Netease Cloud Music как последний источник текстов, когда остальные способы не находят ничего. Лучшее покрытие для азиатской и международной музыки.', + lyricsSourcesTitle: 'Источники текстов', + lyricsSourcesDesc: 'Выберите источники для поиска текстов и их порядок. Перетаскивайте для сортировки. Отключённые источники пропускаются.', + lyricsSourceServer: 'Сервер', + lyricsSourceLrclib: 'LRCLIB', + lyricsSourceNetease: 'Netease Cloud Music', + lyricsModeStandard: 'Стандарт', + lyricsModeStandardDesc: 'Три источника в свободно настраиваемом порядке: серверные теги, LRCLIB, Netease.', + lyricsModeLyricsplus: 'YouLyPlus (Караоке)', + lyricsModeLyricsplusDesc: 'Синхронизация слово-в-слово из Apple Music, Spotify, Musixmatch и QQ (общественный бэкенд). При отсутствии результата незаметно возвращается к стандартным источникам.', + lyricsStaticOnly: 'Показывать текст статично', + lyricsStaticOnlyDesc: 'Синхронизированный текст отображается без авто-прокрутки и подсветки слов.', + downloadsTitle: 'Экспорт ZIP и архивов', + downloadsFolderDesc: 'Куда сохранять альбомы в ZIP архиве на диск.', + downloadsDefault: 'Папка «Загрузки» по умолчанию', + pickFolder: 'Выбрать', + pickFolderTitle: 'Папка для загрузок', + clearFolder: 'Сбросить папку', + logout: 'Выйти', + aboutTitle: 'О Psysonic', + aboutDesc: + 'Современный десктопный плеер, созданный для Navidrome. Использует API Subsonic плюс специфичные для Navidrome расширения. На Tauri v2 и нативном аудиодвижке на Rust — лёгкий и быстрый: волновая шкала, синхронные тексты, Last.fm, 10-полосный EQ, кроссфейд, воспроизведение без пауз, Replay Gain, жанры и много тем оформления.', + aboutLicense: 'Лицензия', + aboutLicenseText: 'GNU GPL v3 — свободное использование и изменение на тех же условиях.', + aboutRepo: 'Исходный код на GitHub', + aboutVersion: 'Версия', + aboutBuiltWith: 'Tauri · React · TypeScript · Rust/rodio', + aboutReleaseNotesLabel: 'Примечания к выпуску', + aboutReleaseNotesLink: 'Открыть «Что нового» этой версии', + aboutContributorsLabel: 'Участники', + showChangelogOnUpdate: 'Показывать «Что нового» после обновления', + showChangelogOnUpdateDesc: 'После обновления над «Сейчас играет» появится ненавязчивый баннер журнала изменений. Клик открывает заметки о выпуске, X скрывает.', + randomMixTitle: 'Чёрный список случайного микса', + luckyMixMenuTitle: 'Показывать «Мне повезёт» в меню', + luckyMixMenuDesc: + 'Включает «Мне повезёт» в «Собрать микс», а при раздельной навигации — отдельным пунктом меню. Видно только при включённом AudioMuse на активном сервере.', + randomMixBlacklistTitle: 'Свои слова-фильтры', + randomMixBlacklistDesc: + 'Треки скрываются, если слово встречается в жанре, названии, альбоме или исполнителе (когда включён фильтр выше).', + randomMixBlacklistPlaceholder: 'Добавить слово…', + randomMixBlacklistAdd: 'Добавить', + randomMixBlacklistEmpty: 'Пока пусто.', + randomMixHardcodedTitle: 'Встроенные слова (при включённом фильтре)', + tabAudio: 'Звук', + tabStorage: 'Офлайн и кэш', + tabAppearance: 'Внешний вид', + tabLibrary: 'Библиотека', + tabServers: 'Серверы', + tabLyrics: 'Тексты песен', + tabPersonalisation: 'Персонализация', + tabIntegrations: 'Интеграции', + inputKeybindingsTitle: 'Горячие клавиши', + aboutContributorsCount_one: '{{count}} вклад', + aboutContributorsCount_few: '{{count}} вклада', + aboutContributorsCount_many: '{{count}} вкладов', + aboutContributorsCount_other: '{{count}} вклада', + searchPlaceholder: 'Поиск в настройках…', + searchNoResults: 'Ничего не найдено по вашему запросу.', + aboutMaintainersLabel: 'Сопровождающие', + integrationsPrivacyTitle: 'Уведомление о конфиденциальности', + integrationsPrivacyBody: 'Все интеграции на этой вкладке включаются по желанию и при активации отправляют данные во внешние сервисы или на ваш сервер Navidrome. Last.fm получает вашу историю прослушивания, Discord показывает текущую композицию в вашем профиле, Bandsintown опрашивается по артисту для получения дат гастролей, а «Сейчас играет» делится текущей композицией с другими пользователями вашего сервера Navidrome. Если вы не хотите ничего из этого, просто оставьте соответствующий раздел отключённым.', + homeCustomizerTitle: 'Главная', + queueToolbarTitle: 'Панель инструментов очереди', + queueToolbarReset: 'Сбросить', + queueToolbarSeparator: 'Разделитель', + sidebarTitle: 'Боковая панель', + sidebarReset: 'Сбросить порядок', + artistLayoutTitle: 'Разделы страницы исполнителя', + artistLayoutDesc: 'Перетаскивайте, чтобы изменить порядок, переключайте, чтобы скрыть отдельные разделы страницы исполнителя. Разделы без данных пропускаются автоматически.', + artistLayoutReset: 'Сбросить', + artistLayoutBio: 'Биография исполнителя', + artistLayoutTopTracks: 'Топ-треки', + artistLayoutSimilar: 'Похожие исполнители', + artistLayoutAlbums: 'Альбомы', + artistLayoutFeatured: 'Также участвует в', + sidebarDrag: 'Перетащите для порядка', + sidebarFixed: 'Всегда показывать', + randomNavSplitTitle: 'Разделить навигацию микса', + randomNavSplitDesc: + 'Показывать «Случайный микс», «Случайные альбомы» и «Мне повезёт» как отдельные пункты боковой панели вместо хаба «Собрать микс».', + tabInput: 'Ввод', + tabUsers: 'Пользователи', + tabSystem: 'Система', + loggingTitle: 'Логирование', + loggingModeDesc: 'Управляет подробностью логов backend в терминале.', + loggingModeOff: 'Выключено', + loggingModeNormal: 'Обычное', + loggingModeDebug: 'Дебаг', + loggingExport: 'Экспорт логов', + loggingExportSuccess: 'Логи экспортированы ({{count}} строк).', + loggingExportError: 'Не удалось экспортировать логи.', + ratingsSectionTitle: 'Рейтинги', + ratingsSkipStarTitle: 'Скипнуть для 1 звезды', + ratingsSkipStarDesc: + 'При N скипов подряд ставить 1★ треку. Только для не оцененных ранее.', + ratingsSkipStarThresholdLabel: 'Скипов', + ratingsMixFilterTitle: 'Фильтрация по рейтингу', + ratingsMixFilterDesc: + 'Фильтровать с низким рейтингом в «{{mix}}» и «{{albums}}». Повторный клик по выбранной звезде отключает порог.', + ratingsMixMinSong: 'Песни', + ratingsMixMinAlbum: 'Альбомы', + ratingsMixMinArtist: 'Исполнители', + ratingsMixMinThresholdAria: 'Минимум звёзд: {{label}}', + backupTitle: 'Резервная копия', + backupExport: 'Экспорт настроек', + backupExportDesc: + 'Сохраняет настройки, серверы, Last.fm, тему, EQ и горячие клавиши в файл .psybkp. Пароли в открытом виде — храните файл в безопасности.', + backupImport: 'Импорт настроек', + backupImportDesc: 'Восстановить из .psybkp. Приложение перезапустится.', + backupImportConfirm: 'Текущие настройки будут заменены. Продолжить?', + backupSuccess: 'Копия сохранена', + backupImportSuccess: 'Настройки восстановлены — перезапуск…', + backupImportError: 'Файл повреждён или не подходит.', + shortcutsReset: 'Сбросить', + shortcutListening: 'Нажмите клавишу…', + shortcutUnbound: '—', + globalShortcutsTitle: 'Глобальные сочетания', + globalShortcutsNote: + 'Работают, когда окно не в фокусе. Нужен модификатор: Ctrl, Alt или Super.', + shortcutClear: 'Сбросить', + shortcutPlayPause: 'Пауза / воспроизведение', + shortcutNext: 'Следующий трек', + shortcutPrev: 'Предыдущий трек', + shortcutVolumeUp: 'Громче', + shortcutVolumeDown: 'Тише', + shortcutSeekForward: 'Вперёд на 10 с', + shortcutSeekBackward: 'Назад на 10 с', + shortcutToggleQueue: 'Показать / скрыть очередь', + shortcutOpenFolderBrowser: 'Открыть {{folderBrowser}}', + shortcutFullscreenPlayer: 'Полноэкранный плеер', + shortcutNativeFullscreen: 'Системный полный экран', + shortcutOpenMiniPlayer: 'Открыть мини-плеер', + shortcutStartSearch: 'Начать поиск', + shortcutStartAdvancedSearch: 'Начать расширенный поиск', + shortcutToggleSidebar: 'Переключить боковую панель', + shortcutMuteSound: 'Без звука', + shortcutToggleEqualizer: 'Открыть / переключить эквалайзер', + shortcutToggleRepeat: 'Переключить повтор', + shortcutOpenNowPlaying: 'Открыть «Сейчас играет»', + shortcutShowLyrics: 'Показать текст песни', + shortcutFavoriteCurrentTrack: 'Добавить текущий трек в избранное', + shortcutOpenHelp: 'Справка', + playbackTitle: 'Воспроизведение', + replayGain: 'Replay Gain', + replayGainDesc: 'Выравнивание громкости по метаданным ReplayGain', + replayGainMode: 'Режим', + replayGainAuto: 'Авто', + replayGainAutoDesc: 'Использует громкость альбома, когда соседние треки в очереди из того же альбома, иначе громкость трека.', + replayGainTrack: 'По треку', + replayGainAlbum: 'По альбому', + replayGainPreGain: 'Предусиление (файлы с тегами)', + replayGainPreGainDesc: 'Общая прибавка, добавляемая к каждому расчёту ReplayGain. Удобно, если библиотека в целом кажется тихой.', + replayGainFallback: 'Резерв (без тегов / радио)', + replayGainFallbackDesc: 'Применяется к трекам (и радиопотокам) без тегов ReplayGain, чтобы непомеченный контент не звучал громче остального.', + normalization: 'Нормализация', + normalizationDesc: 'Выровнять воспринимаемую громкость между треками, альбомами и радио.', + normalizationOff: 'Выкл.', + normalizationReplayGain: 'ReplayGain', + normalizationLufs: 'LUFS', + loudnessTargetLufs: 'Целевой LUFS', + loudnessTargetLufsDesc: 'Опорная громкость, к которой подгоняются все треки. Меньше число = громче на выходе. Стриминг-сервисы обычно держат около -14 LUFS.', + loudnessPreAnalysisAttenuation: 'Ослабление до измерения', + loudnessPreAnalysisAttenuationDesc: + 'Насколько приглушить звук, пока для трека нет сохранённого измерения громкости. При стриме дальше идут лишь грубые оценки, не полный LUFS. 0 dB — без дополнительного приглушения; ниже — тише. Справа показывается фактическая поправка для текущей цели.', + loudnessPreAnalysisAttenuationRef: 'Фактически {{eff}} dB при цели {{tgt}} LUFS.', + loudnessPreAnalysisAttenuationReset: 'По умолчанию', + loudnessFirstPlayNote: + 'При первом прослушивании нового трека громкость может ненадолго колебаться, пока идёт измерение. Со второго раза применяется уже сохранённое значение и всё стабильно. Следующие треки в очереди обычно анализируются во время предыдущей композиции, поэтому на практике это случается редко.', + crossfade: 'Кроссфейд', + crossfadeDesc: 'Плавный переход между треками', + crossfadeSecs: '{{n}} с', + notWithGapless: 'Недоступно при включённом режиме без пауз', + notWithCrossfade: 'Недоступно при включённом кроссфейде', + gapless: 'Без пауз между треками', + gaplessDesc: 'Заранее подгружать следующий трек, чтобы не было тишины', + preservePlayNextOrder: 'Сохранять порядок «Играть следующим»', + preservePlayNextOrderDesc: 'Новые элементы «Играть следующим» становятся в конец очереди, а не лезут вперёд.', + trackPreviewsTitle: 'Превью треков', + trackPreviewsToggle: 'Включить превью треков', + trackPreviewsDesc: 'Показывать встроенные кнопки воспроизведения и превью в списках треков для быстрого прослушивания фрагмента.', + trackPreviewStart: 'Начальная позиция', + trackPreviewStartDesc: 'С какого момента трека начинается превью (% от длительности).', + trackPreviewDuration: 'Длительность', + trackPreviewDurationDesc: 'Сколько играет каждое превью до автоматической остановки.', + trackPreviewDurationSecs: '{{n}} с', + trackPreviewLocationsTitle: 'Где показывать превью', + trackPreviewLocationsDesc: 'Выберите, в каких списках показывать кнопки превью.', + trackPreviewLocation_suggestions: 'В предложениях плейлиста', + trackPreviewLocation_albums: 'В списках треков альбома', + trackPreviewLocation_playlists: 'В плейлистах', + trackPreviewLocation_favorites: 'В избранном', + trackPreviewLocation_artist: 'В топ-треках исполнителя', + trackPreviewLocation_randomMix: 'В Random Mix', + preloadMode: 'Предзагрузка следующего трека', + preloadModeDesc: 'Когда начинать буферизацию следующего в очереди', + nextTrackBufferingTitle: 'Буферизация', + preloadHotCacheMutualExclusive: 'Предзагрузка и Hot Cache выполняют одну функцию — одновременно может быть активна только одна. Включение одной автоматически отключает другую.', + preloadOff: 'Выкл.', + preloadBalanced: 'Умеренно (за 30 с до конца)', + preloadEarly: 'Рано (через 5 с после старта)', + preloadCustom: 'Свой интервал', + preloadCustomSeconds: 'Секунд до конца: {{n}}', + infiniteQueue: 'Бесконечная очередь', + infiniteQueueDesc: 'Подмешивать случайные треки, когда очередь закончится', + experimental: 'Экспериментально', + fsPlayerSection: 'Полноэкранный плеер', + fsShowArtistPortrait: 'Отображать фото артиста', + fsShowArtistPortraitDesc: 'Показывать фото артиста (или обложку альбома) в правой части полноэкранного плеера.', + fsPortraitDim: 'Затемнение фото', + fsLyricsStyle: 'Стиль отображения текста', + fsLyricsStyleRail: 'Рельс', + fsLyricsStyleRailDesc: 'Классическая рамка из 5 строк.', + fsLyricsStyleApple: 'Прокрутка', + fsLyricsStyleAppleDesc: 'Полноэкранный список с прокруткой.', + sidebarLyricsStyle: 'Стиль прокрутки текста', + sidebarLyricsStyleClassic: 'Классический', + sidebarLyricsStyleClassicDesc: 'Активная строка центрируется.', + sidebarLyricsStyleApple: 'Apple Music-like', + sidebarLyricsStyleAppleDesc: 'Активная строка фиксируется сверху с плавной анимацией.', + seekbarStyle: 'Стиль прогресс-бара', + seekbarStyleDesc: 'Выбор внешнего вида полосы воспроизведения', + seekbarTruewave: 'Реальная форма волны', + seekbarPseudowave: 'Псевдо форма волны', + seekbarLinedot: 'Линия и точка', + seekbarBar: 'Полоса', + seekbarThick: 'Толстая полоса', + seekbarSegmented: 'Сегменты', + seekbarNeon: 'Неон', + seekbarPulsewave: 'Пульс-волна', + seekbarParticletrail: 'Частицы', + seekbarLiquidfill: 'Жидкость', + seekbarRetrotape: 'Ретро-лента', + themeSchedulerTitle: 'Расписание тем', + themeSchedulerEnable: 'Включить расписание тем', + themeSchedulerEnableSub: 'Автоматически переключается между двумя темами в зависимости от времени суток', + themeSchedulerDayTheme: 'Дневная тема', + themeSchedulerDayStart: 'День начинается в', + themeSchedulerNightTheme: 'Ночная тема', + themeSchedulerNightStart: 'Ночь начинается в', + themeSchedulerActiveHint: 'Расписание тем активно - темы переключаются автоматически.', + visualOptionsTitle: 'Визуальные Настройки', + coverArtBackground: 'Фон Обложки', + coverArtBackgroundSub: 'Показывать размытую обложку как фон в заголовках альбомов и плейлистов', + playlistCoverPhoto: 'Обложка Плейлиста', + playlistCoverPhotoSub: 'Показывать сетку обложек в детальном виде плейлиста', + showBitrate: 'Показывать Битрейт', + showBitrateSub: 'Отображать битрейт аудио в списках треков', + floatingPlayerBar: 'Плавающая панель плеера', + floatingPlayerBarSub: 'Держать панель плеера плавающей над содержимым', + uiScaleTitle: 'Масштаб интерфейса', + uiScaleLabel: 'Масштаб', +}; diff --git a/src/locales/ru/sharePaste.ts b/src/locales/ru/sharePaste.ts new file mode 100644 index 00000000..0dbe2da8 --- /dev/null +++ b/src/locales/ru/sharePaste.ts @@ -0,0 +1,20 @@ +export const sharePaste = { + notLoggedIn: 'Войдите и добавьте сервер, затем вставьте ссылку.', + noMatchingServer: 'Ни один сохранённый сервер не совпадает с адресом из ссылки. Добавьте сервер: {{url}}', + trackUnavailable: 'Трек на сервере не найден.', + albumUnavailable: 'Альбом на сервере не найден.', + artistUnavailable: 'Исполнитель на сервере не найден.', + composerUnavailable: 'Композитор на сервере не найден.', + openedTrack: 'Воспроизводится присланный трек.', + openedAlbum: 'Открывается присланный альбом.', + openedArtist: 'Открывается присланный исполнитель.', + openedComposer: 'Открывается присланный композитор.', + openedQueue_one: 'Воспроизводится присланная очередь: {{count}} трек.', + openedQueue_few: 'Воспроизводится присланная очередь: {{count}} трека.', + openedQueue_many: 'Воспроизводится присланная очередь: {{count}} треков.', + openedQueue_other: 'Воспроизводится присланная очередь: {{count}} треков.', + openedQueuePartial: + 'Воспроизводится {{played}} из {{total}} треков по ссылке ({{skipped}} на этом сервере не найдены).', + queueAllUnavailable: 'Ни один из треков по ссылке не найден на сервере.', + genericError: 'Не удалось открыть ссылку для обмена.', +}; diff --git a/src/locales/ru/sidebar.ts b/src/locales/ru/sidebar.ts new file mode 100644 index 00000000..42b1b785 --- /dev/null +++ b/src/locales/ru/sidebar.ts @@ -0,0 +1,38 @@ +export const sidebar = { + library: 'Медиатека', + mainstage: 'Для вас', + newReleases: 'Новинки', + allAlbums: 'Все альбомы', + randomAlbums: 'Случайные альбомы', + randomPicker: 'Собрать микс', + artists: 'Исполнители', + composers: 'Композиторы', + randomMix: 'Случайный микс', + favorites: 'Избранное', + nowPlaying: 'Сейчас играет', + system: 'Система', + statistics: 'Статистика', + settings: 'Настройки', + help: 'Справка', + expand: 'Развернуть боковую панель', + collapse: 'Свернуть боковую панель', + downloadingTracks: 'Кэширование {{n}} треков…', + syncingTracks: 'Синхронизация {{done}}/{{total}}…', + cancelDownload: 'Отменить загрузку', + offlineLibrary: 'Офлайн-библиотека', + genres: 'Жанры', + tracks: 'Треки', + playlists: 'Плейлисты', + smartPlaylists: 'Смарт-плейлисты', + mostPlayed: 'Популярное', + losslessAlbums: 'Lossless', + radio: 'Онлайн-радио', + folderBrowser: 'Браузер папок', + deviceSync: 'Синхронизация устройства', + libraryScope: 'Область медиатеки', + allLibraries: 'Все библиотеки', + expandPlaylists: 'Развернуть плейлисты', + collapsePlaylists: 'Свернуть плейлисты', + more: 'Ещё', + feelingLucky: 'Мне повезёт', +}; diff --git a/src/locales/ru/smartPlaylists.ts b/src/locales/ru/smartPlaylists.ts new file mode 100644 index 00000000..86a6c50d --- /dev/null +++ b/src/locales/ru/smartPlaylists.ts @@ -0,0 +1,41 @@ +export const smartPlaylists = { + sectionBasic: '1. База', + sectionGenres: '2. Жанры', + sectionYearsAndFilters: '3. Годы и фильтры', + genreMode: 'Режим жанров', + genreModeInclude: 'Включить жанры', + genreModeExclude: 'Исключить жанры', + genreSearchPlaceholder: 'Фильтр жанров...', + availableGenres: 'Доступные', + selectedGenres: 'Выбранные', + yearMode: 'Режим годов', + yearModeInclude: 'Включить диапазон', + yearModeExclude: 'Исключить диапазон', + name: 'Название (без префикса)', + limit: 'Лимит', + limitHint: 'Сколько треков включать в плейлист (1-{{max}}, обычно 50).', + artistContains: 'Исполнитель содержит…', + albumContains: 'Альбом содержит…', + titleContains: 'Название содержит…', + minRating: 'Мин. рейтинг', + minRatingAria: 'Минимальный рейтинг для смарт-плейлиста', + minRatingHint: '0 — без минимального порога; 1-5 — оставить треки с рейтингом выше выбранного.', + fromYear: 'Год от', + toYear: 'Год до', + excludeUnrated: 'Исключить треки без рейтинга', + compilationOnly: 'Только сборники', + create: 'Создать смарт-плейлист', + save: 'Сохранить смарт-плейлист', + created: 'Создан {{name}}', + updated: 'Обновлён {{name}}', + createFailed: 'Не удалось создать смарт-плейлист.', + updateFailed: 'Не удалось обновить смарт-плейлист.', + navidromeOnly: 'Смарт-плейлисты можно создавать только на серверах Navidrome.', + loadFailed: 'Не удалось загрузить смарт-плейлисты из Navidrome.', + sortRandom: 'Сортировка: случайно', + sortTitleAsc: 'Сортировка: название А-Я', + sortTitleDesc: 'Сортировка: название Я-А', + sortYearDesc: 'Сортировка: год по убыванию', + sortYearAsc: 'Сортировка: год по возрастанию', + sortPlayCountDesc: 'Сортировка: прослушивания по убыванию', +}; diff --git a/src/locales/ru/songInfo.ts b/src/locales/ru/songInfo.ts new file mode 100644 index 00000000..34aea49c --- /dev/null +++ b/src/locales/ru/songInfo.ts @@ -0,0 +1,23 @@ +export const songInfo = { + title: 'О треке', + songTitle: 'Название', + artist: 'Исполнитель', + album: 'Альбом', + albumArtist: 'Альбомный исполнитель', + year: 'Год', + genre: 'Жанр', + duration: 'Длительность', + track: 'Номер', + format: 'Формат', + bitrate: 'Битрейт', + sampleRate: 'Частота', + bitDepth: 'Разрядность', + channels: 'Каналы', + fileSize: 'Размер файла', + path: 'Путь', + replayGainTrack: 'RG по треку', + replayGainAlbum: 'RG по альбому', + replayGainPeak: 'Пик RG', + mono: 'Моно', + stereo: 'Стерео', +}; diff --git a/src/locales/ru/statistics.ts b/src/locales/ru/statistics.ts new file mode 100644 index 00000000..d063f6ea --- /dev/null +++ b/src/locales/ru/statistics.ts @@ -0,0 +1,58 @@ +export const statistics = { + title: 'Статистика', + recentlyPlayed: 'Недавно проиграно', + mostPlayed: 'Самые проигранные альбомы', + highestRated: 'С высоким рейтингом', + genreDistribution: 'Жанры (топ-20)', + loadMore: 'Ещё', + statArtists: 'Исполнители', + statArtistsTooltip: 'Только исполнители альбомов — артисты, присутствующие лишь в треках (фичеринг, гость и т. д.) без собственного альбома, не учитываются.', + statAlbums: 'Альбомы', + statSongs: 'Треки', + statGenres: 'Жанры', + statPlaytime: 'Время звучания', + genreInsights: 'По жанрам', + formatDistribution: 'Форматы', + formatSample: 'Выборка {{n}} треков', + computing: 'Считаем…', + genreSongs_one: '{{count}} композиция', + genreSongs_few: '{{count}} композиции', + genreSongs_many: '{{count}} композиций', + genreSongs_other: '{{count}} композиций', + genreAlbums_one: '{{count}} альбом', + genreAlbums_few: '{{count}} альбома', + genreAlbums_many: '{{count}} альбомов', + genreAlbums_other: '{{count}} альбомов', + recentlyAdded: 'Недавно добавлено', + decadeDistribution: 'Альбомы по десятилетиям', + decadeAlbums_one: '{{count}} альбом', + decadeAlbums_few: '{{count}} альбома', + decadeAlbums_many: '{{count}} альбомов', + decadeAlbums_other: '{{count}} альбомов', + decadeUnknown: 'Неизвестно', + lfmTitle: 'Статистика Last.fm', + lfmTopArtists: 'Топ исполнителей', + lfmTopAlbums: 'Топ альбомов', + lfmTopTracks: 'Топ треков', + lfmPlays_one: '{{count}} прослушивание', + lfmPlays_few: '{{count}} прослушивания', + lfmPlays_many: '{{count}} прослушиваний', + lfmPlays_other: '{{count}} прослушиваний', + lfmPeriodOverall: 'За всё время', + lfmPeriod7day: '7 дней', + lfmPeriod1month: 'Месяц', + lfmPeriod3month: '3 месяца', + lfmPeriod6month: '6 месяцев', + lfmPeriod12month: 'Год', + lfmNotConnected: 'Подключите Last.fm в настройках.', + lfmRecentTracks: 'Последние скробблы', + lfmNowPlaying: 'Сейчас играет', + lfmJustNow: 'только что', + lfmMinutesAgo: '{{n}} мин назад', + lfmHoursAgo: '{{n}} ч назад', + lfmDaysAgo: '{{n}} дн. назад', + topRatedSongs: 'Лучшие по рейтингу треки', + topRatedArtists: 'Лучшие по рейтингу исполнители', + noRatedSongs: 'Нет оценённых треков. Ставьте оценки в альбомах или плейлистах.', + noRatedArtists: 'Нет оценённых исполнителей.', +}; diff --git a/src/locales/ru/tracks.ts b/src/locales/ru/tracks.ts new file mode 100644 index 00000000..4114f101 --- /dev/null +++ b/src/locales/ru/tracks.ts @@ -0,0 +1,17 @@ +export const tracks = { + title: 'Треки', + subtitle: 'Листать. Искать. Открывать.', + heroEyebrow: 'Трек момента', + heroReroll: 'Выбрать другой', + playSong: 'Воспроизвести', + enqueueSong: 'В очередь', + railRandom: 'Случайная подборка', + railHighlyRated: 'Высоко оценённые', + browseTitle: 'Просмотреть все треки', + browseUnsupported: 'Этот сервер не возвращает всю библиотеку сразу. Воспользуйтесь поиском выше, чтобы найти конкретные треки.', + searchPlaceholder: 'Найти трек по названию, исполнителю или альбому…', + count_one: '{{count}} трек', + count_few: '{{count}} трека', + count_many: '{{count}} треков', + count_other: '{{count}} треков', +}; diff --git a/src/locales/ru/tray.ts b/src/locales/ru/tray.ts new file mode 100644 index 00000000..25e5c399 --- /dev/null +++ b/src/locales/ru/tray.ts @@ -0,0 +1,8 @@ +export const tray = { + playPause: 'Воспроизвести / Пауза', + nextTrack: 'Следующий трек', + previousTrack: 'Предыдущий трек', + showHide: 'Показать / Скрыть', + exitPsysonic: 'Закрыть Psysonic', + nothingPlaying: 'Ничего не воспроизводится', +}; diff --git a/src/locales/ru/whatsNew.ts b/src/locales/ru/whatsNew.ts new file mode 100644 index 00000000..d7e67472 --- /dev/null +++ b/src/locales/ru/whatsNew.ts @@ -0,0 +1,8 @@ +export const whatsNew = { + title: 'Что нового', + empty: 'Для этой версии пока нет записи в журнале изменений.', + bannerTitle: 'Журнал изменений', + bannerCollapsed: 'Что нового в v{{version}}', + dismiss: 'Скрыть', + close: 'Закрыть', +}; diff --git a/src/locales/zh.ts b/src/locales/zh.ts deleted file mode 100644 index b88e0ecf..00000000 --- a/src/locales/zh.ts +++ /dev/null @@ -1,1816 +0,0 @@ -export const zhTranslation = { - sidebar: { - library: '音乐库', - mainstage: '主舞台', - newReleases: '新发布', - allAlbums: '全部专辑', - randomAlbums: '随机专辑', - randomPicker: '创建混音', - artists: '艺术家', - composers: '作曲家', - randomMix: '随机混音', - favorites: '收藏夹', - nowPlaying: '正在播放', - system: '系统', - statistics: '统计', - settings: '设置', - help: '帮助', - expand: '展开侧边栏', - collapse: '收起侧边栏', - downloadingTracks: '正在缓存 {{n}} 首歌曲…', - syncingTracks: '同步中 {{done}}/{{total}}…', - cancelDownload: '取消下载', - offlineLibrary: '离线音乐库', - genres: '流派', - tracks: '曲目', - playlists: '播放列表', - mostPlayed: '最常播放', - losslessAlbums: '无损', - radio: '网络电台', - folderBrowser: '文件夹浏览器', - deviceSync: '设备同步', - libraryScope: '资料库范围', - allLibraries: '所有资料库', - expandPlaylists: '展开播放列表', - collapsePlaylists: '收起播放列表', - more: '更多', - feelingLucky: '好运混音', - }, - home: { - hero: '精选', - starred: '个人收藏', - recent: '最近添加', - mostPlayed: '最常播放', - recentlyPlayed: '最近播放', - losslessAlbums: '无损专辑', - discover: '发现', - discoverSongs: '发现曲目', - loadMore: '加载更多', - discoverMore: '发现更多', - discoverArtists: '发现艺术家', - discoverArtistsMore: '全部艺术家', - becauseYouLike: '因为你听过…', - becauseYouLikeFor: '因为你听过 {{artist}}', - similarTo: '类似 {{artist}}', - becauseYouLikeTracks_one: '{{count}} 首', - becauseYouLikeTracks_other: '{{count}} 首' - }, - hero: { - eyebrow: '精选专辑', - playAlbum: '播放专辑', - enqueue: '加入队列', - enqueueTooltip: '将整张专辑添加到播放队列', - }, - search: { - placeholder: '搜索艺术家、专辑或歌曲…', - noResults: '未找到 "{{query}}" 的相关结果', - artists: '艺术家', - albums: '专辑', - songs: '歌曲', - clearLabel: '清除搜索', - addedToQueueToast: '已将"{{title}}"加入队列', - title: '搜索', - resultsFor: '"{{query}}" 的搜索结果', - album: '专辑', - advanced: '高级搜索', - advancedSearchTerm: '搜索词', - advancedSearchPlaceholder: '标题、专辑、艺术家…', - advancedGenre: '流派', - advancedAllGenres: '所有流派', - advancedYear: '年份', - advancedYearFrom: '从', - advancedYearTo: '至', - advancedAll: '全部', - advancedSearch: '搜索', - advancedEmpty: '请输入搜索词或选择过滤器。', - advancedNoResults: '未找到结果。', - advancedGenreNote: '歌曲从该流派中随机选取。', - recentSearches: '最近搜索', - browse: '浏览', - emptyHint: '你想听什么?', - genres: '流派', - }, - nowPlaying: { - tooltip: '谁正在收听?', - title: '谁正在收听?', - loading: '加载中…', - nobody: '当前无人收听。', - minutesAgo: '{{n}} 分钟前', - nothingPlaying: '尚未开始播放。开始播放一首歌曲吧!', - aboutArtist: '关于艺术家', - fromAlbum: '来自此专辑', - viewAlbum: '查看专辑', - goToArtist: '前往艺术家', - readMore: '阅读更多', - showLess: '收起', - genreInfo: '流派', - trackInfo: '曲目信息', - topSongs: '该艺术家最常播放', - topSongsCredit: '{{name}} 的热门曲目', - trackPosition: '第 {{pos}} 首', - playsCount_one: '播放 {{count}} 次', - playsCount_other: '播放 {{count}} 次', - releasedYearsAgo_one: '{{count}} 年前', - releasedYearsAgo_other: '{{count}} 年前', - discography: '专辑列表', - lastfmStats: 'Last.fm 统计', - thisTrack: '这首歌', - thisArtist: '这位艺术家', - listeners: '听众', - scrobbles: '播放记录', - yourScrobbles: '你', - listenersN: '{{n}} 位听众', - scrobblesN: '{{n}} 次播放', - playsByYouN: '你播放了 {{n}} 次', - openTrackOnLastfm: '在 Last.fm 上查看', - openArtistOnLastfm: '在 Last.fm 上查看艺术家', - rgTrackTooltip: 'ReplayGain (曲目)', - rgAlbumTooltip: 'ReplayGain (专辑)', - rgAutoTooltip: 'ReplayGain (自动)', - showMoreTracks: '显示另外 {{count}} 首', - showLessTracks: '收起', - hideCard: '隐藏卡片', - layoutMenu: '布局', - visibleCards: '可见卡片', - hiddenCards: '已隐藏的卡片', - noHiddenCards: '没有已隐藏的卡片', - resetLayout: '重置布局', - emptyColumn: '将卡片拖到此处', - }, - contextMenu: { - playNow: '立即播放', - playNext: '下一首播放', - addToQueue: '添加到队列', - enqueueAlbum: '专辑加入队列', - enqueueAlbums_one: '{{count}} 张专辑加入队列', - enqueueAlbums_other: '{{count}} 张专辑加入队列', - startRadio: '开始电台', - instantMix: '即时混音', - instantMixFailed: '无法生成即时混音 — 服务器或插件出错。', - cliMixNeedsTrack: '当前没有正在播放的内容 — 请先开始播放,然后再执行混音命令。', - lfmLove: '在 Last.fm 上标记喜欢', - lfmUnlove: '取消 Last.fm 喜欢标记', - favorite: '收藏', - favoriteArtist: '收藏艺术家', - favoriteAlbum: '收藏专辑', - unfavorite: '取消收藏', - unfavoriteArtist: '取消收藏艺术家', - unfavoriteAlbum: '取消收藏专辑', - removeFromQueue: '从队列中移除', - openAlbum: '打开专辑', - goToArtist: '前往艺术家', - download: '下载 (ZIP)', - addToPlaylist: '添加到播放列表', - selectedPlaylists: '已选择 {{count}} 个播放列表', - selectedAlbums: '已选择 {{count}} 个专辑', - selectedArtists: '已选择 {{count}} 个艺术家', - songInfo: '歌曲信息', - shareLink: '复制分享链接', - shareCopied: '分享链接已复制到剪贴板。', - shareCopyFailed: '无法复制到剪贴板。', - }, - sharePaste: { - notLoggedIn: '请先登录并添加服务器,再粘贴分享链接。', - noMatchingServer: '没有已保存的服务器与此链接匹配。请添加使用该地址的服务器:{{url}}', - trackUnavailable: '在服务器上找不到此歌曲。', - albumUnavailable: '在服务器上找不到此专辑。', - artistUnavailable: '在服务器上找不到此艺术家。', - composerUnavailable: '在服务器上找不到此作曲家。', - openedTrack: '正在播放分享的歌曲。', - openedAlbum: '正在打开分享的专辑。', - openedArtist: '正在打开分享的艺术家。', - openedComposer: '正在打开分享的作曲家。', - openedQueue_one: '正在播放分享队列中的 {{count}} 首曲目。', - openedQueue_other: '正在播放分享队列中的 {{count}} 首曲目。', - openedQueuePartial: '正在播放链接中的 {{played}} / {{total}} 首曲目({{skipped}} 首在此服务器上未找到)。', - queueAllUnavailable: '此链接中的曲目在服务器上均未找到。', - genericError: '无法打开分享链接。', - }, - albumDetail: { - back: '返回', - orbitDoubleClickHint: '双击将此曲目添加到 Orbit 队列', - playAll: '全部播放', - shareAlbum: '分享专辑', - enqueue: '加入队列', - enqueueTooltip: '将整张专辑添加到播放队列', - artistBio: '艺术家简介', - download: '下载 (ZIP)', - downloading: '加载中…', - cacheOffline: '设为离线可用', - offlineCached: '已离线缓存', - offlineDownloading: '正在缓存… ({{n}}/{{total}})', - removeOffline: '移除离线缓存', - offlineStorageFull: '离线存储空间已满(限制:{{mb}} MB)。请从离线音乐库中删除专辑以释放空间,或在设置中增加限制。', - offlineStorageGoToLibrary: '离线音乐库', - offlineStorageGoToSettings: '设置', - favoriteAdd: '添加到收藏', - favoriteRemove: '从收藏中移除', - favorite: '收藏', - noBio: '暂无简介。', - moreByArtist: '{{artist}} 的更多作品', - tracksCount: '{{n}} 首曲目', - goToArtist: '前往 {{artist}}', - moreLabelAlbums: '{{label}} 的更多专辑', - trackTitle: '标题', - trackAlbum: '专辑', - trackArtist: '艺术家', - trackGenre: '流派', - trackFormat: '格式', - trackFavorite: '收藏', - trackRating: '评分', - trackDuration: '时长', - trackTotal: '总计', - columns: '列', - resetColumns: '重置为默认', - notFound: '未找到专辑。', - bioModal: '艺术家简介', - bioClose: '关闭', - ratingLabel: '评分', - enlargeCover: '放大', - filterSongs: '筛选歌曲…', - sortNatural: '默认顺序', - sortByTitle: 'A–Z(标题)', - sortByArtist: 'A–Z(艺术家)', - sortByAlbum: 'A–Z(专辑)', - }, - entityRating: { - albumShort: '专辑评分', - artistShort: '艺人评分', - albumAriaLabel: '专辑评分', - artistAriaLabel: '艺人评分', - selectedArtistsRatingAriaLabel: '为所选 {{count}} 位艺人设置星级评分', - selectedAlbumsRatingAriaLabel: '为所选 {{count}} 张专辑设置星级评分', - saveFailed: '无法保存评分。', - }, - artistDetail: { - back: '返回', - albums: '专辑', - album: '专辑', - playAll: '全部播放', - shareArtist: '分享艺人', - shuffle: '随机播放', - radio: '电台', - loading: '加载中…', - noRadio: '未找到该艺术家的相似曲目。', - notFound: '未找到艺术家。', - albumsBy: '{{name}} 的专辑', - topTracks: '热门曲目', - noAlbums: '未找到专辑。', - trackTitle: '标题', - trackAlbum: '专辑', - trackDuration: '时长', - favoriteAdd: '添加到收藏', - favoriteRemove: '从收藏中移除', - favorite: '收藏', - albumCount_one: '{{count}} 张专辑', - albumCount_other: '{{count}} 张专辑', - openedInBrowser: '已在浏览器中打开', - featuredOn: '还出现在', - similarArtists: '相似艺术家', - cacheOffline: '离线保存全部专辑', - offlineCached: '全部专辑已缓存', - offlineDownloading: '正在缓存… ({{done}}/{{total}} 张专辑)', - uploadImage: '上传艺术家图片', - uploadImageError: '图片上传失败', - releaseTypes: { - album: '专辑', - ep: 'EP', - single: '单曲', - compilation: '合辑', - live: '现场', - soundtrack: '原声带', - remix: '混音', - other: '其他', - }, - }, - favorites: { - title: '收藏夹', - empty: '您还没有保存任何收藏。', - artists: '艺术家', - albums: '专辑', - songs: '歌曲', - enqueueAll: '全部加入队列', - playAll: '全部播放', - removeSong: '从收藏中移除', - stations: '广播电台', - showingFiltered: '显示 {{filtered}} / {{total}} ({{artist}})', - showingCount: '显示 {{filtered}} / {{total}}', - clearArtistFilter: '清除艺术家筛选', - noFilterResults: '所选筛选条件下无结果。', - allArtists: '全部艺术家', - topArtists: '按收藏数排行的艺术家', - topArtistsSongCount_one: '{{count}} 首歌曲', - topArtistsSongCount_other: '{{count}} 首歌曲', - }, - randomLanding: { - title: '创建混音', - mixByTracks: '按曲目混音', - mixByTracksDesc: '从整个媒体库随机选取曲目', - mixByAlbums: '按专辑混音', - mixByAlbumsDesc: '随机选取专辑,探索新音乐', - mixByLucky: '好运混音', - mixByLuckyDesc: '基于高频艺人、专辑和高评分歌曲的智能 Instant Mix', - }, - randomAlbums: { - title: '随机专辑', - refresh: '刷新', - }, - genres: { - title: '流派', - genreCount: '个流派', - albumCount_one: '{{count}} 张专辑', - albumCount_other: '{{count}} 张专辑', - loading: '正在加载流派…', - empty: '未找到流派。', - albumsLoading: '正在加载专辑…', - albumsEmpty: '未找到该流派的专辑。', - loadMore: '加载更多', - back: '返回', - }, - randomMix: { - title: '随机混音', - remix: '重新混音', - remixTooltip: '加载新的随机歌曲', - remixGenre: '重混 {{genre}}', - remixTooltipGenre: '加载新的{{genre}}歌曲', - playAll: '全部播放', - trackTitle: '标题', - trackArtist: '艺术家', - trackAlbum: '专辑', - trackFavorite: '收藏', - trackDuration: '时长', - favoriteAdd: '添加到收藏', - favoriteRemove: '从收藏中移除', - play: '播放', - trackGenre: '流派', - mixSettingsHeader: '混音设置', - exclusionsHeader: '排除项', - filterPanelInexactSizeNote: '混音大小是一个目标 — 当服务器的随机池耗尽时,较大的请求可能会返回较少的唯一曲目。', - mixSize: '列表大小', - excludeAudiobooks: '排除有声读物和广播剧', - excludeAudiobooksDesc: '根据流派、标题、专辑和艺术家匹配关键词 — 例如 Hörbuch、Audiobook、Spoken Word 等', - genreBlocked: '关键词已屏蔽', - genreAddedToBlacklist: '已添加到过滤列表', - genreAlreadyBlocked: '已屏蔽', - artistBlocked: '艺术家已屏蔽', - artistAddedToBlacklist: '艺术家已添加到过滤列表', - artistClickHint: '点击屏蔽此艺术家', - blacklistToggle: '关键词过滤', - genreMixTitle: '流派混音', - genreMixDesc: '按歌曲数量排列的前 20 个流派 — 点击获取随机混音', - genreMixAll: '所有歌曲', - genreMixLoadMore: '加载 10 首更多', - genreMixNoGenres: '服务器上未找到流派。', - shuffleGenres: '显示其他流派', - filterPanelTitle: '过滤器', - filterPanelDesc: '点击下方列表中的流派标签或艺术家名称,将其从未来的混音中排除。', - genreClickHint: '点击流派标签将其添加为过滤关键词。\\n匹配流派、标题、专辑和艺术家。', - }, - luckyMix: { - done: '好运混音已就绪:{{count}} 首', - failed: '生成好运混音失败,请重试。', - unavailable: '当前服务器不支持好运混音。', - cancelTooltip: '取消生成好运混音', - }, - albums: { - title: '全部专辑', - sortByName: '按名称排序 (A-Z)', - sortByArtist: '按艺术家排序 (A-Z)', - sortNewest: '最新优先', - sortRandom: '随机排序', - yearFrom: '从', - yearTo: '到', - yearFilterClear: '清除年份筛选', - yearFilterLabel: '年份', - compilationLabel: '合辑', - compilationOnly: '仅合辑', - compilationHide: '隐藏合辑', - compilationTooltipAll: '所有专辑 · 点击:仅合辑', - compilationTooltipOnly: '仅合辑 · 点击:隐藏合辑', - compilationTooltipHide: '已隐藏合辑 · 点击:显示全部', - select: '多选', - startSelect: '启用多选', - cancelSelect: '取消', - selectionCount: '{{count}} 已选择', - downloadZips: '下载 ZIP', - addOffline: '添加离线', - enqueueSelected_one: '加入队列 ({{count}})', - enqueueSelected_other: '加入队列 ({{count}})', - enqueueQueued_one: '已将 {{count}} 张专辑加入队列', - enqueueQueued_other: '已将 {{count}} 张专辑加入队列', - downloadingZip: '正在下载 {{current}}/{{total}}: {{name}}', - downloadZipDone: '已下载 {{count}} 个 ZIP', - downloadZipFailed: '下载 {{name}} 失败', - offlineQueuing: '正在将 {{count}} 张专辑加入离线队列…', - offlineFailed: '添加 {{name}} 离线失败', - }, - tracks: { - title: '曲目', - subtitle: '浏览。搜索。发现。', - heroEyebrow: '此刻精选', - heroReroll: '换一首', - playSong: '播放', - enqueueSong: '加入队列', - railRandom: '随机精选', - railHighlyRated: '高分推荐', - browseTitle: '浏览所有曲目', - browseUnsupported: '此服务器不支持一次性列出整个音乐库。使用上方的搜索来查找特定曲目。', - searchPlaceholder: '按标题、艺人或专辑搜索…', - count_one: '{{count}} 首曲目', - count_other: '{{count}} 首曲目', - }, - artists: { - title: '艺术家', - search: '搜索…', - all: '全部', - gridView: '网格视图', - listView: '列表视图', - imagesOn: '艺术家图片已开启 — 可能增加网络和系统负载', - imagesOff: '艺术家图片已关闭 — 仅显示首字母', - loadMore: '加载更多', - notFound: '未找到艺术家。', - albumCount_one: '{{count}} 张专辑', - albumCount_other: '{{count}} 张专辑', - selectionCount: '{{count}} 已选择', - select: '多选', - startSelect: '启用多选', - cancelSelect: '取消', - addToPlaylist: '添加到播放列表', - }, - composers: { - title: '作曲家', - search: '搜索…', - notFound: '未找到作曲家。', - unsupported: '按作曲家浏览需要 Navidrome 0.55 或更新版本。', - loadFailed: '无法加载作曲家。', - retry: '重试', - involvedIn_one: '参与 {{count}} 张专辑', - involvedIn_other: '参与 {{count}} 张专辑', - }, - composerDetail: { - back: '返回', - notFound: '未找到作曲家。', - about: '关于这位作曲家', - works: '作品', - noWorks: '未找到作品。', - workCount_one: '{{count}} 部作品', - workCount_other: '{{count}} 部作品', - shareComposer: '分享作曲家', - unknownComposer: '作曲家', - }, - login: { - subtitle: '您的 Navidrome 桌面播放器', - serverName: '服务器名称(可选)', - serverNamePlaceholder: '我的 Navidrome', - serverUrl: '服务器地址', - serverUrlPlaceholder: '192.168.1.100:4533 或 https://music.example.com', - username: '用户名', - usernamePlaceholder: 'admin', - password: '密码', - showPassword: '显示密码', - hidePassword: '隐藏密码', - connect: '连接', - connecting: '正在连接…', - connected: '已连接!', - error: '连接失败 — 请检查您的信息。', - urlRequired: '请输入服务器地址。', - savedServers: '已保存的服务器', - addNew: '或添加新服务器', - orMagicString: '或使用魔法字符串', - magicStringPlaceholder: '粘贴分享字符串(psysonic1-…)', - magicStringInvalid: '魔法字符串无效或无法解析。', - }, - connection: { - connected: '已连接', - connectedTo: '已连接到 {{server}}', - disconnected: '已断开连接', - disconnectedFrom: '无法连接到 {{server}} — 点击检查设置', - checking: '正在连接…', - extern: '外部', - offlineTitle: '无服务器连接', - offlineSubtitle: '无法连接到 {{server}}。请检查您的网络或服务器。', - offlineModeBanner: '离线模式 — 正在从本地缓存播放', - offlineNoCacheBanner: '无服务器连接 — 无法访问 {{server}}', - offlineLibraryTitle: '离线音乐库', - offlineLibraryEmpty: '尚未缓存任何专辑。请联网,打开专辑并点击"设为离线可用"。', - offlineAlbumCount_one: '{{n}} 张专辑', - offlineAlbumCount_plural: '{{n}} 张专辑', - retry: '重试', - serverSettings: '服务器设置', - switchServerTitle: '切换服务器', - switchServerHint: '点击选择其他已保存的服务器。', - manageServers: '管理服务器…', - switchFailed: '无法切换 — 无法连接服务器。', - lastfmConnected: 'Last.fm 已连接为 @{{user}}', - lastfmSessionInvalid: '会话无效 — 点击重新连接', - }, - common: { - albums: '专辑', - album: '专辑', - loading: '加载中…', - loadingMore: '加载中…', - loadingPlaylists: '正在加载播放列表…', - noAlbums: '未找到专辑。', - downloading: '正在下载…', - downloadZip: '下载 (ZIP)', - back: '返回', - cancel: '取消', - save: '保存', - delete: '删除', - use: '使用', - add: '添加', - new: '新', - active: '当前使用', - download: '下载', - chooseDownloadFolder: '选择下载文件夹', - noFolderSelected: '未选择文件夹', - rememberDownloadFolder: '记住此文件夹', - filterGenre: '流派筛选', - filterSearchGenres: '搜索流派…', - filterNoGenres: '未找到匹配流派', - filterClear: '清除', - favorites: '收藏', - favoritesTooltipOff: '仅显示收藏', - favoritesTooltipOn: '显示全部', - play: '播放', - bulkSelected: '已选 {{count}} 首', - clearSelection: '清除选择', - bulkAddToPlaylist: '添加到播放列表', - bulkRemoveFromPlaylist: '从播放列表移除', - bulkClear: '取消选择', - updaterAvailable: '有可用更新', - updaterVersion: 'v{{version}} 已发布', - updaterWebsite: '官网', - updaterModalTitle: '有新版本可用', - updaterChangelog: '更新内容', - updaterDownloadBtn: '立即下载', - updaterSkipBtn: '跳过此版本', - updaterRemindBtn: '稍后提醒', - updaterDone: '下载完成', - updaterShowFolder: '在文件夹中显示', - updaterInstallHint: '请关闭 Psysonic 并手动运行安装程序。', - updaterAurHint: '通过 AUR 安装更新:', - updaterErrorMsg: '下载失败', - updaterRetryBtn: '重试', - durationHoursMinutes: '{{hours}}小时{{minutes}}分钟', - durationMinutesOnly: '{{minutes}}分钟', - updaterOpenGitHub: '在 GitHub 上打开', - filters: '筛选器', - more: '更多', - yearRange: '年份范围', - clearAll: '清除全部', - }, - settings: { - title: '设置', - language: '语言', - languageEn: 'English', - languageDe: 'Deutsch', - languageEs: 'Español', - languageFr: 'Français', - languageNl: 'Nederlands', - languageNb: 'Norsk', - languageRu: 'Русский', - languageZh: '中文', - languageRo: 'Română', - font: '字体', - fontHintOpenDyslexic: '阅读障碍友好 · 不支持中文', - theme: '主题', - appearance: '外观', - servers: '服务器', - serverName: '服务器名称', - serverUrl: '服务器地址', - serverUrlPlaceholder: '192.168.1.100:4533 或 https://music.example.com', - serverUsername: '用户名', - serverPassword: '密码', - addServer: '添加服务器', - addServerTitle: '添加新服务器', - useServer: '使用', - deleteServer: '删除', - noServers: '未保存任何服务器。', - serverActive: '当前使用', - confirmDeleteServer: '删除服务器 "{{name}}"?', - serverConnecting: '正在连接…', - serverConnected: '已连接!', - serverFailed: '连接失败。', - testBtn: '测试连接', - testingBtn: '正在测试…', - serverCompatible: '专为 Navidrome 构建。其他兼容 Subsonic 的服务器(Gonic、Airsonic 等)可能功能受限,因为 Psysonic 使用了许多 Navidrome 特有的 API 端点。', - userMgmtTitle: '用户管理', - userMgmtDesc: '管理此服务器上的用户。需要管理员权限。', - userMgmtNoAdmin: '需要管理员权限才能管理此服务器上的用户。', - userMgmtLoadError: '加载用户失败。', - userMgmtLoadFriendly: '服务器未响应 — 通常是偶发问题。', - userMgmtRetry: '重试', - userMgmtEmpty: '未找到用户。', - userMgmtYouBadge: '您', - userMgmtAdminBadge: '管理员', - userMgmtAddUser: '添加用户', - userMgmtAddUserTitle: '新建用户', - userMgmtEditUserTitle: '编辑用户', - userMgmtUsername: '用户名', - userMgmtName: '显示名称', - userMgmtEmail: '电子邮箱', - userMgmtPassword: '密码', - userMgmtPasswordEditHint: '输入新密码以更新。', - userMgmtRoleAdmin: '管理员', - userMgmtLibraries: '音乐库', - userMgmtLibrariesAdminHint: '管理员用户自动拥有所有音乐库的访问权限。', - userMgmtLibrariesEmpty: '此服务器上没有可用的音乐库。', - userMgmtLibrariesValidation: '请至少选择一个音乐库。', - userMgmtLibrariesUpdateError: '用户已保存,但音乐库分配失败', - userMgmtNoLibraries: '未分配音乐库', - userMgmtNeverSeen: '从未', - userMgmtSave: '保存', - userMgmtCancel: '取消', - userMgmtDelete: '删除', - userMgmtEdit: '编辑', - userMgmtConfirmDelete: '删除用户 "{{username}}"?此操作无法撤销。', - userMgmtCreateError: '创建用户失败。', - userMgmtUpdateError: '更新用户失败。', - userMgmtDeleteError: '删除用户失败。', - userMgmtCreated: '用户已创建。', - userMgmtUpdated: '用户已更新。', - userMgmtDeleted: '用户已删除。', - userMgmtValidationMissing: '用户名、显示名称和密码均为必填项。', - userMgmtValidationMissingIdentity: '用户名和显示名称为必填项。', - userMgmtMagicStringGenerate: '生成魔法字符串', - userMgmtSaveAndMagicString: '保存并获取魔法字符串', - userMgmtMagicStringPasswordNavHint: - 'Navidrome 会保存此密码。若与当前密码不同,服务器上的登录密码将被更新。', - userMgmtMagicStringPlaintextWarning: - '请谨慎分享魔法字符串:其中包含未加密的密码(编码不等于加密)。掌握完整字符串的人可以以该用户身份登录。', - userMgmtMagicStringCopied: '魔法字符串已复制到剪贴板。', - userMgmtMagicStringCopyFailed: '无法复制到剪贴板。', - userMgmtMagicStringLoginFailed: '密码验证失败,无法确认凭据。', - userMgmtMagicStringModalTitle: '生成魔法字符串', - userMgmtMagicStringModalDesc: '请输入用户「{{username}}」的 Subsonic 密码,它会包含在复制的魔法字符串中。', - userMgmtMagicStringModalConfirm: '复制字符串', - audiomuseTitle: 'AudioMuse-AI(Navidrome)', - audiomuseDesc: - '若此服务器已配置 AudioMuse-AI Navidrome 插件请开启。可从曲目启动即时混音,并在艺人页使用服务器返回的相似艺人,而非 Last.fm。', - audiomuseIssueHint: - '近期即时混音失败 — 请检查 Navidrome 插件与 AudioMuse API。若服务器无结果,将回退使用 Last.fm 的相似艺人。', - connected: '已连接', - failed: '失败', - eqTitle: '均衡器', - eqEnabled: '启用均衡器', - eqPreset: '预设', - eqPresetCustom: '自定义', - eqPresetBuiltin: '内置预设', - eqPresetCustomGroup: '我的预设', - eqSavePreset: '保存为预设', - eqPresetName: '预设名称…', - eqDeletePreset: '删除预设', - eqResetBands: '重置为平直', - eqPreGain: '预增益', - eqResetPreGain: '重置预增益', - eqAutoEqTitle: 'AutoEQ 耳机查询', - eqAutoEqPlaceholder: '搜索耳机/入耳式型号…', - eqAutoEqSearching: '搜索中…', - eqAutoEqNoResults: '未找到结果', - eqAutoEqError: '搜索失败', - eqAutoEqRateLimit: 'GitHub 请求限制 — 请一分钟后重试', - eqAutoEqFetchError: '无法获取 EQ 配置', - lfmTitle: 'Last.fm', - lfmConnect: '连接 Last.fm', - lfmConnecting: '等待授权…', - lfmConfirm: '我已完成授权', - lfmConnected: '已连接为', - lfmDisconnect: '断开连接', - lfmConnectDesc: '连接您的 Last.fm 账户以启用歌曲记录和正在播放更新,直接从 Psysonic 发送 — 无需配置 Navidrome。', - lfmOpenBrowser: '将打开浏览器窗口。在 Last.fm 上授权 Psysonic,然后点击下方按钮。', - lfmScrobbles: '{{n}} 次记录', - lfmMemberSince: '{{year}} 年加入', - scrobbleEnabled: '启用歌曲记录', - scrobbleDesc: '播放 50% 后发送歌曲到 Last.fm', - behavior: '应用行为', - cacheTitle: '最大存储大小', - cacheDesc: '封面和艺术家图片。存满时,最旧的条目将自动移除。离线专辑不会自动移除,但手动清除缓存时会被删除。', - cacheUsedImages: '图片:', - cacheUsedOffline: '离线曲目:', - cacheUsedHot: '占用空间:', - hotCacheTrackCount: '缓存曲目数:', - cacheMaxLabel: '最大容量', - cacheClearBtn: '清除缓存', - cacheClearWarning: '这将同时移除音乐库中的所有离线专辑。', - cacheClearConfirm: '全部清除', - cacheClearCancel: '取消', - offlineDirTitle: '离线音乐库(应用内)', - offlineDirDesc: '用于在 Psysonic 中离线可用的曲目存储位置。', - offlineDirDefault: '默认(应用数据)', - offlineDirChange: '更改目录', - offlineDirClear: '重置为默认', - offlineDirHint: '新下载将保存到此位置,现有下载保留在原始路径。', - hotCacheTitle: '热播放缓存', - hotCacheDisclaimer: '预加载队列中即将播放的曲目并保留近期已播放的。开启后占用磁盘与网络。', - hotCacheDirDefault: '默认(应用数据)', - hotCacheDirChange: '更改目录', - hotCacheDirClear: '重置为默认', - hotCacheDirHint: '更换目录会重置应用内索引;已下载的文件仍留在原路径,需自行删除。', - hotCacheEnabled: '启用热播放缓存', - hotCacheMaxMb: '最大缓存大小', - hotCacheDebounce: '队列变更去抖', - hotCacheDebounceImmediate: '立即', - hotCacheDebounceSeconds: '{{n}} 秒', - hotCacheClearBtn: '清空热缓存', - audioOutputDevice: '音频输出设备', - audioOutputDeviceDesc: '选择 Psysonic 播放音频的设备。更改立即生效并重新开始当前曲目。', - audioOutputDeviceDefault: '系统默认', - audioOutputDeviceRefresh: '刷新设备列表', - audioOutputDeviceOsDefaultNow: '当前系统输出', - audioOutputDeviceListError: '无法加载音频设备列表。', - audioOutputDeviceNotInCurrentList: '不在当前列表中', - audioOutputDeviceMacNotice: '在 macOS 上,出于技术原因,目前播放始终跟随系统输出设备。请通过 系统设置 → 声音 或菜单栏扬声器图标切换目标设备。背景:打开非默认音频流时 CoreAudio 会触发麦克风权限提示 —— 我们通过始终使用系统默认输出来避免此提示。', - hiResTitle: '原生高清晰度播放', - hiResEnabled: '启用原生高清晰度播放', - hiResDesc: "默认强制 44.1 kHz 输出以获得最大稳定性。仅在硬件和网络可靠支持高采样率(88.2 kHz+)时启用。", - showArtistImages: '显示艺术家图片', - showArtistImagesDesc: '在艺术家概览中加载并显示艺术家图片。默认关闭以减少大型音乐库的服务器磁盘I/O和网络负载。', - showOrbitTrigger: '在顶栏显示"Orbit"', - showOrbitTriggerDesc: '用于启动或加入共享收听会话的顶栏按钮。如果不使用 Orbit,可以隐藏 — 随时可在此重新开启。', - showTrayIcon: '显示托盘图标', - showTrayIconDesc: '在系统通知区域 / 菜单栏显示 Psysonic 图标。', - minimizeToTray: '最小化到托盘', - minimizeToTrayDesc: '关闭窗口时,Psysonic 将继续在系统托盘中运行,而不是退出。', - preloadMiniPlayer: '预加载迷你播放器', - preloadMiniPlayerDesc: '在应用启动时于后台构建迷你播放器窗口,使其首次打开即可立即显示内容。会占用少量额外内存。', - linuxWebkitSmoothScroll: '滚轮平滑(Linux)', - linuxWebkitSmoothScrollDesc: '开:惯性滚动。关:逐行,类似 GTK。', - discordRichPresence: 'Discord Rich Presence', - discordRichPresenceDesc: '在 Discord 个人资料上显示当前播放的曲目。需要 Discord 处于运行状态。', - discordCoverSource: '封面来源', - discordCoverSourceDesc: '从何处获取 Discord 个人资料上显示的专辑封面。', - discordCoverNone: '无(仅显示应用图标)', - discordCoverServer: '服务器(通过专辑信息)', - discordCoverApple: 'Apple Music', - discordOptions: 'Discord 高级选项', - discordTemplates: '自定义文本模板', - discordTemplatesDesc: '自定义在 Discord 个人资料上显示的信息。变量:{title}, {artist}, {album}', - discordTemplateDetails: '主行 (details)', - discordTemplateState: '副行 (state)', - discordTemplateLargeText: '专辑提示 (largeText)', - nowPlayingEnabled: '在实时窗口中显示', - nowPlayingEnabledDesc: '将当前播放的曲目广播到服务器的实时听众视图。禁用以停止发送播放数据。', - enableBandsintown: 'Bandsintown 巡演日期', - enableBandsintownDesc: '在信息标签页中显示当前艺术家的即将到来的演出。数据通过公开的 Bandsintown API 获取。', - lyricsServerFirst: '优先使用服务器歌词', - lyricsServerFirstDesc: '先查询服务器提供的歌词(内嵌标签、sidecar 文件),再查询 LRCLIB。禁用则优先使用 LRCLIB。', - enableNeteaselyrics: '网易云音乐歌词', - enableNeteaselyricsDesc: '当服务器和 LRCLIB 均无结果时,使用网易云音乐作为最终歌词来源。对亚洲及国际音乐覆盖最佳。', - lyricsSourcesTitle: '歌词来源', - lyricsSourcesDesc: '选择要查询的歌词来源及其顺序。拖动以排序。已禁用的来源将被跳过。', - lyricsSourceServer: '服务器', - lyricsSourceLrclib: 'LRCLIB', - lyricsSourceNetease: '网易云音乐', - lyricsModeStandard: '标准', - lyricsModeStandardDesc: '三个可自由排序的来源:服务器标签、LRCLIB、网易云。', - lyricsModeLyricsplus: 'YouLyPlus(卡拉OK)', - lyricsModeLyricsplusDesc: '来自 Apple Music、Spotify、Musixmatch 和 QQ 音乐的逐字同步歌词(社区后端)。找不到时静默回退到标准来源。', - lyricsStaticOnly: '仅以静态文本显示歌词', - lyricsStaticOnlyDesc: '同步歌词将不自动滚动、不逐字高亮,以静态文本显示。', - downloadsTitle: 'ZIP 导出与归档', - downloadsFolderDesc: '将专辑以 ZIP 文件下载到电脑时的目标文件夹。', - downloadsDefault: '默认下载文件夹', - pickFolder: '选择', - pickFolderTitle: '选择下载文件夹', - clearFolder: '清除下载文件夹', - logout: '退出登录', - aboutTitle: '关于 Psysonic', - aboutDesc: '一款专为 Navidrome 构建的现代桌面音乐播放器。使用 Subsonic API 以及 Navidrome 特有的扩展。基于 Tauri v2 和原生 Rust 音频引擎——轻量快速,功能丰富:波形进度条、同步歌词、Last.fm 集成、10 段均衡器、交叉淡入淡出、无缝播放、响度增益、流派浏览以及大量精美主题。', - aboutLicense: '许可证', - aboutLicenseText: 'GNU GPL v3 — 在相同许可证下可自由使用、修改和分发。', - aboutRepo: 'GitHub 上的源代码', - aboutVersion: '版本', - aboutBuiltWith: '使用 Tauri · React · TypeScript · Rust/rodio 构建', - aboutReleaseNotesLabel: '版本说明', - aboutReleaseNotesLink: '打开此版本的新功能', - aboutContributorsLabel: '贡献者', - showChangelogOnUpdate: '更新时显示"新功能"', - showChangelogOnUpdateDesc: '更新后在「正在播放」上方显示一个低调的更新日志横幅。点击打开发行说明,X 按钮关闭。', - randomMixTitle: '随机混音黑名单', - luckyMixMenuTitle: '在菜单中显示“好运混音”', - luckyMixMenuDesc: '在“创建混音”中启用“好运混音”,并在分离导航时作为独立菜单项显示。仅当当前服务器启用 AudioMuse 时可见。', - randomMixBlacklistTitle: '自定义过滤关键词', - randomMixBlacklistDesc: '当任何关键词匹配流派、标题、专辑或艺术家时,歌曲将被排除(当上方复选框开启时生效)。', - randomMixBlacklistPlaceholder: '添加关键词…', - randomMixBlacklistAdd: '添加', - randomMixBlacklistEmpty: '尚未添加自定义关键词。', - randomMixHardcodedTitle: '内置关键词(复选框开启时生效)', - tabAudio: '音频', - tabStorage: '离线与缓存', - tabAppearance: '外观', - tabLibrary: '媒体库', - tabServers: '服务器', - tabLyrics: '歌词', - tabPersonalisation: '个性化', - tabIntegrations: '集成', - inputKeybindingsTitle: '键盘快捷键', - aboutContributorsCount_one: '{{count}} 项贡献', - aboutContributorsCount_other: '{{count}} 项贡献', - searchPlaceholder: '搜索设置…', - searchNoResults: '没有设置匹配您的搜索。', - aboutMaintainersLabel: '维护者', - integrationsPrivacyTitle: '隐私说明', - integrationsPrivacyBody: '此标签页中的所有集成均为 选择加入,启用后会向外部服务或您的 Navidrome 服务器发送数据。Last.fm 接收您的收听历史,Discord 在您的个人资料中显示正在播放的曲目,Bandsintown 会按艺人查询以获取巡演日期,"正在播放" 分享会向您 Navidrome 服务器的其他用户公开您当前的曲目。如果您不需要这些功能,只需将相应部分保持停用即可。', - homeCustomizerTitle: '首页', - queueToolbarTitle: '队列工具栏', - queueToolbarReset: '重置为默认', - queueToolbarSeparator: '分隔符', - sidebarTitle: '侧边栏', - sidebarReset: '重置为默认', - artistLayoutTitle: '艺术家页面板块', - artistLayoutDesc: '拖动以重新排序,切换以隐藏艺术家页面的各个板块。没有数据的板块会自动跳过。', - artistLayoutReset: '重置为默认', - artistLayoutBio: '艺术家简介', - artistLayoutTopTracks: '热门曲目', - artistLayoutSimilar: '相似艺术家', - artistLayoutAlbums: '专辑', - artistLayoutFeatured: '也参与了', - sidebarDrag: '拖动以重新排序', - sidebarFixed: '始终显示', - randomNavSplitTitle: '拆分混音导航', - randomNavSplitDesc: '在侧边栏中将“随机混音”、“随机专辑”和“好运混音”显示为独立条目,而非“创建混音”合并入口。', - tabInput: '输入', - tabUsers: '用户', - tabSystem: '系统', - loggingTitle: '日志记录', - loggingModeDesc: '控制终端中后端日志的详细程度。', - loggingModeOff: '关闭', - loggingModeNormal: '普通', - loggingModeDebug: '调试', - loggingExport: '导出日志', - loggingExportSuccess: '日志已导出({{count}} 行)。', - loggingExportError: '无法导出日志。', - ratingsSectionTitle: '评分', - ratingsSkipStarTitle: '跳过以评 1 星', - ratingsSkipStarDesc: - '连续多次跳过后将曲目设为 1 星。仅适用于此前未评分的曲目。', - ratingsSkipStarThresholdLabel: '跳过次数', - ratingsMixFilterTitle: '按评分筛选', - ratingsMixFilterDesc: - '在{{mix}}与{{albums}}中筛选低评分内容。再次点击所选星标可关闭阈值。', - ratingsMixMinSong: '歌曲', - ratingsMixMinAlbum: '专辑', - ratingsMixMinArtist: '艺人', - ratingsMixMinThresholdAria: '最低星数:{{label}}', - backupTitle: '备份与恢复', - backupExport: '导出设置', - backupExportDesc: '将所有设置、服务器配置、Last.fm 配置、主题、均衡器和快捷键保存到 .psybkp 文件。密码以明文存储——请妥善保管该文件。', - backupImport: '导入设置', - backupImportDesc: '从 .psybkp 文件恢复设置。导入后应用将重新加载。', - backupImportConfirm: '所有当前设置将被覆盖。是否继续?', - backupSuccess: '备份已保存', - backupImportSuccess: '设置已恢复——正在重新加载…', - backupImportError: '备份文件无效或已损坏。', - shortcutsReset: '恢复默认', - shortcutListening: '请按下按键…', - shortcutUnbound: '—', - globalShortcutsTitle: '全局快捷键', - globalShortcutsNote: '即使 Psysonic 在后台也能在系统范围内工作。需要 Ctrl、Alt 或 Super 作为修饰键。', - shortcutClear: '清除', - shortcutPlayPause: '播放 / 暂停', - shortcutNext: '下一首', - shortcutPrev: '上一首', - shortcutVolumeUp: '音量增大', - shortcutVolumeDown: '音量减小', - shortcutSeekForward: '快进 10 秒', - shortcutSeekBackward: '快退 10 秒', - shortcutToggleQueue: '切换队列', - shortcutOpenFolderBrowser: '打开{{folderBrowser}}', - shortcutFullscreenPlayer: '全屏播放器', - shortcutNativeFullscreen: '原生全屏', - shortcutOpenMiniPlayer: '打开迷你播放器', - shortcutStartSearch: '开始搜索', - shortcutStartAdvancedSearch: '开始高级搜索', - shortcutToggleSidebar: '切换侧边栏', - shortcutMuteSound: '静音', - shortcutToggleEqualizer: '打开 / 切换均衡器', - shortcutToggleRepeat: '切换循环', - shortcutOpenNowPlaying: '打开"正在播放"', - shortcutShowLyrics: '显示歌词', - shortcutFavoriteCurrentTrack: '将当前曲目添加到收藏', - shortcutOpenHelp: '帮助', - playbackTitle: '播放', - replayGain: '回放增益', - replayGainDesc: '使用 ReplayGain 元数据标准化曲目音量', - replayGainMode: '模式', - replayGainAuto: '自动', - replayGainAutoDesc: '当队列中相邻曲目来自同一专辑时使用专辑增益,否则使用曲目增益。', - replayGainTrack: '曲目', - replayGainAlbum: '专辑', - replayGainPreGain: '预增益(有标签文件)', - replayGainPreGainDesc: '对所有 ReplayGain 计算结果叠加的统一增益。适合在曲库整体偏轻时用作整体补偿。', - replayGainFallback: '回退增益(无标签 / 收音机)', - replayGainFallbackDesc: '应用于没有 ReplayGain 标签的曲目(以及电台流),避免未打标签的内容比其余素材更响。', - normalization: '响度归一化', - normalizationDesc: '在曲目、专辑和电台之间统一可感知的响度。', - normalizationOff: '关闭', - normalizationReplayGain: 'ReplayGain', - normalizationLufs: 'LUFS', - loudnessTargetLufs: '目标 LUFS', - loudnessTargetLufsDesc: '所有曲目对齐的参考响度。数值越小,输出越响。流媒体服务通常在 -14 LUFS 左右。', - loudnessPreAnalysisAttenuation: '测量前衰减', - loudnessPreAnalysisAttenuationDesc: - '在曲目响度数据保存前的额外压低。流式阶段之后只是粗略估计,不是完整测量。0 dB 为不压低;更负则更安静。右侧显示当前目标下的等效 dB。', - loudnessPreAnalysisAttenuationRef: '目标 {{tgt}} LUFS 时等效 {{eff}} dB。', - loudnessPreAnalysisAttenuationReset: '恢复默认', - loudnessFirstPlayNote: - '首次播放新曲目时,音量可能在测量过程中略有波动。下一次播放将使用缓存的测量结果,保持稳定。队列中即将播放的曲目通常在上一首播放期间已完成预分析,所以这种情况在实际使用中很少出现。', - crossfade: '交叉淡入淡出', - crossfadeDesc: '曲目间淡入淡出', - crossfadeSecs: '{{n}} 秒', - notWithGapless: '无缝播放开启时不可用', - notWithCrossfade: '交叉淡入淡出开启时不可用', - gapless: '无缝播放', - gaplessDesc: '预缓冲下一首曲目以消除歌曲间的间隙', - preservePlayNextOrder: '保留"下一首播放"顺序', - preservePlayNextOrderDesc: '新添加的"下一首播放"项目排在现有项目之后,而不是插到前面。', - trackPreviewsTitle: '曲目预览', - trackPreviewsToggle: '启用曲目预览', - trackPreviewsDesc: '在曲目列表中显示内联播放与预览按钮,可快速试听歌曲中段。', - trackPreviewStart: '起始位置', - trackPreviewStartDesc: '预览从曲目何处开始(占总时长的百分比)。', - trackPreviewDuration: '时长', - trackPreviewDurationDesc: '每段预览自动停止前的播放时长。', - trackPreviewDurationSecs: '{{n}} 秒', - trackPreviewLocationsTitle: '预览显示位置', - trackPreviewLocationsDesc: '选择在哪些列表中显示预览按钮。', - trackPreviewLocation_suggestions: '播放列表建议中', - trackPreviewLocation_albums: '专辑曲目列表中', - trackPreviewLocation_playlists: '播放列表中', - trackPreviewLocation_favorites: '收藏中', - trackPreviewLocation_artist: '艺人热门曲目中', - trackPreviewLocation_randomMix: 'Random Mix 中', - preloadMode: '预加载下一曲目', - preloadModeDesc: '何时开始缓冲队列中的下一曲目', - nextTrackBufferingTitle: '缓冲', - preloadHotCacheMutualExclusive: '预加载与热缓存用途相同——两者不能同时启用。启用其中一个会自动禁用另一个。', - preloadOff: '关闭', - preloadBalanced: '均衡(结束前30秒)', - preloadEarly: '提前(播放5秒后)', - preloadCustom: '自定义', - preloadCustomSeconds: '结束前秒数:{{n}}', - infiniteQueue: '无限队列', - infiniteQueueDesc: '队列播完时自动追加随机曲目', - experimental: '实验性', - fsPlayerSection: '全屏播放器', - fsShowArtistPortrait: '显示艺术家照片', - fsShowArtistPortraitDesc: '在全屏播放器右侧显示艺术家照片(或专辑封面)。', - fsPortraitDim: '照片暗化', - fsLyricsStyle: '歌词显示样式', - fsLyricsStyleRail: '轨道', - fsLyricsStyleRailDesc: '经典5行滑动轨道。', - fsLyricsStyleApple: '滚动', - fsLyricsStyleAppleDesc: '全屏可滚动列表。', - sidebarLyricsStyle: '歌词滚动样式', - sidebarLyricsStyleClassic: '经典', - sidebarLyricsStyleClassicDesc: '活动行居中显示。', - sidebarLyricsStyleApple: 'Apple Music-like', - sidebarLyricsStyleAppleDesc: '活动行固定在顶部,带有平滑弹簧动画。', - seekbarStyle: '进度条样式', - seekbarStyleDesc: '选择播放进度条的外观', - seekbarTruewave: '真实波形', - seekbarPseudowave: '伪波形', - seekbarLinedot: '线条与点', - seekbarBar: '条形', - seekbarThick: '粗条形', - seekbarSegmented: '分段式', - seekbarNeon: '霓虹', - seekbarPulsewave: '脉冲波', - seekbarParticletrail: '粒子轨迹', - seekbarLiquidfill: '液体填充', - seekbarRetrotape: '复古磁带', - themeSchedulerTitle: '主题定时切换', - themeSchedulerEnable: '启用主题定时器', - themeSchedulerEnableSub: '根据一天中的时间自动在两个主题之间切换', - themeSchedulerDayTheme: '白天主题', - themeSchedulerDayStart: '白天开始时间', - themeSchedulerNightTheme: '夜晚主题', - themeSchedulerNightStart: '夜晚开始时间', - themeSchedulerActiveHint: '主题定时器已启用 - 主题将自动切换。', - visualOptionsTitle: '视觉选项', - coverArtBackground: '封面背景', - coverArtBackgroundSub: '在专辑/播放列表标题中显示模糊的封面作为背景', - playlistCoverPhoto: '播放列表封面照片', - playlistCoverPhotoSub: '在播放列表详细视图中显示封面照片网格', - showBitrate: '显示比特率', - showBitrateSub: '在曲目列表中显示音频比特率', - floatingPlayerBar: '浮动播放栏', - floatingPlayerBarSub: '保持播放栏悬浮在内容上方', - uiScaleTitle: '界面缩放', - uiScaleLabel: '缩放', - }, - changelog: { - modalTitle: '新功能', - dontShowAgain: '不再显示', - close: '知道了', - }, - whatsNew: { - title: '新功能', - empty: '此版本暂无更新日志。', - bannerTitle: '更新日志', - bannerCollapsed: 'v{{version}} 新功能', - dismiss: '关闭', - close: '关闭', - }, - help: { - title: '帮助', - searchPlaceholder: '搜索帮助…', - noResults: '没有匹配的主题。请尝试其他搜索词。', - s1: '入门指南', - q1: '支持哪些服务器?', - a1: 'Psysonic 主要为 Navidrome 而构建,并完全兼容 Subsonic — Gonic、Airsonic、LMS 和其他 Subsonic-API 服务器也可使用。某些高级功能(评分、智能播放列表、Magic-String 共享、用户管理)需要 Navidrome。', - q2: '如何添加服务器?', - a2: '设置 → 服务器 → 添加服务器。输入 URL(例如 http://192.168.1.100:4533)、用户名和密码。Psysonic 会在保存前测试连接 — 失败则不保存任何内容。您可以添加任意数量的服务器并在标题栏中切换;同一时刻只有一个处于活动状态。', - q3: '快速 UI 介绍?', - a3: '左侧栏用于导航,中间是 Mainstage / 各页面,底部是播放栏,右侧是队列面板(通过右上角紧邻 Now-Playing 指示器的图标打开)。顶部搜索栏搜索整个音乐库;"Now Playing"显示同一 Navidrome 服务器上其他用户正在听什么。', - s2: '播放与队列', - q4: '如何使用队列?', - a4: '从右上角标题栏打开队列面板。拖动行重新排序,将其拖出以移除,或使用工具栏来打乱、将队列保存为播放列表或跳转到某曲目。可将行从面板拖出到其他位置作为转移。', - q5: 'Gapless 与 Crossfade — 区别?', - a5: 'Gapless 预缓冲下一首曲目,使歌曲之间没有静音(适合现场专辑和 DJ 混音)。Crossfade 在 1–10 秒内将当前曲目淡出同时下一首淡入(适合混合播放)。两者互斥 — 启用其中一个会禁用另一个。在设置 → 音频中配置。', - q6: '什么是无限队列?', - a6: '当队列结束且重复关闭时,Psysonic 会静默地从您的音乐库中追加相似/随机曲目,使播放永不停止。自动添加的曲目显示在"— 自动添加 —"分隔符下。通过队列标题栏中的无限符号图标切换;在设置 → 队列中将自动添加限制为某个流派。', - q7: '多选和 Shift+点击范围?', - a7: '在专辑 / 新发行 / 随机专辑 / 播放列表上激活"选择"。点击一项以切换,然后按住 Shift 并点击另一项 — 可见顺序中两者之间的所有项都将被选中。Shift+点击从最近点击的锚点扩展。网格上方的工具栏提供批量操作(队列、下载、删除等)。', - q8: '键盘快捷键和全局热键?', - a8: '默认应用内键:空格 = 播放 / 暂停,Esc = 关闭全屏 / 模态框,F1 = 快捷键速查表。设置 → 输入允许重新分配每个应用内动作(包括 Ctrl+Shift+P 等组合键)并设置即使 Psysonic 在后台或最小化时也能工作的系统级全局快捷键。多媒体键(播放/暂停、下一首、上一首)在所有平台上都可用。', - s3: '音频工具', - q9: 'Replay Gain 模式?', - a9: '设置 → 音频 → Replay Gain。曲目模式将每首歌曲规范化到目标电平。专辑模式保留专辑内的响度曲线。自动模式根据队列是否来自单个专辑选择曲目或专辑。没有 Replay Gain 标签的曲目回退到可配置的前置放大。', - q10: '什么是 Smart Loudness Normalization (LUFS)?', - a10: '设置 → 音频中 Replay Gain 的现代替代品。Psysonic 将每个曲目分析到 LUFS / EBU R128 并存储结果,以便整个音乐库的音量保持一致 — 包括没有 Replay Gain 标签的曲目。冷缓存分析在后台运行,CPU 使用约 35–40 % 持续约 1 分钟,然后降至 0。一次性设置目标响度(默认 −10 LUFS)。', - q11: 'EQ 和 AutoEQ?', - a11: '设置 → 音频 → 均衡器中有一个 10 频段参数 EQ,带有手动频段和预设。旁边的 AutoEQ 从 AutoEQ 数据库为您的耳机型号拉取测量的校正配置文件并自动应用到频段 — 选择您的耳机,EQ 即对正确曲线。', - q12: '如何切换音频输出设备?', - a12: '设置 → 音频 → 输出设备。Psysonic 列出所有可用输出,选中后立即切换。刷新按钮重新扫描启动后接入的设备。Linux ALSA 名称如"sysdefault"会自动清理以提高可读性。', - q13: '什么是 Hot Cache?', - a13: 'Hot Cache 将当前曲目和接下来的几首预加载到 RAM 和磁盘,使播放无缓冲延迟启动 — 在慢速 / 远程服务器上尤其有用。当达到大小限制时触发驱逐。在设置 → 音频中配置大小和防抖延迟(防止快速跳过时过度获取)。', - s4: '音乐库与发现', - q14: '评分和 Skip-to-1★ 如何工作?', - a14: 'Psysonic 通过 OpenSubsonic(Navidrome ≥ 0.53)支持 1–5 星评分。在曲目列表、右键菜单或播放栏中的艺术家名下方为曲目评分;在专辑页面为专辑评分;在艺术家页面为艺术家评分。Skip-to-1★(设置 → 音乐库 → 评分)在配置数量的连续跳过后自动分配 1 星。同一面板允许为生成的混音设置最低评分作为筛选条件。', - q15: '如何浏览 — 文件夹、流派、曲目?', - a15: '文件夹浏览器(侧边栏)以 Miller-column 布局浏览服务器的音乐目录树 — 点击文件夹进入,点击曲目或文件夹的播放图标以播放/添加。流派使用按曲目数量缩放的标签云视图;点击流派以打开。曲目是一个扁平的音乐库中心,带有可按列排序的虚拟列表和实时搜索。', - q16: '搜索和高级搜索?', - a16: '标题栏搜索栏在您输入时跨艺术家、专辑和曲目运行快速实时搜索。打开高级搜索(侧边栏)以获得更丰富的视图:按年份、流派、评分、格式、声道、采样率、BPM、心情过滤,并组合条件。右键单击任何结果会打开与其他地方相同的上下文菜单。', - q17: '什么是混音(Random / Genre / Super Genre / Lucky)?', - a17: 'Random Mix 从您的音乐库构建随机曲目播放列表;关键字过滤器通过流派/标题/专辑子字符串排除有声读物、喜剧等。Super Genre Mix 将您的音乐库按广泛风格分组(摇滚、金属、电子、爵士、古典…)并构建专注的混音。Lucky Mix 使用您的收听历史、评分和 AudioMuse-AI 相似曲目,一键组装即时播放列表。', - q18: '统计页面?', - a18: '统计(侧边栏)显示热门艺术家、热门专辑、热门曲目、流派分布、随时间变化的收听时间,以及在配置多个音乐文件夹时的每库范围。多个视图可作为可分享的卡片图像导出。', - q19: '如何将专辑下载为 ZIP?', - a19: '专辑页面 → "下载(ZIP)"。服务器先压缩专辑 — 对于大型或无损专辑(FLAC / WAV),进度条仅在压缩完成且传输开始后才会出现。这是正常现象。', - s5: '歌词', - q20: '歌词来自哪里?', - a20: '设置 → 歌词中可配置三个来源:您的 Navidrome 服务器(嵌入式 / OpenSubsonic 歌词)、LRCLIB(社区贡献的同步歌词)和网易云音乐(庞大的亚洲 + 国际目录)。每个来源可启用/禁用并通过拖动重新排序。', - q21: '播放期间如何查看歌词?', - a21: '点击播放栏中的麦克风图标以打开队列面板内的歌词标签。同步歌词自动滚动并支持点击-跳转;纯文本歌词以静态块滚动。通过播放栏封面切换全屏播放器以获得带 mesh-blob 背景的沉浸式歌词视图。', - s6: '分享与社交', - q22: '什么是 Magic Strings?', - a22: 'Magic Strings 是无需任何第三方服务器即可在 Psysonic 用户之间共享内容的简短复制粘贴令牌。Server-Invite 字符串让朋友通过一次粘贴加入您的 Navidrome;专辑 / 艺术家 / 队列 Magic Strings 在接收方打开相同的专辑 / 艺术家 / 队列。从分享菜单生成,粘贴到搜索栏以使用。', - q23: '什么是 Orbit?', - a23: 'Orbit 是同步的一起听:主持人播放一首曲目,每个客人同步听到,客人可以建议曲目,主持人可以接受到队列中。从标题栏中的 Orbit 按钮启动会话,分享邀请链接,其他人可以从任何 Psysonic 安装加入。主持人拥有播放(跳过、搜索、队列) — 客人获得实时视图和建议框。会话是临时的,主持人关闭即结束。', - q24: '什么是 Now Playing 下拉?', - a24: '右上角标题栏的广播图标显示 Navidrome 服务器上其他用户当前正在听什么,每 10 秒刷新。您自己的条目在暂停时立即消失。按服务器划分,因此不会显示其他活动服务器上的用户。', - s7: '个性化', - q25: '主题和主题调度器?', - a25: '设置 → 外观 → 主题从 8 个组中的 60+ 个主题中选择(Psysonic、Mediaplayer、操作系统、游戏、电影、电视剧、社交媒体、Open Source Classics — Catppuccin / Nord / Gruvbox / Nightfox / Dracula)。Auto-Switch Theme 让您设置带启动时间的日间主题 + 夜间主题,使 Psysonic 自动切换。', - q26: '可以自定义侧边栏、首页和艺术家页面吗?', - a26: '可以 — 设置 → 个性化。侧边栏定制器让您拖动 nav 项目到所需顺序并隐藏您不使用的。首页定制器切换每个 Mainstage 行(Hero、Recent、Discover、Recently Played、Starred…)。艺术家页面定制器重新排序章节(Top Songs、专辑、单曲、合辑、相似艺术家等)并隐藏您从不查看的章节。', - q27: '什么是 Mini Player?', - a27: '一个带有封面、传输控件和紧凑队列的小浮动窗口。从播放栏中的 mini-player 图标或其键盘快捷键打开。窗口在会话之间记住其位置和大小。在 Windows 上,mini-webview 在启动时预先创建,因此打开是即时的;Linux / macOS 通过设置 → 外观 → 预加载 mini player 选择加入。', - q28: '什么是 Floating Player Bar?', - a28: '一个可选的播放栏样式(设置 → 外观),它从底部边缘脱离,带有主题背景、强调边框、圆角专辑封面和居中音量部分。在高显示器或紧凑主题上很有用。', - q29: '悬停时的曲目预览?', - a29: '将鼠标悬停在曲目行上,点击封面上的小预览按钮,或从右键菜单触发预览 — Psysonic 通过相同的 Rust 音频引擎流式传输前 ~15 秒,因此响度规范化适用。对于您还没听过的专辑很有用。', - q30: '睡眠定时器?', - a30: '点击播放栏中的月亮图标以打开睡眠定时器。选择持续时间(或"当前曲目结束"),Psysonic 会在结束时淡出并暂停。计时器运行时按钮显示圆形环和按钮内倒计时。', - q31: 'UI 缩放、字体、seekbar 样式?', - a31: '设置 → 外观 — 界面缩放(80–125%,不影响系统字体大小)、字体(10 种 UI 字体,包括 IBM Plex Mono、Fira Code、Geist、Golos Text…)、Seekbar 样式(波形分析 / pseudowave 确定性 / 线条与点 / 条形 / 厚条 / 分段 / 霓虹辉光 / 脉冲波 / 粒子轨迹 / 液体填充 / 复古磁带)。', - s8: '高级用户', - q32: 'CLI 播放器控制?', - a32: 'Psysonic 二进制文件兼作运行中应用的远程控制。示例:psysonic --player play / pause / next / prev、--player volume 75、--player seek 15、--player shuffle、--player repeat off|all|one、--player rating 1-5。切换服务器、音频设备、音乐库;触发 Instant Mix;搜索艺术家 / 专辑 / 曲目。完整列表请运行 psysonic --player --help。bash 和 zsh 的 shell 自动补全可通过 psysonic completions 获得。', - q33: '智能播放列表(Navidrome)?', - a33: '智能播放列表是由规则定义的 Navidrome 端动态播放列表(流派 = 摇滚 AND 年份 > 2020 等)。Psysonic 中的播放列表页面允许使用可视化规则编辑器创建、编辑和删除它们 — Psysonic 通过 Navidrome 原生 API 进行操作。它们在应用其余部分中表现为普通播放列表,并在音乐库更改时自动更新。', - q34: '备份和恢复设置?', - a34: '设置 → 存储 → 备份与恢复将服务器配置文件、主题、键绑定和其他设置导出到单个 JSON 文件。在另一台机器或重新安装后导入文件以一次恢复所有内容。服务器密码包含在内 — 请将文件保存在私密位置。', - q35: '在哪里查看所有开源许可证?', - a35: '设置 → 系统 → Open Source Licenses。完整的依赖列表(cargo crates 和 npm 包)随构建附带捆绑的许可证文本。点击条目查看完整文本;顶部的精选高亮块突出显示用户可识别的库(Tauri、React、rodio、symphonia 等)。', - s9: '离线与同步', - q36: '离线模式 — 缓存专辑和播放列表?', - a36: '打开任何专辑或播放列表,点击标题中的下载图标 — Psysonic 在本地缓存每个曲目,使其无需网络调用即可从磁盘播放。离线音乐库页面(侧边栏)列出所有缓存内容,显示进行中的进度,并允许通过垃圾桶图标移除条目(在下载完成后出现)。', - q37: '离线存储限制?', - a37: '设置 → 音乐库 → 离线让您设置最大缓存大小。当达到限制时,专辑页面下载按钮显示警告横幅。通过从离线音乐库页面移除专辑或播放列表来释放空间。', - q38: 'Device Sync — 将音乐复制到 USB / SD?', - a38: 'Device Sync(侧边栏)将专辑、播放列表或整个艺术家复制到外部驱动器,以便在其他设备上离线收听。选择目标文件夹,从浏览器选项卡中选择源,点击"传输到设备"。Psysonic 写入清单(psysonic-sync.json),即使您在不同 OS 上以不同的文件名模板重新打开 Device Sync,也能知道哪些文件已经在那里。模板支持 {artist} / {album} / {title} / {track_number} / {disc_number} / {year} 令牌,使用 / 作为文件夹分隔符。', - s10: '集成与故障排除', - q39: 'Last.fm 抓取?', - a39: '设置 → 集成 → Last.fm。一次连接您的账户,Psysonic 直接抓取到 Last.fm — 无需 Navidrome 配置。在听完曲目 50 % 后发送抓取。Now-playing pings 在开始时发送。', - q40: 'Discord Rich Presence?', - a40: '设置 → 集成 → Discord 在您的 Discord 个人资料上显示当前曲目。在应用图标、您服务器的封面(通过 getAlbumInfo2 — 需要可公开访问的服务器)或 Apple Music 封面之间选择。使用令牌模板自定义显示字符串(详细信息、状态、提示)。', - q41: 'Bandsintown 巡演日期?', - a41: '在设置 → 集成 → Now-Playing Info 中选择启用。然后 Now Playing 页面上的 Now Playing 选项卡通过 Bandsintown widget API 显示正在播放艺术家的即将到来的巡演日期。默认关闭 — 在您启用之前不发出任何请求。', - q42: 'Internet Radio — 播放实时流?', - a42: 'Internet Radio(侧边栏)播放存储在您 Navidrome 服务器上的任何实时流(通过 Navidrome 管理 UI 添加电台)。播放通过浏览器 HTML5 音频引擎运行 — 大多数 EQ / Replay Gain / Loudness 设置不适用于电台,但 ICY 元数据(当前歌曲名)会显示。支持 MP3、AAC、OGG Vorbis 和大多数 HLS 流;编解码器支持取决于平台。', - q43: '连接测试失败 — 怎么办?', - a43: '仔细检查 URL 包括端口(例如 http://192.168.1.100:4533)。在本地网络上 http:// 通常在 https:// 不工作的地方工作(无证书)。确保没有防火墙阻塞端口,并且用户名和密码正确。如果您的服务器位于反向代理之后,请先尝试直接 URL 以隔离原因。', - q44: '封面和艺术家图像加载缓慢。', - a44: '图像在首次查看时从服务器获取,然后本地缓存 30 天。如果您服务器的存储速度慢,第一次访问页面可能需要片刻;后续访问是即时的。Hot Cache 也对曲目有帮助,但图像缓存是独立的。', - q45: 'Linux 问题 — 黑屏或无声音?', - a45: '黑屏通常是 WebKitGTK 中的 GPU / EGL 驱动程序问题 — 使用 GDK_BACKEND=x11 WEBKIT_DISABLE_COMPOSITING_MODE=1 WEBKIT_DISABLE_DMABUF_RENDERER=1 启动(AUR / .deb / .rpm 安装程序自动设置这些)。对于音频,确保 PipeWire 或 PulseAudio 正在运行。睡眠/唤醒后的音频丢失现在由 post-sleep 恢复钩子自动处理。', - }, - queue: { - title: '队列', - savePlaylist: '保存为播放列表', - updatePlaylist: '更新播放列表', - filterPlaylists: '筛选播放列表…', - playlistName: '播放列表名称', - cancel: '取消', - save: '保存', - loadPlaylist: '加载播放列表', - loading: '加载中…', - noPlaylists: '未找到播放列表。', - load: '替换队列并播放', - appendToQueue: '追加到队列', - delete: '删除', - deleteConfirm: '删除播放列表 "{{name}}"?', - clear: '清空', - shuffle: '随机打乱队列', - gapless: '无缝播放', - crossfade: '交叉淡入淡出', - infiniteQueue: '无限队列', - autoAdded: '— 自动添加 —', - radioAdded: '— 收音机 —', - hide: '隐藏', - hideNowPlaying: '隐藏播放信息', - showNowPlaying: '显示播放信息', - close: '关闭', - nextTracks: '即将播放', - shareQueue: '复制队列分享链接', - shareQueueEmpty: '队列为空,无法分享。', - emptyQueue: '队列为空。', - trackSingular: '首曲目', - trackPlural: '首曲目', - showRemaining: '显示剩余时间', - showTotal: '显示总时间', - showEta: '显示预计结束时间', - replayGain: 'ReplayGain', - rgTrack: '曲目 {{db}} dB', - rgAlbum: '专辑 {{db}} dB', - rgPeak: '峰值 {{pk}}', - sourceOffline: '正在从离线库播放', - sourceHot: '正在从缓存播放', - sourceStream: '正在从网络流播放', - clearCachedLoudnessWaveform: 'Clear cached loudness and waveform, then re-analyze this track', - recalculatingLoudnessWaveform: 'Recalculating loudness and waveform for this track…', - }, - miniPlayer: { - showQueue: '显示队列', - hideQueue: '隐藏队列', - pinOnTop: '置顶', - pinOff: '取消置顶', - openMainWindow: '打开主窗口', - close: '关闭', - emptyQueue: '队列为空', - }, - statistics: { - title: '统计', - recentlyPlayed: '最近播放', - mostPlayed: '最常播放的专辑', - highestRated: '评分最高的专辑', - genreDistribution: '流派分布(前 20)', - loadMore: '加载更多', - statArtists: '艺术家', - statArtistsTooltip: '仅限专辑艺术家——仅作为单曲艺术家出现(合唱、客串等)且无自己专辑的艺术家不计入此处。', - statAlbums: '专辑', - statSongs: '歌曲', - statGenres: '流派', - statPlaytime: '音频总时长', - genreInsights: '流派洞察', - formatDistribution: '格式分布', - formatSample: '{{n}} 首曲目的样本', - computing: '计算中…', - genreSongs: '{{count}} 首歌曲', - genreAlbums: '{{count}} 张专辑', - recentlyAdded: '最近添加', - decadeDistribution: '按年代分布的专辑', - decadeAlbums_one: '{{count}} 张专辑', - decadeAlbums_other: '{{count}} 张专辑', - decadeUnknown: '未知', - lfmTitle: 'Last.fm 统计', - lfmTopArtists: '热门艺术家', - lfmTopAlbums: '热门专辑', - lfmTopTracks: '热门曲目', - lfmPlays: '{{count}} 次播放', - lfmPeriodOverall: '全部时间', - lfmPeriod7day: '7 天', - lfmPeriod1month: '1 个月', - lfmPeriod3month: '3 个月', - lfmPeriod6month: '6 个月', - lfmPeriod12month: '12 个月', - lfmNotConnected: '在设置中连接 Last.fm 以查看您的统计。', - lfmRecentTracks: '最近记录', - lfmNowPlaying: '正在播放', - lfmJustNow: '刚刚', - lfmMinutesAgo: '{{n}} 分钟前', - lfmHoursAgo: '{{n}} 小时前', - lfmDaysAgo: '{{n}} 天前', - topRatedSongs: '最高评分歌曲', - topRatedArtists: '最高评分艺人', - noRatedSongs: '暂无已评分歌曲。请在专辑或播放列表中为歌曲评分。', - noRatedArtists: '暂无已评分艺人。', - }, - player: { - regionLabel: '音乐播放器', - openFullscreen: '打开全屏播放器', - fullscreen: '全屏播放器', - closeFullscreen: '关闭全屏', - closeTooltip: '关闭 (Esc)', - noTitle: '无标题', - stop: '停止', - prev: '上一首', - play: '播放', - pause: '暂停', - previewActive: '正在试听', - previewLabel: '试听', - delayModalTitle: '定时', - delayPauseSection: '多久后暂停', - delayStartSection: '多久后开始', - delayPreviewPause: '暂停于', - delayPreviewStart: '开始于', - delaySchedulePause: '安排暂停', - delayScheduleStart: '安排开始', - delayCancelPause: '取消暂停定时', - delayCancelStart: '取消开始定时', - delayInactivePause: '仅在正在播放时可用。', - delayInactiveStart: '仅在暂停且已加载曲目或电台时可用。', - delayCustomMinutes: '自定义延迟(分钟)', - delayCustomPlaceholder: '例如 2.5', - closeDelayModal: '关闭', - delayIn: '还有', - delayFmtSec: '{{n}} 秒', - delayFmtMin: '{{n}} 分钟', - delayFmtHr: '{{n}} 小时', - delayCancel: '取消', - delayApply: '应用', - next: '下一首', - repeat: '重复', - repeatOff: '关闭', - repeatAll: '全部', - repeatOne: '单曲', - progress: '播放进度', - volume: '音量', - toggleQueue: '切换队列', - collapseQueueResize: '收起队列,调整宽度', - moreOptions: '更多选项', - equalizer: '均衡器', - miniPlayer: '迷你播放器', - lyrics: '歌词', - fsLyricsToggle: '全屏歌词', - lyricsLoading: '正在加载歌词…', - lyricsNotFound: '未找到此曲目的歌词', - lyricsSourceServer: '来源:服务器', - lyricsSourceLrclib: '来源:LRCLIB', - lyricsSourceNetease: '来源:网易云', - lyricsSourceLyricsplus: '来源:YouLyPlus', - showDuration: '显示时长', - showRemainingTime: '显示剩余时间', - }, - nowPlayingInfo: { - tab: '信息', - empty: '播放歌曲以查看信息', - artist: '艺术家', - songInfo: '歌曲信息', - onTour: '巡演', - noTourEvents: '没有即将到来的演出', - tourLoading: '加载中…', - poweredByBandsintown: '巡演数据来自 Bandsintown', - bioReadMore: '展开', - bioReadLess: '收起', - showMoreTours_one: '显示更多 {{count}} 个', - showMoreTours_other: '显示更多 {{count}} 个', - showLessTours: '收起', - enableBandsintownPrompt: '查看即将到来的巡演日期?', - enableBandsintownPromptDesc: '可选。通过公开的 Bandsintown API 加载当前艺术家的演出。', - enableBandsintownPrivacy: '启用后,当前播放的艺术家名称将发送到 Bandsintown API 以获取巡演日期。不会发送任何账户或个人数据。', - enableBandsintownAction: '启用', - role: { - artist: '艺术家', - albumArtist: '专辑艺术家', - composer: '作曲', - }, - }, - songInfo: { - title: '歌曲信息', - songTitle: '标题', - artist: '艺术家', - album: '专辑', - albumArtist: '专辑艺术家', - year: '年份', - genre: '流派', - duration: '时长', - track: '曲目', - format: '格式', - bitrate: '比特率', - sampleRate: '采样率', - bitDepth: '位深度', - channels: '声道', - fileSize: '文件大小', - path: '文件路径', - replayGainTrack: 'RG 曲目增益', - replayGainAlbum: 'RG 专辑增益', - replayGainPeak: 'RG 曲目峰值', - mono: '单声道', - stereo: '立体声', - }, - playlists: { - title: '播放列表', - newPlaylist: '新建播放列表', - unnamed: '未命名播放列表', - createName: '播放列表名称…', - create: '创建', - cancel: '取消', - empty: '暂无播放列表。', - emptyPlaylist: '此播放列表为空。', - addFirstSong: '添加第一首歌曲', - notFound: '未找到播放列表。', - songs: '{{n}} 首歌曲', - playAll: '全部播放', - shuffle: '随机播放', - addToQueue: '添加到队列', - back: '返回播放列表', - deletePlaylist: '删除', - confirmDelete: '再次点击确认删除', - removeSong: '从播放列表中移除', - addSongs: '添加歌曲', - searchPlaceholder: '搜索音乐库…', - noResults: '无结果。', - suggestions: '推荐歌曲', - noSuggestions: '暂无推荐。', - titleBadge: '播放列表', - refreshSuggestions: '新建议', - addSong: '添加到播放列表', - preview: '试听 (30 秒)', - previewStop: '停止试听', - playNextSuggestion: '播放下一首', - suggestionsHint: '双击行可添加到播放列表', - addSelected: '添加所选', - cacheOffline: '离线缓存播放列表', - offlineCached: '播放列表已缓存', - removeOffline: '从离线缓存中移除', - offlineDownloading: '正在缓存… ({{done}}/{{total}} 张专辑)', - publicLabel: '公开', - privateLabel: '私有', - editMeta: '编辑播放列表', - editNamePlaceholder: '播放列表名称…', - editCommentPlaceholder: '添加描述…', - editPublic: '公开播放列表', - editSave: '保存', - editCancel: '取消', - changeCover: '更改封面图片', - changeCoverLabel: '更改照片', - removeCover: '删除照片', - coverUpdated: '封面已更新', - metaSaved: '播放列表已更新', - downloadZip: '下载 (ZIP)', - // Toast notifications for multi-select - addSuccess: '{{count}} 首歌曲已添加到 {{playlist}}', - addPartial: '{{added}} 首已添加,{{skipped}} 首跳过(重复)', - addAllSkipped: '全部跳过({{count}} 首重复)', - addedAsDuplicates: '{{count}} 首歌曲已添加到 {{playlist}}(作为重复项)', - duplicateConfirmTitle: '已在播放列表中', - duplicateConfirmMessage: '所有 {{count}} 首歌曲已在 "{{playlist}}" 中。仍要作为重复项添加吗?', - duplicateConfirmAction: '仍要添加', - addError: '添加歌曲时出错', - createAndAddSuccess: '播放列表 "{{playlist}}" 已创建,包含 {{count}} 首歌曲', - createError: '创建播放列表时出错', - deleteSuccess: '{{count}} 个播放列表已删除', - deleteFailed: '删除 {{name}} 时出错', - deleteSelected: '删除所选', - deleteSelectedPartial: '所选 {{total}} 个播放列表中只有 {{n}} 个可删除(其余属于他人)。', - mergeSuccess: '{{count}} 首歌曲已合并到 {{playlist}}', - mergeNoNewSongs: '没有新歌曲可添加', - mergeError: '合并播放列表时出错', - mergeInto: '合并到', - selectionCount: '{{count}} 已选择', - select: '选择', - startSelect: '启用选择', - cancelSelect: '取消', - loadingAlbums: '正在解析 {{count}} 张专辑…', - loadingArtists: '正在解析 {{count}} 位艺术家…', - myPlaylists: '我的播放列表', - noOtherPlaylists: '没有其他可用播放列表', - addToPlaylistSuccess: '{{count}} 首歌曲已添加到 {{playlist}}', - addToPlaylistNoNew: '{{playlist}} 没有新歌曲', - addToPlaylistError: '添加到播放列表时出错', - importCSV: '导入 CSV', - importCSVTooltip: '从 Spotify CSV 导入', - csvImportReport: 'CSV 导入报告', - csvImportTotal: '总计', - csvImportAdded: '已添加', - csvImportDuplicates: '重复项', - csvImportNotFound: '未找到', - csvImportNetworkErrors: '网络错误', - csvImportDuplicatesTitle: '重复曲目(已在播放列表中):', - csvImportNotFoundTitle: '未找到的曲目:', - csvImportNetworkErrorsTitle: '网络错误(可重试导入):', - csvImportDownloadReport: '下载报告', - csvImportClose: '关闭', - csvImportNoValidTracks: 'CSV 文件中未找到有效曲目', - csvImportFailed: 'CSV 文件导入失败', - csvImportToast: '{{added}} 已添加,{{notFound}} 未找到,{{duplicates}} 重复项', - csvImportDownloadSuccess: '报告下载成功', - csvImportDownloadError: '报告下载失败', - }, - smartPlaylists: { - sectionBasic: '1. 基础', - sectionGenres: '2. 流派', - sectionYearsAndFilters: '3. 年份与筛选', - genreMode: '流派模式', - genreModeInclude: '包含流派', - genreModeExclude: '排除流派', - genreSearchPlaceholder: '筛选流派...', - availableGenres: '可用', - selectedGenres: '已选', - yearMode: '年份模式', - yearModeInclude: '包含范围', - yearModeExclude: '排除范围', - name: '名称(不含前缀)', - limit: '数量上限', - limitHint: '要包含在播放列表中的曲目数量(1-{{max}},通常为 50)。', - artistContains: '艺术家包含…', - albumContains: '专辑包含…', - titleContains: '标题包含…', - minRating: '最低评分', - minRatingAria: '智能播放列表的最低评分', - minRatingHint: '0 表示关闭最低阈值;1-5 仅保留评分高于所选值的曲目。', - fromYear: '起始年份', - toYear: '结束年份', - excludeUnrated: '排除未评分曲目', - compilationOnly: '仅合集', - create: '新建智能播放列表', - save: '保存智能播放列表', - created: '已创建 {{name}}', - updated: '已更新 {{name}}', - createFailed: '无法创建智能播放列表。', - updateFailed: '无法更新智能播放列表。', - navidromeOnly: '仅 Navidrome 服务器支持创建智能播放列表。', - loadFailed: '无法从 Navidrome 加载智能播放列表。', - sortRandom: '排序:随机', - sortTitleAsc: '排序:标题 A-Z', - sortTitleDesc: '排序:标题 Z-A', - sortYearDesc: '排序:年份降序', - sortYearAsc: '排序:年份升序', - sortPlayCountDesc: '排序:播放次数降序', - }, - mostPlayed: { - title: '最常播放', - topArtists: '热门艺术家', - topAlbums: '热门专辑', - plays: '播放 {{n}} 次', - sortMost: '最多播放在前', - sortLeast: '最少播放在前', - loadMore: '加载更多专辑', - noData: '暂无播放数据。开始收听吧!', - noArtists: '所有艺术家已过滤。', - filterCompilations: '隐藏合辑艺术家(Various Artists、原声带等)', - filterCompilationsShort: '隐藏合辑', - }, - losslessAlbums: { - empty: '此媒体库中还没有无损专辑。', - unsupported: '此服务器未公开查找无损专辑所需的元数据。', - slowFetchHint: '加载比其他专辑页面慢 — Psysonic 按音质遍历整个歌曲目录。', - }, - radio: { - title: '网络电台', - empty: '未配置任何电台。', - addStation: '添加电台', - editStation: '编辑', - deleteStation: '删除电台', - confirmDelete: '再次点击确认', - stationName: '电台名称…', - streamUrl: '流地址…', - homepageUrl: '主页地址(可选)', - save: '保存', - cancel: '取消', - live: '直播', - liveStream: '网络电台', - openHomepage: '打开主页', - changeCoverLabel: '更换封面', - removeCover: '移除封面', - browseDirectory: '搜索目录', - directoryPlaceholder: '搜索电台…', - noResults: '未找到电台。', - stationAdded: '电台已添加', - filterAll: '全部', - filterFavorites: '收藏', - sortManual: '手动', - sortAZ: 'A → Z', - sortZA: 'Z → A', - sortNewest: '最新', - favorite: '添加到收藏', - unfavorite: '从收藏移除', - noFavorites: '没有收藏的电台。', - listenerCount_one: '{{count}} 位听众', - listenerCount_other: '{{count}} 位听众', - recentlyPlayed: '最近播放', - upNext: '即将播放', - }, - folderBrowser: { - empty: '空文件夹', - error: '加载失败', - }, - deviceSync: { - title: '设备同步', - targetFolder: '目标文件夹', - noFolderChosen: '未选择文件夹', - selectDrive: '选择驱动器…', - refreshDrives: '刷新驱动器', - noDrivesDetected: '未检测到可移动驱动器', - browseManual: '手动浏览…', - free: '可用', - notMountedVolume: '目标不在已挂载的卷上。驱动器可能已断开。', - chooseFolder: '选择…', - filenameTemplate: '文件名模板', - targetDevice: '目标设备', - templateHint: '变量:{artist}、{album}、{title}、{track_number}、{disc_number}、{year}', - cleanupButton: '删除不在选择范围内的文件', - cleanupNothingToDelete: '无需删除 — 设备已同步。', - confirmCleanup: '将从设备中删除 {{count}} 个不在当前选择范围内的文件。继续?', - cleanupComplete: '已从设备中删除 {{count}} 个文件。', - selectedSources: '已选来源', - noSourcesSelected: '未选择来源。点击浏览器中的项目以添加。', - clearAll: '全部清除', - tabPlaylists: '播放列表', - tabAlbums: '专辑', - tabArtists: '艺术家', - searchPlaceholder: '搜索…', - syncButton: '同步到设备', - actionTransfer: '传输到设备', - actionDelete: '从设备删除', - actionApplyAll: '应用所有更改', - templatePreview: '预览', - templatePresetStandard: '标准', - templatePresetMultiDisc: '多碟', - templatePresetAltFolder: '备用文件夹', - tokenSlashHint: '/ = 文件夹分隔符', - cancel: '取消', - noTargetDir: '请先选择目标文件夹。', - noSources: '请至少选择一个来源。', - noTracks: '所选来源中未找到曲目。', - fetchError: '从服务器加载曲目失败。', - syncComplete: '同步完成。', - dismiss: '关闭', - cancelSync: '取消', - syncCancelled: '同步已取消(已传输 {{done}} / {{total}})。', - colName: '名称', - colType: '类型', - colStatus: '状态', - onDevice: '设备管理器', - addSources: '添加…', - syncResult: '已传输 {{done}},{{skipped}} 已是最新(共 {{total}})', - deleteFromDevice: '标记为删除({{count}})', - confirmDelete: '从设备删除 {{count}} 个项目:{{names}}?', - deleteComplete: '已从设备删除 {{count}} 个项目。', - manifestImported: '已从设备清单导入 {{count}} 个来源。', - statusSynced: '已同步', - statusPending: '待处理', - statusDeletion: '删除中', - markForDeletion: '标记为删除', - removeSource: '移除', - undoDeletion: '撤销删除', - syncInBackground: '同步已在后台启动 — 您可以离开此页面。', - syncInProgress: '{{done}} / {{total}} 首曲目…', - syncSummary: '同步摘要', - calculating: '正在计算所需数据…', - filesToAdd: '要添加的文件:', - filesToDelete: '要删除的文件:', - netChange: '净变化:', - availableSpace: '可用磁盘空间:', - spaceWarning: '警告:目标设备的可用空间不足。', - proceed: '继续同步', - notEnoughSpace: '检测到物理磁盘空间不足!', - liveSearch: '实时', - randomAlbumsLabel: '随机专辑', - }, - orbit: { - triggerLabel: 'Orbit', - triggerTooltip: '开始或加入共享收听会话', - launchCreate: '创建会话', - launchJoin: '加入会话', - launchHelp: '这是怎么工作的?', - launchHelpSoon: '即将推出', - joinModalTitle: '加入 Orbit 会话', - joinModalSub: '粘贴主持人发给你的邀请链接。', - joinModalLinkLabel: '邀请链接', - joinModalLinkPlaceholder: 'psysonic2-…', - joinModalLinkHelper: '适用于任何有效的 Orbit 链接。必须指向你当前登录的服务器。', - joinModalPasteTooltip: '从剪贴板粘贴', - joinModalSubmit: '加入', - joinModalBusy: '加入中…', - joinErrEmpty: '请粘贴一个邀请链接。', - joinErrInvalid: '这看起来不像 Orbit 邀请链接。', - closeAria: '关闭', - heroTitlePrefix: '一起听音乐 —', - heroTitleBrand: 'Orbit', - heroSub: '开始会话 — {{server}} 上的其他用户将一起收听并可以推荐曲目。', - fallbackServer: '此服务器', - tipLan: '你当前通过本地网络地址连接。网络外的访客无法加入 — 请在启动前切换到公共服务器地址。', - tipRemote: '为了让家庭网络外的访客能够加入,你的服务器地址必须公开可达。如果你的服务器仅限内部使用,请在启动前切换。', - labelName: '会话名称', - namePlaceholder: 'Velvet Orbit', - reshuffleTooltip: '新建议', - reshuffleAria: '建议新名称', - helperName: '会话对访客的显示方式 — 保留或输入自己的名称。', - labelMax: '最大访客数', - helperMax: '你不计算在内 — 这仅限制加入的访客。', - labelLink: '邀请链接', - tooltipCopied: '已复制', - tooltipCopy: '复制', - ariaCopyLink: '复制邀请链接', - helperLink: '将此链接发送给你的访客。他们可以在 Psysonic 的任何位置使用 Ctrl+V 粘贴。', - labelClearQueue: '先清空我的队列', - helperClearQueue: '以空队列启动会话。关闭:你已排队的曲目保留并与访客共享。', - btnCancel: '取消', - btnStarting: '启动中…', - btnStart: '启动 Orbit', - btnCopyAndStart: '复制链接并启动', - errNameRequired: '请为你的会话命名。', - errStartFailed: '无法启动。', - hostLabel: '主持人:{{name}}', - participantsTooltip: '参与者', - settingsTooltip: '会话设置', - shareTooltip: '分享邀请链接', - shuffleLabel: '下次洗牌', - catchUpLabel: '跟上', - catchUpTooltip: '跳到主持人当前位置', - hostAway: '主持人离线', - hostOnline: '主持人在线', - endTooltip: '结束会话', - leaveTooltip: '离开会话', - helpTooltip: 'Orbit 的工作原理', - diag: { - openTooltip: '诊断 — 可复制的事件日志', - title: 'Orbit 诊断', - role: '角色', - hostTrack: '主持人曲目 ID', - hostPos: '主持人位置', - guestTrack: '我的曲目 ID', - guestPos: '我的位置', - drift: '偏差', - stateAge: '状态时长', - eventLog: '事件日志 ({{count}})', - copyLabel: '复制', - copyTooltip: '将日志复制到剪贴板', - clearLabel: '清除', - clearTooltip: '清空缓冲区', - empty: '暂无事件 — Orbit 同步时会显示。', - hint: '在重现问题前打开此面板,然后点击复制并粘贴到错误报告中。', - copied: '已复制 {{count}} 行', - copyFailed: '无法复制到剪贴板', - cleared: '缓冲区已清空', - }, - helpTitle: 'Orbit 的工作原理', - helpIntro: 'Orbit 将 Psysonic 变成一个共享的收听空间。主持人选择音乐;访客同步收听并可以推荐曲目。', - helpHostOnly: '(主持人)', - helpSec1Title: '什么是 Orbit?', - helpSec1Body: '"一起听"模式 — 主持人驱动播放,访客加入收听。一切都通过你自己的 Navidrome 服务器上的播放列表进行;没有外部基础设施。', - helpSec2Title: '主持人和访客', - helpSec2Body: '主持人控制播放(播放 / 暂停 / 跳过 / 跳转),并决定会话何时结束。访客跟随主持人的播放,可以推荐曲目,随时离开或重新加入。只有主持人可以踢出或永久封禁参与者。', - helpSec2WarnHead: '重要:使用独立账户。', - helpSec2WarnBody: '每个参与者都需要自己的 Navidrome 账户。如果主持人和访客使用同一用户登录,他们的提交会冲突,主持人将永远看不到访客的建议。', - helpSec3Title: '启动和邀请', - helpSec3Body: '点击"Orbit"按钮 → 创建会话 → 启动弹窗显示可复制的邀请链接,并可选清空你当前的队列。以任何方式分享该链接。会话运行时,顶部会话栏中的分享按钮可随时再次复制链接。', - helpSec4Title: '加入', - helpSec4Body: '使用 Ctrl+V / Cmd+V 在 Psysonic 的任何位置粘贴邀请链接 — 加入提示会自动弹出。或者:「Orbit」→ 加入会话 → 粘贴到字段中。如果链接指向你有账户的服务器,Psysonic 会为你切换。当你在该服务器上有多个账户时,小型选择器会询问使用哪个。', - helpSec5Title: '推荐曲目', - helpSec5Body: '在任何曲目列表中:双击一行,或右键 → "添加到 Orbit 会话"。单击会显示提示而不是将整张专辑扔进共享队列 — 这是有意的。明确的批量操作(如"全部播放"或"播放专辑")先要求确认然后追加(永不替换)。', - helpSec6Title: '共享队列', - helpSec6Body: '队列显示主持人即将播放的曲目 — 所有人可见。批量添加总是追加到末尾,因此访客的建议不会丢失。自动洗牌定期重新排序队列(可配置:1 / 5 / 10 / 15 / 30 分钟)。如果你的播放偏离主持人,会话栏中的"跟上"按钮会让你回到主持人的实时位置。', - helpSec7Title: '审批', - helpSec7Body: '默认情况下,访客建议需要手动审批 — 它们出现在队列面板顶部的"审批"栏中,带有接受 / 拒绝按钮。可以在会话设置中打开自动审批,使所有建议直接生效。', - helpSec8Title: '参与者和设置', - helpSec8Body: '打开会话栏中的设置图标以配置洗牌频率、自动审批和"立即洗牌"快捷方式。点击参与者数量查看谁已连接 — 踢出(可通过链接重新加入)或封禁(在该会话中被锁定)。访客也可以看到参与者列表,但仅为只读。', - helpSec9Title: '结束会话', - helpSec9Body: '主持人 X → 确认对话框 → 会话对所有人关闭,服务器播放列表会自动清理。访客 X → 访客离开,会话继续运行。如果主持人保持静默 5 分钟,访客会自动退出并收到通知;该窗口内的短时间重连不可见。', - participantsInviteLabel: '邀请链接', - participantsCountLabel: '{{count}} 人在会话中', - participantsHost: '主持人', - participantsEmpty: '还没有访客', - participantsKickTooltip: '从会话中移除', - participantsKickAria: '移除 {{user}}', - participantsRemoveTooltip: '从会话中移除', - participantsRemoveAria: '从此会话中移除 {{user}}', - participantsBanTooltip: '永久封禁', - participantsBanAria: '永久封禁 {{user}}', - participantsMuteTooltip: '禁止投歌', - participantsUnmuteTooltip: '允许投歌', - participantsMuteAria: '禁止 {{user}} 投歌', - participantsUnmuteAria: '允许 {{user}} 重新投歌', - confirmRemoveTitle: '从会话中移除?', - confirmRemoveBody: '{{user}} 将从会话中移除,但可以通过你的邀请链接重新加入。', - confirmRemoveConfirm: '移除', - confirmBanTitle: '永久封禁?', - confirmBanBody: '{{user}} 将被移除并被阻止重新加入此会话。在会话存在期间无法撤销。', - confirmBanConfirm: '封禁', - confirmCancel: '取消', - confirmJoinTitle: '加入 Orbit 会话?', - confirmJoinBody: '{{host}} 邀请你加入"{{name}}"。加入会话?', - confirmJoinConfirm: '加入', - confirmLeaveTitle: '离开会话?', - confirmLeaveBody: '离开"{{name}}"?你可以随时通过 {{host}} 的邀请链接重新加入。', - confirmLeaveConfirm: '离开', - confirmEndTitle: '为所有人结束会话?', - confirmEndBody: '"{{name}}"将对所有参与者关闭。会话的播放列表会自动清理。', - confirmEndConfirm: '结束会话', - invalidLinkTitle: '邀请链接已失效', - invalidLinkBody: '此 Orbit 会话不再存在或已结束。请主持人提供新的邀请链接。', - settingsTitle: '会话设置', - settingAutoApprove: '自动批准建议', - settingAutoApproveHint: '访客建议立即进入你的队列。关闭:它们保留在会话列表中供稍后审查。', - settingAutoShuffle: '自动洗牌', - settingAutoShuffleHint: '即将播放队列的定期 Fisher-Yates 洗牌。关闭:顺序仅在你手动重新排列时改变。', - settingShuffleInterval: '洗牌间隔', - settingShuffleIntervalHint: '会话运行时即将播放队列的重新洗牌频率。', - suggestBlockedMuted: '主持人已禁止你在本场会话投歌。', - settingShuffleIntervalValue_one: '{{count}} 分钟', - settingShuffleIntervalValue_other: '{{count}} 分钟', - settingShuffleNow: '立即洗牌', - toastSuggested: '{{user}} 推荐了"{{title}}"', - toastSuggestedMany: '队列中有 {{count}} 个新建议', - toastShuffled: '队列已洗牌', - toastJoined: '已加入会话', - toastLoginFirst: '加入会话前请先登录', - toastSwitchServer: '请先切换到 {{url}},然后再次粘贴', - toastNoAccountForServer: '你没有 {{url}} 的访问权限。请主持人发送邀请。', - toastSwitchFailed: '无法切换到 {{url}}', - accountPickerTitle: '使用哪个账户?', - accountPickerSub: '你在 {{url}} 上有多个账户。选择用于加入会话的账户。', - toastJoinFail: '无法加入会话', - joinErrNotFound: '未找到会话', - joinErrEnded: '会话已结束', - joinErrFull: '会话已满', - joinErrKicked: '你无法重新加入此会话', - joinErrNoUser: '没有活动服务器', - joinErrServerError: '无法加入', - ctxAddToSession: '添加到 Orbit 会话', - ctxSuggestedToast: '已推荐到会话', - ctxSuggestFailed: '无法推荐 — 未加入', - ctxAddToSessionHost: '添加到 Orbit 会话', - ctxAddedHostToast: '已添加到会话', - ctxAddHostFailed: '无法添加到会话', - bulkConfirmTitle: '全部添加到 Orbit 队列?', - bulkConfirmBody: '这将一次性把 {{count}} 首曲目放入共享队列。对你的访客来说信息量很大。继续?', - bulkConfirmYes: '全部添加', - bulkConfirmNo: '取消', - guestLive: '直播', - guestPlaying: '正在播放', - guestPaused: '已暂停', - guestLoading: '加载中…', - guestSuggestions: '建议', - guestUpNext: '接下来', - guestUpNextEmpty: '队列为空。打开曲目的上下文菜单并选择"添加到 Orbit 会话"来推荐一首。', - guestPendingTitle: '等待主持人', - guestPendingHint: '已推荐 — 主持人接受后会出现在队列中。', - approvalTitle: '待批准', - approvalFrom: '由 {{user}} 推荐', - approvalAccept: '接受', - approvalDecline: '拒绝', - guestUpNextMore: '+ 主持人队列中还有 {{count}} 首', - guestSubmitter: '来自 {{user}}', - queueAddedByHost: '由主持人添加', - queueAddedByYou: '由你添加', - queueAddedByUser: '由 {{user}} 添加', - guestEmpty: '还没有建议。打开曲目的上下文菜单并选择"添加到 Orbit 会话"。', - guestFooter: '主持人控制播放 — 你无法更改列表。', - exitKickedTitle: '你已被会话封禁', - exitRemovedTitle: '你已从会话中移除', - exitEndedTitle: '主持人已结束会话', - exitHostTimeoutTitle: '主持人无响应', - exitHostTimeoutBody: '{{host}} 有一段时间没有发送更新了,所以"{{name}}"在你这边已关闭。你可以随时通过邀请链接重新加入。', - exitKickedBody: '{{host}} 已将你从"{{name}}"封禁。你无法重新加入。', - exitRemovedBody: '{{host}} 已将你从"{{name}}"移除。你可以随时通过邀请链接重新加入。', - exitEndedBody: '"{{name}}"已结束。希望你玩得开心。', - exitOk: '好的', - }, - tray: { - playPause: '播放 / 暂停', - nextTrack: '下一首', - previousTrack: '上一首', - showHide: '显示 / 隐藏', - exitPsysonic: '退出 Psysonic', - nothingPlaying: '当前没有播放', - }, - licenses: { - title: '开源许可证', - intro: 'Psysonic 基于开源软件构建。下方列表显示了应用程序中包含的每个依赖项的版本、许可证以及完整的许可证文本。', - highlights: '主要依赖项', - searchPlaceholder: '按名称、版本或许可证搜索…', - noResults: '没有匹配项。', - loading: '加载许可证…', - loadError: '无法加载许可证数据。', - noLicenseText: '此依赖项未包含许可证文本。', - viewSource: '查看源代码', - totalLine: '{{total}} 个依赖项 — {{cargo}} cargo, {{npm}} npm', - generatedAt: '最后生成时间 {{date}}', - }, -}; diff --git a/src/locales/zh/albumDetail.ts b/src/locales/zh/albumDetail.ts new file mode 100644 index 00000000..f9af5789 --- /dev/null +++ b/src/locales/zh/albumDetail.ts @@ -0,0 +1,47 @@ +export const albumDetail = { + back: '返回', + orbitDoubleClickHint: '双击将此曲目添加到 Orbit 队列', + playAll: '全部播放', + shareAlbum: '分享专辑', + enqueue: '加入队列', + enqueueTooltip: '将整张专辑添加到播放队列', + artistBio: '艺术家简介', + download: '下载 (ZIP)', + downloading: '加载中…', + cacheOffline: '设为离线可用', + offlineCached: '已离线缓存', + offlineDownloading: '正在缓存… ({{n}}/{{total}})', + removeOffline: '移除离线缓存', + offlineStorageFull: '离线存储空间已满(限制:{{mb}} MB)。请从离线音乐库中删除专辑以释放空间,或在设置中增加限制。', + offlineStorageGoToLibrary: '离线音乐库', + offlineStorageGoToSettings: '设置', + favoriteAdd: '添加到收藏', + favoriteRemove: '从收藏中移除', + favorite: '收藏', + noBio: '暂无简介。', + moreByArtist: '{{artist}} 的更多作品', + tracksCount: '{{n}} 首曲目', + goToArtist: '前往 {{artist}}', + moreLabelAlbums: '{{label}} 的更多专辑', + trackTitle: '标题', + trackAlbum: '专辑', + trackArtist: '艺术家', + trackGenre: '流派', + trackFormat: '格式', + trackFavorite: '收藏', + trackRating: '评分', + trackDuration: '时长', + trackTotal: '总计', + columns: '列', + resetColumns: '重置为默认', + notFound: '未找到专辑。', + bioModal: '艺术家简介', + bioClose: '关闭', + ratingLabel: '评分', + enlargeCover: '放大', + filterSongs: '筛选歌曲…', + sortNatural: '默认顺序', + sortByTitle: 'A–Z(标题)', + sortByArtist: 'A–Z(艺术家)', + sortByAlbum: 'A–Z(专辑)', +}; diff --git a/src/locales/zh/albums.ts b/src/locales/zh/albums.ts new file mode 100644 index 00000000..7248ec6e --- /dev/null +++ b/src/locales/zh/albums.ts @@ -0,0 +1,32 @@ +export const albums = { + title: '全部专辑', + sortByName: '按名称排序 (A-Z)', + sortByArtist: '按艺术家排序 (A-Z)', + sortNewest: '最新优先', + sortRandom: '随机排序', + yearFrom: '从', + yearTo: '到', + yearFilterClear: '清除年份筛选', + yearFilterLabel: '年份', + compilationLabel: '合辑', + compilationOnly: '仅合辑', + compilationHide: '隐藏合辑', + compilationTooltipAll: '所有专辑 · 点击:仅合辑', + compilationTooltipOnly: '仅合辑 · 点击:隐藏合辑', + compilationTooltipHide: '已隐藏合辑 · 点击:显示全部', + select: '多选', + startSelect: '启用多选', + cancelSelect: '取消', + selectionCount: '{{count}} 已选择', + downloadZips: '下载 ZIP', + addOffline: '添加离线', + enqueueSelected_one: '加入队列 ({{count}})', + enqueueSelected_other: '加入队列 ({{count}})', + enqueueQueued_one: '已将 {{count}} 张专辑加入队列', + enqueueQueued_other: '已将 {{count}} 张专辑加入队列', + downloadingZip: '正在下载 {{current}}/{{total}}: {{name}}', + downloadZipDone: '已下载 {{count}} 个 ZIP', + downloadZipFailed: '下载 {{name}} 失败', + offlineQueuing: '正在将 {{count}} 张专辑加入离线队列…', + offlineFailed: '添加 {{name}} 离线失败', +}; diff --git a/src/locales/zh/artistDetail.ts b/src/locales/zh/artistDetail.ts new file mode 100644 index 00000000..8d55a2c5 --- /dev/null +++ b/src/locales/zh/artistDetail.ts @@ -0,0 +1,41 @@ +export const artistDetail = { + back: '返回', + albums: '专辑', + album: '专辑', + playAll: '全部播放', + shareArtist: '分享艺人', + shuffle: '随机播放', + radio: '电台', + loading: '加载中…', + noRadio: '未找到该艺术家的相似曲目。', + notFound: '未找到艺术家。', + albumsBy: '{{name}} 的专辑', + topTracks: '热门曲目', + noAlbums: '未找到专辑。', + trackTitle: '标题', + trackAlbum: '专辑', + trackDuration: '时长', + favoriteAdd: '添加到收藏', + favoriteRemove: '从收藏中移除', + favorite: '收藏', + albumCount_one: '{{count}} 张专辑', + albumCount_other: '{{count}} 张专辑', + openedInBrowser: '已在浏览器中打开', + featuredOn: '还出现在', + similarArtists: '相似艺术家', + cacheOffline: '离线保存全部专辑', + offlineCached: '全部专辑已缓存', + offlineDownloading: '正在缓存… ({{done}}/{{total}} 张专辑)', + uploadImage: '上传艺术家图片', + uploadImageError: '图片上传失败', + releaseTypes: { + album: '专辑', + ep: 'EP', + single: '单曲', + compilation: '合辑', + live: '现场', + soundtrack: '原声带', + remix: '混音', + other: '其他', + }, +}; diff --git a/src/locales/zh/artists.ts b/src/locales/zh/artists.ts new file mode 100644 index 00000000..a4f52f26 --- /dev/null +++ b/src/locales/zh/artists.ts @@ -0,0 +1,18 @@ +export const artists = { + title: '艺术家', + search: '搜索…', + all: '全部', + gridView: '网格视图', + listView: '列表视图', + imagesOn: '艺术家图片已开启 — 可能增加网络和系统负载', + imagesOff: '艺术家图片已关闭 — 仅显示首字母', + loadMore: '加载更多', + notFound: '未找到艺术家。', + albumCount_one: '{{count}} 张专辑', + albumCount_other: '{{count}} 张专辑', + selectionCount: '{{count}} 已选择', + select: '多选', + startSelect: '启用多选', + cancelSelect: '取消', + addToPlaylist: '添加到播放列表', +}; diff --git a/src/locales/zh/changelog.ts b/src/locales/zh/changelog.ts new file mode 100644 index 00000000..831767d3 --- /dev/null +++ b/src/locales/zh/changelog.ts @@ -0,0 +1,5 @@ +export const changelog = { + modalTitle: '新功能', + dontShowAgain: '不再显示', + close: '知道了', +}; diff --git a/src/locales/zh/common.ts b/src/locales/zh/common.ts new file mode 100644 index 00000000..085ce954 --- /dev/null +++ b/src/locales/zh/common.ts @@ -0,0 +1,56 @@ +export const common = { + albums: '专辑', + album: '专辑', + loading: '加载中…', + loadingMore: '加载中…', + loadingPlaylists: '正在加载播放列表…', + noAlbums: '未找到专辑。', + downloading: '正在下载…', + downloadZip: '下载 (ZIP)', + back: '返回', + cancel: '取消', + save: '保存', + delete: '删除', + use: '使用', + add: '添加', + new: '新', + active: '当前使用', + download: '下载', + chooseDownloadFolder: '选择下载文件夹', + noFolderSelected: '未选择文件夹', + rememberDownloadFolder: '记住此文件夹', + filterGenre: '流派筛选', + filterSearchGenres: '搜索流派…', + filterNoGenres: '未找到匹配流派', + filterClear: '清除', + favorites: '收藏', + favoritesTooltipOff: '仅显示收藏', + favoritesTooltipOn: '显示全部', + play: '播放', + bulkSelected: '已选 {{count}} 首', + clearSelection: '清除选择', + bulkAddToPlaylist: '添加到播放列表', + bulkRemoveFromPlaylist: '从播放列表移除', + bulkClear: '取消选择', + updaterAvailable: '有可用更新', + updaterVersion: 'v{{version}} 已发布', + updaterWebsite: '官网', + updaterModalTitle: '有新版本可用', + updaterChangelog: '更新内容', + updaterDownloadBtn: '立即下载', + updaterSkipBtn: '跳过此版本', + updaterRemindBtn: '稍后提醒', + updaterDone: '下载完成', + updaterShowFolder: '在文件夹中显示', + updaterInstallHint: '请关闭 Psysonic 并手动运行安装程序。', + updaterAurHint: '通过 AUR 安装更新:', + updaterErrorMsg: '下载失败', + updaterRetryBtn: '重试', + durationHoursMinutes: '{{hours}}小时{{minutes}}分钟', + durationMinutesOnly: '{{minutes}}分钟', + updaterOpenGitHub: '在 GitHub 上打开', + filters: '筛选器', + more: '更多', + yearRange: '年份范围', + clearAll: '清除全部', +}; diff --git a/src/locales/zh/composerDetail.ts b/src/locales/zh/composerDetail.ts new file mode 100644 index 00000000..a761a7b1 --- /dev/null +++ b/src/locales/zh/composerDetail.ts @@ -0,0 +1,11 @@ +export const composerDetail = { + back: '返回', + notFound: '未找到作曲家。', + about: '关于这位作曲家', + works: '作品', + noWorks: '未找到作品。', + workCount_one: '{{count}} 部作品', + workCount_other: '{{count}} 部作品', + shareComposer: '分享作曲家', + unknownComposer: '作曲家', +}; diff --git a/src/locales/zh/composers.ts b/src/locales/zh/composers.ts new file mode 100644 index 00000000..8fe3caec --- /dev/null +++ b/src/locales/zh/composers.ts @@ -0,0 +1,10 @@ +export const composers = { + title: '作曲家', + search: '搜索…', + notFound: '未找到作曲家。', + unsupported: '按作曲家浏览需要 Navidrome 0.55 或更新版本。', + loadFailed: '无法加载作曲家。', + retry: '重试', + involvedIn_one: '参与 {{count}} 张专辑', + involvedIn_other: '参与 {{count}} 张专辑', +}; diff --git a/src/locales/zh/connection.ts b/src/locales/zh/connection.ts new file mode 100644 index 00000000..f2f7673a --- /dev/null +++ b/src/locales/zh/connection.ts @@ -0,0 +1,24 @@ +export const connection = { + connected: '已连接', + connectedTo: '已连接到 {{server}}', + disconnected: '已断开连接', + disconnectedFrom: '无法连接到 {{server}} — 点击检查设置', + checking: '正在连接…', + extern: '外部', + offlineTitle: '无服务器连接', + offlineSubtitle: '无法连接到 {{server}}。请检查您的网络或服务器。', + offlineModeBanner: '离线模式 — 正在从本地缓存播放', + offlineNoCacheBanner: '无服务器连接 — 无法访问 {{server}}', + offlineLibraryTitle: '离线音乐库', + offlineLibraryEmpty: '尚未缓存任何专辑。请联网,打开专辑并点击"设为离线可用"。', + offlineAlbumCount_one: '{{n}} 张专辑', + offlineAlbumCount_plural: '{{n}} 张专辑', + retry: '重试', + serverSettings: '服务器设置', + switchServerTitle: '切换服务器', + switchServerHint: '点击选择其他已保存的服务器。', + manageServers: '管理服务器…', + switchFailed: '无法切换 — 无法连接服务器。', + lastfmConnected: 'Last.fm 已连接为 @{{user}}', + lastfmSessionInvalid: '会话无效 — 点击重新连接', +}; diff --git a/src/locales/zh/contextMenu.ts b/src/locales/zh/contextMenu.ts new file mode 100644 index 00000000..63986f83 --- /dev/null +++ b/src/locales/zh/contextMenu.ts @@ -0,0 +1,32 @@ +export const contextMenu = { + playNow: '立即播放', + playNext: '下一首播放', + addToQueue: '添加到队列', + enqueueAlbum: '专辑加入队列', + enqueueAlbums_one: '{{count}} 张专辑加入队列', + enqueueAlbums_other: '{{count}} 张专辑加入队列', + startRadio: '开始电台', + instantMix: '即时混音', + instantMixFailed: '无法生成即时混音 — 服务器或插件出错。', + cliMixNeedsTrack: '当前没有正在播放的内容 — 请先开始播放,然后再执行混音命令。', + lfmLove: '在 Last.fm 上标记喜欢', + lfmUnlove: '取消 Last.fm 喜欢标记', + favorite: '收藏', + favoriteArtist: '收藏艺术家', + favoriteAlbum: '收藏专辑', + unfavorite: '取消收藏', + unfavoriteArtist: '取消收藏艺术家', + unfavoriteAlbum: '取消收藏专辑', + removeFromQueue: '从队列中移除', + openAlbum: '打开专辑', + goToArtist: '前往艺术家', + download: '下载 (ZIP)', + addToPlaylist: '添加到播放列表', + selectedPlaylists: '已选择 {{count}} 个播放列表', + selectedAlbums: '已选择 {{count}} 个专辑', + selectedArtists: '已选择 {{count}} 个艺术家', + songInfo: '歌曲信息', + shareLink: '复制分享链接', + shareCopied: '分享链接已复制到剪贴板。', + shareCopyFailed: '无法复制到剪贴板。', +}; diff --git a/src/locales/zh/deviceSync.ts b/src/locales/zh/deviceSync.ts new file mode 100644 index 00000000..ca0cc5b6 --- /dev/null +++ b/src/locales/zh/deviceSync.ts @@ -0,0 +1,73 @@ +export const deviceSync = { + title: '设备同步', + targetFolder: '目标文件夹', + noFolderChosen: '未选择文件夹', + selectDrive: '选择驱动器…', + refreshDrives: '刷新驱动器', + noDrivesDetected: '未检测到可移动驱动器', + browseManual: '手动浏览…', + free: '可用', + notMountedVolume: '目标不在已挂载的卷上。驱动器可能已断开。', + chooseFolder: '选择…', + filenameTemplate: '文件名模板', + targetDevice: '目标设备', + templateHint: '变量:{artist}、{album}、{title}、{track_number}、{disc_number}、{year}', + cleanupButton: '删除不在选择范围内的文件', + cleanupNothingToDelete: '无需删除 — 设备已同步。', + confirmCleanup: '将从设备中删除 {{count}} 个不在当前选择范围内的文件。继续?', + cleanupComplete: '已从设备中删除 {{count}} 个文件。', + selectedSources: '已选来源', + noSourcesSelected: '未选择来源。点击浏览器中的项目以添加。', + clearAll: '全部清除', + tabPlaylists: '播放列表', + tabAlbums: '专辑', + tabArtists: '艺术家', + searchPlaceholder: '搜索…', + syncButton: '同步到设备', + actionTransfer: '传输到设备', + actionDelete: '从设备删除', + actionApplyAll: '应用所有更改', + templatePreview: '预览', + templatePresetStandard: '标准', + templatePresetMultiDisc: '多碟', + templatePresetAltFolder: '备用文件夹', + tokenSlashHint: '/ = 文件夹分隔符', + cancel: '取消', + noTargetDir: '请先选择目标文件夹。', + noSources: '请至少选择一个来源。', + noTracks: '所选来源中未找到曲目。', + fetchError: '从服务器加载曲目失败。', + syncComplete: '同步完成。', + dismiss: '关闭', + cancelSync: '取消', + syncCancelled: '同步已取消(已传输 {{done}} / {{total}})。', + colName: '名称', + colType: '类型', + colStatus: '状态', + onDevice: '设备管理器', + addSources: '添加…', + syncResult: '已传输 {{done}},{{skipped}} 已是最新(共 {{total}})', + deleteFromDevice: '标记为删除({{count}})', + confirmDelete: '从设备删除 {{count}} 个项目:{{names}}?', + deleteComplete: '已从设备删除 {{count}} 个项目。', + manifestImported: '已从设备清单导入 {{count}} 个来源。', + statusSynced: '已同步', + statusPending: '待处理', + statusDeletion: '删除中', + markForDeletion: '标记为删除', + removeSource: '移除', + undoDeletion: '撤销删除', + syncInBackground: '同步已在后台启动 — 您可以离开此页面。', + syncInProgress: '{{done}} / {{total}} 首曲目…', + syncSummary: '同步摘要', + calculating: '正在计算所需数据…', + filesToAdd: '要添加的文件:', + filesToDelete: '要删除的文件:', + netChange: '净变化:', + availableSpace: '可用磁盘空间:', + spaceWarning: '警告:目标设备的可用空间不足。', + proceed: '继续同步', + notEnoughSpace: '检测到物理磁盘空间不足!', + liveSearch: '实时', + randomAlbumsLabel: '随机专辑', +}; diff --git a/src/locales/zh/entityRating.ts b/src/locales/zh/entityRating.ts new file mode 100644 index 00000000..53bd486c --- /dev/null +++ b/src/locales/zh/entityRating.ts @@ -0,0 +1,9 @@ +export const entityRating = { + albumShort: '专辑评分', + artistShort: '艺人评分', + albumAriaLabel: '专辑评分', + artistAriaLabel: '艺人评分', + selectedArtistsRatingAriaLabel: '为所选 {{count}} 位艺人设置星级评分', + selectedAlbumsRatingAriaLabel: '为所选 {{count}} 张专辑设置星级评分', + saveFailed: '无法保存评分。', +}; diff --git a/src/locales/zh/favorites.ts b/src/locales/zh/favorites.ts new file mode 100644 index 00000000..7f1575c8 --- /dev/null +++ b/src/locales/zh/favorites.ts @@ -0,0 +1,19 @@ +export const favorites = { + title: '收藏夹', + empty: '您还没有保存任何收藏。', + artists: '艺术家', + albums: '专辑', + songs: '歌曲', + enqueueAll: '全部加入队列', + playAll: '全部播放', + removeSong: '从收藏中移除', + stations: '广播电台', + showingFiltered: '显示 {{filtered}} / {{total}} ({{artist}})', + showingCount: '显示 {{filtered}} / {{total}}', + clearArtistFilter: '清除艺术家筛选', + noFilterResults: '所选筛选条件下无结果。', + allArtists: '全部艺术家', + topArtists: '按收藏数排行的艺术家', + topArtistsSongCount_one: '{{count}} 首歌曲', + topArtistsSongCount_other: '{{count}} 首歌曲', +}; diff --git a/src/locales/zh/folderBrowser.ts b/src/locales/zh/folderBrowser.ts new file mode 100644 index 00000000..d12191a5 --- /dev/null +++ b/src/locales/zh/folderBrowser.ts @@ -0,0 +1,4 @@ +export const folderBrowser = { + empty: '空文件夹', + error: '加载失败', +}; diff --git a/src/locales/zh/genres.ts b/src/locales/zh/genres.ts new file mode 100644 index 00000000..657dde10 --- /dev/null +++ b/src/locales/zh/genres.ts @@ -0,0 +1,12 @@ +export const genres = { + title: '流派', + genreCount: '个流派', + albumCount_one: '{{count}} 张专辑', + albumCount_other: '{{count}} 张专辑', + loading: '正在加载流派…', + empty: '未找到流派。', + albumsLoading: '正在加载专辑…', + albumsEmpty: '未找到该流派的专辑。', + loadMore: '加载更多', + back: '返回', +}; diff --git a/src/locales/zh/help.ts b/src/locales/zh/help.ts new file mode 100644 index 00000000..eb6e92e7 --- /dev/null +++ b/src/locales/zh/help.ts @@ -0,0 +1,105 @@ +export const help = { + title: '帮助', + searchPlaceholder: '搜索帮助…', + noResults: '没有匹配的主题。请尝试其他搜索词。', + s1: '入门指南', + q1: '支持哪些服务器?', + a1: 'Psysonic 主要为 Navidrome 而构建,并完全兼容 Subsonic — Gonic、Airsonic、LMS 和其他 Subsonic-API 服务器也可使用。某些高级功能(评分、智能播放列表、Magic-String 共享、用户管理)需要 Navidrome。', + q2: '如何添加服务器?', + a2: '设置 → 服务器 → 添加服务器。输入 URL(例如 http://192.168.1.100:4533)、用户名和密码。Psysonic 会在保存前测试连接 — 失败则不保存任何内容。您可以添加任意数量的服务器并在标题栏中切换;同一时刻只有一个处于活动状态。', + q3: '快速 UI 介绍?', + a3: '左侧栏用于导航,中间是 Mainstage / 各页面,底部是播放栏,右侧是队列面板(通过右上角紧邻 Now-Playing 指示器的图标打开)。顶部搜索栏搜索整个音乐库;"Now Playing"显示同一 Navidrome 服务器上其他用户正在听什么。', + s2: '播放与队列', + q4: '如何使用队列?', + a4: '从右上角标题栏打开队列面板。拖动行重新排序,将其拖出以移除,或使用工具栏来打乱、将队列保存为播放列表或跳转到某曲目。可将行从面板拖出到其他位置作为转移。', + q5: 'Gapless 与 Crossfade — 区别?', + a5: 'Gapless 预缓冲下一首曲目,使歌曲之间没有静音(适合现场专辑和 DJ 混音)。Crossfade 在 1–10 秒内将当前曲目淡出同时下一首淡入(适合混合播放)。两者互斥 — 启用其中一个会禁用另一个。在设置 → 音频中配置。', + q6: '什么是无限队列?', + a6: '当队列结束且重复关闭时,Psysonic 会静默地从您的音乐库中追加相似/随机曲目,使播放永不停止。自动添加的曲目显示在"— 自动添加 —"分隔符下。通过队列标题栏中的无限符号图标切换;在设置 → 队列中将自动添加限制为某个流派。', + q7: '多选和 Shift+点击范围?', + a7: '在专辑 / 新发行 / 随机专辑 / 播放列表上激活"选择"。点击一项以切换,然后按住 Shift 并点击另一项 — 可见顺序中两者之间的所有项都将被选中。Shift+点击从最近点击的锚点扩展。网格上方的工具栏提供批量操作(队列、下载、删除等)。', + q8: '键盘快捷键和全局热键?', + a8: '默认应用内键:空格 = 播放 / 暂停,Esc = 关闭全屏 / 模态框,F1 = 快捷键速查表。设置 → 输入允许重新分配每个应用内动作(包括 Ctrl+Shift+P 等组合键)并设置即使 Psysonic 在后台或最小化时也能工作的系统级全局快捷键。多媒体键(播放/暂停、下一首、上一首)在所有平台上都可用。', + s3: '音频工具', + q9: 'Replay Gain 模式?', + a9: '设置 → 音频 → Replay Gain。曲目模式将每首歌曲规范化到目标电平。专辑模式保留专辑内的响度曲线。自动模式根据队列是否来自单个专辑选择曲目或专辑。没有 Replay Gain 标签的曲目回退到可配置的前置放大。', + q10: '什么是 Smart Loudness Normalization (LUFS)?', + a10: '设置 → 音频中 Replay Gain 的现代替代品。Psysonic 将每个曲目分析到 LUFS / EBU R128 并存储结果,以便整个音乐库的音量保持一致 — 包括没有 Replay Gain 标签的曲目。冷缓存分析在后台运行,CPU 使用约 35–40 % 持续约 1 分钟,然后降至 0。一次性设置目标响度(默认 −10 LUFS)。', + q11: 'EQ 和 AutoEQ?', + a11: '设置 → 音频 → 均衡器中有一个 10 频段参数 EQ,带有手动频段和预设。旁边的 AutoEQ 从 AutoEQ 数据库为您的耳机型号拉取测量的校正配置文件并自动应用到频段 — 选择您的耳机,EQ 即对正确曲线。', + q12: '如何切换音频输出设备?', + a12: '设置 → 音频 → 输出设备。Psysonic 列出所有可用输出,选中后立即切换。刷新按钮重新扫描启动后接入的设备。Linux ALSA 名称如"sysdefault"会自动清理以提高可读性。', + q13: '什么是 Hot Cache?', + a13: 'Hot Cache 将当前曲目和接下来的几首预加载到 RAM 和磁盘,使播放无缓冲延迟启动 — 在慢速 / 远程服务器上尤其有用。当达到大小限制时触发驱逐。在设置 → 音频中配置大小和防抖延迟(防止快速跳过时过度获取)。', + s4: '音乐库与发现', + q14: '评分和 Skip-to-1★ 如何工作?', + a14: 'Psysonic 通过 OpenSubsonic(Navidrome ≥ 0.53)支持 1–5 星评分。在曲目列表、右键菜单或播放栏中的艺术家名下方为曲目评分;在专辑页面为专辑评分;在艺术家页面为艺术家评分。Skip-to-1★(设置 → 音乐库 → 评分)在配置数量的连续跳过后自动分配 1 星。同一面板允许为生成的混音设置最低评分作为筛选条件。', + q15: '如何浏览 — 文件夹、流派、曲目?', + a15: '文件夹浏览器(侧边栏)以 Miller-column 布局浏览服务器的音乐目录树 — 点击文件夹进入,点击曲目或文件夹的播放图标以播放/添加。流派使用按曲目数量缩放的标签云视图;点击流派以打开。曲目是一个扁平的音乐库中心,带有可按列排序的虚拟列表和实时搜索。', + q16: '搜索和高级搜索?', + a16: '标题栏搜索栏在您输入时跨艺术家、专辑和曲目运行快速实时搜索。打开高级搜索(侧边栏)以获得更丰富的视图:按年份、流派、评分、格式、声道、采样率、BPM、心情过滤,并组合条件。右键单击任何结果会打开与其他地方相同的上下文菜单。', + q17: '什么是混音(Random / Genre / Super Genre / Lucky)?', + a17: 'Random Mix 从您的音乐库构建随机曲目播放列表;关键字过滤器通过流派/标题/专辑子字符串排除有声读物、喜剧等。Super Genre Mix 将您的音乐库按广泛风格分组(摇滚、金属、电子、爵士、古典…)并构建专注的混音。Lucky Mix 使用您的收听历史、评分和 AudioMuse-AI 相似曲目,一键组装即时播放列表。', + q18: '统计页面?', + a18: '统计(侧边栏)显示热门艺术家、热门专辑、热门曲目、流派分布、随时间变化的收听时间,以及在配置多个音乐文件夹时的每库范围。多个视图可作为可分享的卡片图像导出。', + q19: '如何将专辑下载为 ZIP?', + a19: '专辑页面 → "下载(ZIP)"。服务器先压缩专辑 — 对于大型或无损专辑(FLAC / WAV),进度条仅在压缩完成且传输开始后才会出现。这是正常现象。', + s5: '歌词', + q20: '歌词来自哪里?', + a20: '设置 → 歌词中可配置三个来源:您的 Navidrome 服务器(嵌入式 / OpenSubsonic 歌词)、LRCLIB(社区贡献的同步歌词)和网易云音乐(庞大的亚洲 + 国际目录)。每个来源可启用/禁用并通过拖动重新排序。', + q21: '播放期间如何查看歌词?', + a21: '点击播放栏中的麦克风图标以打开队列面板内的歌词标签。同步歌词自动滚动并支持点击-跳转;纯文本歌词以静态块滚动。通过播放栏封面切换全屏播放器以获得带 mesh-blob 背景的沉浸式歌词视图。', + s6: '分享与社交', + q22: '什么是 Magic Strings?', + a22: 'Magic Strings 是无需任何第三方服务器即可在 Psysonic 用户之间共享内容的简短复制粘贴令牌。Server-Invite 字符串让朋友通过一次粘贴加入您的 Navidrome;专辑 / 艺术家 / 队列 Magic Strings 在接收方打开相同的专辑 / 艺术家 / 队列。从分享菜单生成,粘贴到搜索栏以使用。', + q23: '什么是 Orbit?', + a23: 'Orbit 是同步的一起听:主持人播放一首曲目,每个客人同步听到,客人可以建议曲目,主持人可以接受到队列中。从标题栏中的 Orbit 按钮启动会话,分享邀请链接,其他人可以从任何 Psysonic 安装加入。主持人拥有播放(跳过、搜索、队列) — 客人获得实时视图和建议框。会话是临时的,主持人关闭即结束。', + q24: '什么是 Now Playing 下拉?', + a24: '右上角标题栏的广播图标显示 Navidrome 服务器上其他用户当前正在听什么,每 10 秒刷新。您自己的条目在暂停时立即消失。按服务器划分,因此不会显示其他活动服务器上的用户。', + s7: '个性化', + q25: '主题和主题调度器?', + a25: '设置 → 外观 → 主题从 8 个组中的 60+ 个主题中选择(Psysonic、Mediaplayer、操作系统、游戏、电影、电视剧、社交媒体、Open Source Classics — Catppuccin / Nord / Gruvbox / Nightfox / Dracula)。Auto-Switch Theme 让您设置带启动时间的日间主题 + 夜间主题,使 Psysonic 自动切换。', + q26: '可以自定义侧边栏、首页和艺术家页面吗?', + a26: '可以 — 设置 → 个性化。侧边栏定制器让您拖动 nav 项目到所需顺序并隐藏您不使用的。首页定制器切换每个 Mainstage 行(Hero、Recent、Discover、Recently Played、Starred…)。艺术家页面定制器重新排序章节(Top Songs、专辑、单曲、合辑、相似艺术家等)并隐藏您从不查看的章节。', + q27: '什么是 Mini Player?', + a27: '一个带有封面、传输控件和紧凑队列的小浮动窗口。从播放栏中的 mini-player 图标或其键盘快捷键打开。窗口在会话之间记住其位置和大小。在 Windows 上,mini-webview 在启动时预先创建,因此打开是即时的;Linux / macOS 通过设置 → 外观 → 预加载 mini player 选择加入。', + q28: '什么是 Floating Player Bar?', + a28: '一个可选的播放栏样式(设置 → 外观),它从底部边缘脱离,带有主题背景、强调边框、圆角专辑封面和居中音量部分。在高显示器或紧凑主题上很有用。', + q29: '悬停时的曲目预览?', + a29: '将鼠标悬停在曲目行上,点击封面上的小预览按钮,或从右键菜单触发预览 — Psysonic 通过相同的 Rust 音频引擎流式传输前 ~15 秒,因此响度规范化适用。对于您还没听过的专辑很有用。', + q30: '睡眠定时器?', + a30: '点击播放栏中的月亮图标以打开睡眠定时器。选择持续时间(或"当前曲目结束"),Psysonic 会在结束时淡出并暂停。计时器运行时按钮显示圆形环和按钮内倒计时。', + q31: 'UI 缩放、字体、seekbar 样式?', + a31: '设置 → 外观 — 界面缩放(80–125%,不影响系统字体大小)、字体(10 种 UI 字体,包括 IBM Plex Mono、Fira Code、Geist、Golos Text…)、Seekbar 样式(波形分析 / pseudowave 确定性 / 线条与点 / 条形 / 厚条 / 分段 / 霓虹辉光 / 脉冲波 / 粒子轨迹 / 液体填充 / 复古磁带)。', + s8: '高级用户', + q32: 'CLI 播放器控制?', + a32: 'Psysonic 二进制文件兼作运行中应用的远程控制。示例:psysonic --player play / pause / next / prev、--player volume 75、--player seek 15、--player shuffle、--player repeat off|all|one、--player rating 1-5。切换服务器、音频设备、音乐库;触发 Instant Mix;搜索艺术家 / 专辑 / 曲目。完整列表请运行 psysonic --player --help。bash 和 zsh 的 shell 自动补全可通过 psysonic completions 获得。', + q33: '智能播放列表(Navidrome)?', + a33: '智能播放列表是由规则定义的 Navidrome 端动态播放列表(流派 = 摇滚 AND 年份 > 2020 等)。Psysonic 中的播放列表页面允许使用可视化规则编辑器创建、编辑和删除它们 — Psysonic 通过 Navidrome 原生 API 进行操作。它们在应用其余部分中表现为普通播放列表,并在音乐库更改时自动更新。', + q34: '备份和恢复设置?', + a34: '设置 → 存储 → 备份与恢复将服务器配置文件、主题、键绑定和其他设置导出到单个 JSON 文件。在另一台机器或重新安装后导入文件以一次恢复所有内容。服务器密码包含在内 — 请将文件保存在私密位置。', + q35: '在哪里查看所有开源许可证?', + a35: '设置 → 系统 → Open Source Licenses。完整的依赖列表(cargo crates 和 npm 包)随构建附带捆绑的许可证文本。点击条目查看完整文本;顶部的精选高亮块突出显示用户可识别的库(Tauri、React、rodio、symphonia 等)。', + s9: '离线与同步', + q36: '离线模式 — 缓存专辑和播放列表?', + a36: '打开任何专辑或播放列表,点击标题中的下载图标 — Psysonic 在本地缓存每个曲目,使其无需网络调用即可从磁盘播放。离线音乐库页面(侧边栏)列出所有缓存内容,显示进行中的进度,并允许通过垃圾桶图标移除条目(在下载完成后出现)。', + q37: '离线存储限制?', + a37: '设置 → 音乐库 → 离线让您设置最大缓存大小。当达到限制时,专辑页面下载按钮显示警告横幅。通过从离线音乐库页面移除专辑或播放列表来释放空间。', + q38: 'Device Sync — 将音乐复制到 USB / SD?', + a38: 'Device Sync(侧边栏)将专辑、播放列表或整个艺术家复制到外部驱动器,以便在其他设备上离线收听。选择目标文件夹,从浏览器选项卡中选择源,点击"传输到设备"。Psysonic 写入清单(psysonic-sync.json),即使您在不同 OS 上以不同的文件名模板重新打开 Device Sync,也能知道哪些文件已经在那里。模板支持 {artist} / {album} / {title} / {track_number} / {disc_number} / {year} 令牌,使用 / 作为文件夹分隔符。', + s10: '集成与故障排除', + q39: 'Last.fm 抓取?', + a39: '设置 → 集成 → Last.fm。一次连接您的账户,Psysonic 直接抓取到 Last.fm — 无需 Navidrome 配置。在听完曲目 50 % 后发送抓取。Now-playing pings 在开始时发送。', + q40: 'Discord Rich Presence?', + a40: '设置 → 集成 → Discord 在您的 Discord 个人资料上显示当前曲目。在应用图标、您服务器的封面(通过 getAlbumInfo2 — 需要可公开访问的服务器)或 Apple Music 封面之间选择。使用令牌模板自定义显示字符串(详细信息、状态、提示)。', + q41: 'Bandsintown 巡演日期?', + a41: '在设置 → 集成 → Now-Playing Info 中选择启用。然后 Now Playing 页面上的 Now Playing 选项卡通过 Bandsintown widget API 显示正在播放艺术家的即将到来的巡演日期。默认关闭 — 在您启用之前不发出任何请求。', + q42: 'Internet Radio — 播放实时流?', + a42: 'Internet Radio(侧边栏)播放存储在您 Navidrome 服务器上的任何实时流(通过 Navidrome 管理 UI 添加电台)。播放通过浏览器 HTML5 音频引擎运行 — 大多数 EQ / Replay Gain / Loudness 设置不适用于电台,但 ICY 元数据(当前歌曲名)会显示。支持 MP3、AAC、OGG Vorbis 和大多数 HLS 流;编解码器支持取决于平台。', + q43: '连接测试失败 — 怎么办?', + a43: '仔细检查 URL 包括端口(例如 http://192.168.1.100:4533)。在本地网络上 http:// 通常在 https:// 不工作的地方工作(无证书)。确保没有防火墙阻塞端口,并且用户名和密码正确。如果您的服务器位于反向代理之后,请先尝试直接 URL 以隔离原因。', + q44: '封面和艺术家图像加载缓慢。', + a44: '图像在首次查看时从服务器获取,然后本地缓存 30 天。如果您服务器的存储速度慢,第一次访问页面可能需要片刻;后续访问是即时的。Hot Cache 也对曲目有帮助,但图像缓存是独立的。', + q45: 'Linux 问题 — 黑屏或无声音?', + a45: '黑屏通常是 WebKitGTK 中的 GPU / EGL 驱动程序问题 — 使用 GDK_BACKEND=x11 WEBKIT_DISABLE_COMPOSITING_MODE=1 WEBKIT_DISABLE_DMABUF_RENDERER=1 启动(AUR / .deb / .rpm 安装程序自动设置这些)。对于音频,确保 PipeWire 或 PulseAudio 正在运行。睡眠/唤醒后的音频丢失现在由 post-sleep 恢复钩子自动处理。', +}; diff --git a/src/locales/zh/hero.ts b/src/locales/zh/hero.ts new file mode 100644 index 00000000..5f62f588 --- /dev/null +++ b/src/locales/zh/hero.ts @@ -0,0 +1,6 @@ +export const hero = { + eyebrow: '精选专辑', + playAlbum: '播放专辑', + enqueue: '加入队列', + enqueueTooltip: '将整张专辑添加到播放队列', +}; diff --git a/src/locales/zh/home.ts b/src/locales/zh/home.ts new file mode 100644 index 00000000..8a8158c2 --- /dev/null +++ b/src/locales/zh/home.ts @@ -0,0 +1,19 @@ +export const home = { + hero: '精选', + starred: '个人收藏', + recent: '最近添加', + mostPlayed: '最常播放', + recentlyPlayed: '最近播放', + losslessAlbums: '无损专辑', + discover: '发现', + discoverSongs: '发现曲目', + loadMore: '加载更多', + discoverMore: '发现更多', + discoverArtists: '发现艺术家', + discoverArtistsMore: '全部艺术家', + becauseYouLike: '因为你听过…', + becauseYouLikeFor: '因为你听过 {{artist}}', + similarTo: '类似 {{artist}}', + becauseYouLikeTracks_one: '{{count}} 首', + becauseYouLikeTracks_other: '{{count}} 首' +}; diff --git a/src/locales/zh/index.ts b/src/locales/zh/index.ts new file mode 100644 index 00000000..48115911 --- /dev/null +++ b/src/locales/zh/index.ts @@ -0,0 +1,91 @@ +import { sidebar } from './sidebar'; +import { home } from './home'; +import { hero } from './hero'; +import { search } from './search'; +import { nowPlaying } from './nowPlaying'; +import { contextMenu } from './contextMenu'; +import { sharePaste } from './sharePaste'; +import { albumDetail } from './albumDetail'; +import { entityRating } from './entityRating'; +import { artistDetail } from './artistDetail'; +import { favorites } from './favorites'; +import { randomLanding } from './randomLanding'; +import { randomAlbums } from './randomAlbums'; +import { genres } from './genres'; +import { randomMix } from './randomMix'; +import { luckyMix } from './luckyMix'; +import { albums } from './albums'; +import { tracks } from './tracks'; +import { artists } from './artists'; +import { composers } from './composers'; +import { composerDetail } from './composerDetail'; +import { login } from './login'; +import { connection } from './connection'; +import { common } from './common'; +import { settings } from './settings'; +import { changelog } from './changelog'; +import { whatsNew } from './whatsNew'; +import { help } from './help'; +import { queue } from './queue'; +import { miniPlayer } from './miniPlayer'; +import { statistics } from './statistics'; +import { player } from './player'; +import { nowPlayingInfo } from './nowPlayingInfo'; +import { songInfo } from './songInfo'; +import { playlists } from './playlists'; +import { smartPlaylists } from './smartPlaylists'; +import { mostPlayed } from './mostPlayed'; +import { losslessAlbums } from './losslessAlbums'; +import { radio } from './radio'; +import { folderBrowser } from './folderBrowser'; +import { deviceSync } from './deviceSync'; +import { orbit } from './orbit'; +import { tray } from './tray'; +import { licenses } from './licenses'; + +export const zhTranslation = { + sidebar, + home, + hero, + search, + nowPlaying, + contextMenu, + sharePaste, + albumDetail, + entityRating, + artistDetail, + favorites, + randomLanding, + randomAlbums, + genres, + randomMix, + luckyMix, + albums, + tracks, + artists, + composers, + composerDetail, + login, + connection, + common, + settings, + changelog, + whatsNew, + help, + queue, + miniPlayer, + statistics, + player, + nowPlayingInfo, + songInfo, + playlists, + smartPlaylists, + mostPlayed, + losslessAlbums, + radio, + folderBrowser, + deviceSync, + orbit, + tray, + licenses, +}; diff --git a/src/locales/zh/licenses.ts b/src/locales/zh/licenses.ts new file mode 100644 index 00000000..0bcfb8ad --- /dev/null +++ b/src/locales/zh/licenses.ts @@ -0,0 +1,13 @@ +export const licenses = { + title: '开源许可证', + intro: 'Psysonic 基于开源软件构建。下方列表显示了应用程序中包含的每个依赖项的版本、许可证以及完整的许可证文本。', + highlights: '主要依赖项', + searchPlaceholder: '按名称、版本或许可证搜索…', + noResults: '没有匹配项。', + loading: '加载许可证…', + loadError: '无法加载许可证数据。', + noLicenseText: '此依赖项未包含许可证文本。', + viewSource: '查看源代码', + totalLine: '{{total}} 个依赖项 — {{cargo}} cargo, {{npm}} npm', + generatedAt: '最后生成时间 {{date}}', +}; diff --git a/src/locales/zh/login.ts b/src/locales/zh/login.ts new file mode 100644 index 00000000..57f5459a --- /dev/null +++ b/src/locales/zh/login.ts @@ -0,0 +1,22 @@ +export const login = { + subtitle: '您的 Navidrome 桌面播放器', + serverName: '服务器名称(可选)', + serverNamePlaceholder: '我的 Navidrome', + serverUrl: '服务器地址', + serverUrlPlaceholder: '192.168.1.100:4533 或 https://music.example.com', + username: '用户名', + usernamePlaceholder: 'admin', + password: '密码', + showPassword: '显示密码', + hidePassword: '隐藏密码', + connect: '连接', + connecting: '正在连接…', + connected: '已连接!', + error: '连接失败 — 请检查您的信息。', + urlRequired: '请输入服务器地址。', + savedServers: '已保存的服务器', + addNew: '或添加新服务器', + orMagicString: '或使用魔法字符串', + magicStringPlaceholder: '粘贴分享字符串(psysonic1-…)', + magicStringInvalid: '魔法字符串无效或无法解析。', +}; diff --git a/src/locales/zh/losslessAlbums.ts b/src/locales/zh/losslessAlbums.ts new file mode 100644 index 00000000..82590963 --- /dev/null +++ b/src/locales/zh/losslessAlbums.ts @@ -0,0 +1,5 @@ +export const losslessAlbums = { + empty: '此媒体库中还没有无损专辑。', + unsupported: '此服务器未公开查找无损专辑所需的元数据。', + slowFetchHint: '加载比其他专辑页面慢 — Psysonic 按音质遍历整个歌曲目录。', +}; diff --git a/src/locales/zh/luckyMix.ts b/src/locales/zh/luckyMix.ts new file mode 100644 index 00000000..b1cece00 --- /dev/null +++ b/src/locales/zh/luckyMix.ts @@ -0,0 +1,6 @@ +export const luckyMix = { + done: '好运混音已就绪:{{count}} 首', + failed: '生成好运混音失败,请重试。', + unavailable: '当前服务器不支持好运混音。', + cancelTooltip: '取消生成好运混音', +}; diff --git a/src/locales/zh/miniPlayer.ts b/src/locales/zh/miniPlayer.ts new file mode 100644 index 00000000..44124812 --- /dev/null +++ b/src/locales/zh/miniPlayer.ts @@ -0,0 +1,9 @@ +export const miniPlayer = { + showQueue: '显示队列', + hideQueue: '隐藏队列', + pinOnTop: '置顶', + pinOff: '取消置顶', + openMainWindow: '打开主窗口', + close: '关闭', + emptyQueue: '队列为空', +}; diff --git a/src/locales/zh/mostPlayed.ts b/src/locales/zh/mostPlayed.ts new file mode 100644 index 00000000..9dde0c8c --- /dev/null +++ b/src/locales/zh/mostPlayed.ts @@ -0,0 +1,13 @@ +export const mostPlayed = { + title: '最常播放', + topArtists: '热门艺术家', + topAlbums: '热门专辑', + plays: '播放 {{n}} 次', + sortMost: '最多播放在前', + sortLeast: '最少播放在前', + loadMore: '加载更多专辑', + noData: '暂无播放数据。开始收听吧!', + noArtists: '所有艺术家已过滤。', + filterCompilations: '隐藏合辑艺术家(Various Artists、原声带等)', + filterCompilationsShort: '隐藏合辑', +}; diff --git a/src/locales/zh/nowPlaying.ts b/src/locales/zh/nowPlaying.ts new file mode 100644 index 00000000..4f4bee44 --- /dev/null +++ b/src/locales/zh/nowPlaying.ts @@ -0,0 +1,47 @@ +export const nowPlaying = { + tooltip: '谁正在收听?', + title: '谁正在收听?', + loading: '加载中…', + nobody: '当前无人收听。', + minutesAgo: '{{n}} 分钟前', + nothingPlaying: '尚未开始播放。开始播放一首歌曲吧!', + aboutArtist: '关于艺术家', + fromAlbum: '来自此专辑', + viewAlbum: '查看专辑', + goToArtist: '前往艺术家', + readMore: '阅读更多', + showLess: '收起', + genreInfo: '流派', + trackInfo: '曲目信息', + topSongs: '该艺术家最常播放', + topSongsCredit: '{{name}} 的热门曲目', + trackPosition: '第 {{pos}} 首', + playsCount_one: '播放 {{count}} 次', + playsCount_other: '播放 {{count}} 次', + releasedYearsAgo_one: '{{count}} 年前', + releasedYearsAgo_other: '{{count}} 年前', + discography: '专辑列表', + lastfmStats: 'Last.fm 统计', + thisTrack: '这首歌', + thisArtist: '这位艺术家', + listeners: '听众', + scrobbles: '播放记录', + yourScrobbles: '你', + listenersN: '{{n}} 位听众', + scrobblesN: '{{n}} 次播放', + playsByYouN: '你播放了 {{n}} 次', + openTrackOnLastfm: '在 Last.fm 上查看', + openArtistOnLastfm: '在 Last.fm 上查看艺术家', + rgTrackTooltip: 'ReplayGain (曲目)', + rgAlbumTooltip: 'ReplayGain (专辑)', + rgAutoTooltip: 'ReplayGain (自动)', + showMoreTracks: '显示另外 {{count}} 首', + showLessTracks: '收起', + hideCard: '隐藏卡片', + layoutMenu: '布局', + visibleCards: '可见卡片', + hiddenCards: '已隐藏的卡片', + noHiddenCards: '没有已隐藏的卡片', + resetLayout: '重置布局', + emptyColumn: '将卡片拖到此处', +}; diff --git a/src/locales/zh/nowPlayingInfo.ts b/src/locales/zh/nowPlayingInfo.ts new file mode 100644 index 00000000..5240935d --- /dev/null +++ b/src/locales/zh/nowPlayingInfo.ts @@ -0,0 +1,24 @@ +export const nowPlayingInfo = { + tab: '信息', + empty: '播放歌曲以查看信息', + artist: '艺术家', + songInfo: '歌曲信息', + onTour: '巡演', + noTourEvents: '没有即将到来的演出', + tourLoading: '加载中…', + poweredByBandsintown: '巡演数据来自 Bandsintown', + bioReadMore: '展开', + bioReadLess: '收起', + showMoreTours_one: '显示更多 {{count}} 个', + showMoreTours_other: '显示更多 {{count}} 个', + showLessTours: '收起', + enableBandsintownPrompt: '查看即将到来的巡演日期?', + enableBandsintownPromptDesc: '可选。通过公开的 Bandsintown API 加载当前艺术家的演出。', + enableBandsintownPrivacy: '启用后,当前播放的艺术家名称将发送到 Bandsintown API 以获取巡演日期。不会发送任何账户或个人数据。', + enableBandsintownAction: '启用', + role: { + artist: '艺术家', + albumArtist: '专辑艺术家', + composer: '作曲', + }, +}; diff --git a/src/locales/zh/orbit.ts b/src/locales/zh/orbit.ts new file mode 100644 index 00000000..faa818c7 --- /dev/null +++ b/src/locales/zh/orbit.ts @@ -0,0 +1,200 @@ +export const orbit = { + triggerLabel: 'Orbit', + triggerTooltip: '开始或加入共享收听会话', + launchCreate: '创建会话', + launchJoin: '加入会话', + launchHelp: '这是怎么工作的?', + launchHelpSoon: '即将推出', + joinModalTitle: '加入 Orbit 会话', + joinModalSub: '粘贴主持人发给你的邀请链接。', + joinModalLinkLabel: '邀请链接', + joinModalLinkPlaceholder: 'psysonic2-…', + joinModalLinkHelper: '适用于任何有效的 Orbit 链接。必须指向你当前登录的服务器。', + joinModalPasteTooltip: '从剪贴板粘贴', + joinModalSubmit: '加入', + joinModalBusy: '加入中…', + joinErrEmpty: '请粘贴一个邀请链接。', + joinErrInvalid: '这看起来不像 Orbit 邀请链接。', + closeAria: '关闭', + heroTitlePrefix: '一起听音乐 —', + heroTitleBrand: 'Orbit', + heroSub: '开始会话 — {{server}} 上的其他用户将一起收听并可以推荐曲目。', + fallbackServer: '此服务器', + tipLan: '你当前通过本地网络地址连接。网络外的访客无法加入 — 请在启动前切换到公共服务器地址。', + tipRemote: '为了让家庭网络外的访客能够加入,你的服务器地址必须公开可达。如果你的服务器仅限内部使用,请在启动前切换。', + labelName: '会话名称', + namePlaceholder: 'Velvet Orbit', + reshuffleTooltip: '新建议', + reshuffleAria: '建议新名称', + helperName: '会话对访客的显示方式 — 保留或输入自己的名称。', + labelMax: '最大访客数', + helperMax: '你不计算在内 — 这仅限制加入的访客。', + labelLink: '邀请链接', + tooltipCopied: '已复制', + tooltipCopy: '复制', + ariaCopyLink: '复制邀请链接', + helperLink: '将此链接发送给你的访客。他们可以在 Psysonic 的任何位置使用 Ctrl+V 粘贴。', + labelClearQueue: '先清空我的队列', + helperClearQueue: '以空队列启动会话。关闭:你已排队的曲目保留并与访客共享。', + btnCancel: '取消', + btnStarting: '启动中…', + btnStart: '启动 Orbit', + btnCopyAndStart: '复制链接并启动', + errNameRequired: '请为你的会话命名。', + errStartFailed: '无法启动。', + hostLabel: '主持人:{{name}}', + participantsTooltip: '参与者', + settingsTooltip: '会话设置', + shareTooltip: '分享邀请链接', + shuffleLabel: '下次洗牌', + catchUpLabel: '跟上', + catchUpTooltip: '跳到主持人当前位置', + hostAway: '主持人离线', + hostOnline: '主持人在线', + endTooltip: '结束会话', + leaveTooltip: '离开会话', + helpTooltip: 'Orbit 的工作原理', + diag: { + openTooltip: '诊断 — 可复制的事件日志', + title: 'Orbit 诊断', + role: '角色', + hostTrack: '主持人曲目 ID', + hostPos: '主持人位置', + guestTrack: '我的曲目 ID', + guestPos: '我的位置', + drift: '偏差', + stateAge: '状态时长', + eventLog: '事件日志 ({{count}})', + copyLabel: '复制', + copyTooltip: '将日志复制到剪贴板', + clearLabel: '清除', + clearTooltip: '清空缓冲区', + empty: '暂无事件 — Orbit 同步时会显示。', + hint: '在重现问题前打开此面板,然后点击复制并粘贴到错误报告中。', + copied: '已复制 {{count}} 行', + copyFailed: '无法复制到剪贴板', + cleared: '缓冲区已清空', + }, + helpTitle: 'Orbit 的工作原理', + helpIntro: 'Orbit 将 Psysonic 变成一个共享的收听空间。主持人选择音乐;访客同步收听并可以推荐曲目。', + helpHostOnly: '(主持人)', + helpSec1Title: '什么是 Orbit?', + helpSec1Body: '"一起听"模式 — 主持人驱动播放,访客加入收听。一切都通过你自己的 Navidrome 服务器上的播放列表进行;没有外部基础设施。', + helpSec2Title: '主持人和访客', + helpSec2Body: '主持人控制播放(播放 / 暂停 / 跳过 / 跳转),并决定会话何时结束。访客跟随主持人的播放,可以推荐曲目,随时离开或重新加入。只有主持人可以踢出或永久封禁参与者。', + helpSec2WarnHead: '重要:使用独立账户。', + helpSec2WarnBody: '每个参与者都需要自己的 Navidrome 账户。如果主持人和访客使用同一用户登录,他们的提交会冲突,主持人将永远看不到访客的建议。', + helpSec3Title: '启动和邀请', + helpSec3Body: '点击"Orbit"按钮 → 创建会话 → 启动弹窗显示可复制的邀请链接,并可选清空你当前的队列。以任何方式分享该链接。会话运行时,顶部会话栏中的分享按钮可随时再次复制链接。', + helpSec4Title: '加入', + helpSec4Body: '使用 Ctrl+V / Cmd+V 在 Psysonic 的任何位置粘贴邀请链接 — 加入提示会自动弹出。或者:「Orbit」→ 加入会话 → 粘贴到字段中。如果链接指向你有账户的服务器,Psysonic 会为你切换。当你在该服务器上有多个账户时,小型选择器会询问使用哪个。', + helpSec5Title: '推荐曲目', + helpSec5Body: '在任何曲目列表中:双击一行,或右键 → "添加到 Orbit 会话"。单击会显示提示而不是将整张专辑扔进共享队列 — 这是有意的。明确的批量操作(如"全部播放"或"播放专辑")先要求确认然后追加(永不替换)。', + helpSec6Title: '共享队列', + helpSec6Body: '队列显示主持人即将播放的曲目 — 所有人可见。批量添加总是追加到末尾,因此访客的建议不会丢失。自动洗牌定期重新排序队列(可配置:1 / 5 / 10 / 15 / 30 分钟)。如果你的播放偏离主持人,会话栏中的"跟上"按钮会让你回到主持人的实时位置。', + helpSec7Title: '审批', + helpSec7Body: '默认情况下,访客建议需要手动审批 — 它们出现在队列面板顶部的"审批"栏中,带有接受 / 拒绝按钮。可以在会话设置中打开自动审批,使所有建议直接生效。', + helpSec8Title: '参与者和设置', + helpSec8Body: '打开会话栏中的设置图标以配置洗牌频率、自动审批和"立即洗牌"快捷方式。点击参与者数量查看谁已连接 — 踢出(可通过链接重新加入)或封禁(在该会话中被锁定)。访客也可以看到参与者列表,但仅为只读。', + helpSec9Title: '结束会话', + helpSec9Body: '主持人 X → 确认对话框 → 会话对所有人关闭,服务器播放列表会自动清理。访客 X → 访客离开,会话继续运行。如果主持人保持静默 5 分钟,访客会自动退出并收到通知;该窗口内的短时间重连不可见。', + participantsInviteLabel: '邀请链接', + participantsCountLabel: '{{count}} 人在会话中', + participantsHost: '主持人', + participantsEmpty: '还没有访客', + participantsKickTooltip: '从会话中移除', + participantsKickAria: '移除 {{user}}', + participantsRemoveTooltip: '从会话中移除', + participantsRemoveAria: '从此会话中移除 {{user}}', + participantsBanTooltip: '永久封禁', + participantsBanAria: '永久封禁 {{user}}', + participantsMuteTooltip: '禁止投歌', + participantsUnmuteTooltip: '允许投歌', + participantsMuteAria: '禁止 {{user}} 投歌', + participantsUnmuteAria: '允许 {{user}} 重新投歌', + confirmRemoveTitle: '从会话中移除?', + confirmRemoveBody: '{{user}} 将从会话中移除,但可以通过你的邀请链接重新加入。', + confirmRemoveConfirm: '移除', + confirmBanTitle: '永久封禁?', + confirmBanBody: '{{user}} 将被移除并被阻止重新加入此会话。在会话存在期间无法撤销。', + confirmBanConfirm: '封禁', + confirmCancel: '取消', + confirmJoinTitle: '加入 Orbit 会话?', + confirmJoinBody: '{{host}} 邀请你加入"{{name}}"。加入会话?', + confirmJoinConfirm: '加入', + confirmLeaveTitle: '离开会话?', + confirmLeaveBody: '离开"{{name}}"?你可以随时通过 {{host}} 的邀请链接重新加入。', + confirmLeaveConfirm: '离开', + confirmEndTitle: '为所有人结束会话?', + confirmEndBody: '"{{name}}"将对所有参与者关闭。会话的播放列表会自动清理。', + confirmEndConfirm: '结束会话', + invalidLinkTitle: '邀请链接已失效', + invalidLinkBody: '此 Orbit 会话不再存在或已结束。请主持人提供新的邀请链接。', + settingsTitle: '会话设置', + settingAutoApprove: '自动批准建议', + settingAutoApproveHint: '访客建议立即进入你的队列。关闭:它们保留在会话列表中供稍后审查。', + settingAutoShuffle: '自动洗牌', + settingAutoShuffleHint: '即将播放队列的定期 Fisher-Yates 洗牌。关闭:顺序仅在你手动重新排列时改变。', + settingShuffleInterval: '洗牌间隔', + settingShuffleIntervalHint: '会话运行时即将播放队列的重新洗牌频率。', + suggestBlockedMuted: '主持人已禁止你在本场会话投歌。', + settingShuffleIntervalValue_one: '{{count}} 分钟', + settingShuffleIntervalValue_other: '{{count}} 分钟', + settingShuffleNow: '立即洗牌', + toastSuggested: '{{user}} 推荐了"{{title}}"', + toastSuggestedMany: '队列中有 {{count}} 个新建议', + toastShuffled: '队列已洗牌', + toastJoined: '已加入会话', + toastLoginFirst: '加入会话前请先登录', + toastSwitchServer: '请先切换到 {{url}},然后再次粘贴', + toastNoAccountForServer: '你没有 {{url}} 的访问权限。请主持人发送邀请。', + toastSwitchFailed: '无法切换到 {{url}}', + accountPickerTitle: '使用哪个账户?', + accountPickerSub: '你在 {{url}} 上有多个账户。选择用于加入会话的账户。', + toastJoinFail: '无法加入会话', + joinErrNotFound: '未找到会话', + joinErrEnded: '会话已结束', + joinErrFull: '会话已满', + joinErrKicked: '你无法重新加入此会话', + joinErrNoUser: '没有活动服务器', + joinErrServerError: '无法加入', + ctxAddToSession: '添加到 Orbit 会话', + ctxSuggestedToast: '已推荐到会话', + ctxSuggestFailed: '无法推荐 — 未加入', + ctxAddToSessionHost: '添加到 Orbit 会话', + ctxAddedHostToast: '已添加到会话', + ctxAddHostFailed: '无法添加到会话', + bulkConfirmTitle: '全部添加到 Orbit 队列?', + bulkConfirmBody: '这将一次性把 {{count}} 首曲目放入共享队列。对你的访客来说信息量很大。继续?', + bulkConfirmYes: '全部添加', + bulkConfirmNo: '取消', + guestLive: '直播', + guestPlaying: '正在播放', + guestPaused: '已暂停', + guestLoading: '加载中…', + guestSuggestions: '建议', + guestUpNext: '接下来', + guestUpNextEmpty: '队列为空。打开曲目的上下文菜单并选择"添加到 Orbit 会话"来推荐一首。', + guestPendingTitle: '等待主持人', + guestPendingHint: '已推荐 — 主持人接受后会出现在队列中。', + approvalTitle: '待批准', + approvalFrom: '由 {{user}} 推荐', + approvalAccept: '接受', + approvalDecline: '拒绝', + guestUpNextMore: '+ 主持人队列中还有 {{count}} 首', + guestSubmitter: '来自 {{user}}', + queueAddedByHost: '由主持人添加', + queueAddedByYou: '由你添加', + queueAddedByUser: '由 {{user}} 添加', + guestEmpty: '还没有建议。打开曲目的上下文菜单并选择"添加到 Orbit 会话"。', + guestFooter: '主持人控制播放 — 你无法更改列表。', + exitKickedTitle: '你已被会话封禁', + exitRemovedTitle: '你已从会话中移除', + exitEndedTitle: '主持人已结束会话', + exitHostTimeoutTitle: '主持人无响应', + exitHostTimeoutBody: '{{host}} 有一段时间没有发送更新了,所以"{{name}}"在你这边已关闭。你可以随时通过邀请链接重新加入。', + exitKickedBody: '{{host}} 已将你从"{{name}}"封禁。你无法重新加入。', + exitRemovedBody: '{{host}} 已将你从"{{name}}"移除。你可以随时通过邀请链接重新加入。', + exitEndedBody: '"{{name}}"已结束。希望你玩得开心。', + exitOk: '好的', +}; diff --git a/src/locales/zh/player.ts b/src/locales/zh/player.ts new file mode 100644 index 00000000..6f7f84f4 --- /dev/null +++ b/src/locales/zh/player.ts @@ -0,0 +1,56 @@ +export const player = { + regionLabel: '音乐播放器', + openFullscreen: '打开全屏播放器', + fullscreen: '全屏播放器', + closeFullscreen: '关闭全屏', + closeTooltip: '关闭 (Esc)', + noTitle: '无标题', + stop: '停止', + prev: '上一首', + play: '播放', + pause: '暂停', + previewActive: '正在试听', + previewLabel: '试听', + delayModalTitle: '定时', + delayPauseSection: '多久后暂停', + delayStartSection: '多久后开始', + delayPreviewPause: '暂停于', + delayPreviewStart: '开始于', + delaySchedulePause: '安排暂停', + delayScheduleStart: '安排开始', + delayCancelPause: '取消暂停定时', + delayCancelStart: '取消开始定时', + delayInactivePause: '仅在正在播放时可用。', + delayInactiveStart: '仅在暂停且已加载曲目或电台时可用。', + delayCustomMinutes: '自定义延迟(分钟)', + delayCustomPlaceholder: '例如 2.5', + closeDelayModal: '关闭', + delayIn: '还有', + delayFmtSec: '{{n}} 秒', + delayFmtMin: '{{n}} 分钟', + delayFmtHr: '{{n}} 小时', + delayCancel: '取消', + delayApply: '应用', + next: '下一首', + repeat: '重复', + repeatOff: '关闭', + repeatAll: '全部', + repeatOne: '单曲', + progress: '播放进度', + volume: '音量', + toggleQueue: '切换队列', + collapseQueueResize: '收起队列,调整宽度', + moreOptions: '更多选项', + equalizer: '均衡器', + miniPlayer: '迷你播放器', + lyrics: '歌词', + fsLyricsToggle: '全屏歌词', + lyricsLoading: '正在加载歌词…', + lyricsNotFound: '未找到此曲目的歌词', + lyricsSourceServer: '来源:服务器', + lyricsSourceLrclib: '来源:LRCLIB', + lyricsSourceNetease: '来源:网易云', + lyricsSourceLyricsplus: '来源:YouLyPlus', + showDuration: '显示时长', + showRemainingTime: '显示剩余时间', +}; diff --git a/src/locales/zh/playlists.ts b/src/locales/zh/playlists.ts new file mode 100644 index 00000000..b17b1074 --- /dev/null +++ b/src/locales/zh/playlists.ts @@ -0,0 +1,99 @@ +export const playlists = { + title: '播放列表', + newPlaylist: '新建播放列表', + unnamed: '未命名播放列表', + createName: '播放列表名称…', + create: '创建', + cancel: '取消', + empty: '暂无播放列表。', + emptyPlaylist: '此播放列表为空。', + addFirstSong: '添加第一首歌曲', + notFound: '未找到播放列表。', + songs: '{{n}} 首歌曲', + playAll: '全部播放', + shuffle: '随机播放', + addToQueue: '添加到队列', + back: '返回播放列表', + deletePlaylist: '删除', + confirmDelete: '再次点击确认删除', + removeSong: '从播放列表中移除', + addSongs: '添加歌曲', + searchPlaceholder: '搜索音乐库…', + noResults: '无结果。', + suggestions: '推荐歌曲', + noSuggestions: '暂无推荐。', + titleBadge: '播放列表', + refreshSuggestions: '新建议', + addSong: '添加到播放列表', + preview: '试听 (30 秒)', + previewStop: '停止试听', + playNextSuggestion: '播放下一首', + suggestionsHint: '双击行可添加到播放列表', + addSelected: '添加所选', + cacheOffline: '离线缓存播放列表', + offlineCached: '播放列表已缓存', + removeOffline: '从离线缓存中移除', + offlineDownloading: '正在缓存… ({{done}}/{{total}} 张专辑)', + publicLabel: '公开', + privateLabel: '私有', + editMeta: '编辑播放列表', + editNamePlaceholder: '播放列表名称…', + editCommentPlaceholder: '添加描述…', + editPublic: '公开播放列表', + editSave: '保存', + editCancel: '取消', + changeCover: '更改封面图片', + changeCoverLabel: '更改照片', + removeCover: '删除照片', + coverUpdated: '封面已更新', + metaSaved: '播放列表已更新', + downloadZip: '下载 (ZIP)', + // Toast notifications for multi-select + addSuccess: '{{count}} 首歌曲已添加到 {{playlist}}', + addPartial: '{{added}} 首已添加,{{skipped}} 首跳过(重复)', + addAllSkipped: '全部跳过({{count}} 首重复)', + addedAsDuplicates: '{{count}} 首歌曲已添加到 {{playlist}}(作为重复项)', + duplicateConfirmTitle: '已在播放列表中', + duplicateConfirmMessage: '所有 {{count}} 首歌曲已在 "{{playlist}}" 中。仍要作为重复项添加吗?', + duplicateConfirmAction: '仍要添加', + addError: '添加歌曲时出错', + createAndAddSuccess: '播放列表 "{{playlist}}" 已创建,包含 {{count}} 首歌曲', + createError: '创建播放列表时出错', + deleteSuccess: '{{count}} 个播放列表已删除', + deleteFailed: '删除 {{name}} 时出错', + deleteSelected: '删除所选', + deleteSelectedPartial: '所选 {{total}} 个播放列表中只有 {{n}} 个可删除(其余属于他人)。', + mergeSuccess: '{{count}} 首歌曲已合并到 {{playlist}}', + mergeNoNewSongs: '没有新歌曲可添加', + mergeError: '合并播放列表时出错', + mergeInto: '合并到', + selectionCount: '{{count}} 已选择', + select: '选择', + startSelect: '启用选择', + cancelSelect: '取消', + loadingAlbums: '正在解析 {{count}} 张专辑…', + loadingArtists: '正在解析 {{count}} 位艺术家…', + myPlaylists: '我的播放列表', + noOtherPlaylists: '没有其他可用播放列表', + addToPlaylistSuccess: '{{count}} 首歌曲已添加到 {{playlist}}', + addToPlaylistNoNew: '{{playlist}} 没有新歌曲', + addToPlaylistError: '添加到播放列表时出错', + importCSV: '导入 CSV', + importCSVTooltip: '从 Spotify CSV 导入', + csvImportReport: 'CSV 导入报告', + csvImportTotal: '总计', + csvImportAdded: '已添加', + csvImportDuplicates: '重复项', + csvImportNotFound: '未找到', + csvImportNetworkErrors: '网络错误', + csvImportDuplicatesTitle: '重复曲目(已在播放列表中):', + csvImportNotFoundTitle: '未找到的曲目:', + csvImportNetworkErrorsTitle: '网络错误(可重试导入):', + csvImportDownloadReport: '下载报告', + csvImportClose: '关闭', + csvImportNoValidTracks: 'CSV 文件中未找到有效曲目', + csvImportFailed: 'CSV 文件导入失败', + csvImportToast: '{{added}} 已添加,{{notFound}} 未找到,{{duplicates}} 重复项', + csvImportDownloadSuccess: '报告下载成功', + csvImportDownloadError: '报告下载失败', +}; diff --git a/src/locales/zh/queue.ts b/src/locales/zh/queue.ts new file mode 100644 index 00000000..ad71d98b --- /dev/null +++ b/src/locales/zh/queue.ts @@ -0,0 +1,45 @@ +export const queue = { + title: '队列', + savePlaylist: '保存为播放列表', + updatePlaylist: '更新播放列表', + filterPlaylists: '筛选播放列表…', + playlistName: '播放列表名称', + cancel: '取消', + save: '保存', + loadPlaylist: '加载播放列表', + loading: '加载中…', + noPlaylists: '未找到播放列表。', + load: '替换队列并播放', + appendToQueue: '追加到队列', + delete: '删除', + deleteConfirm: '删除播放列表 "{{name}}"?', + clear: '清空', + shuffle: '随机打乱队列', + gapless: '无缝播放', + crossfade: '交叉淡入淡出', + infiniteQueue: '无限队列', + autoAdded: '— 自动添加 —', + radioAdded: '— 收音机 —', + hide: '隐藏', + hideNowPlaying: '隐藏播放信息', + showNowPlaying: '显示播放信息', + close: '关闭', + nextTracks: '即将播放', + shareQueue: '复制队列分享链接', + shareQueueEmpty: '队列为空,无法分享。', + emptyQueue: '队列为空。', + trackSingular: '首曲目', + trackPlural: '首曲目', + showRemaining: '显示剩余时间', + showTotal: '显示总时间', + showEta: '显示预计结束时间', + replayGain: 'ReplayGain', + rgTrack: '曲目 {{db}} dB', + rgAlbum: '专辑 {{db}} dB', + rgPeak: '峰值 {{pk}}', + sourceOffline: '正在从离线库播放', + sourceHot: '正在从缓存播放', + sourceStream: '正在从网络流播放', + clearCachedLoudnessWaveform: 'Clear cached loudness and waveform, then re-analyze this track', + recalculatingLoudnessWaveform: 'Recalculating loudness and waveform for this track…', +}; diff --git a/src/locales/zh/radio.ts b/src/locales/zh/radio.ts new file mode 100644 index 00000000..ba23805c --- /dev/null +++ b/src/locales/zh/radio.ts @@ -0,0 +1,35 @@ +export const radio = { + title: '网络电台', + empty: '未配置任何电台。', + addStation: '添加电台', + editStation: '编辑', + deleteStation: '删除电台', + confirmDelete: '再次点击确认', + stationName: '电台名称…', + streamUrl: '流地址…', + homepageUrl: '主页地址(可选)', + save: '保存', + cancel: '取消', + live: '直播', + liveStream: '网络电台', + openHomepage: '打开主页', + changeCoverLabel: '更换封面', + removeCover: '移除封面', + browseDirectory: '搜索目录', + directoryPlaceholder: '搜索电台…', + noResults: '未找到电台。', + stationAdded: '电台已添加', + filterAll: '全部', + filterFavorites: '收藏', + sortManual: '手动', + sortAZ: 'A → Z', + sortZA: 'Z → A', + sortNewest: '最新', + favorite: '添加到收藏', + unfavorite: '从收藏移除', + noFavorites: '没有收藏的电台。', + listenerCount_one: '{{count}} 位听众', + listenerCount_other: '{{count}} 位听众', + recentlyPlayed: '最近播放', + upNext: '即将播放', +}; diff --git a/src/locales/zh/randomAlbums.ts b/src/locales/zh/randomAlbums.ts new file mode 100644 index 00000000..a4a4e4a2 --- /dev/null +++ b/src/locales/zh/randomAlbums.ts @@ -0,0 +1,4 @@ +export const randomAlbums = { + title: '随机专辑', + refresh: '刷新', +}; diff --git a/src/locales/zh/randomLanding.ts b/src/locales/zh/randomLanding.ts new file mode 100644 index 00000000..24e3ec6f --- /dev/null +++ b/src/locales/zh/randomLanding.ts @@ -0,0 +1,9 @@ +export const randomLanding = { + title: '创建混音', + mixByTracks: '按曲目混音', + mixByTracksDesc: '从整个媒体库随机选取曲目', + mixByAlbums: '按专辑混音', + mixByAlbumsDesc: '随机选取专辑,探索新音乐', + mixByLucky: '好运混音', + mixByLuckyDesc: '基于高频艺人、专辑和高评分歌曲的智能 Instant Mix', +}; diff --git a/src/locales/zh/randomMix.ts b/src/locales/zh/randomMix.ts new file mode 100644 index 00000000..007df4fd --- /dev/null +++ b/src/locales/zh/randomMix.ts @@ -0,0 +1,39 @@ +export const randomMix = { + title: '随机混音', + remix: '重新混音', + remixTooltip: '加载新的随机歌曲', + remixGenre: '重混 {{genre}}', + remixTooltipGenre: '加载新的{{genre}}歌曲', + playAll: '全部播放', + trackTitle: '标题', + trackArtist: '艺术家', + trackAlbum: '专辑', + trackFavorite: '收藏', + trackDuration: '时长', + favoriteAdd: '添加到收藏', + favoriteRemove: '从收藏中移除', + play: '播放', + trackGenre: '流派', + mixSettingsHeader: '混音设置', + exclusionsHeader: '排除项', + filterPanelInexactSizeNote: '混音大小是一个目标 — 当服务器的随机池耗尽时,较大的请求可能会返回较少的唯一曲目。', + mixSize: '列表大小', + excludeAudiobooks: '排除有声读物和广播剧', + excludeAudiobooksDesc: '根据流派、标题、专辑和艺术家匹配关键词 — 例如 Hörbuch、Audiobook、Spoken Word 等', + genreBlocked: '关键词已屏蔽', + genreAddedToBlacklist: '已添加到过滤列表', + genreAlreadyBlocked: '已屏蔽', + artistBlocked: '艺术家已屏蔽', + artistAddedToBlacklist: '艺术家已添加到过滤列表', + artistClickHint: '点击屏蔽此艺术家', + blacklistToggle: '关键词过滤', + genreMixTitle: '流派混音', + genreMixDesc: '按歌曲数量排列的前 20 个流派 — 点击获取随机混音', + genreMixAll: '所有歌曲', + genreMixLoadMore: '加载 10 首更多', + genreMixNoGenres: '服务器上未找到流派。', + shuffleGenres: '显示其他流派', + filterPanelTitle: '过滤器', + filterPanelDesc: '点击下方列表中的流派标签或艺术家名称,将其从未来的混音中排除。', + genreClickHint: '点击流派标签将其添加为过滤关键词。\\n匹配流派、标题、专辑和艺术家。', +}; diff --git a/src/locales/zh/search.ts b/src/locales/zh/search.ts new file mode 100644 index 00000000..d813be9c --- /dev/null +++ b/src/locales/zh/search.ts @@ -0,0 +1,29 @@ +export const search = { + placeholder: '搜索艺术家、专辑或歌曲…', + noResults: '未找到 "{{query}}" 的相关结果', + artists: '艺术家', + albums: '专辑', + songs: '歌曲', + clearLabel: '清除搜索', + addedToQueueToast: '已将"{{title}}"加入队列', + title: '搜索', + resultsFor: '"{{query}}" 的搜索结果', + album: '专辑', + advanced: '高级搜索', + advancedSearchTerm: '搜索词', + advancedSearchPlaceholder: '标题、专辑、艺术家…', + advancedGenre: '流派', + advancedAllGenres: '所有流派', + advancedYear: '年份', + advancedYearFrom: '从', + advancedYearTo: '至', + advancedAll: '全部', + advancedSearch: '搜索', + advancedEmpty: '请输入搜索词或选择过滤器。', + advancedNoResults: '未找到结果。', + advancedGenreNote: '歌曲从该流派中随机选取。', + recentSearches: '最近搜索', + browse: '浏览', + emptyHint: '你想听什么?', + genres: '流派', +}; diff --git a/src/locales/zh/settings.ts b/src/locales/zh/settings.ts new file mode 100644 index 00000000..16c3d77d --- /dev/null +++ b/src/locales/zh/settings.ts @@ -0,0 +1,440 @@ +export const settings = { + title: '设置', + language: '语言', + languageEn: 'English', + languageDe: 'Deutsch', + languageEs: 'Español', + languageFr: 'Français', + languageNl: 'Nederlands', + languageNb: 'Norsk', + languageRu: 'Русский', + languageZh: '中文', + languageRo: 'Română', + font: '字体', + fontHintOpenDyslexic: '阅读障碍友好 · 不支持中文', + theme: '主题', + appearance: '外观', + servers: '服务器', + serverName: '服务器名称', + serverUrl: '服务器地址', + serverUrlPlaceholder: '192.168.1.100:4533 或 https://music.example.com', + serverUsername: '用户名', + serverPassword: '密码', + addServer: '添加服务器', + addServerTitle: '添加新服务器', + useServer: '使用', + deleteServer: '删除', + noServers: '未保存任何服务器。', + serverActive: '当前使用', + confirmDeleteServer: '删除服务器 "{{name}}"?', + serverConnecting: '正在连接…', + serverConnected: '已连接!', + serverFailed: '连接失败。', + testBtn: '测试连接', + testingBtn: '正在测试…', + serverCompatible: '专为 Navidrome 构建。其他兼容 Subsonic 的服务器(Gonic、Airsonic 等)可能功能受限,因为 Psysonic 使用了许多 Navidrome 特有的 API 端点。', + userMgmtTitle: '用户管理', + userMgmtDesc: '管理此服务器上的用户。需要管理员权限。', + userMgmtNoAdmin: '需要管理员权限才能管理此服务器上的用户。', + userMgmtLoadError: '加载用户失败。', + userMgmtLoadFriendly: '服务器未响应 — 通常是偶发问题。', + userMgmtRetry: '重试', + userMgmtEmpty: '未找到用户。', + userMgmtYouBadge: '您', + userMgmtAdminBadge: '管理员', + userMgmtAddUser: '添加用户', + userMgmtAddUserTitle: '新建用户', + userMgmtEditUserTitle: '编辑用户', + userMgmtUsername: '用户名', + userMgmtName: '显示名称', + userMgmtEmail: '电子邮箱', + userMgmtPassword: '密码', + userMgmtPasswordEditHint: '输入新密码以更新。', + userMgmtRoleAdmin: '管理员', + userMgmtLibraries: '音乐库', + userMgmtLibrariesAdminHint: '管理员用户自动拥有所有音乐库的访问权限。', + userMgmtLibrariesEmpty: '此服务器上没有可用的音乐库。', + userMgmtLibrariesValidation: '请至少选择一个音乐库。', + userMgmtLibrariesUpdateError: '用户已保存,但音乐库分配失败', + userMgmtNoLibraries: '未分配音乐库', + userMgmtNeverSeen: '从未', + userMgmtSave: '保存', + userMgmtCancel: '取消', + userMgmtDelete: '删除', + userMgmtEdit: '编辑', + userMgmtConfirmDelete: '删除用户 "{{username}}"?此操作无法撤销。', + userMgmtCreateError: '创建用户失败。', + userMgmtUpdateError: '更新用户失败。', + userMgmtDeleteError: '删除用户失败。', + userMgmtCreated: '用户已创建。', + userMgmtUpdated: '用户已更新。', + userMgmtDeleted: '用户已删除。', + userMgmtValidationMissing: '用户名、显示名称和密码均为必填项。', + userMgmtValidationMissingIdentity: '用户名和显示名称为必填项。', + userMgmtMagicStringGenerate: '生成魔法字符串', + userMgmtSaveAndMagicString: '保存并获取魔法字符串', + userMgmtMagicStringPasswordNavHint: + 'Navidrome 会保存此密码。若与当前密码不同,服务器上的登录密码将被更新。', + userMgmtMagicStringPlaintextWarning: + '请谨慎分享魔法字符串:其中包含未加密的密码(编码不等于加密)。掌握完整字符串的人可以以该用户身份登录。', + userMgmtMagicStringCopied: '魔法字符串已复制到剪贴板。', + userMgmtMagicStringCopyFailed: '无法复制到剪贴板。', + userMgmtMagicStringLoginFailed: '密码验证失败,无法确认凭据。', + userMgmtMagicStringModalTitle: '生成魔法字符串', + userMgmtMagicStringModalDesc: '请输入用户「{{username}}」的 Subsonic 密码,它会包含在复制的魔法字符串中。', + userMgmtMagicStringModalConfirm: '复制字符串', + audiomuseTitle: 'AudioMuse-AI(Navidrome)', + audiomuseDesc: + '若此服务器已配置 AudioMuse-AI Navidrome 插件请开启。可从曲目启动即时混音,并在艺人页使用服务器返回的相似艺人,而非 Last.fm。', + audiomuseIssueHint: + '近期即时混音失败 — 请检查 Navidrome 插件与 AudioMuse API。若服务器无结果,将回退使用 Last.fm 的相似艺人。', + connected: '已连接', + failed: '失败', + eqTitle: '均衡器', + eqEnabled: '启用均衡器', + eqPreset: '预设', + eqPresetCustom: '自定义', + eqPresetBuiltin: '内置预设', + eqPresetCustomGroup: '我的预设', + eqSavePreset: '保存为预设', + eqPresetName: '预设名称…', + eqDeletePreset: '删除预设', + eqResetBands: '重置为平直', + eqPreGain: '预增益', + eqResetPreGain: '重置预增益', + eqAutoEqTitle: 'AutoEQ 耳机查询', + eqAutoEqPlaceholder: '搜索耳机/入耳式型号…', + eqAutoEqSearching: '搜索中…', + eqAutoEqNoResults: '未找到结果', + eqAutoEqError: '搜索失败', + eqAutoEqRateLimit: 'GitHub 请求限制 — 请一分钟后重试', + eqAutoEqFetchError: '无法获取 EQ 配置', + lfmTitle: 'Last.fm', + lfmConnect: '连接 Last.fm', + lfmConnecting: '等待授权…', + lfmConfirm: '我已完成授权', + lfmConnected: '已连接为', + lfmDisconnect: '断开连接', + lfmConnectDesc: '连接您的 Last.fm 账户以启用歌曲记录和正在播放更新,直接从 Psysonic 发送 — 无需配置 Navidrome。', + lfmOpenBrowser: '将打开浏览器窗口。在 Last.fm 上授权 Psysonic,然后点击下方按钮。', + lfmScrobbles: '{{n}} 次记录', + lfmMemberSince: '{{year}} 年加入', + scrobbleEnabled: '启用歌曲记录', + scrobbleDesc: '播放 50% 后发送歌曲到 Last.fm', + behavior: '应用行为', + cacheTitle: '最大存储大小', + cacheDesc: '封面和艺术家图片。存满时,最旧的条目将自动移除。离线专辑不会自动移除,但手动清除缓存时会被删除。', + cacheUsedImages: '图片:', + cacheUsedOffline: '离线曲目:', + cacheUsedHot: '占用空间:', + hotCacheTrackCount: '缓存曲目数:', + cacheMaxLabel: '最大容量', + cacheClearBtn: '清除缓存', + cacheClearWarning: '这将同时移除音乐库中的所有离线专辑。', + cacheClearConfirm: '全部清除', + cacheClearCancel: '取消', + offlineDirTitle: '离线音乐库(应用内)', + offlineDirDesc: '用于在 Psysonic 中离线可用的曲目存储位置。', + offlineDirDefault: '默认(应用数据)', + offlineDirChange: '更改目录', + offlineDirClear: '重置为默认', + offlineDirHint: '新下载将保存到此位置,现有下载保留在原始路径。', + hotCacheTitle: '热播放缓存', + hotCacheDisclaimer: '预加载队列中即将播放的曲目并保留近期已播放的。开启后占用磁盘与网络。', + hotCacheDirDefault: '默认(应用数据)', + hotCacheDirChange: '更改目录', + hotCacheDirClear: '重置为默认', + hotCacheDirHint: '更换目录会重置应用内索引;已下载的文件仍留在原路径,需自行删除。', + hotCacheEnabled: '启用热播放缓存', + hotCacheMaxMb: '最大缓存大小', + hotCacheDebounce: '队列变更去抖', + hotCacheDebounceImmediate: '立即', + hotCacheDebounceSeconds: '{{n}} 秒', + hotCacheClearBtn: '清空热缓存', + audioOutputDevice: '音频输出设备', + audioOutputDeviceDesc: '选择 Psysonic 播放音频的设备。更改立即生效并重新开始当前曲目。', + audioOutputDeviceDefault: '系统默认', + audioOutputDeviceRefresh: '刷新设备列表', + audioOutputDeviceOsDefaultNow: '当前系统输出', + audioOutputDeviceListError: '无法加载音频设备列表。', + audioOutputDeviceNotInCurrentList: '不在当前列表中', + audioOutputDeviceMacNotice: '在 macOS 上,出于技术原因,目前播放始终跟随系统输出设备。请通过 系统设置 → 声音 或菜单栏扬声器图标切换目标设备。背景:打开非默认音频流时 CoreAudio 会触发麦克风权限提示 —— 我们通过始终使用系统默认输出来避免此提示。', + hiResTitle: '原生高清晰度播放', + hiResEnabled: '启用原生高清晰度播放', + hiResDesc: "默认强制 44.1 kHz 输出以获得最大稳定性。仅在硬件和网络可靠支持高采样率(88.2 kHz+)时启用。", + showArtistImages: '显示艺术家图片', + showArtistImagesDesc: '在艺术家概览中加载并显示艺术家图片。默认关闭以减少大型音乐库的服务器磁盘I/O和网络负载。', + showOrbitTrigger: '在顶栏显示"Orbit"', + showOrbitTriggerDesc: '用于启动或加入共享收听会话的顶栏按钮。如果不使用 Orbit,可以隐藏 — 随时可在此重新开启。', + showTrayIcon: '显示托盘图标', + showTrayIconDesc: '在系统通知区域 / 菜单栏显示 Psysonic 图标。', + minimizeToTray: '最小化到托盘', + minimizeToTrayDesc: '关闭窗口时,Psysonic 将继续在系统托盘中运行,而不是退出。', + preloadMiniPlayer: '预加载迷你播放器', + preloadMiniPlayerDesc: '在应用启动时于后台构建迷你播放器窗口,使其首次打开即可立即显示内容。会占用少量额外内存。', + linuxWebkitSmoothScroll: '滚轮平滑(Linux)', + linuxWebkitSmoothScrollDesc: '开:惯性滚动。关:逐行,类似 GTK。', + discordRichPresence: 'Discord Rich Presence', + discordRichPresenceDesc: '在 Discord 个人资料上显示当前播放的曲目。需要 Discord 处于运行状态。', + discordCoverSource: '封面来源', + discordCoverSourceDesc: '从何处获取 Discord 个人资料上显示的专辑封面。', + discordCoverNone: '无(仅显示应用图标)', + discordCoverServer: '服务器(通过专辑信息)', + discordCoverApple: 'Apple Music', + discordOptions: 'Discord 高级选项', + discordTemplates: '自定义文本模板', + discordTemplatesDesc: '自定义在 Discord 个人资料上显示的信息。变量:{title}, {artist}, {album}', + discordTemplateDetails: '主行 (details)', + discordTemplateState: '副行 (state)', + discordTemplateLargeText: '专辑提示 (largeText)', + nowPlayingEnabled: '在实时窗口中显示', + nowPlayingEnabledDesc: '将当前播放的曲目广播到服务器的实时听众视图。禁用以停止发送播放数据。', + enableBandsintown: 'Bandsintown 巡演日期', + enableBandsintownDesc: '在信息标签页中显示当前艺术家的即将到来的演出。数据通过公开的 Bandsintown API 获取。', + lyricsServerFirst: '优先使用服务器歌词', + lyricsServerFirstDesc: '先查询服务器提供的歌词(内嵌标签、sidecar 文件),再查询 LRCLIB。禁用则优先使用 LRCLIB。', + enableNeteaselyrics: '网易云音乐歌词', + enableNeteaselyricsDesc: '当服务器和 LRCLIB 均无结果时,使用网易云音乐作为最终歌词来源。对亚洲及国际音乐覆盖最佳。', + lyricsSourcesTitle: '歌词来源', + lyricsSourcesDesc: '选择要查询的歌词来源及其顺序。拖动以排序。已禁用的来源将被跳过。', + lyricsSourceServer: '服务器', + lyricsSourceLrclib: 'LRCLIB', + lyricsSourceNetease: '网易云音乐', + lyricsModeStandard: '标准', + lyricsModeStandardDesc: '三个可自由排序的来源:服务器标签、LRCLIB、网易云。', + lyricsModeLyricsplus: 'YouLyPlus(卡拉OK)', + lyricsModeLyricsplusDesc: '来自 Apple Music、Spotify、Musixmatch 和 QQ 音乐的逐字同步歌词(社区后端)。找不到时静默回退到标准来源。', + lyricsStaticOnly: '仅以静态文本显示歌词', + lyricsStaticOnlyDesc: '同步歌词将不自动滚动、不逐字高亮,以静态文本显示。', + downloadsTitle: 'ZIP 导出与归档', + downloadsFolderDesc: '将专辑以 ZIP 文件下载到电脑时的目标文件夹。', + downloadsDefault: '默认下载文件夹', + pickFolder: '选择', + pickFolderTitle: '选择下载文件夹', + clearFolder: '清除下载文件夹', + logout: '退出登录', + aboutTitle: '关于 Psysonic', + aboutDesc: '一款专为 Navidrome 构建的现代桌面音乐播放器。使用 Subsonic API 以及 Navidrome 特有的扩展。基于 Tauri v2 和原生 Rust 音频引擎——轻量快速,功能丰富:波形进度条、同步歌词、Last.fm 集成、10 段均衡器、交叉淡入淡出、无缝播放、响度增益、流派浏览以及大量精美主题。', + aboutLicense: '许可证', + aboutLicenseText: 'GNU GPL v3 — 在相同许可证下可自由使用、修改和分发。', + aboutRepo: 'GitHub 上的源代码', + aboutVersion: '版本', + aboutBuiltWith: '使用 Tauri · React · TypeScript · Rust/rodio 构建', + aboutReleaseNotesLabel: '版本说明', + aboutReleaseNotesLink: '打开此版本的新功能', + aboutContributorsLabel: '贡献者', + showChangelogOnUpdate: '更新时显示"新功能"', + showChangelogOnUpdateDesc: '更新后在「正在播放」上方显示一个低调的更新日志横幅。点击打开发行说明,X 按钮关闭。', + randomMixTitle: '随机混音黑名单', + luckyMixMenuTitle: '在菜单中显示“好运混音”', + luckyMixMenuDesc: '在“创建混音”中启用“好运混音”,并在分离导航时作为独立菜单项显示。仅当当前服务器启用 AudioMuse 时可见。', + randomMixBlacklistTitle: '自定义过滤关键词', + randomMixBlacklistDesc: '当任何关键词匹配流派、标题、专辑或艺术家时,歌曲将被排除(当上方复选框开启时生效)。', + randomMixBlacklistPlaceholder: '添加关键词…', + randomMixBlacklistAdd: '添加', + randomMixBlacklistEmpty: '尚未添加自定义关键词。', + randomMixHardcodedTitle: '内置关键词(复选框开启时生效)', + tabAudio: '音频', + tabStorage: '离线与缓存', + tabAppearance: '外观', + tabLibrary: '媒体库', + tabServers: '服务器', + tabLyrics: '歌词', + tabPersonalisation: '个性化', + tabIntegrations: '集成', + inputKeybindingsTitle: '键盘快捷键', + aboutContributorsCount_one: '{{count}} 项贡献', + aboutContributorsCount_other: '{{count}} 项贡献', + searchPlaceholder: '搜索设置…', + searchNoResults: '没有设置匹配您的搜索。', + aboutMaintainersLabel: '维护者', + integrationsPrivacyTitle: '隐私说明', + integrationsPrivacyBody: '此标签页中的所有集成均为 选择加入,启用后会向外部服务或您的 Navidrome 服务器发送数据。Last.fm 接收您的收听历史,Discord 在您的个人资料中显示正在播放的曲目,Bandsintown 会按艺人查询以获取巡演日期,"正在播放" 分享会向您 Navidrome 服务器的其他用户公开您当前的曲目。如果您不需要这些功能,只需将相应部分保持停用即可。', + homeCustomizerTitle: '首页', + queueToolbarTitle: '队列工具栏', + queueToolbarReset: '重置为默认', + queueToolbarSeparator: '分隔符', + sidebarTitle: '侧边栏', + sidebarReset: '重置为默认', + artistLayoutTitle: '艺术家页面板块', + artistLayoutDesc: '拖动以重新排序,切换以隐藏艺术家页面的各个板块。没有数据的板块会自动跳过。', + artistLayoutReset: '重置为默认', + artistLayoutBio: '艺术家简介', + artistLayoutTopTracks: '热门曲目', + artistLayoutSimilar: '相似艺术家', + artistLayoutAlbums: '专辑', + artistLayoutFeatured: '也参与了', + sidebarDrag: '拖动以重新排序', + sidebarFixed: '始终显示', + randomNavSplitTitle: '拆分混音导航', + randomNavSplitDesc: '在侧边栏中将“随机混音”、“随机专辑”和“好运混音”显示为独立条目,而非“创建混音”合并入口。', + tabInput: '输入', + tabUsers: '用户', + tabSystem: '系统', + loggingTitle: '日志记录', + loggingModeDesc: '控制终端中后端日志的详细程度。', + loggingModeOff: '关闭', + loggingModeNormal: '普通', + loggingModeDebug: '调试', + loggingExport: '导出日志', + loggingExportSuccess: '日志已导出({{count}} 行)。', + loggingExportError: '无法导出日志。', + ratingsSectionTitle: '评分', + ratingsSkipStarTitle: '跳过以评 1 星', + ratingsSkipStarDesc: + '连续多次跳过后将曲目设为 1 星。仅适用于此前未评分的曲目。', + ratingsSkipStarThresholdLabel: '跳过次数', + ratingsMixFilterTitle: '按评分筛选', + ratingsMixFilterDesc: + '在{{mix}}与{{albums}}中筛选低评分内容。再次点击所选星标可关闭阈值。', + ratingsMixMinSong: '歌曲', + ratingsMixMinAlbum: '专辑', + ratingsMixMinArtist: '艺人', + ratingsMixMinThresholdAria: '最低星数:{{label}}', + backupTitle: '备份与恢复', + backupExport: '导出设置', + backupExportDesc: '将所有设置、服务器配置、Last.fm 配置、主题、均衡器和快捷键保存到 .psybkp 文件。密码以明文存储——请妥善保管该文件。', + backupImport: '导入设置', + backupImportDesc: '从 .psybkp 文件恢复设置。导入后应用将重新加载。', + backupImportConfirm: '所有当前设置将被覆盖。是否继续?', + backupSuccess: '备份已保存', + backupImportSuccess: '设置已恢复——正在重新加载…', + backupImportError: '备份文件无效或已损坏。', + shortcutsReset: '恢复默认', + shortcutListening: '请按下按键…', + shortcutUnbound: '—', + globalShortcutsTitle: '全局快捷键', + globalShortcutsNote: '即使 Psysonic 在后台也能在系统范围内工作。需要 Ctrl、Alt 或 Super 作为修饰键。', + shortcutClear: '清除', + shortcutPlayPause: '播放 / 暂停', + shortcutNext: '下一首', + shortcutPrev: '上一首', + shortcutVolumeUp: '音量增大', + shortcutVolumeDown: '音量减小', + shortcutSeekForward: '快进 10 秒', + shortcutSeekBackward: '快退 10 秒', + shortcutToggleQueue: '切换队列', + shortcutOpenFolderBrowser: '打开{{folderBrowser}}', + shortcutFullscreenPlayer: '全屏播放器', + shortcutNativeFullscreen: '原生全屏', + shortcutOpenMiniPlayer: '打开迷你播放器', + shortcutStartSearch: '开始搜索', + shortcutStartAdvancedSearch: '开始高级搜索', + shortcutToggleSidebar: '切换侧边栏', + shortcutMuteSound: '静音', + shortcutToggleEqualizer: '打开 / 切换均衡器', + shortcutToggleRepeat: '切换循环', + shortcutOpenNowPlaying: '打开"正在播放"', + shortcutShowLyrics: '显示歌词', + shortcutFavoriteCurrentTrack: '将当前曲目添加到收藏', + shortcutOpenHelp: '帮助', + playbackTitle: '播放', + replayGain: '回放增益', + replayGainDesc: '使用 ReplayGain 元数据标准化曲目音量', + replayGainMode: '模式', + replayGainAuto: '自动', + replayGainAutoDesc: '当队列中相邻曲目来自同一专辑时使用专辑增益,否则使用曲目增益。', + replayGainTrack: '曲目', + replayGainAlbum: '专辑', + replayGainPreGain: '预增益(有标签文件)', + replayGainPreGainDesc: '对所有 ReplayGain 计算结果叠加的统一增益。适合在曲库整体偏轻时用作整体补偿。', + replayGainFallback: '回退增益(无标签 / 收音机)', + replayGainFallbackDesc: '应用于没有 ReplayGain 标签的曲目(以及电台流),避免未打标签的内容比其余素材更响。', + normalization: '响度归一化', + normalizationDesc: '在曲目、专辑和电台之间统一可感知的响度。', + normalizationOff: '关闭', + normalizationReplayGain: 'ReplayGain', + normalizationLufs: 'LUFS', + loudnessTargetLufs: '目标 LUFS', + loudnessTargetLufsDesc: '所有曲目对齐的参考响度。数值越小,输出越响。流媒体服务通常在 -14 LUFS 左右。', + loudnessPreAnalysisAttenuation: '测量前衰减', + loudnessPreAnalysisAttenuationDesc: + '在曲目响度数据保存前的额外压低。流式阶段之后只是粗略估计,不是完整测量。0 dB 为不压低;更负则更安静。右侧显示当前目标下的等效 dB。', + loudnessPreAnalysisAttenuationRef: '目标 {{tgt}} LUFS 时等效 {{eff}} dB。', + loudnessPreAnalysisAttenuationReset: '恢复默认', + loudnessFirstPlayNote: + '首次播放新曲目时,音量可能在测量过程中略有波动。下一次播放将使用缓存的测量结果,保持稳定。队列中即将播放的曲目通常在上一首播放期间已完成预分析,所以这种情况在实际使用中很少出现。', + crossfade: '交叉淡入淡出', + crossfadeDesc: '曲目间淡入淡出', + crossfadeSecs: '{{n}} 秒', + notWithGapless: '无缝播放开启时不可用', + notWithCrossfade: '交叉淡入淡出开启时不可用', + gapless: '无缝播放', + gaplessDesc: '预缓冲下一首曲目以消除歌曲间的间隙', + preservePlayNextOrder: '保留"下一首播放"顺序', + preservePlayNextOrderDesc: '新添加的"下一首播放"项目排在现有项目之后,而不是插到前面。', + trackPreviewsTitle: '曲目预览', + trackPreviewsToggle: '启用曲目预览', + trackPreviewsDesc: '在曲目列表中显示内联播放与预览按钮,可快速试听歌曲中段。', + trackPreviewStart: '起始位置', + trackPreviewStartDesc: '预览从曲目何处开始(占总时长的百分比)。', + trackPreviewDuration: '时长', + trackPreviewDurationDesc: '每段预览自动停止前的播放时长。', + trackPreviewDurationSecs: '{{n}} 秒', + trackPreviewLocationsTitle: '预览显示位置', + trackPreviewLocationsDesc: '选择在哪些列表中显示预览按钮。', + trackPreviewLocation_suggestions: '播放列表建议中', + trackPreviewLocation_albums: '专辑曲目列表中', + trackPreviewLocation_playlists: '播放列表中', + trackPreviewLocation_favorites: '收藏中', + trackPreviewLocation_artist: '艺人热门曲目中', + trackPreviewLocation_randomMix: 'Random Mix 中', + preloadMode: '预加载下一曲目', + preloadModeDesc: '何时开始缓冲队列中的下一曲目', + nextTrackBufferingTitle: '缓冲', + preloadHotCacheMutualExclusive: '预加载与热缓存用途相同——两者不能同时启用。启用其中一个会自动禁用另一个。', + preloadOff: '关闭', + preloadBalanced: '均衡(结束前30秒)', + preloadEarly: '提前(播放5秒后)', + preloadCustom: '自定义', + preloadCustomSeconds: '结束前秒数:{{n}}', + infiniteQueue: '无限队列', + infiniteQueueDesc: '队列播完时自动追加随机曲目', + experimental: '实验性', + fsPlayerSection: '全屏播放器', + fsShowArtistPortrait: '显示艺术家照片', + fsShowArtistPortraitDesc: '在全屏播放器右侧显示艺术家照片(或专辑封面)。', + fsPortraitDim: '照片暗化', + fsLyricsStyle: '歌词显示样式', + fsLyricsStyleRail: '轨道', + fsLyricsStyleRailDesc: '经典5行滑动轨道。', + fsLyricsStyleApple: '滚动', + fsLyricsStyleAppleDesc: '全屏可滚动列表。', + sidebarLyricsStyle: '歌词滚动样式', + sidebarLyricsStyleClassic: '经典', + sidebarLyricsStyleClassicDesc: '活动行居中显示。', + sidebarLyricsStyleApple: 'Apple Music-like', + sidebarLyricsStyleAppleDesc: '活动行固定在顶部,带有平滑弹簧动画。', + seekbarStyle: '进度条样式', + seekbarStyleDesc: '选择播放进度条的外观', + seekbarTruewave: '真实波形', + seekbarPseudowave: '伪波形', + seekbarLinedot: '线条与点', + seekbarBar: '条形', + seekbarThick: '粗条形', + seekbarSegmented: '分段式', + seekbarNeon: '霓虹', + seekbarPulsewave: '脉冲波', + seekbarParticletrail: '粒子轨迹', + seekbarLiquidfill: '液体填充', + seekbarRetrotape: '复古磁带', + themeSchedulerTitle: '主题定时切换', + themeSchedulerEnable: '启用主题定时器', + themeSchedulerEnableSub: '根据一天中的时间自动在两个主题之间切换', + themeSchedulerDayTheme: '白天主题', + themeSchedulerDayStart: '白天开始时间', + themeSchedulerNightTheme: '夜晚主题', + themeSchedulerNightStart: '夜晚开始时间', + themeSchedulerActiveHint: '主题定时器已启用 - 主题将自动切换。', + visualOptionsTitle: '视觉选项', + coverArtBackground: '封面背景', + coverArtBackgroundSub: '在专辑/播放列表标题中显示模糊的封面作为背景', + playlistCoverPhoto: '播放列表封面照片', + playlistCoverPhotoSub: '在播放列表详细视图中显示封面照片网格', + showBitrate: '显示比特率', + showBitrateSub: '在曲目列表中显示音频比特率', + floatingPlayerBar: '浮动播放栏', + floatingPlayerBarSub: '保持播放栏悬浮在内容上方', + uiScaleTitle: '界面缩放', + uiScaleLabel: '缩放', +}; diff --git a/src/locales/zh/sharePaste.ts b/src/locales/zh/sharePaste.ts new file mode 100644 index 00000000..d4594eb8 --- /dev/null +++ b/src/locales/zh/sharePaste.ts @@ -0,0 +1,17 @@ +export const sharePaste = { + notLoggedIn: '请先登录并添加服务器,再粘贴分享链接。', + noMatchingServer: '没有已保存的服务器与此链接匹配。请添加使用该地址的服务器:{{url}}', + trackUnavailable: '在服务器上找不到此歌曲。', + albumUnavailable: '在服务器上找不到此专辑。', + artistUnavailable: '在服务器上找不到此艺术家。', + composerUnavailable: '在服务器上找不到此作曲家。', + openedTrack: '正在播放分享的歌曲。', + openedAlbum: '正在打开分享的专辑。', + openedArtist: '正在打开分享的艺术家。', + openedComposer: '正在打开分享的作曲家。', + openedQueue_one: '正在播放分享队列中的 {{count}} 首曲目。', + openedQueue_other: '正在播放分享队列中的 {{count}} 首曲目。', + openedQueuePartial: '正在播放链接中的 {{played}} / {{total}} 首曲目({{skipped}} 首在此服务器上未找到)。', + queueAllUnavailable: '此链接中的曲目在服务器上均未找到。', + genericError: '无法打开分享链接。', +}; diff --git a/src/locales/zh/sidebar.ts b/src/locales/zh/sidebar.ts new file mode 100644 index 00000000..aa240882 --- /dev/null +++ b/src/locales/zh/sidebar.ts @@ -0,0 +1,37 @@ +export const sidebar = { + library: '音乐库', + mainstage: '主舞台', + newReleases: '新发布', + allAlbums: '全部专辑', + randomAlbums: '随机专辑', + randomPicker: '创建混音', + artists: '艺术家', + composers: '作曲家', + randomMix: '随机混音', + favorites: '收藏夹', + nowPlaying: '正在播放', + system: '系统', + statistics: '统计', + settings: '设置', + help: '帮助', + expand: '展开侧边栏', + collapse: '收起侧边栏', + downloadingTracks: '正在缓存 {{n}} 首歌曲…', + syncingTracks: '同步中 {{done}}/{{total}}…', + cancelDownload: '取消下载', + offlineLibrary: '离线音乐库', + genres: '流派', + tracks: '曲目', + playlists: '播放列表', + mostPlayed: '最常播放', + losslessAlbums: '无损', + radio: '网络电台', + folderBrowser: '文件夹浏览器', + deviceSync: '设备同步', + libraryScope: '资料库范围', + allLibraries: '所有资料库', + expandPlaylists: '展开播放列表', + collapsePlaylists: '收起播放列表', + more: '更多', + feelingLucky: '好运混音', +}; diff --git a/src/locales/zh/smartPlaylists.ts b/src/locales/zh/smartPlaylists.ts new file mode 100644 index 00000000..94d0b758 --- /dev/null +++ b/src/locales/zh/smartPlaylists.ts @@ -0,0 +1,41 @@ +export const smartPlaylists = { + sectionBasic: '1. 基础', + sectionGenres: '2. 流派', + sectionYearsAndFilters: '3. 年份与筛选', + genreMode: '流派模式', + genreModeInclude: '包含流派', + genreModeExclude: '排除流派', + genreSearchPlaceholder: '筛选流派...', + availableGenres: '可用', + selectedGenres: '已选', + yearMode: '年份模式', + yearModeInclude: '包含范围', + yearModeExclude: '排除范围', + name: '名称(不含前缀)', + limit: '数量上限', + limitHint: '要包含在播放列表中的曲目数量(1-{{max}},通常为 50)。', + artistContains: '艺术家包含…', + albumContains: '专辑包含…', + titleContains: '标题包含…', + minRating: '最低评分', + minRatingAria: '智能播放列表的最低评分', + minRatingHint: '0 表示关闭最低阈值;1-5 仅保留评分高于所选值的曲目。', + fromYear: '起始年份', + toYear: '结束年份', + excludeUnrated: '排除未评分曲目', + compilationOnly: '仅合集', + create: '新建智能播放列表', + save: '保存智能播放列表', + created: '已创建 {{name}}', + updated: '已更新 {{name}}', + createFailed: '无法创建智能播放列表。', + updateFailed: '无法更新智能播放列表。', + navidromeOnly: '仅 Navidrome 服务器支持创建智能播放列表。', + loadFailed: '无法从 Navidrome 加载智能播放列表。', + sortRandom: '排序:随机', + sortTitleAsc: '排序:标题 A-Z', + sortTitleDesc: '排序:标题 Z-A', + sortYearDesc: '排序:年份降序', + sortYearAsc: '排序:年份升序', + sortPlayCountDesc: '排序:播放次数降序', +}; diff --git a/src/locales/zh/songInfo.ts b/src/locales/zh/songInfo.ts new file mode 100644 index 00000000..94e13c76 --- /dev/null +++ b/src/locales/zh/songInfo.ts @@ -0,0 +1,23 @@ +export const songInfo = { + title: '歌曲信息', + songTitle: '标题', + artist: '艺术家', + album: '专辑', + albumArtist: '专辑艺术家', + year: '年份', + genre: '流派', + duration: '时长', + track: '曲目', + format: '格式', + bitrate: '比特率', + sampleRate: '采样率', + bitDepth: '位深度', + channels: '声道', + fileSize: '文件大小', + path: '文件路径', + replayGainTrack: 'RG 曲目增益', + replayGainAlbum: 'RG 专辑增益', + replayGainPeak: 'RG 曲目峰值', + mono: '单声道', + stereo: '立体声', +}; diff --git a/src/locales/zh/statistics.ts b/src/locales/zh/statistics.ts new file mode 100644 index 00000000..b05c288f --- /dev/null +++ b/src/locales/zh/statistics.ts @@ -0,0 +1,47 @@ +export const statistics = { + title: '统计', + recentlyPlayed: '最近播放', + mostPlayed: '最常播放的专辑', + highestRated: '评分最高的专辑', + genreDistribution: '流派分布(前 20)', + loadMore: '加载更多', + statArtists: '艺术家', + statArtistsTooltip: '仅限专辑艺术家——仅作为单曲艺术家出现(合唱、客串等)且无自己专辑的艺术家不计入此处。', + statAlbums: '专辑', + statSongs: '歌曲', + statGenres: '流派', + statPlaytime: '音频总时长', + genreInsights: '流派洞察', + formatDistribution: '格式分布', + formatSample: '{{n}} 首曲目的样本', + computing: '计算中…', + genreSongs: '{{count}} 首歌曲', + genreAlbums: '{{count}} 张专辑', + recentlyAdded: '最近添加', + decadeDistribution: '按年代分布的专辑', + decadeAlbums_one: '{{count}} 张专辑', + decadeAlbums_other: '{{count}} 张专辑', + decadeUnknown: '未知', + lfmTitle: 'Last.fm 统计', + lfmTopArtists: '热门艺术家', + lfmTopAlbums: '热门专辑', + lfmTopTracks: '热门曲目', + lfmPlays: '{{count}} 次播放', + lfmPeriodOverall: '全部时间', + lfmPeriod7day: '7 天', + lfmPeriod1month: '1 个月', + lfmPeriod3month: '3 个月', + lfmPeriod6month: '6 个月', + lfmPeriod12month: '12 个月', + lfmNotConnected: '在设置中连接 Last.fm 以查看您的统计。', + lfmRecentTracks: '最近记录', + lfmNowPlaying: '正在播放', + lfmJustNow: '刚刚', + lfmMinutesAgo: '{{n}} 分钟前', + lfmHoursAgo: '{{n}} 小时前', + lfmDaysAgo: '{{n}} 天前', + topRatedSongs: '最高评分歌曲', + topRatedArtists: '最高评分艺人', + noRatedSongs: '暂无已评分歌曲。请在专辑或播放列表中为歌曲评分。', + noRatedArtists: '暂无已评分艺人。', +}; diff --git a/src/locales/zh/tracks.ts b/src/locales/zh/tracks.ts new file mode 100644 index 00000000..6d7e3662 --- /dev/null +++ b/src/locales/zh/tracks.ts @@ -0,0 +1,15 @@ +export const tracks = { + title: '曲目', + subtitle: '浏览。搜索。发现。', + heroEyebrow: '此刻精选', + heroReroll: '换一首', + playSong: '播放', + enqueueSong: '加入队列', + railRandom: '随机精选', + railHighlyRated: '高分推荐', + browseTitle: '浏览所有曲目', + browseUnsupported: '此服务器不支持一次性列出整个音乐库。使用上方的搜索来查找特定曲目。', + searchPlaceholder: '按标题、艺人或专辑搜索…', + count_one: '{{count}} 首曲目', + count_other: '{{count}} 首曲目', +}; diff --git a/src/locales/zh/tray.ts b/src/locales/zh/tray.ts new file mode 100644 index 00000000..7124f50b --- /dev/null +++ b/src/locales/zh/tray.ts @@ -0,0 +1,8 @@ +export const tray = { + playPause: '播放 / 暂停', + nextTrack: '下一首', + previousTrack: '上一首', + showHide: '显示 / 隐藏', + exitPsysonic: '退出 Psysonic', + nothingPlaying: '当前没有播放', +}; diff --git a/src/locales/zh/whatsNew.ts b/src/locales/zh/whatsNew.ts new file mode 100644 index 00000000..cf15f0f9 --- /dev/null +++ b/src/locales/zh/whatsNew.ts @@ -0,0 +1,8 @@ +export const whatsNew = { + title: '新功能', + empty: '此版本暂无更新日志。', + bannerTitle: '更新日志', + bannerCollapsed: 'v{{version}} 新功能', + dismiss: '关闭', + close: '关闭', +};