i18n: add Settings, Storage, and Blacklist Manager translations

- MusicBrainz integration labels
- Storage section summary
- Complete BlacklistManagerView translations (title, description,
  search, empty states, confirm modal)
This commit is contained in:
vicrodh committed 2026-02-02 16:38:02 -06:00
1 parent a63bc1cbcd
commit 1d2a9f6636
4 files changed
+74 -25

No files matched your search

@@ -2,6 +2,7 @@
import { onMount } from 'svelte';
import { ArrowLeft, Search, X, Trash2, Ban, ToggleLeft, ToggleRight, AlertCircle } from 'lucide-svelte';
import ViewTransition from '../ViewTransition.svelte';
import { t } from '$lib/i18n';
import { showToast } from '$lib/stores/toastStore';
import {
subscribe,
@@ -108,17 +109,17 @@
<div class="header">
<button class="back-btn" onclick={onBack}>
<ArrowLeft size={16} />
<span>Back</span>
<span>{$t('actions.back')}</span>
</button>
<div class="title-section">
<Ban size={24} class="title-icon" />
<h1>Artist Blacklist</h1>
<h1>{$t('settings.blacklist.title')}</h1>
</div>
</div>
<!-- Description -->
<p class="description">
Blacklisted artists are hidden from search results, radio, suggestions, and similar artists.
{$t('settings.blacklist.description')}
</p>
<!-- Controls -->
@@ -131,10 +132,10 @@
>
{#if enabled}
<ToggleRight size={20} />
<span>Enabled</span>
<span>{$t('settings.blacklist.enabled')}</span>
{:else}
<ToggleLeft size={20} />
<span>Disabled</span>
<span>{$t('settings.blacklist.disabled')}</span>
{/if}
</button>
@@ -143,7 +144,7 @@
<Search size={16} class="search-icon" />
<input
type="text"
placeholder="Search blacklisted artists..."
placeholder={$t('settings.blacklist.searchPlaceholder')}
bind:value={searchQuery}
class="search-input"
/>
@@ -161,18 +162,18 @@
onclick={() => confirmClearOpen = true}
>
<Trash2 size={16} />
<span>Clear All</span>
<span>{$t('settings.blacklist.clearAll')}</span>
</button>
{/if}
<span class="count">{getCount()} artists</span>
<span class="count">{$t('settings.blacklist.artistCount', { values: { count: getCount() } })}</span>
</div>
<!-- Disabled Warning -->
{#if !enabled}
<div class="warning-banner">
<AlertCircle size={16} />
<span>Blacklist is currently disabled. Artists below will appear in results.</span>
<span>{$t('settings.blacklist.disabledWarning')}</span>
</div>
{/if}
@@ -180,18 +181,18 @@
{#if loading}
<div class="loading">
<div class="spinner"></div>
<p>Loading blacklist...</p>
<p>{$t('settings.blacklist.loadingBlacklist')}</p>
</div>
{:else if artists.length === 0}
<div class="empty">
<Ban size={48} class="empty-icon" />
<p>No blacklisted artists</p>
<span class="empty-hint">To blacklist an artist, go to their page and click the ban icon.</span>
<p>{$t('settings.blacklist.noArtists')}</p>
<span class="empty-hint">{$t('settings.blacklist.noArtistsHint')}</span>
</div>
{:else if filteredArtists.length === 0}
<div class="empty">
<Search size={48} class="empty-icon" />
<p>No results for "{searchQuery}"</p>
<p>{$t('settings.blacklist.noResults', { values: { query: searchQuery } })}</p>
</div>
{:else}
<div class="list">
@@ -209,7 +210,7 @@
</div>
<div class="artist-details">
<span class="artist-name">{artist.artist_name}</span>
<span class="artist-meta">Added {formatDate(artist.added_at)}</span>
<span class="artist-meta">{$t('settings.blacklist.addedOn', { values: { date: formatDate(artist.added_at) } })}</span>
{#if artist.notes}
<span class="artist-notes">{artist.notes}</span>
{/if}
@@ -218,7 +219,7 @@
<button
class="remove-btn"
onclick={() => handleRemove(artist.artist_id)}
title="Remove from blacklist"
title={$t('settings.blacklist.remove')}
>
<X size={18} />
</button>
@@ -244,16 +245,16 @@
aria-modal="true"
onclick={(e) => e.stopPropagation()}
>
<h2 class="modal-title">Clear Blacklist?</h2>
<h2 class="modal-title">{$t('settings.blacklist.confirmClearTitle')}</h2>
<p class="modal-text">
This will remove all {artists.length} artists from your blacklist. This action cannot be undone.
{$t('settings.blacklist.confirmClearText', { values: { count: artists.length } })}
</p>
<div class="modal-actions">
<button class="modal-btn cancel" onclick={() => confirmClearOpen = false}>
Cancel
{$t('actions.cancel')}
</button>
<button class="modal-btn danger" onclick={handleClearAll}>
Clear All
{$t('settings.blacklist.clearAll')}
</button>
</div>
</div>
+4 -4
View File
@@ -2582,9 +2582,9 @@
<!-- MusicBrainz Integration -->
<div class="setting-row last">
<div class="setting-info">
<span class="setting-label">MusicBrainz</span>
<span class="setting-label">{$t('settings.integrations.musicbrainz')}</span>
<small class="setting-note">
Enable artist relationships and enhanced metadata from MusicBrainz.
{$t('settings.integrations.musicbrainzDesc')}
</small>
</div>
<Toggle enabled={musicbrainzEnabled} onchange={handleMusicBrainzChange} />
@@ -2674,7 +2674,7 @@
<section class="section collapsible-section" bind:this={storageSection}>
<button class="section-title-btn" onclick={() => storageCollapsed = !storageCollapsed}>
<h3 class="section-title">{$t('settings.storage.title')}</h3>
<span class="section-summary">Queue, lyrics, artwork, and metadata caches</span>
<span class="section-summary">{$t('settings.storage.sectionSummary')}</span>
{#if storageCollapsed}
<ChevronDown size={16} />
{:else}
@@ -2734,7 +2734,7 @@
</div>
<div class="setting-row">
<div class="setting-info">
<span class="setting-label">MusicBrainz Cache</span>
<span class="setting-label">{$t('settings.integrations.musicbrainzCache')}</span>
<small class="setting-note">
{#if musicBrainzCacheStats}
{musicBrainzCacheStats.artists} artists, {musicBrainzCacheStats.relations} relations, {musicBrainzCacheStats.recordings} recordings
+25 -1
View File
@@ -480,10 +480,15 @@
"connect": "Connect",
"disconnect": "Disconnect",
"scrobbling": "Scrobbling",
"configureApi": "Configure API"
"configureApi": "Configure API",
"musicbrainz": "MusicBrainz",
"musicbrainzDesc": "Enable artist relationships and enhanced metadata from MusicBrainz.",
"musicbrainzCache": "MusicBrainz Cache",
"listenbrainz": "ListenBrainz"
},
"storage": {
"title": "Storage",
"sectionSummary": "Queue, lyrics, artwork, and metadata caches",
"queueCacheNote": "Queue list storage. Clear if you have playback issues. (This is not the Offline Library cache.)",
"queueCacheStats": "{tracks} tracks using {used} / {max}",
"cachedTracks": "Cached Queue Tracks",
@@ -491,6 +496,25 @@
"clearCache": "Clear queue cache",
"clearing": "Clearing..."
},
"blacklist": {
"title": "Artist Blacklist",
"description": "Blacklisted artists are hidden from search results, radio, suggestions, and similar artists.",
"enabled": "Enabled",
"disabled": "Disabled",
"clearAll": "Clear All",
"noArtists": "No blacklisted artists",
"noArtistsHint": "To blacklist an artist, go to their page and click the ban icon.",
"artistCount": "{count} artists",
"loadingBlacklist": "Loading blacklist...",
"confirmClear": "Remove all artists from blacklist?",
"disabledWarning": "Blacklist is currently disabled. Artists below will appear in results.",
"searchPlaceholder": "Search blacklisted artists...",
"noResults": "No results for \"{query}\"",
"addedOn": "Added {date}",
"remove": "Remove from blacklist",
"confirmClearTitle": "Clear Blacklist?",
"confirmClearText": "This will remove all {count} artists from your blacklist. This action cannot be undone."
},
"offlineLibrary": {
"title": "Offline Library",
"disclaimer": "The offline library is a temporary playback cache for offline listening while you have a valid Qobuz subscription. You do not receive a license to keep or redistribute the content. If your subscription becomes invalid, QBZ will remove all cached content after 3 days.",
+25 -1
View File
@@ -480,10 +480,15 @@
"connect": "Conectar",
"disconnect": "Desconectar",
"scrobbling": "Scrobbling",
"configureApi": "Configurar API"
"configureApi": "Configurar API",
"musicbrainz": "MusicBrainz",
"musicbrainzDesc": "Habilita relaciones de artistas y metadatos mejorados de MusicBrainz.",
"musicbrainzCache": "Caché de MusicBrainz",
"listenbrainz": "ListenBrainz"
},
"storage": {
"title": "Almacenamiento",
"sectionSummary": "Cachés de cola, letras, carátulas y metadatos",
"queueCacheNote": "Almacenamiento de la cola. Límpialo si tienes problemas de reproducción. (No es la Biblioteca Offline.)",
"queueCacheStats": "{tracks} pistas usando {used} / {max}",
"cachedTracks": "Pistas de la cola en caché",
@@ -491,6 +496,25 @@
"clearCache": "Limpiar caché de la cola",
"clearing": "Limpiando..."
},
"blacklist": {
"title": "Lista Negra de Artistas",
"description": "Los artistas en la lista negra están ocultos en resultados de búsqueda, radio, sugerencias y artistas similares.",
"enabled": "Activado",
"disabled": "Desactivado",
"clearAll": "Limpiar Todo",
"noArtists": "No hay artistas en la lista negra",
"noArtistsHint": "Para añadir un artista a la lista negra, ve a su página y haz clic en el ícono de prohibición.",
"artistCount": "{count} artistas",
"loadingBlacklist": "Cargando lista negra...",
"confirmClear": "¿Eliminar todos los artistas de la lista negra?",
"disabledWarning": "La lista negra está desactivada. Los artistas de abajo aparecerán en los resultados.",
"searchPlaceholder": "Buscar artistas en la lista negra...",
"noResults": "Sin resultados para \"{query}\"",
"addedOn": "Añadido {date}",
"remove": "Eliminar de la lista negra",
"confirmClearTitle": "¿Limpiar Lista Negra?",
"confirmClearText": "Esto eliminará los {count} artistas de tu lista negra. Esta acción no se puede deshacer."
},
"offlineLibrary": {
"title": "Biblioteca Offline",
"disclaimer": "La biblioteca offline es un caché temporal de reproducción para escucha sin conexión mientras tengas una suscripción válida de Qobuz. No recibes una licencia para conservar o redistribuir el contenido. Si tu suscripción deja de ser válida, QBZ eliminará todo el contenido en caché después de 3 días.",