mirror of
https://github.com/kilyabin/psysonic.git
synced 2026-07-22 06:25:41 +00:00
* feat(composer): Browse by Composer page (issue #465) New library section listing every artist credited as composer on at least one track, with a detail page showing all works they're credited on in that role. Targeted at classical-music libraries where the "recording artist" tag carries the orchestra and the "composer" tag carries Bach / Mozart / Chopin. Hits Navidrome's native /api/artist?_filters={"role":"composer"} for the listing and /api/album?_filters={"role_composer_id":"…"} for the works grid — Subsonic getArtist only follows AlbumArtist relations and returns 0 albums for composer-only credits, so the native API is the only path that works. Requires Navidrome 0.55+ (uses library_artist.stats role aggregation); on older / pure-Subsonic servers the page shows a one-line capability banner. - Two new Tauri commands: nd_list_artists_by_role + nd_list_albums_by_artist_role, generic over participant role so conductor / lyricist / arranger pages are trivial to add later. - Composers grid: text-only compact tiles (name + participation count pulled from stats[role].albumCount). No avatars — composer libraries carry no useful imagery and the listing endpoint exposes no image URLs anyway. - ComposerDetail: hero with Last.fm bio (via getArtistInfo2) plus the full work grid, with a graceful fallback when the artist has no external info synced. - Sidebar entry default off (Feather icon) — opt-in for the niche classical use case. - nd_retry backoffs widened from [500] to [300, 800, 1800] — helps every nd_* call survive intermittent TLS-handshake-EOF errors that some reverse-proxy setups produce when keep-alive pools churn. - Distinguishes "server can't do this" (HTTP 400/404/422/501) from transient errors so the capability banner only fires when the server actually rejects the request shape; everything else gets a retry button. - i18n in all 8 supported locales. * fix(composer): address review feedback on detail page + role queries - Re-fetch ComposerDetail when music-library scope changes; previously the album grid stayed stale until navigation while the list refreshed. - Thread library_id through nd_list_artists_by_role and nd_list_albums_by_artist_role so role queries respect the active Navidrome library, matching the Subsonic musicFolderId already piped through libraryFilterParams(). - Fix CachedImage cache-key mismatch on ComposerDetail: a Last.fm header image was stored under the Subsonic cover-art key, aliasing cache entries and risking cross-source pollution. - Consolidate the two contradictory composer-imagery comments in Composers.tsx into a single accurate one (the older one referenced an Images toggle that was never implemented). - Align openLink toast duration with ArtistDetail (1500ms -> 2500ms). * fix(composer): keep bio across scope changes, add share, degrade gracefully Three remaining items from the latest review pass on the composer flow. 1. Bio survives a music-library scope change. The previous fix added musicLibraryFilterVersion to the load effect, but that effect also did setInfo(null) while the getArtistInfo effect still depended on [id] alone — so a scope bump on the open page wiped the bio without re-fetching it. Move the info reset into the bio effect (keyed on id) and out of the load effect: the album grid still refreshes on scope change; the Last.fm header image and biography survive untouched, since both are library-independent. 2. Composers join the share pipeline as a first-class entity kind. Extend EntityShareKind with 'composer' (and isEntityKind), branch applySharePastePayload to validate via getArtist (same id pool) and navigate to /composer/:id, and wire a Share button into ComposerDetail. A pasted composer link now opens the composer view instead of the artist view, matching what was copied. i18n added in all 8 locales (sharePaste.composerUnavailable, openedComposer; composerDetail.shareComposer, unknownComposer). 3. Partial server failure no longer hides the works. If getArtist rejects but ndListAlbumsByArtistRole succeeds, the page used to show full "not found" despite having data to display. Switch the not-found gate to require both empty (`!artist && !albums`) and render a degraded header (placeholder name, no Wikipedia / favourite / share / Last.fm image) when only metadata is missing. * fix(composer): right-click share copies a composer link, not an artist link The context menu opened from a composer card / row uses type='artist' because every composer-action (radio, favourite, rating, add-to-playlist) is identical to the artist counterpart — they share an id space and a backend representation. Sharing was the one exception: the "Share Link" entry produced a 'psysonic2-' string with k='artist', so a paste opened /artist/:id even though the user came from /composers. Add an optional shareKindOverride to openContextMenu (default: undefined, preserves existing behaviour) and have the artist-typed branch consult it when calling copyShareLink. Composers.tsx now passes 'composer' on both right-click sites; nothing else changes downstream because the override only affects the share kind. * polish(composer): show Last.fm avatar even without server metadata Two minor follow-ups from the latest review. - ComposerDetail: drop the `&& artist` guard on the header-avatar render path. info?.largeImageUrl can resolve through getArtistInfo(id) without ever needing the SubsonicArtist record, so the previous gate hid a perfectly good Last.fm portrait whenever getArtist failed but the bio fetch succeeded. Replace artist.name with displayName so the alt / aria-label degrade to the localised "Composer" placeholder instead of empty strings. - copyEntityShareLink: doc comment now mentions composer alongside track / album / artist. * fix(composer): derive Last.fm cache key from route id, not from artist record Follow-up to the previous polish: the avatar render path no longer requires `artist` to be populated, but the cache-key gate still did. So when getArtist failed but getArtistInfo returned a Last.fm portrait, the key fell through to coverKey — which is empty without an artist record, re-creating the very aliasing bug the earlier Subsonic-vs-Last.fm fix was meant to close. Switch the Last.fm branch to the route id (same id namespace as the SubsonicArtist record), so the key stays stable whenever Last.fm art is shown, independent of getArtist succeeding. * docs: CHANGELOG + Contributors entry for composer browsing (PR #487)
This commit is contained in:
committed by
GitHub
parent
c83447ebd2
commit
59744601d4
@@ -7,6 +7,7 @@ export const deTranslation = {
|
||||
randomAlbums: 'Zufallsalben',
|
||||
randomPicker: 'Mix erstellen',
|
||||
artists: 'Künstler',
|
||||
composers: 'Komponist*innen',
|
||||
randomMix: 'Zufallsmix',
|
||||
favorites: 'Favoriten',
|
||||
nowPlaying: 'Now Playing',
|
||||
@@ -168,9 +169,11 @@ export const deTranslation = {
|
||||
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:
|
||||
@@ -429,6 +432,27 @@ export const deTranslation = {
|
||||
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)',
|
||||
|
||||
@@ -7,6 +7,7 @@ export const enTranslation = {
|
||||
randomAlbums: 'Random Albums',
|
||||
randomPicker: 'Build a Mix',
|
||||
artists: 'Artists',
|
||||
composers: 'Composers',
|
||||
randomMix: 'Random Mix',
|
||||
favorites: 'Favorites',
|
||||
nowPlaying: 'Now Playing',
|
||||
@@ -170,9 +171,11 @@ export const enTranslation = {
|
||||
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:
|
||||
@@ -431,6 +434,27 @@ export const enTranslation = {
|
||||
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)',
|
||||
|
||||
@@ -6,6 +6,7 @@ export const esTranslation = {
|
||||
allAlbums: 'Todos los Álbumes',
|
||||
randomAlbums: 'Álbumes Aleatorios',
|
||||
artists: 'Artistas',
|
||||
composers: 'Compositores',
|
||||
randomMix: 'Mezcla Aleatoria',
|
||||
randomPicker: 'Crear Mezcla',
|
||||
favorites: 'Favoritos',
|
||||
@@ -169,9 +170,11 @@ export const esTranslation = {
|
||||
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:
|
||||
@@ -431,6 +434,27 @@ export const esTranslation = {
|
||||
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)',
|
||||
|
||||
@@ -7,6 +7,7 @@ export const frTranslation = {
|
||||
randomAlbums: 'Albums aléatoires',
|
||||
randomPicker: 'Créer un mix',
|
||||
artists: 'Artistes',
|
||||
composers: 'Compositeurs',
|
||||
randomMix: 'Mix aléatoire',
|
||||
favorites: 'Favoris',
|
||||
nowPlaying: 'En cours',
|
||||
@@ -168,9 +169,11 @@ export const frTranslation = {
|
||||
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:
|
||||
@@ -429,6 +432,27 @@ export const frTranslation = {
|
||||
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)',
|
||||
|
||||
@@ -7,6 +7,7 @@ export const nbTranslation = {
|
||||
randomAlbums: 'Tilfeldige album',
|
||||
randomPicker: 'Lag en miks',
|
||||
artists: 'Artister',
|
||||
composers: 'Komponister',
|
||||
randomMix: 'Tilfeldig miks',
|
||||
favorites: 'Favoritter',
|
||||
nowPlaying: 'Spilles nå',
|
||||
@@ -168,9 +169,11 @@ export const nbTranslation = {
|
||||
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:
|
||||
@@ -429,6 +432,27 @@ export const nbTranslation = {
|
||||
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)',
|
||||
|
||||
@@ -7,6 +7,7 @@ export const nlTranslation = {
|
||||
randomAlbums: 'Willekeurige albums',
|
||||
randomPicker: 'Mix samenstellen',
|
||||
artists: 'Artiesten',
|
||||
composers: 'Componisten',
|
||||
randomMix: 'Willekeurige mix',
|
||||
favorites: 'Favorieten',
|
||||
nowPlaying: 'Nu bezig',
|
||||
@@ -167,9 +168,11 @@ export const nlTranslation = {
|
||||
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:
|
||||
@@ -428,6 +431,27 @@ export const nlTranslation = {
|
||||
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)',
|
||||
|
||||
@@ -8,6 +8,7 @@ export const ruTranslation = {
|
||||
randomAlbums: 'Случайные альбомы',
|
||||
randomPicker: 'Собрать микс',
|
||||
artists: 'Исполнители',
|
||||
composers: 'Композиторы',
|
||||
randomMix: 'Случайный микс',
|
||||
favorites: 'Избранное',
|
||||
nowPlaying: 'Сейчас играет',
|
||||
@@ -176,9 +177,11 @@ export const ruTranslation = {
|
||||
trackUnavailable: 'Трек на сервере не найден.',
|
||||
albumUnavailable: 'Альбом на сервере не найден.',
|
||||
artistUnavailable: 'Исполнитель на сервере не найден.',
|
||||
composerUnavailable: 'Композитор на сервере не найден.',
|
||||
openedTrack: 'Воспроизводится присланный трек.',
|
||||
openedAlbum: 'Открывается присланный альбом.',
|
||||
openedArtist: 'Открывается присланный исполнитель.',
|
||||
openedComposer: 'Открывается присланный композитор.',
|
||||
openedQueue_one: 'Воспроизводится присланная очередь: {{count}} трек.',
|
||||
openedQueue_few: 'Воспроизводится присланная очередь: {{count}} трека.',
|
||||
openedQueue_many: 'Воспроизводится присланная очередь: {{count}} треков.',
|
||||
@@ -457,6 +460,27 @@ export const ruTranslation = {
|
||||
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: 'Название сервера (необязательно)',
|
||||
|
||||
@@ -7,6 +7,7 @@ export const zhTranslation = {
|
||||
randomAlbums: '随机专辑',
|
||||
randomPicker: '创建混音',
|
||||
artists: '艺术家',
|
||||
composers: '作曲家',
|
||||
randomMix: '随机混音',
|
||||
favorites: '收藏夹',
|
||||
nowPlaying: '正在播放',
|
||||
@@ -167,9 +168,11 @@ export const zhTranslation = {
|
||||
trackUnavailable: '在服务器上找不到此歌曲。',
|
||||
albumUnavailable: '在服务器上找不到此专辑。',
|
||||
artistUnavailable: '在服务器上找不到此艺术家。',
|
||||
composerUnavailable: '在服务器上找不到此作曲家。',
|
||||
openedTrack: '正在播放分享的歌曲。',
|
||||
openedAlbum: '正在打开分享的专辑。',
|
||||
openedArtist: '正在打开分享的艺术家。',
|
||||
openedComposer: '正在打开分享的作曲家。',
|
||||
openedQueue_one: '正在播放分享队列中的 {{count}} 首曲目。',
|
||||
openedQueue_other: '正在播放分享队列中的 {{count}} 首曲目。',
|
||||
openedQueuePartial: '正在播放链接中的 {{played}} / {{total}} 首曲目({{skipped}} 首在此服务器上未找到)。',
|
||||
@@ -427,6 +430,27 @@ export const zhTranslation = {
|
||||
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: '服务器名称(可选)',
|
||||
|
||||
Reference in New Issue
Block a user