Files
psysonic/src/i18n.ts
T
Psychotoxical d3ffa30bf5 feat: statistics upgrade, playlists redesign, artist cards, and UX improvements (v1.4.0)
- Statistics page: library stat cards, recently played, most played, highest rated, genre chart
- Playlists page: list layout with sort (Name/Tracks/Duration) and filter input
- Favorites songs: full tracklist layout with artist column, context menu, enqueue-all button
- AlbumDetail: extracted AlbumHeader and AlbumTrackList components
- Artist cards: square cover, same sizing as album cards (clamp 140-180px)
- Random Albums: removed renderKey remount, added loadingRef guard, fixed manual refresh race
- Context menu: "Go to Album" option for song and queue-item types
- Queue panel meta box: artist → artist page, album → album page, removed year
- Random Mix: hover persistence via .context-active class while context menu is open
- i18n: "Warteschlange" consistently used for queue in German

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 17:36:58 +01:00

860 lines
37 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
// English Translations
const enTranslation = {
sidebar: {
library: 'Library',
mainstage: 'Mainstage',
newReleases: 'New Releases',
allAlbums: 'All Albums',
randomAlbums: 'Random Albums',
artists: 'Artists',
playlists: 'Playlists',
randomMix: 'Random Mix',
favorites: 'Favorites',
system: 'System',
statistics: 'Statistics',
settings: 'Settings',
help: 'Help',
expand: 'Expand Sidebar',
collapse: 'Collapse Sidebar',
updateAvailable: 'Update available',
updateReady: '{{version}} is ready',
updateLink: 'Go to release →'
},
home: {
starred: 'Personal Favorites',
recent: 'Recently Added',
mostPlayed: 'Most Played',
discover: 'Discover',
loadMore: 'Load More',
discoverMore: 'Discover More'
},
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',
title: 'Search',
resultsFor: 'Results for "{{query}}"',
album: 'Album',
},
nowPlaying: {
tooltip: 'Who is listening?',
title: 'Who is listening?',
loading: 'Loading…',
nobody: 'Nobody is currently listening.',
minutesAgo: '{{n}}m ago',
},
contextMenu: {
playNow: 'Play Now',
playNext: 'Play Next',
addToQueue: 'Add to Queue',
enqueueAlbum: 'Enqueue Album',
startRadio: 'Start Radio',
favorite: 'Favorite',
favoriteArtist: 'Favorite Artist',
favoriteAlbum: 'Favorite Album',
removeFromQueue: 'Remove from Queue',
openAlbum: 'Open Album',
goToArtist: 'Go to Artist',
download: 'Download (ZIP)',
},
albumDetail: {
back: 'Back',
playAll: 'Play All',
enqueue: 'Enqueue',
enqueueTooltip: 'Add entire album to queue',
artistBio: 'Artist Bio',
download: 'Download (ZIP)',
downloading: 'Loading…',
downloadHint: 'FLAC/WAV albums are zipped server-side first — large albums may take a moment before the download starts.',
downloadHintShort: 'Server zips first — may take a moment depending on file size',
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',
trackArtist: 'Artist',
trackFormat: 'Format',
trackFavorite: 'Favorite',
trackRating: 'Rating',
trackDuration: 'Duration',
trackTotal: 'Total',
notFound: 'Album not found.',
bioModal: 'Artist Biography',
bioClose: 'Close',
ratingLabel: 'Rating',
},
artistDetail: {
back: 'Back',
albums: 'Albums',
album: 'Album',
playAll: 'Play All',
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',
},
favorites: {
title: 'Favorites',
empty: "You haven't saved any favorites yet.",
artists: 'Artists',
albums: 'Albums',
songs: 'Songs',
enqueueAll: 'Add all to queue',
},
randomAlbums: {
title: 'Random Albums',
refresh: 'Refresh',
},
randomMix: {
title: 'Random Mix',
remix: 'Remix',
remixTooltip: 'Load new random 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',
excludeAudiobooks: 'Exclude audiobooks & radio plays',
excludeAudiobooksDesc: 'Matches keywords against genre, title, and album — e.g. Hörbuch, Audiobook, Spoken Word, …',
genreBlocked: 'Keyword blocked',
genreAddedToBlacklist: 'Added to filter list',
genreAlreadyBlocked: 'Already blocked',
blacklistToggle: 'Keyword Filter',
genreMixTitle: 'Genre Mix',
genreMixDesc: 'Select a genre to get a curated random mix',
genreMixLoadMore: 'Load 10 more',
genreMixNoGenres: 'No genres found on server.',
filterPanelTitle: 'Filters',
genreClickHint: 'Click a genre tag to add it\nas a filter keyword.\nMatches genre, title & album.',
},
playlists: {
title: 'Playlists',
loading: 'Loading playlists…',
empty: 'No playlists found.\nUse the queue to create playlists.',
play: 'Play',
deleteTooltip: 'Delete',
confirmDelete: 'Really delete playlist "{{name}}"?',
minutes: 'min.',
track_one: '{{count}} Track',
track_other: '{{count}} Tracks',
filterPlaceholder: 'Filter playlists…',
colName: 'Name',
colTracks: 'Tracks',
colDuration: 'Duration',
noResults: 'No playlists match your filter.',
},
albums: {
title: 'All Albums',
sortByName: 'AZ (Album)',
sortByArtist: 'AZ (Artist)',
sortNewest: 'Newest first',
sortRandom: 'Random',
},
artists: {
title: 'Artists',
search: 'Search…',
all: 'All',
gridView: 'Grid view',
listView: 'List view',
loadMore: 'Load more',
notFound: 'No artists found.',
albumCount_one: '{{count}} Album',
albumCount_other: '{{count}} Albums',
},
login: {
subtitle: 'Your Navidrome Desktop Player',
serverName: 'Server Name (optional)',
serverNamePlaceholder: 'My Navidrome',
serverUrl: 'Server URL',
serverUrlPlaceholder: '192.168.1.100:4533 or 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',
},
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',
save: 'Save',
delete: 'Delete',
use: 'Use',
add: 'Add',
active: 'Active',
},
settings: {
title: 'Settings',
language: 'Language',
languageEn: 'English',
languageDe: 'German',
theme: 'Theme',
appearance: 'Appearance',
servers: 'Servers',
serverName: 'Server Name',
serverUrl: 'Server URL',
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…',
connected: 'Connected',
failed: 'Failed',
lfmTitle: 'Last.fm Scrobbling',
lfmDesc1: 'Psysonic supports server-side scrobbling directly via Navidrome. To link Last.fm, please log in once via the',
lfmDesc1NavidromeWebplayer: 'Navidrome Webplayer',
lfmDesc1b: 'in your browser, go to your profile, and connect your Last.fm account.',
lfmDesc2: 'Once that is done, Psysonic automatically forwards your currently playing songs to Navidrome, and they will appear on Last.fm.',
scrobbleEnabled: 'Scrobbling enabled',
scrobbleDesc: 'Send songs to Last.fm after 50% playtime',
behavior: 'App Behavior',
trayTitle: 'Minimize to Tray',
trayDesc: 'Minimize app to the system tray on close (X)',
cacheTitle: 'Max. Cache Size',
cacheDesc: 'For preloaded tracks',
downloadsTitle: 'Download Folder',
downloadsDefault: 'Default Downloads Folder',
pickFolder: 'Select',
pickFolderTitle: 'Select Download Folder',
logout: 'Logout',
aboutTitle: 'About Psysonic',
aboutDesc: 'A desktop music player for Subsonic-compatible servers (Navidrome, Gonic, and others). Streams your self-hosted music library with a clean, modern interface styled after the Catppuccin colour palette.',
aboutFeatures: 'Multi-server support · Scrobbling · Fullscreen player · Album downloads · Image caching · Catppuccin themes',
aboutLicense: 'License',
aboutLicenseText: 'MIT — free to use, modify, and distribute.',
aboutRepo: 'Source Code on GitHub',
aboutVersion: 'Version',
aboutBuiltWith: 'Built with Tauri · React · TypeScript · Rust/rodio',
aboutAiCredit: 'Developed with the support of Claude Code by Anthropic',
randomMixTitle: 'Random Mix',
randomMixBlacklistTitle: 'Custom Filter Keywords',
randomMixBlacklistDesc: 'Songs are excluded when any keyword matches their genre, title, or album (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)',
},
help: {
title: 'Help',
s1: 'Getting Started',
q1: 'Which servers are compatible?',
a1: 'Psysonic works with any Subsonic-compatible server: Navidrome, Gonic, Subsonic, Airsonic, and others. Navidrome is the recommended choice.',
q2: 'How do I connect to my server?',
a2: 'Open Settings and click "Add Server". Enter the server URL (e.g. 192.168.1.100:4533), your username, and password. Psysonic tests the connection before saving — nothing is stored if the connection fails.',
q3: 'Can I use multiple servers?',
a3: 'Yes. You can add as many servers as you like in Settings and switch between them at any time. Only one server is active at a time.',
s2: 'Playback',
q4: 'How do I play music?',
a4: 'Double-click any track to play it. On album and artist pages, use "Play All" to start the whole album. You can also drag tracks into the queue panel.',
q5: 'What keyboard shortcuts are available?',
a5: 'Space = Play / Pause · Escape = Close fullscreen player. Media keys (Play/Pause, Next, Previous) work on macOS and Windows. On Linux, use the player bar buttons.',
q6: 'What is the queue?',
a6: 'The queue shows all upcoming tracks. Open it with the panel icon in the top-right header (next to the Now Playing indicator). You can reorder tracks by dragging, shuffle with the shuffle button, and save the queue as a playlist.',
q7: 'How do I open the fullscreen player?',
a7: 'Click the album art thumbnail in the player bar at the bottom, or the expand icon next to it. Press Escape to close it again.',
q8: 'How does repeat work?',
a8: 'Click the repeat button in the player bar to cycle through: Off → Repeat All → Repeat One.',
s3: 'Library',
q9: 'How do I download an album?',
a9: 'Open an album\'s detail page and click "Download (ZIP)". The server zips the album first — this may take a moment for large albums or lossless files (FLAC / WAV). A progress bar shows the download status.',
q10: 'How do I star / favorite tracks and albums?',
a10: 'Click the star icon on any track row or on the album header. Starred items appear in the Favorites section in the sidebar.',
q11: 'What is the hero carousel on the home page?',
a11: 'The banner at the top of the home page randomly picks albums from your library and rotates through them every 10 seconds. Click the dots to jump to a specific one, or click the banner to open the album.',
s4: 'Settings',
q12: 'How do I change the theme?',
a12: 'Settings → Theme. Choose between Catppuccin Mocha (dark) and Catppuccin Latte (light).',
q13: 'How do I change the language?',
a13: 'Settings → Language. English and German are currently supported.',
q14: 'What does "Minimize to Tray" do?',
a14: 'When enabled, clicking the × button hides Psysonic to the system tray instead of closing it. Music keeps playing. Right-click the tray icon for controls or to quit.',
q15: 'How do I set a download folder?',
a15: 'Settings → App Behavior → Download Folder. Pick any folder — downloaded albums are saved there as ZIP files. Without a custom folder, your browser\'s default downloads location is used.',
s5: 'Scrobbling',
q16: 'How does scrobbling work?',
a16: 'Psysonic uses your Navidrome server\'s built-in Last.fm integration. First, connect your Last.fm account in Navidrome\'s web interface. Then enable scrobbling in Psysonic\'s Settings.',
q17: 'When is a scrobble sent?',
a17: 'A scrobble is submitted after you\'ve listened to 50% of a track.',
q22: 'What is the waveform in the player bar?',
a22: 'The waveform seekbar replaces the classic progress slider. Click anywhere on it to jump to that position, or drag to scrub. The played portion glows with a blue-to-mauve gradient, the buffered range appears slightly brighter, and the unplayed portion is faded.',
q23: 'How do I use the MilkDrop visualizer?',
a23: 'Open the fullscreen player (click the album art in the player bar), then click the waveform icon in the top-right corner. The visualizer starts with a random MilkDrop preset. Use the shuffle button next to it to cycle through hundreds of presets.',
q24: 'Can I shuffle the queue?',
a24: 'Yes. Open the queue panel and click the shuffle icon in the queue header. The currently playing track stays at position 1 — all remaining tracks are randomly reordered.',
q25: 'Do Last.fm and Wikipedia links on artist pages open in a browser?',
a25: 'No — they open in a dedicated in-app window so you never leave Psysonic. The window shows the full website and can be closed independently.',
s7: 'Random Mix',
q26: 'What is Random Mix?',
a26: 'Random Mix builds a playlist of random tracks from your entire library. Open it via "Random Mix" in the sidebar and click "New Mix". You can adjust the track count before generating.',
q27: 'What is the Keyword Filter?',
a27: 'The Keyword Filter excludes tracks whose genre, title, or album name contains specific words. Audiobooks are filtered automatically. Add custom keywords in Settings → Random Mix, or click any genre tag in the track list to add it instantly.',
q28: 'What is the Super Genre Mix?',
a28: 'The Super Genre Mix groups your library into broad categories (Rock, Metal, Electronic, Jazz, Classical, etc.) and builds a focused mix from that style. Select a category chip below the track list. Results appear progressively as each sub-genre is fetched.',
s6: 'Troubleshooting',
q18: 'Cover art and artist images load slowly.',
a18: 'Images are fetched from your server\'s disk on first load and then cached locally for 30 days. If your server\'s storage is slow, the first visit to a page may take a moment. Subsequent visits will be instant.',
q19: 'The connection test fails.',
a19: 'Check the URL including the port (e.g. http://192.168.1.100:4533). Make sure no firewall blocks the connection. Try http:// instead of https:// on a local network. Also verify that your username and password are correct.',
q20: 'No audio on Linux (AppImage).',
a20: 'The AppImage bundles GStreamer. If audio still doesn\'t work, try installing system GStreamer packages: gstreamer1.0-plugins-good, gstreamer1.0-plugins-bad, gstreamer1.0-libav.',
q21: 'The app crashes or shows a black screen on old Linux hardware.',
a21: 'This is usually caused by GPU / EGL driver issues in WebKitGTK. The official AppImage already patches the launcher to disable GPU compositing. If you build from source, launch with: WEBKIT_DISABLE_COMPOSITING_MODE=1 WEBKIT_DISABLE_DMABUF_RENDERER=1 ./psysonic',
},
queue: {
title: 'Queue',
savePlaylist: 'Save Playlist',
playlistName: 'Playlist Name',
cancel: 'Cancel',
save: 'Save',
loadPlaylist: 'Load Playlist',
loading: 'Loading…',
noPlaylists: 'No playlists found.',
load: 'Load',
delete: 'Delete',
deleteConfirm: 'Delete playlist "{{name}}"?',
clear: 'Clear',
shuffle: 'Shuffle queue',
hide: 'Hide',
close: 'Close',
nextTracks: 'Next Tracks',
emptyQueue: 'The 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',
statAlbums: 'Albums',
statSongs: 'Songs',
statGenres: 'Genres',
genreSongs: '{{count}} Songs',
genreAlbums: '{{count}} Albums',
recentlyAdded: 'Recently Added',
decadeDistribution: 'Albums by Decade',
decadeAlbums_one: '{{count}} Album',
decadeAlbums_other: '{{count}} Albums',
decadeUnknown: 'Unknown',
},
player: {
regionLabel: 'Music Player',
openFullscreen: 'Open Fullscreen Player',
fullscreen: 'Fullscreen Player',
closeFullscreen: 'Close Fullscreen',
visualizer: 'Visualizer',
nextPreset: 'Next preset',
closeTooltip: 'Close (Esc)',
noTitle: 'No Title',
stop: 'Stop',
prev: 'Previous Track',
play: 'Play',
pause: 'Pause',
next: 'Next Track',
repeat: 'Repeat',
repeatOff: 'Off',
repeatAll: 'All',
repeatOne: 'One',
progress: 'Song Progress',
volume: 'Volume',
toggleQueue: 'Toggle Queue'
}
};
// German Translations
const deTranslation = {
sidebar: {
library: 'Bibliothek',
mainstage: 'Mainstage',
newReleases: 'Neueste',
allAlbums: 'Alle Alben',
randomAlbums: 'Zufallsalben',
artists: 'Künstler',
playlists: 'Playlists',
randomMix: 'Zufallsmix',
favorites: 'Favoriten',
system: 'System',
statistics: 'Statistiken',
settings: 'Einstellungen',
help: 'Hilfe',
expand: 'Sidebar einblenden',
collapse: 'Sidebar ausblenden',
updateAvailable: 'Update verfügbar',
updateReady: '{{version}} ist bereit',
updateLink: 'Zum Release →'
},
home: {
starred: 'Persönliche Favoriten',
recent: 'Zuletzt hinzugefügt',
mostPlayed: 'Meistgehört',
discover: 'Entdecken',
loadMore: 'Mehr laden',
discoverMore: 'Mehr entdecken'
},
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',
title: 'Suche',
resultsFor: 'Ergebnisse für „{{query}}"',
album: 'Album',
},
nowPlaying: {
tooltip: 'Wer hört was?',
title: 'Wer hört was?',
loading: 'Lädt…',
nobody: 'Gerade hört niemand Musik.',
minutesAgo: 'vor {{n}}m',
},
contextMenu: {
playNow: 'Direkt abspielen',
playNext: 'Als Nächstes abspielen',
addToQueue: 'Zur Warteschlange hinzufügen',
enqueueAlbum: 'Ganzes Album einreihen',
startRadio: 'Radio starten',
favorite: 'Favorisieren',
favoriteArtist: 'Künstler favorisieren',
favoriteAlbum: 'Album favorisieren',
removeFromQueue: 'Diesen Song entfernen',
openAlbum: 'Album öffnen',
goToArtist: 'Zum Künstler',
download: 'Herunterladen (ZIP)',
},
albumDetail: {
back: 'Zurück',
playAll: 'Alle abspielen',
enqueue: 'Einreihen',
enqueueTooltip: 'Ganzes Album zur Warteschlange hinzufügen',
artistBio: 'Künstler-Bio',
download: 'Download (ZIP)',
downloading: 'Lade…',
downloadHint: 'FLAC/WAV-Alben werden serverseitig zuerst gezippt — bei großen Alben kann es einen Moment dauern, bevor der Download startet.',
downloadHintShort: 'Server zippt zuerst — je nach Dateigröße kann es etwas dauern bevor der Download startet',
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',
trackArtist: 'Interpret',
trackFormat: 'Format',
trackFavorite: 'Favorit',
trackRating: 'Bewertung',
trackDuration: 'Dauer',
trackTotal: 'Gesamt',
notFound: 'Album nicht gefunden.',
bioModal: 'Künstler-Biografie',
bioClose: 'Schließen',
ratingLabel: 'Bewertung',
},
artistDetail: {
back: 'Zurück',
albums: 'Alben',
album: 'Album',
playAll: 'Alle abspielen',
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',
},
favorites: {
title: 'Favoriten',
empty: 'Du hast noch keine Favoriten gespeichert.',
artists: 'Künstler',
albums: 'Alben',
songs: 'Songs',
enqueueAll: 'Alle in die Warteschlange',
},
randomAlbums: {
title: 'Zufallsalben',
refresh: 'Neu laden',
},
randomMix: {
title: 'Zufallsmix',
remix: 'Neu mixen',
remixTooltip: 'Neue 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',
excludeAudiobooks: 'Hörbücher & Hörspiele ausschließen',
excludeAudiobooksDesc: 'Prüft Keywords gegen Genre, Titel und Album — z. B. Hörbuch, Audiobook, Spoken Word, …',
genreBlocked: 'Keyword gesperrt',
genreAddedToBlacklist: 'Zur Filterliste hinzugefügt',
genreAlreadyBlocked: 'Bereits gesperrt',
blacklistToggle: 'Keyword-Filter',
genreMixTitle: 'Genre-Mix',
genreMixDesc: 'Genre auswählen für einen passenden Zufallsmix',
genreMixLoadMore: '10 weitere laden',
genreMixNoGenres: 'Keine Genres auf dem Server gefunden.',
filterPanelTitle: 'Filter',
genreClickHint: 'Genre-Tag anklicken,\num es als Filter-Keyword hinzuzufügen.\nPrüft Genre, Titel & Album.',
},
playlists: {
title: 'Playlists',
loading: 'Lade Playlists…',
empty: 'Keine Playlists gefunden.\nNutze die Warteschlange, um Playlists zu erstellen.',
play: 'Abspielen',
deleteTooltip: 'Löschen',
confirmDelete: 'Playlist "{{name}}" wirklich löschen?',
minutes: 'Min.',
track_one: '{{count}} Track',
track_other: '{{count}} Tracks',
filterPlaceholder: 'Playlists filtern…',
colName: 'Name',
colTracks: 'Tracks',
colDuration: 'Dauer',
noResults: 'Keine Playlists entsprechen dem Filter.',
},
albums: {
title: 'Alle Alben',
sortByName: 'AZ (Album)',
sortByArtist: 'AZ (Künstler)',
sortNewest: 'Neueste zuerst',
sortRandom: 'Zufällig',
},
artists: {
title: 'Künstler',
search: 'Suchen…',
all: 'Alle',
gridView: 'Gitteransicht',
listView: 'Listenansicht',
loadMore: 'Mehr laden',
notFound: 'Keine Künstler gefunden.',
albumCount_one: '{{count}} Album',
albumCount_other: '{{count}} Alben',
},
login: {
subtitle: 'Dein Navidrome Desktop Player',
serverName: 'Server-Name (optional)',
serverNamePlaceholder: 'Mein Navidrome',
serverUrl: 'Server-URL',
serverUrlPlaceholder: '192.168.1.100:4533 oder 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',
},
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',
save: 'Speichern',
delete: 'Löschen',
use: 'Verwenden',
add: 'Hinzufügen',
active: 'Aktiv',
},
settings: {
title: 'Einstellungen',
language: 'Sprache',
languageEn: 'Englisch',
languageDe: 'Deutsch',
theme: 'Design',
appearance: 'Darstellung',
servers: 'Server',
serverName: 'Server-Name',
serverUrl: 'Server-URL',
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…',
connected: 'Verbunden',
failed: 'Fehlgeschlagen',
lfmTitle: 'Last.fm Scrobbling',
lfmDesc1: 'Psysonic unterstützt serverseitiges Scrobbling direkt über Navidrome. Um Last.fm zu verknüpfen, logge dich bitte einmalig über den',
lfmDesc1NavidromeWebplayer: 'Navidrome Webplayer',
lfmDesc1b: 'im Browser ein, gehe auf dein Profil und verbinde deinen Last.fm Account.',
lfmDesc2: 'Sobald das erledigt ist, leitet Psysonic deine aktuell gespielten Songs automatisch an Navidrome weiter, und diese erscheinen auf Last.fm.',
scrobbleEnabled: 'Scrobbling aktiviert',
scrobbleDesc: 'Songs nach 50% Laufzeit an Last.fm senden',
behavior: 'App-Verhalten',
trayTitle: 'In Tray minimieren',
trayDesc: 'App beim Schließen (X) in den System-Tray minimieren',
cacheTitle: 'Max. Cache-Größe',
cacheDesc: 'Für vorgeladene Tracks',
downloadsTitle: 'Download-Ordner',
downloadsDefault: 'Standard-Downloads-Ordner',
pickFolder: 'Auswählen',
pickFolderTitle: 'Download-Ordner auswählen',
logout: 'Abmelden',
aboutTitle: 'Über Psysonic',
aboutDesc: 'Ein Desktop-Musikplayer für Subsonic-kompatible Server (Navidrome, Gonic u. a.). Streame deine selbst gehostete Musikbibliothek mit einer modernen Oberfläche im Catppuccin-Design.',
aboutFeatures: 'Multi-Server · Scrobbling · Vollbild-Player · Album-Downloads · Bild-Cache · Catppuccin-Themes',
aboutLicense: 'Lizenz',
aboutLicenseText: 'MIT — kostenlos nutzbar, veränderbar und weiterzugeben.',
aboutRepo: 'Quellcode auf GitHub',
aboutVersion: 'Version',
aboutBuiltWith: 'Gebaut mit Tauri · React · TypeScript · Rust/rodio',
aboutAiCredit: 'Mit freundlicher Unterstützung von Claude Code by Anthropic',
randomMixTitle: 'Zufallsmix',
randomMixBlacklistTitle: 'Eigene Filter-Keywords',
randomMixBlacklistDesc: 'Songs werden ausgeschlossen, wenn ein Keyword auf Genre, Titel oder Album 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)',
},
help: {
title: 'Hilfe',
s1: 'Erste Schritte',
q1: 'Welche Server sind kompatibel?',
a1: 'Psysonic funktioniert mit jedem Subsonic-kompatiblen Server: Navidrome, Gonic, Subsonic, Airsonic und anderen. Navidrome ist die empfohlene Wahl.',
q2: 'Wie verbinde ich mich mit meinem Server?',
a2: 'Öffne die Einstellungen und klicke auf "Server hinzufügen". Gib die Server-URL (z. B. 192.168.1.100:4533), Benutzername und Passwort ein. Psysonic testet die Verbindung vor dem Speichern — bei Fehler wird nichts gespeichert.',
q3: 'Kann ich mehrere Server verwenden?',
a3: 'Ja. Du kannst beliebig viele Server in den Einstellungen hinzufügen und jederzeit zwischen ihnen wechseln. Immer ist nur ein Server aktiv.',
s2: 'Wiedergabe',
q4: 'Wie spiele ich Musik ab?',
a4: 'Doppelklick auf einen Track startet die Wiedergabe. Auf Album- und Künstlerseiten gibt es "Alle abspielen". Tracks lassen sich auch per Drag & Drop in die Warteschlange ziehen.',
q5: 'Welche Tastenkürzel gibt es?',
a5: 'Leertaste = Play / Pause · Escape = Vollbild schließen. Medientasten (Play/Pause, Weiter, Zurück) funktionieren unter macOS und Windows. Unter Linux bitte die Buttons in der Playerleiste nutzen.',
q6: 'Was ist die Warteschlange?',
a6: 'Die Warteschlange zeigt alle kommenden Tracks. Öffnen mit dem Panel-Icon oben rechts im Header (neben dem Now-Playing-Indikator). Tracks per Drag & Drop umsortieren, mit dem Shuffle-Button mischen oder als Playlist speichern.',
q7: 'Wie öffne ich den Vollbild-Player?',
a7: 'Klick auf das Album-Cover unten in der Playerleiste oder auf das Expand-Icon daneben. Mit Escape wieder schließen.',
q8: 'Wie funktioniert die Wiederholfunktion?',
a8: 'Klick auf den Wiederhol-Button in der Playerleiste, um zwischen den Modi zu wechseln: Aus → Alles wiederholen → Einen wiederholen.',
s3: 'Bibliothek',
q9: 'Wie lade ich ein Album herunter?',
a9: 'Auf der Album-Detailseite auf "Download (ZIP)" klicken. Der Server zieht das Album zuerst zusammen — bei großen Alben oder verlustfreien Dateien (FLAC / WAV) kann das einen Moment dauern. Ein Fortschrittsbalken zeigt den Status.',
q10: 'Wie markiere ich Tracks und Alben als Favoriten?',
a10: 'Das Stern-Icon auf einem Track oder im Album-Header anklicken. Markierte Einträge erscheinen im Bereich "Favoriten" in der Seitenleiste.',
q11: 'Was ist das Karussell auf der Startseite?',
a11: 'Das Banner oben auf der Startseite wählt zufällige Alben aus der Bibliothek und rotiert alle 10 Sekunden weiter. Mit den Punkten kann man manuell springen, Klick auf das Banner öffnet das Album.',
s4: 'Einstellungen',
q12: 'Wie ändere ich das Theme?',
a12: 'Einstellungen → Theme. Wahl zwischen Catppuccin Mocha (dunkel) und Catppuccin Latte (hell).',
q13: 'Wie ändere ich die Sprache?',
a13: 'Einstellungen → Sprache. Aktuell verfügbar: Englisch und Deutsch.',
q14: 'Was bewirkt "In Tray minimieren"?',
a14: 'Wenn aktiviert, versteckt sich Psysonic beim Klick auf × im System-Tray statt sich zu schließen. Die Musik läuft weiter. Rechtsklick auf das Tray-Icon zeigt Steueroptionen und "Beenden".',
q15: 'Wie lege ich einen Download-Ordner fest?',
a15: 'Einstellungen → App-Verhalten → Download-Ordner. Beliebigen Ordner wählen — heruntergeladene Alben werden dort als ZIP gespeichert. Ohne eigenen Ordner landet alles im Standard-Downloads-Ordner.',
s5: 'Scrobbling',
q16: 'Wie funktioniert Scrobbling?',
a16: 'Psysonic nutzt die eingebaute Last.fm-Integration von Navidrome. Zuerst das Last.fm-Konto im Navidrome-Webinterface verbinden, dann Scrobbling in den Psysonic-Einstellungen aktivieren.',
q17: 'Wann wird ein Scrobble gesendet?',
a17: 'Ein Scrobble wird übermittelt, wenn 50 % eines Tracks gehört wurden.',
q22: 'Was ist die Waveform in der Playerleiste?',
a22: 'Die Waveform-Leiste ersetzt den klassischen Fortschrittsbalken. Klick auf eine beliebige Stelle zum Springen, ziehen zum Scrubben. Der gespielte Teil leuchtet in einem Blau-Mauve-Farbverlauf, der gepufferte Bereich erscheint etwas heller, der ungespielter Teil ist abgeblendet.',
q23: 'Wie benutze ich den MilkDrop-Visualizer?',
a23: 'Vollbild-Player öffnen (Klick auf das Album-Cover in der Playerleiste), dann oben rechts auf das Waveform-Icon klicken. Der Visualizer startet mit einem zufälligen MilkDrop-Preset. Mit dem Shuffle-Button daneben durch Hunderte von Presets wechseln.',
q24: 'Kann ich die Warteschlange mischen?',
a24: 'Ja. Die Warteschlange öffnen und auf das Shuffle-Icon im Header klicken. Der aktuell laufende Track bleibt an Position 1 — alle restlichen Tracks werden zufällig neu geordnet.',
q25: 'Öffnen Last.fm- und Wikipedia-Links auf Künstlerseiten im Browser?',
a25: 'Nein — sie öffnen sich in einem eigenen In-App-Fenster, sodass du Psysonic nie verlassen musst. Das Fenster zeigt die vollständige Website und kann unabhängig geschlossen werden.',
s7: 'Zufallsmix',
q26: 'Was ist der Zufallsmix?',
a26: 'Der Zufallsmix erstellt eine Playlist aus zufälligen Tracks deiner gesamten Bibliothek. Über "Zufallsmix" in der Seitenleiste erreichbar, dann "Neuer Mix" klicken. Die Anzahl der Tracks ist vor der Generierung einstellbar.',
q27: 'Was ist der Keyword-Filter?',
a27: 'Der Keyword-Filter schließt Tracks aus, deren Genre, Titel oder Album bestimmte Wörter enthält. Hörbücher werden automatisch gefiltert. Eigene Keywords in Einstellungen → Zufallsmix hinzufügen oder per Klick auf ein Genre-Tag direkt in der Trackliste.',
q28: 'Was ist der Super-Genre-Mix?',
a28: 'Der Super-Genre-Mix fasst die Bibliothek in übergeordnete Kategorien zusammen (Rock, Metal, Electronic, Jazz, Klassik usw.) und erstellt daraus einen fokussierten Mix. Einen Kategorie-Chip unterhalb der Trackliste auswählen. Ergebnisse erscheinen schrittweise, während die einzelnen Sub-Genres geladen werden.',
s6: 'Problemlösung',
q18: 'Cover und Künstlerbilder laden langsam.',
a18: '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 geht alles sofort.',
q19: 'Der Verbindungstest schlägt fehl.',
a19: 'URL inklusive Port prüfen (z. B. http://192.168.1.100:4533). Sicherstellen, dass keine Firewall die Verbindung blockiert. Im lokalen Netzwerk http:// statt https:// versuchen. Benutzername und Passwort kontrollieren.',
q20: 'Kein Ton unter Linux (AppImage).',
a20: 'Das AppImage bündelt GStreamer. Falls trotzdem kein Ton kommt, diese System-Pakete installieren: gstreamer1.0-plugins-good, gstreamer1.0-plugins-bad, gstreamer1.0-libav.',
q21: 'Die App stürzt ab oder zeigt einen schwarzen Bildschirm auf alter Linux-Hardware.',
a21: 'Das liegt meist an GPU/EGL-Treiberproblemen in WebKitGTK. Das offizielle AppImage deaktiviert GPU-Compositing bereits automatisch. Beim Selbst-Kompilieren: WEBKIT_DISABLE_COMPOSITING_MODE=1 WEBKIT_DISABLE_DMABUF_RENDERER=1 ./psysonic',
},
queue: {
title: 'Warteschlange',
savePlaylist: 'Playlist speichern',
playlistName: 'Name der Playlist',
cancel: 'Abbrechen',
save: 'Speichern',
loadPlaylist: 'Playlist laden',
loading: 'Lade…',
noPlaylists: 'Keine Playlists gefunden.',
load: 'Laden',
delete: 'Löschen',
deleteConfirm: 'Playlist "{{name}}" löschen?',
clear: 'Leeren',
shuffle: 'Warteschlange mischen',
hide: 'Verbergen',
close: 'Schließen',
nextTracks: 'Nächste Titel',
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',
statAlbums: 'Alben',
statSongs: 'Songs',
statGenres: 'Genres',
genreSongs: '{{count}} Songs',
genreAlbums: '{{count}} Alben',
recentlyAdded: 'Neu hinzugefügt',
decadeDistribution: 'Alben nach Jahrzehnt',
decadeAlbums_one: '{{count}} Album',
decadeAlbums_other: '{{count}} Alben',
decadeUnknown: 'Unbekannt',
},
player: {
regionLabel: 'Musikplayer',
openFullscreen: 'Vollbild-Player öffnen',
fullscreen: 'Vollbild-Player',
closeFullscreen: 'Vollbild schließen',
visualizer: 'Visualizer',
nextPreset: 'Nächstes Preset',
closeTooltip: 'Schließen (Esc)',
noTitle: 'Kein Titel',
stop: 'Stop',
prev: 'Vorheriger Titel',
play: 'Play',
pause: 'Pause',
next: 'Nächster Titel',
repeat: 'Wiederholen',
repeatOff: 'Aus',
repeatAll: 'Alle',
repeatOne: 'Einen',
progress: 'Songfortschritt',
volume: 'Lautstärke',
toggleQueue: 'Warteschlange umschalten'
}
};
// Retrieve language from local storage or default to 'en'
const savedLanguage = localStorage.getItem('psysonic_language') || 'en';
i18n
.use(initReactI18next)
.init({
resources: {
en: { translation: enTranslation },
de: { translation: deTranslation }
},
lng: savedLanguage,
fallbackLng: 'en',
interpolation: {
escapeValue: false
}
});
i18n.on('languageChanged', (lng) => {
localStorage.setItem('psysonic_language', lng);
});
export default i18n;