mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-21 14:55:43 +00:00
f9df918c72
* feat(themes): add semantic tokens for the theme-store contract (B0 P1) Additive: define --highlight, --accent-2, --bg-deep, --bg-elevated and --text-on-accent on the :root base as --ctp-* mappings. They resolve per-theme automatically and nothing consumes them yet (zero behaviour change) — groundwork for replacing direct --ctp-* use in components. * refactor(themes): components consume semantic tokens, not --ctp-* (B0 P2) Replace every direct --ctp-* reference in component/layout/track CSS and TSX inline styles with the readable semantic token (--bg-app, --accent, --highlight, --text-on-accent, …). --ctp-* now survives only as the Catppuccin palette layer the base maps from, and as the deliberate categorical rainbow in Composers/Genres/artistsHelpers (left untouched). This is the readable contract surface for the community theme store. Divergences (theme set a semantic var != its --ctp- source) are corrections — the element now uses the theme's real semantic colour. * feat(themes): add player-bar title/artist color tokens New optional --player-title / --player-artist, defaulting to --text-primary / --text-secondary so nothing changes unless a theme overrides them. Lets a theme give the now-playing readout its own colour as a plain token. * refactor(themes): token-only theme library (flatten, whitelist, one file per theme) Turn every built-in theme into a single self-contained [data-theme] var block of semantic whitelist tokens (plus the internal --ctp-* palette layer): - Flatten all themes: drop structural override rules, @keyframes, and global-token overrides (radius / shadow-elevation / transition / spacing / font / focus-ring). Signature player-bar readout colours are preserved via the new --player-title / --player-artist tokens. - Normalize the var blocks to the semantic whitelist: drop the alternate token vocabulary (nav-active / scrollbar / bg-input / success / border-default / ...); rename --success -> --positive and --border-default -> --border where no whitelist equivalent was set. Migrate the few components that read those tokens to the whitelist equivalents. - Split multi-theme files so each theme ships as its own file, making the built-in set 1:1 with the per-theme store packaging. Kept as-is (built-in, not flattened): the two colour-blind-safe accessibility themes, plus the two curated core skins. * chore(themes): remove seven themes retired after the token refactor These themes leaned on heavy structural overrides and were dropped rather than flattened. Full removal each: the CSS file(s), the index.css import, the Theme type union, and the ThemePicker entry. * feat(themes): granular tokens — track lists Wire track rows to per-region tokens: row hover (--row-hover), the now-playing row + indicator (--row-playing-bg / --row-playing-text), track title/artist/ number/duration text, column-header text, row dividers, and the resize-handle active colour. Covers the desktop tracklist, the shared song-row (Tracks hub / search), and the mobile tracklist. Drop a baked border fallback. Visual no-op. * feat(themes): granular tokens — cards Wire album and artist cards to per-region tokens (--card-hover-border, --card-title, --card-subtitle, --card-placeholder-bg). Visual no-op. * fix(themes): drop undefined/baked colour aliases Replace the undefined --bg-surface (resolved to nothing — broken placeholder backgrounds and filter input) with --card-placeholder-bg / --input-bg, and the baked-hex aliases --color-error / --color-warning with --danger / --warning so themes can actually recolour them. * feat(themes): Spectrum demo theme + trim unused cascade tokens Add a loud built-in demo theme that gives each region its own hue (sidebar green, player pink, lists cyan, cards gold, menus red, controls blue) so the per-region granularity is obvious when you switch to it. Drop two unused cascade tokens (--sidebar-text-active, --row-active-bg) and the unused on-media block (those media surfaces stay static by design). * style(themes): make Spectrum demo brutally loud Full-saturation neon per region (toxic green sidebar, magenta player, cyan lists, acid-yellow cards, blood-red menus, electric-blue controls, purple scrollbar) so the per-region separation is unmistakable. The earlier soft tints were too subtle to read. * feat(themes): name the granular demo theme Braindead * feat(themes): granular per-region tokens — cascade layer + sidebar Add an optional per-region token layer (semantic-cascade.css) so a theme can recolour individual regions — sidebar hover, player controls, list rows, menus, inputs, on-media surfaces — independently of the global tokens. Every token defaults to its base token (or a media-safe literal), so this is a visual no-op until a theme overrides one; it only adds control points. Wire the sidebar region as the first consumer and drop the baked grey fallbacks (--bg-tertiary, etc.) that no theme could reach. * feat(themes): granular tokens — controls, menus, scrollbar Wire inputs, buttons, sliders, the custom-select, context menus, submenus and modals to per-region tokens, and tokenise the scrollbar. Complete B0 by dropping the last direct --ctp-* references in the input/button/progress/ scrollbar utility CSS. Fix three undefined-token bugs that fell back to nothing (so no theme could reach them): --surface-2 (context-menu hover had no highlight), --bg-surface (submenu create-input had no background), and the baked grey fallbacks in the custom-select. Every other new token defaults to today's value — a visual no-op that only adds override points. * feat(themes): granular tokens — player bar Wire the desktop player bar's transport controls, time toggle, and overflow menu to per-region tokens (--player-control, --player-time-toggle-*, etc.). Fix the undefined --surface-hover/--surface-active grey fallbacks on the time toggle. Visual no-op; defaults match today's values. * chore(themes): remove empty theme stub files Six theme CSS files were reduced to comment-only stubs by the flatten sweep but their files and @import lines remained. Five are empty structural companions of now-flattened themes (morpheus, p-dvd, aero-glass, luna-teal) and two are orphans of cut themes (order-of-the-phoenix, pandora). Removed the files and their imports. * feat(themes): runtime injection foundation for the theme store Plumbing for installed community themes ahead of the in-app store UI, nothing user-visible yet: - installedThemesStore: persisted (localStorage) record of installed community themes incl. their CSS text, so an active community theme is available synchronously at startup (no flash, fully offline). - themeInjection: reconcile <head> <style data-installed-theme> elements with the store; lightweight defense-in-depth sanitize on top of CI. - themeRegistry: jsDelivr registry client with a 12h localStorage cache and stale-on-error fallback. - App: inject installed themes before applying data-theme, in both webviews. - themeStore: widen the Theme type to accept dynamic installed ids. * feat(themes): dedicated Themes settings tab Move theme selection and the day/night scheduler out of Appearance into a new dedicated Themes tab — the future home of the community Theme Store. Appearance keeps grid columns, visual options, UI scale, font and seekbar. - ThemesTab: theme picker + scheduler (relocated verbatim). - AppearanceTab: drop the two relocated sections + now-unused imports. - Register the tab in settingsTabs (Tab union, resolveTab, search index) and Settings (tab bar, render, label map). - i18n: settings.tabThemes in all 9 locales. * feat(themes): community Theme Store browse + install Add the Theme Store section to the Themes tab: - Fetch the jsDelivr registry (12h cache, stale-on-error fallback). - Search by name/author/description + filter by light/dark + refresh. - Per-row CDN thumbnail, name, author, description and actions: Install / Apply / Update / Uninstall. Installing fetches the CSS, persists it (localStorage) and the runtime injection applies it; uninstalling the active theme falls back to the matching core. - Rating slot left reserved (deferred). - i18n: themeStore* keys in all 9 locales. * feat(themes): slim bundle to fixed cores + flat Themes tab Remove the 86 store palettes (incl. braindead) from the app bundle — the CSS files, their index.css imports, the Theme union and the picker data — leaving only the six fixed cores (Catppuccin Mocha/Latte, Kanagawa Wave, Stark HUD, Vision Dark/Navy). Everything else installs from the store. Themes tab is rebuilt flat (no collapsible accordions): - "Your Themes": one card grid of the fixed cores + installed community themes; click to apply, uninstall on community ones (active theme falls back to the matching core). Catppuccin prefix on Mocha/Latte; a CVD-safe pill on the colour-blind-safe Vision themes. - Scheduler day/night options include installed themes. - Theme Store: alphabetical order, thumbnail lightbox, and a submit hint above the search linking to the themes repository. - Nav order: Servers, Library, Audio, Themes, Appearance, Lyrics, … - ThemePicker accordion removed; fixed-theme data moved to fixedThemes.ts. - i18n for all new strings across 9 locales. * feat(themes): reset removed-from-bundle themes to a bundled fallback After slimming the bundle to the six fixed core themes, a profile upgraded from an older build may have an active or scheduler theme that is now store-only and not installed — it has no [data-theme] block and would render as unstyled :root. Reset any theme/themeDay/themeNight that is neither bundled nor installed to a bundled fallback: Mocha for the main + night slots, Latte for the day slot. Runs synchronously in runPreReactBootstrap, rewriting the persisted selection in localStorage before React mounts (no flash; Zustand rehydrates after first paint). No auto-install and no network — the fallback is always a bundled theme, so it works offline. * feat(themes): floating back-to-top button on the Themes tab The Themes tab can get long (theme grid + scheduler + full store list), so add a floating back-to-top affordance that appears once the page is scrolled and smooth-scrolls to the top. It is portalled into the route host and positioned absolute against it — the main scroll viewport sets contain: paint, which would otherwise make position: fixed resolve against the scrolling box and drift with the content. Reusable component (scroll viewport id + threshold props); i18n common.backToTop added in all nine locales. * feat(themes): accessibility + state polish for the Theme Store - Reuse the shared CoverLightbox for the thumbnail preview instead of a second inline dialog — gains a visible close button and a focus-managed, portalled dialog, and drops duplicated markup. - Theme cards expose aria-pressed so assistive tech announces the selected theme, not just the visual check. - Transient store messages get live-region roles (loading/empty/install failure = status, fetch error = alert). - Thumbnails degrade gracefully when offline/missing (hide the broken-image glyph; the thumbnail button no longer stretches with the row, so its background can't show as letterbox bars). * feat(themes): larger store-row thumbnails (120x75 -> 200x125) The list previews were too small to make a theme out; bump the display size (same 1.6 aspect). Thumbnails are now served at 720x450, so the larger display stays crisp. * fix(themes): bust thumbnail cache on registry change jsDelivr serves theme thumbnails with a 7-day max-age, so when a thumbnail is updated the webview keeps showing its cached old image (the path is unchanged). Append the registry's generatedAt as a cache-busting query to the thumbnail URLs (list + lightbox); it changes on every themes push, so a registry refresh makes the webview re-fetch and reflect the current CDN image instead of a stale one. * docs(themes): changelog + credits for the Theme Store Add the 1.48.0 "Themes — community Theme Store" changelog entry (PR #1009) and the matching line in the Psychotoxical credits. * fix(themes): address PR review (uninstall hygiene, validation, polish) Uninstall/scheduler & validation: - uninstallTheme() repairs every selection slot (active + day + night), not just the manual one, and is shared by both uninstall buttons (dedup). - Validate theme CSS at install time and skip persisting CSS that won't inject (no more "installed/active but renders nothing" with no feedback). - Harden the runtime validator: exactly one rule, scoped exactly to the theme's [data-theme='<id>'] selector (no unscoped/foreign selectors), no at-rules, url() only data:, no expression()/javascript:, size-capped. Tokens & polish: - Fix three dangling undefined tokens (--surface-2 x2, --bg-surface). - Finish the warning/success token sweep (--warning / --positive, themeable). - Apply the active theme synchronously before React mounts (no first-frame flash) and inject installed themes up front. - One-time, dismissible notice when the slim-bundle migration reset a theme. - Update badge uses semver, not string inequality. - Offline/stale indicator in the store; cross-window theme sync; drop the now dead REMOVED_THEME_REMAP and Card.mode field. Tests: themeInjection (validator + sync), themeRegistry (cache/force/stale/ malformed), uninstallTheme (slot repair), migration notice. i18n in all nine locales. Full suite green (1755 tests). * test(bootstrap): cover startup theme apply + cross-window sync The review fixes added applyThemeAtStartup / installCrossWindowThemeSync to bootstrap.ts (a hot-path file) without tests, dropping its coverage to 68.3% and failing the frontend hot-path coverage gate (>=70%). Add unit tests for both (and the no-op / malformed-storage paths); bootstrap.ts is back to ~98%.
642 lines
40 KiB
TypeScript
642 lines
40 KiB
TypeScript
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',
|
||
serverAlternateUrl: 'Andre adresse (valgfritt)',
|
||
serverAlternateUrlPlaceholderPublic: 'https://music.example.com',
|
||
serverAlternateUrlPlaceholderLocal: '192.168.1.100:4533',
|
||
serverAlternateUrlHintAddPublic: 'Du kan legge til en offentlig adresse for tilgang utenfor hjemmenettverket.',
|
||
serverAlternateUrlHintAddLocal: 'Du kan legge til en lokal adresse for raskere tilkobling hjemme.',
|
||
serverBothLanError: 'Begge adressene er lokale — behold én eller legg til en offentlig adresse.',
|
||
dualAddressVerifying: 'Sjekker at begge adressene peker til samme tjener…',
|
||
dualAddressMismatch: 'De to adressene peker til ulike tjenere. Sjekk skrivemåten og prøv igjen.',
|
||
dualAddressInsufficient: 'Kunne ikke bekrefte at begge adressene er samme tjener. Fjern én adresse for å fortsette.',
|
||
dualAddressUnreachable: 'Kunne ikke nå {{host}}. Sjekk adressen og nettverket, og prøv igjen.',
|
||
urlRemigrationTitle: 'Flytte biblioteksdataene?',
|
||
urlRemigrationMessage: 'Å endre adressen vil flytte alle biblioteks-, analyse- og omslags-buffer-data fra {{oldKey}} til {{newKey}}. Dette kan ikke angres.',
|
||
urlRemigrationConfirm: 'Flytt data',
|
||
urlRemigrationProgress: 'Flytter biblioteksdata…',
|
||
urlRemigrationFailureInspect: 'Kunne ikke sjekke hva som ville bli flyttet. Prøv igjen eller åpne feilsøkingsloggen.',
|
||
urlRemigrationFailureRun: 'Flyttingen av biblioteksdataene mislyktes. Lagrede data er uendret — prøv igjen.',
|
||
urlRemigrationFailureCoverRename: 'Biblioteksdataene ble flyttet, men omslagsfilene kunne ikke endre navn. Omslag bygges opp igjen ved neste tilgang.',
|
||
shareUsesLocalUrl: 'Bruk lokal adresse i delingslenker',
|
||
shareUsesLocalUrlDesc: 'Påvirker Orbit-invitasjoner og biblioteksdeling. Standard: offentlig adresse.',
|
||
serverUsername: 'Brukernavn',
|
||
serverPassword: 'Passord',
|
||
addServer: 'Legg til tjener',
|
||
addServerTitle: 'Legg til ny tjener',
|
||
editServer: 'Rediger',
|
||
editServerTitle: 'Rediger 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 <pluginLink>AudioMuse-AI Navidrome-plugin</pluginLink>. 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: 'Nettlesercache for plateomslag og artistbilder (IndexedDB). Når den er full, fjernes de eldste oppføringene automatisk.',
|
||
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: 'Sletter alle bufrede omslag og artistbilder. De lastes ned igjen ved behov.',
|
||
cacheClearConfirm: 'Tøm bildecache',
|
||
cacheClearCancel: 'Avbryt',
|
||
mediaDirTitle: 'Mediemappe',
|
||
mediaDirDesc: 'Rotmappe for lokal avspilling. Frakoblet bibliotek: library/; købuffer: cache/.',
|
||
mediaDirDefault: 'Standard (App-data)',
|
||
mediaDirChange: 'Endre mappe',
|
||
mediaDirClear: 'Tilbakestill til standard',
|
||
mediaDirHint: 'Nye nedlastinger bruker denne plasseringen. Eksisterende filer blir på sin opprinnelige sti til du fjerner dem.',
|
||
offlineStorageTitle: 'Frakoblet lagring',
|
||
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.',
|
||
clockFormat: 'Klokkeformat',
|
||
clockFormatDesc: 'Klokkevisning brukt av kø-ETA og forhåndsvisningen av hviletimeren.',
|
||
clockFormatAuto: 'Automatisk (systemspråk)',
|
||
clockFormatTwentyFour: '24-timers',
|
||
clockFormatTwelve: '12-timers (AM/PM)',
|
||
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.',
|
||
linuxWebkitInputForceRepaint: 'Tegne om tekstfelt ved fokus (Linux)',
|
||
linuxWebkitInputForceRepaintDesc: 'Omgår WebKitGTK 2.50.x der tekstfelt fryser ved klikk. Søkeikoner blinker kort ved fokus.',
|
||
linuxWaylandTextRender: 'Wayland-tekstgjengivelse (Linux)',
|
||
linuxWaylandTextRenderDesc:
|
||
'Utjevning i grensesnittet skjer med én gang. WebKit-maskinvareakselerasjon (skarp/GPU) lagres og brukes ved neste appstart — live bytte kan fryse WebKitGTK.',
|
||
linuxWaylandTextRenderBalanced: 'Balansert',
|
||
linuxWaylandTextRenderSharp: 'Skarpt (CPU-vennlig)',
|
||
linuxWaylandTextRenderGpu: 'GPU først',
|
||
linuxWaylandTextRenderMinimal: 'Minimum (standard CSS-utjevning)',
|
||
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)',
|
||
discordTemplateName: 'Brukerliste-linje (name)',
|
||
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',
|
||
lyricsYouLyPlus: 'YouLyPlus (Karaoke)',
|
||
lyricsYouLyPlusDesc: 'Ord-for-ord-synkronisering fra en fellesskapsbackend (Apple Music, Spotify, Musixmatch, QQ). Prøves først; de aktiverte kildene under fungerer som reserve.',
|
||
lyricsSourcesFallbackHint: 'Brukes som reserve når YouLyPlus ikke finner noe. Dra for å endre rekkefølge.',
|
||
lyricsSourcesPrimaryHint: 'Prøves i rekkefølge. Dra for å endre rekkefølge. Alt av = tekster deaktivert.',
|
||
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.",
|
||
libraryGridMaxColumnsTitle: 'Kortrutenett i biblioteket',
|
||
libraryGridMaxColumnsPerfHint: 'Flere kolonner gir flere fliser per rad og kan øke layout- og tegnearbeid — merkbart på veldig store biblioteker eller tregere maskiner.',
|
||
libraryGridMaxColumnsRangeLabel: 'Maksimalt antall kolonner ({{min}}–{{max}})',
|
||
libraryGridMaxColumnsDesc: 'Gjelder album-, artist-, spilleliste-, radio-, offline- og andre kortbaserte bibliotekvisninger. Færre kolonner = større fliser og vanligvis mindre CPU-belastning.',
|
||
libraryIndexTitle: 'Lokalt biblioteksindeks (forhåndsvisning)',
|
||
libraryIndexDesc: 'Holder en lokal kopi av hver servers spordatabase slik at blaing og søk forblir raskt og fungerer offline. Første synkronisering kjører for alle konfigurerte servere; offline servere prøves automatisk på nytt.',
|
||
libraryIndexDeltaHint: 'Delta-synkronisering i bakgrunnen sjekker tilknyttede servere hvert 30. sekund og kjører når det er på tide — vanligvis hvert 5.–45. minutt avhengig av biblioteksstørrelse og belastning.',
|
||
libraryIndexEnable: 'Aktiver lokalt biblioteksindeks',
|
||
libraryIndexEnableAllDesc: 'Indekser og synkroniser alle konfigurerte servere i bakgrunnen.',
|
||
libraryIndexNoServer: 'Legg til en server først.',
|
||
libraryIndexServerListTitle: 'Indekserte servere',
|
||
libraryIndexAllExcluded: 'Alle servere er ekskludert fra synkronisering. Aktiver indeksen igjen eller legg til en server.',
|
||
libraryIndexServerOffline: 'Server offline — synkronisering utsatt',
|
||
libraryIndexServerDeferred: 'Utsatt',
|
||
libraryIndexServerSyncing: 'Synkroniserer…',
|
||
libraryIndexFullResync: 'Full resynkronisering',
|
||
libraryIndexDeltaSync: 'Delta-synkronisering',
|
||
libraryIndexExcludeServer: 'Ekskluder fra synkronisering',
|
||
libraryIndexExcludingServer: 'Ekskluderer…',
|
||
libraryIndexExcludedTitle: 'Ekskludert fra synkronisering',
|
||
libraryIndexIncludeServer: 'Inkluder igjen',
|
||
libraryIndexIncludingServer: 'Inkluderer…',
|
||
libraryIndexStatus: 'Status',
|
||
libraryIndexStatusIdle: 'Inaktiv',
|
||
libraryIndexStatusProbing: 'Sjekker server…',
|
||
libraryIndexStatusInitial: 'Første synkronisering…',
|
||
libraryIndexStatusReady: 'Klar ({{count}} spor)',
|
||
libraryIndexStatusError: 'Feil — se logger',
|
||
libraryIndexProgressIngest: '{{count}} spor indeksert…',
|
||
libraryIndexProgressVerify: '{{checked}} verifisert ({{deleted}} fjernet)',
|
||
libraryIndexSyncNow: 'Synkroniser nå',
|
||
libraryIndexVerify: 'Verifiser bibliotekets integritet',
|
||
libraryIndexCancel: 'Avbryt',
|
||
libraryIndexAutoReconcile: 'Auto-avstemming ved fall i antall',
|
||
libraryIndexAutoReconcileDesc: 'Sjekker automatisk etter fjernede spor når serveren rapporterer færre enn forventet.',
|
||
libraryIndexSyncError: 'Biblioteksynkronisering mislyktes: {{error}}',
|
||
libraryIndexBindError: 'Kunne ikke aktivere indeks: {{error}}',
|
||
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',
|
||
tabThemes: 'Temaer',
|
||
themesYourThemesTitle: 'Dine temaer',
|
||
themesCvdTooltip: 'Fargeblind-sikker – deuteranopi, protanopi, tritanopi',
|
||
themeStoreTitle: 'Temabutikk',
|
||
themeStoreSubmitText: 'Laget ditt eget tema? Del det med fellesskapet — mer info i tema-repoet.',
|
||
themeStoreSubmitLink: 'Åpne tema-repoet',
|
||
themeStoreSearchPlaceholder: 'Søk i temaer…',
|
||
themeStoreFilterMode: 'Filtrer etter modus',
|
||
themeStoreModeAll: 'Alle',
|
||
themeStoreModeDark: 'Mørk',
|
||
themeStoreModeLight: 'Lys',
|
||
themeStoreRefresh: 'Oppdater',
|
||
themeStoreLoading: 'Laster temaer…',
|
||
themeStoreError: 'Kunne ikke laste temabutikken. Sjekk tilkoblingen din.',
|
||
themeStoreRetry: 'Prøv igjen',
|
||
themeStoreEmpty: 'Ingen temaer samsvarer med filtrene dine.',
|
||
themeStoreActive: 'Aktiv',
|
||
themeStoreEnlarge: 'Forstørr forhåndsvisning',
|
||
themeStoreByAuthor: 'av {{author}}',
|
||
themeMigrationNoticeTitle: 'Temaet er flyttet til butikken',
|
||
themeMigrationNoticeBody: '{{themes}} følger ikke lenger med appen. Du kan installere det på nytt fra temabutikken (Innstillinger → Temaer), eller velge et annet tema.',
|
||
themeMigrationNoticeOpen: 'Åpne temabutikken',
|
||
themeStoreOffline: 'Viser den sist bufrede katalogen — du ser ut til å være frakoblet.',
|
||
themeStoreInstall: 'Installer',
|
||
themeStoreInstalling: 'Installerer…',
|
||
themeStoreApply: 'Bruk',
|
||
themeStoreUpdate: 'Oppdater',
|
||
themeStoreUpdating: 'Oppdaterer…',
|
||
themeStoreUninstall: 'Avinstaller',
|
||
themeStoreInstallFailed: 'Installasjonen mislyktes',
|
||
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 <strong>frivillige</strong> 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: 'Hovedscene',
|
||
queueModeTitle: 'Visningsmodus for kø',
|
||
queueModeQueueSub: 'Viser bare kommende spor. Det gjeldende sporet blir i toppen og forsvinner fra listen når det er spilt.',
|
||
queueModePlaylistSub: 'Beholder hele køen i listen med gjeldende spor uthevet øverst; avspilte spor blir værende.',
|
||
queueModeTimelineSub: 'Sentrer gjeldende spor, med avspilt historikk over og kommende spor (i shuffle-rekkefølge) under.',
|
||
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å',
|
||
playlistLayoutTitle: 'Sideoppsett for spilleliste',
|
||
playlistLayoutDesc: 'Vis eller skjul individuelle elementer på spillelistesiden.',
|
||
playlistLayoutReset: 'Tilbakestill til standard',
|
||
playerBarTitle: 'Spillerlinje',
|
||
playerBarReset: 'Tilbakestill til standard',
|
||
playerBarStarRating: 'Stjernevurdering',
|
||
playerBarFavorite: 'Favoritt (hjerte)',
|
||
playerBarLastfmLove: 'Last.fm love',
|
||
playerBarPlaybackRate: 'Avspillingshastighet',
|
||
playerBarEqualizer: 'Equalizer',
|
||
playerBarMiniPlayer: 'Miniavspiller',
|
||
playbackRateTitle: 'Avspillingshastighet',
|
||
playbackRateEnabled: 'Aktiver avspillingshastighet',
|
||
playbackRateEnabledDesc: 'Global hastighet for alle spor. Gjelder ikke radio og forhåndsvisninger.',
|
||
playbackRateStrategy: 'Strategi',
|
||
playbackRateStrategySpeed: 'Hastighet',
|
||
playbackRateStrategyVarispeed: 'Med tone',
|
||
playbackRateStrategyPreserve: 'Tonehøyde',
|
||
playbackRateSpeed: 'Hastighet',
|
||
playbackRatePitch: 'Tonehøyde',
|
||
playbackRateDerivedPitch: 'Tonehøydeforskyvning fra hastighet: {{value}}',
|
||
playbackRateAutoPitch: 'Tonehøyden korrigeres automatisk.',
|
||
playbackRateHint: '« Hastighet » beholder naturlig tonehøyde. « Med tone » endrer tonehøyden med hastigheten. « Tonehøyde » legger til manuell forskyvning. Mer CPU enn « Med tone ». Ikke for radio, forhåndsvisninger eller Orbit.',
|
||
playbackRateNeutral: 'Ved 1,0× og uten toneforskyvning er avspilling normal.',
|
||
playbackRateOrbitPaused: 'Ikke aktiv under Orbit-økter — avspilling forblir 1,0× for synk.',
|
||
playbackRateOrbitPausedShort: 'Orbit: 1,0× for synk.',
|
||
advancedMode: 'Avansert',
|
||
advancedModeTooltip: 'Vis avanserte alternativer i alle innstillinger-faner. Bidrag fra fellesskapet som ikke nødvendigvis gjenspeiler design-filosofien til Psysonic-vedlikeholderne.',
|
||
advancedBadge: 'Avansert',
|
||
sidebarDrag: 'Dra for å endre rekkefølge',
|
||
sidebarFixed: 'Alltid synlig',
|
||
nowPlayingTopTitle: '"Spilles nå" øverst',
|
||
nowPlayingTopDesc: 'Fest "Spilles nå" øverst i sidefeltet i stedet for nederst.',
|
||
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',
|
||
nextTrackBufferingTitle: 'Bufring',
|
||
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',
|
||
confirmDeleteServerLibrary: 'Vil du også slette denne serverens lokale bibliotekindeks? Klikk Avbryt for å beholde den bufrede kopien for offline bruk.',
|
||
waveformCacheClearBtn: 'Tøm waveform-cache',
|
||
waveformCacheCleared: 'Waveform-cache tømt ({{count}} rader).',
|
||
waveformCacheClearFailed: 'Kunne ikke tømme waveform-cache.',
|
||
showTrayIcon: 'Vis systemstatusikon',
|
||
showTrayIconDesc: 'Vis Psysonic-ikonet i systemstatusfeltet / menylinjen.',
|
||
useCustomTitlebar: 'Tilpasset tittellinje',
|
||
useCustomTitlebarDesc: 'Erstatt systemets tittellinje med en innebygd som matcher app-temaet. Slå av for å bruke den native GNOME/GTK-tittellinjen.',
|
||
analyticsStrategyTitle: 'Analysestrategier',
|
||
analyticsStrategyDesc: 'Velg analysestil for biblioteket.',
|
||
analyticsStrategyLabel: 'Strategi',
|
||
analyticsStrategyLazy: 'Lat',
|
||
analyticsStrategyLazyDesc: 'Analyserer bare når spor spiller eller går inn i hot/offline-cache — minimalt CPU- og nettverksbruk.',
|
||
analyticsStrategyAdvanced: 'Aggressiv',
|
||
analyticsStrategyAdvancedDesc: 'Mer aggressiv bakgrunnsskanning. Når den er ferdig får du BPM for alle spor samt umiddelbar lasting av loudness og waveform.',
|
||
analyticsStrategyPriorityTitle: 'Analyseprioritet (alltid aktiv)',
|
||
analyticsStrategyPriorityHigh: '1 — Spiller nå: last ned og analyser først (avspillingsbytes, loudness-backfill eller HTTP ved behov).',
|
||
analyticsStrategyPriorityMiddle: '2 — Neste opp: de neste ~5 køsporene og hot-cache-naboer — analyser fra cache/nedlastede bytes når mulig; HTTP-backfill kun ved bom.',
|
||
analyticsStrategyPriorityLow: '3 — Bibliotekbatch (kun Aggressiv): automatisk bakgrunnskø bakerst; fylles på ved watermark (~3× workers) uten å vente på tom kø.',
|
||
analyticsStrategyServerLabel: 'Server',
|
||
analyticsStrategyProgressLabel: 'Analysefremdrift:',
|
||
analyticsStrategyProgressValue: '{{percent}}% ({{done}}/{{total}})',
|
||
analyticsStrategyActionsLabel: 'Handlinger',
|
||
analyticsStrategyParallelismLabel: 'Parallelle workers',
|
||
analyticsStrategyParallelismValue: '{{n}} tråder',
|
||
analyticsStrategyParallelismDesc: 'Hvor mange spor som lastes ned og analyseres samtidig (HTTP + CPU). Høyere verdi gjør bibliotekinnhentingen raskere, men bruker mer nettverk og CPU.',
|
||
analyticsStrategyAdvancedWarning: 'Aggressiv bruker mer CPU og nettverksbåndbredde mens bibliotekbatchen kjører i bakgrunnen.',
|
||
analyticsStrategyServerRemoved: 'Fjernet server',
|
||
analyticsStrategyClearAction: 'Tøm analyse',
|
||
analyticsStrategyClearTitle: 'Tøm analyse?',
|
||
analyticsStrategyClearDesc: 'Å tømme analyse for {{server}} fjerner bufrede waveforms og loudness. Å legge til serveren igjen senere kan kreve lang reindeksering.',
|
||
analyticsStrategyClearCancel: 'Avbryt',
|
||
analyticsStrategyClearConfirm: 'Tøm analyse',
|
||
analyticsStrategyClearSuccess: 'Analyse tømt for den fjernede serveren.',
|
||
analyticsStrategyClearError: 'Kunne ikke tømme analyse for den fjernede serveren.',
|
||
analyticsStrategyProgressEmptyAfterFailed: '100% (0/0, blokkert av feilede spor)',
|
||
analyticsFailedTracksOpenTitle: 'Feilede spor: {{count}}',
|
||
analyticsFailedTracksTitle: 'Feilede analysespor — {{server}}',
|
||
analyticsFailedTracksDesc: 'Disse sporene feilet gjentatte ganger i decode/enrichment og er ekskludert fra automatisk bakgrunnsanalyse.',
|
||
analyticsFailedTracksLoading: 'Laster liste over feilede spor…',
|
||
analyticsFailedTracksEmpty: 'Ingen feilede spor for denne serveren.',
|
||
analyticsFailedTracksClose: 'Lukk',
|
||
analyticsFailedTracksExport: 'Eksporter liste',
|
||
analyticsFailedTracksExportSuccess: 'Liste over feilede spor eksportert ({{count}}).',
|
||
analyticsFailedTracksExportError: 'Kunne ikke eksportere liste over feilede spor.',
|
||
analyticsFailedTracksRescan: 'Skann feilede spor på nytt',
|
||
analyticsFailedTracksRescanSuccess: 'Ny skanning planlagt for {{count}} feilede spor.',
|
||
analyticsFailedTracksRescanError: 'Kunne ikke skanne feilede spor på nytt.',
|
||
analyticsFailedTracksLoadError: 'Kunne ikke laste feilede spor.',
|
||
tabAudio: 'Lyd',
|
||
tabInput: 'Inndata',
|
||
backupImportAny: 'Importer sikkerhetskopi',
|
||
backupImportAnyConfirm: 'Importer valgt sikkerhetskopifil og bruk innholdet (innstillinger, bibliotekdatabaser eller full). Fortsette?',
|
||
backupModeFull: 'Full',
|
||
backupModeLibrary: 'Bibliotekdatabaser',
|
||
backupModeConfig: 'Konfig',
|
||
backupFullDesc: 'Arkiverer innstillinger og bibliotekdatabaser i én sikkerhetskopifil.',
|
||
backupFullExport: 'Eksporter full sikkerhetskopi',
|
||
backupFullImport: 'Importer full sikkerhetskopi',
|
||
backupFullImportConfirm: 'Dette vil overskrive innstillinger, erstatte nåværende bibliotekdatabaser og flytte dem til .bak. Fortsette?',
|
||
backupFullExportSuccess: 'Full sikkerhetskopi eksportert.',
|
||
backupFullImportSuccess: 'Full sikkerhetskopi importert — laster inn på nytt…',
|
||
backupFullImportError: 'Kunne ikke importere full sikkerhetskopi.',
|
||
backupLibraryExport: 'Eksporter databaser',
|
||
backupLibraryExportDesc: 'Lager et komprimert arkiv med rene SQLite-øyeblikksbilder av bibliotekdatabaser.',
|
||
backupLibraryImport: 'Importer databaser',
|
||
backupLibraryImportDesc: 'Gjenoppretter bibliotekdatabaser fra en arkivfil. Nåværende databaser flyttes til .bak før bytte.',
|
||
backupLibraryImportConfirm: 'Dette vil erstatte nåværende bibliotekdatabaser og flytte dem til .bak. Fortsette?',
|
||
backupLibraryExportSuccess: 'Databasesikkerhetskopi eksportert.',
|
||
backupLibraryImportSuccess: 'Databasesikkerhetskopi importert.',
|
||
backupLibraryImportError: 'Kunne ikke importere databasesikkerhetskopi.',
|
||
backupOverlayExportTitle: 'Oppretter sikkerhetskopi…',
|
||
backupOverlayImportTitle: 'Gjenoppretter sikkerhetskopi…',
|
||
backupOverlayHint: 'Du kan holde vinduet åpent mens vi behandler filer. Inndata er midlertidig låst.',
|
||
};
|