From c276088fe6d0b6569ae9fd4af095c99152402aa4 Mon Sep 17 00:00:00 2001 From: Hans Dijkema Date: Fri, 28 Aug 2026 16:59:45 +0200 Subject: [PATCH] extra translations --- ARCHITECTURE.md | 5 +- README.md | 5 +- private/playlists.rkt | 9 +- private/translate.rkt | 141 ++++++++++++++++++++++++++++++- public/index.html | 2 +- public/translate.js | 123 ++++++++++++++++++++++++++- scribblings/rkt-web-player.scrbl | 9 +- 7 files changed, 278 insertions(+), 16 deletions(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 4aa4027..5447702 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -249,8 +249,9 @@ header. Command failures are returned as HTTP 400 JSON responses with an - implements keyboard actions and playlist drag-and-drop in the browser. [`public/translate.js`](public/translate.js) follows the key-based translation -model used by rktplayer. It supports Dutch, English, German, French and Spanish -with English fallback. Browser preferences select the initial language; a +model used by rktplayer. It supports Dutch, English, German, French, Spanish, +Italian, Swedish, Norwegian, Finnish and Icelandic with English fallback. +Browser preferences select the initial language; a manual selection is stored server-side per username and therefore follows the user across browsers. The native agent uses the equivalent [`private/translate.rkt`](private/translate.rkt) module and the operating-system diff --git a/README.md b/README.md index 4bee30c..9e25945 100644 --- a/README.md +++ b/README.md @@ -120,7 +120,8 @@ nieuwe gebruiker het over. Een oudere `playlists-for-local`-verzameling blijft in de keystore staan, maar wordt niet automatisch aan een gebruiker toegewezen. -De webinterface ondersteunt Nederlands, Engels, Duits, Frans en Spaans. Bij +De webinterface ondersteunt Nederlands, Engels, Duits, Frans, Spaans, +Italiaans, Zweeds, Noors, Fins en IJslands. Bij het eerste bezoek wordt de voorkeurstaal van de browser gebruikt. Een keuze in de taalselector wordt daarna per gebruiker als `language-for-` in `data/playlists.keystore` opgeslagen en geldt daardoor ook op andere apparaten. @@ -173,7 +174,7 @@ toe wanneer zijn volledige applicatie-ID vooraf als key onder HTTP 403 en wordt niet als uitvoerpunt aangemaakt. De agent toont in dat geval zijn ID en meldt dat de serverbeheerder deze eerst aan de INI moet toevoegen. De GUI en het systeemvak volgen automatisch de systeemtaal en ondersteunen -dezelfde vijf talen als de webinterface. +dezelfde tien talen als de webinterface. Onder **Afspelen** toont de agent het playlistnummer, de huidige track en bestandsnaam, afspeeltoestand, verstreken en totale tijd, bitdiepte, diff --git a/private/playlists.rkt b/private/playlists.rkt index 1ca6ca5..8872aa4 100644 --- a/private/playlists.rkt +++ b/private/playlists.rkt @@ -24,7 +24,8 @@ (define (user-language-key username) (format "language-for-~a" username)) -(define supported-language-names '("en" "nl" "de" "fr" "es")) +(define supported-language-names + '("en" "nl" "de" "fr" "es" "it" "sv" "no" "fi" "is")) (define (track->datum item) (hasheq 'file (path->string (track-file item)) @@ -143,7 +144,7 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; goal : Persist one user's interface language. ; pre : Store is #f or open, username is normalized, and language is one of -; en, nl, de, fr, or es. +; en, nl, de, fr, es, it, sv, no, fi, or is. ; post : The user's language key contains language when a store exists. ; result : Void. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -151,7 +152,7 @@ (unless (member language supported-language-names) (raise-argument-error 'save-user-language! - "one of en, nl, de, fr, or es" + "one of en, nl, de, fr, es, it, sv, no, fi, or is" language)) (when store (call-with-semaphore @@ -215,6 +216,8 @@ (check-false (load-user-language store "hans")) (save-user-language! store "hans" "fr") (check-equal? (load-user-language store "hans") "fr") + (save-user-language! store "hans" "fi") + (check-equal? (load-user-language store "hans") "fi") (check-exn exn:fail:contract? (λ () (save-user-language! store "hans" "it"))) diff --git a/private/translate.rkt b/private/translate.rkt index 0beda67..676a14c 100644 --- a/private/translate.rkt +++ b/private/translate.rkt @@ -134,13 +134,141 @@ 'channel "canal" 'channels "canales" 'tray-open "Abrir el agente de RKT Web Player" - 'quit "Salir"))) + 'quit "Salir") + 'it + (hasheq + 'app-title "Agente RKT Web Player" + 'server "Server RKT Web Player" + 'name "Nome" + 'application-id "ID applicazione" + 'playback "Riproduzione" + 'no-track "Nessuna riproduzione in corso" + 'no-track-selected "Nessuna traccia selezionata" + 'save-connect "Salva e connetti" + 'reconnect "Riconnetti" + 'connecting "Connessione…" + 'connected "Connesso" + 'denied-title "Agente di riproduzione non consentito" + 'denied-message "Questo agente di riproduzione non è consentito dal server. Aggiungi il seguente ID applicazione a [playback-agents] nel file INI del server:\n\n~a" + 'unauthorized-status "Non autorizzato — l’ID applicazione non è nel file INI del server" + 'disconnected "Non connesso: ~a" + 'playing "In riproduzione" + 'paused "In pausa" + 'loading "Caricamento" + 'stopped "Arrestato" + 'channel "canale" + 'channels "canali" + 'tray-open "Apri l’agente RKT Web Player" + 'quit "Esci") + 'sv + (hasheq + 'app-title "RKT Web Player-agent" + 'server "RKT Web Player-server" + 'name "Namn" + 'application-id "Program-ID" + 'playback "Uppspelning" + 'no-track "Inget spelas upp" + 'no-track-selected "Inget spår har valts" + 'save-connect "Spara och anslut" + 'reconnect "Anslut igen" + 'connecting "Ansluter…" + 'connected "Ansluten" + 'denied-title "Uppspelningsagenten är inte tillåten" + 'denied-message "Servern tillåter inte den här uppspelningsagenten. Lägg till följande program-ID under [playback-agents] i serverns INI-fil:\n\n~a" + 'unauthorized-status "Inte behörig — program-ID saknas i serverns INI-fil" + 'disconnected "Inte ansluten: ~a" + 'playing "Spelar" + 'paused "Pausad" + 'loading "Läser in" + 'stopped "Stoppad" + 'channel "kanal" + 'channels "kanaler" + 'tray-open "Öppna RKT Web Player-agenten" + 'quit "Avsluta") + 'no + (hasheq + 'app-title "RKT Web Player-agent" + 'server "RKT Web Player-server" + 'name "Navn" + 'application-id "Applikasjons-ID" + 'playback "Avspilling" + 'no-track "Ingenting spilles av" + 'no-track-selected "Ingen spor er valgt" + 'save-connect "Lagre og koble til" + 'reconnect "Koble til på nytt" + 'connecting "Kobler til…" + 'connected "Tilkoblet" + 'denied-title "Avspillingsagenten er ikke tillatt" + 'denied-message "Serveren tillater ikke denne avspillingsagenten. Legg til følgende applikasjons-ID under [playback-agents] i serverens INI-fil:\n\n~a" + 'unauthorized-status "Ikke autorisert — applikasjons-ID mangler i serverens INI-fil" + 'disconnected "Ikke tilkoblet: ~a" + 'playing "Spiller" + 'paused "På pause" + 'loading "Laster" + 'stopped "Stoppet" + 'channel "kanal" + 'channels "kanaler" + 'tray-open "Åpne RKT Web Player-agenten" + 'quit "Avslutt") + 'fi + (hasheq + 'app-title "RKT Web Player -agentti" + 'server "RKT Web Player -palvelin" + 'name "Nimi" + 'application-id "Sovellustunnus" + 'playback "Toisto" + 'no-track "Mitään ei toisteta" + 'no-track-selected "Kappaletta ei ole valittu" + 'save-connect "Tallenna ja yhdistä" + 'reconnect "Yhdistä uudelleen" + 'connecting "Yhdistetään…" + 'connected "Yhdistetty" + 'denied-title "Toistoagenttia ei sallita" + 'denied-message "Palvelin ei salli tätä toistoagenttia. Lisää seuraava sovellustunnus palvelimen INI-tiedoston [playback-agents]-osioon:\n\n~a" + 'unauthorized-status "Ei valtuutettu — sovellustunnus puuttuu palvelimen INI-tiedostosta" + 'disconnected "Ei yhteyttä: ~a" + 'playing "Toistetaan" + 'paused "Keskeytetty" + 'loading "Ladataan" + 'stopped "Pysäytetty" + 'channel "kanava" + 'channels "kanavaa" + 'tray-open "Avaa RKT Web Player -agentti" + 'quit "Lopeta") + 'is + (hasheq + 'app-title "RKT Web Player-spilari" + 'server "RKT Web Player-þjónn" + 'name "Nafn" + 'application-id "Forritsauðkenni" + 'playback "Spilun" + 'no-track "Ekkert er í spilun" + 'no-track-selected "Ekkert lag valið" + 'save-connect "Vista og tengjast" + 'reconnect "Tengjast aftur" + 'connecting "Tengist…" + 'connected "Tengt" + 'denied-title "Spilarinn er ekki leyfður" + 'denied-message "Þessi spilari er ekki leyfður af þjóninum. Bættu eftirfarandi forritsauðkenni við [playback-agents] í INI-skrá þjónsins:\n\n~a" + 'unauthorized-status "Ekki heimilað — forritsauðkenni vantar í INI-skrá þjónsins" + 'disconnected "Ekki tengt: ~a" + 'playing "Spilar" + 'paused "Í bið" + 'loading "Hleður" + 'stopped "Stöðvað" + 'channel "rás" + 'channels "rásir" + 'tray-open "Opna RKT Web Player-spilarann" + 'quit "Hætta"))) (define (system-language) (define language-name (string-downcase (format "~a" (system-language+country)))) (define short-name (car (regexp-split #px"[-_]" language-name))) - (define candidate (string->symbol short-name)) + (define candidate + (case (string->symbol short-name) + ((nb nn) 'no) + (else (string->symbol short-name)))) (if (hash-has-key? translation-map candidate) candidate 'en)) (define language (system-language)) @@ -156,7 +284,12 @@ (nl "Nederlands") (de "Deutsch") (fr "Français") - (es "Español"))) + (es "Español") + (it "Italiano") + (sv "Svenska") + (no "Norsk") + (fi "Suomi") + (is "Íslenska"))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; goal : Select the language used by tr and __. @@ -212,6 +345,8 @@ (check-equal? (tr 'connected) "Verbonden") (set-lang! 'de) (check-equal? (__ 'quit) "Beenden") + (set-lang! 'is) + (check-equal? (tr 'connected) "Tengt") (check-equal? (tr 'unknown-translation) "unknown-translation") (check-exn exn:fail:contract? (λ () (set-lang! 'xx)))) (λ () (set-lang! original-language)))) diff --git a/public/index.html b/public/index.html index c5bb91d..47a4596 100644 --- a/public/index.html +++ b/public/index.html @@ -20,7 +20,7 @@ diff --git a/public/translate.js b/public/translate.js index 86359dc..37e9a7b 100644 --- a/public/translate.js +++ b/public/translate.js @@ -122,12 +122,133 @@ authUnknown: "Estado de autenticación desconocido: {message}", noConnection: "Sin conexión: {message}", loggedOut: "Has cerrado la sesión.", volumePercent: "Ajustar volumen, {value} por ciento", }, + it: { + output: "USCITA", searchPlayers: "Cerca lettori di rete", logout: "ESCI", + rendererLocal: "LOCALE", defaultPlaylist: "Predefinita", + playbackControls: "Controlli di riproduzione", previousTrack: "Traccia precedente", + playOrPause: "Riproduci o metti in pausa", play: "Riproduci", pause: "Pausa", stop: "Arresta", + nextTrack: "Traccia successiva", playbackPosition: "Posizione di riproduzione", + repeatMode: "Modalità ripetizione", setVolume: "Regola il volume", volume: "Volume", + musicLibrary: "LIBRERIA MUSICALE", upFolder: "Cartella superiore", currentFolder: "Cartella corrente", + noLibraryConfigured: "Nessuna libreria configurata.", folderContents: "Contenuto della cartella", + nowPlaying: "IN RIPRODUZIONE", nothingSelected: "Nessuna selezione", + addTrackHint: "Aggiungi una traccia dalla libreria", playlists: "Playlist", + newPlaylist: "Nuova playlist", playlist: "PLAYLIST", clearList: "SVUOTA ELENCO", + emptyPlaylist: "Questa playlist è vuota.", emptyPlaylistHint: "Usa + accanto a una traccia o cartella.", + title: "TITOLO", album: "ALBUM", duration: "DURATA", actions: "Azioni", + connecting: "Connessione…", signIn: "Accedi", username: "Nome utente", + password: "Password", noLibrary: "Nessuna libreria", playNow: "Riproduci {name} ora", + addNamed: "Aggiungi {name}", loadingNamed: "Caricamento di {name}…", addingNamed: "Aggiunta di {name}…", + playlistName: "Nome della playlist", removePlaylist: "Rimuovi playlist", + removeNamed: "Rimuovi {name}", oneTrack: "traccia", manyTracks: "tracce", + repeatOff: "Ripetizione disattivata", repeatAll: "Ripeti tutto", repeatOne: "Ripeti una traccia", + channels: "canali", oneChannel: "canale", searchingPlayers: "Ricerca dei lettori di rete…", + authUnknown: "Stato di autenticazione sconosciuto: {message}", noConnection: "Nessuna connessione: {message}", + loggedOut: "Hai effettuato la disconnessione.", volumePercent: "Regola il volume, {value} percento", + }, + sv: { + output: "UTGÅNG", searchPlayers: "Sök efter nätverksspelare", logout: "LOGGA UT", + rendererLocal: "LOKAL", defaultPlaylist: "Standard", + playbackControls: "Uppspelningskontroller", previousTrack: "Föregående spår", + playOrPause: "Spela eller pausa", play: "Spela", pause: "Pausa", stop: "Stoppa", + nextTrack: "Nästa spår", playbackPosition: "Uppspelningsposition", + repeatMode: "Upprepningsläge", setVolume: "Ställ in volym", volume: "Volym", + musicLibrary: "MUSIKBIBLIOTEK", upFolder: "En mapp upp", currentFolder: "Aktuell mapp", + noLibraryConfigured: "Inget bibliotek har konfigurerats.", folderContents: "Mappinnehåll", + nowPlaying: "SPELAR NU", nothingSelected: "Inget har valts", + addTrackHint: "Lägg till ett spår från biblioteket", playlists: "Spellistor", + newPlaylist: "Ny spellista", playlist: "SPELLISTA", clearList: "TÖM LISTAN", + emptyPlaylist: "Den här spellistan är tom.", emptyPlaylistHint: "Använd + bredvid ett spår eller en mapp.", + title: "TITEL", album: "ALBUM", duration: "LÄNGD", actions: "Åtgärder", + connecting: "Ansluter…", signIn: "Logga in", username: "Användarnamn", + password: "Lösenord", noLibrary: "Inget bibliotek", playNow: "Spela {name} nu", + addNamed: "Lägg till {name}", loadingNamed: "Läser in {name}…", addingNamed: "Lägger till {name}…", + playlistName: "Spellistans namn", removePlaylist: "Ta bort spellista", + removeNamed: "Ta bort {name}", oneTrack: "spår", manyTracks: "spår", + repeatOff: "Upprepning av", repeatAll: "Upprepa alla", repeatOne: "Upprepa ett spår", + channels: "kanaler", oneChannel: "kanal", searchingPlayers: "Söker efter nätverksspelare…", + authUnknown: "Okänd autentiseringsstatus: {message}", noConnection: "Ingen anslutning: {message}", + loggedOut: "Du har loggats ut.", volumePercent: "Ställ in volymen på {value} procent", + }, + no: { + output: "UTGANG", searchPlayers: "Søk etter nettverksspillere", logout: "LOGG UT", + rendererLocal: "LOKAL", defaultPlaylist: "Standard", + playbackControls: "Avspillingskontroller", previousTrack: "Forrige spor", + playOrPause: "Spill av eller sett på pause", play: "Spill av", pause: "Pause", stop: "Stopp", + nextTrack: "Neste spor", playbackPosition: "Avspillingsposisjon", + repeatMode: "Gjentakelsesmodus", setVolume: "Still inn volum", volume: "Volum", + musicLibrary: "MUSIKKBIBLIOTEK", upFolder: "Én mappe opp", currentFolder: "Gjeldende mappe", + noLibraryConfigured: "Ingen bibliotek er konfigurert.", folderContents: "Mappeinnhold", + nowPlaying: "SPILLER NÅ", nothingSelected: "Ingenting er valgt", + addTrackHint: "Legg til et spor fra biblioteket", playlists: "Spillelister", + newPlaylist: "Ny spilleliste", playlist: "SPILLELISTE", clearList: "TØM LISTEN", + emptyPlaylist: "Denne spillelisten er tom.", emptyPlaylistHint: "Bruk + ved siden av et spor eller en mappe.", + title: "TITTEL", album: "ALBUM", duration: "VARIGHET", actions: "Handlinger", + connecting: "Kobler til…", signIn: "Logg inn", username: "Brukernavn", + password: "Passord", noLibrary: "Ingen bibliotek", playNow: "Spill av {name} nå", + addNamed: "Legg til {name}", loadingNamed: "Laster inn {name}…", addingNamed: "Legger til {name}…", + playlistName: "Navn på spilleliste", removePlaylist: "Fjern spilleliste", + removeNamed: "Fjern {name}", oneTrack: "spor", manyTracks: "spor", + repeatOff: "Gjentakelse av", repeatAll: "Gjenta alle", repeatOne: "Gjenta ett spor", + channels: "kanaler", oneChannel: "kanal", searchingPlayers: "Søker etter nettverksspillere…", + authUnknown: "Ukjent autentiseringsstatus: {message}", noConnection: "Ingen tilkobling: {message}", + loggedOut: "Du er logget ut.", volumePercent: "Still inn volumet på {value} prosent", + }, + fi: { + output: "ULOSTULO", searchPlayers: "Etsi verkkosoittimia", logout: "KIRJAUDU ULOS", + rendererLocal: "PAIKALLINEN", defaultPlaylist: "Oletus", + playbackControls: "Toiston ohjaimet", previousTrack: "Edellinen kappale", + playOrPause: "Toista tai keskeytä", play: "Toista", pause: "Keskeytä", stop: "Pysäytä", + nextTrack: "Seuraava kappale", playbackPosition: "Toistokohta", + repeatMode: "Toistotila", setVolume: "Säädä äänenvoimakkuutta", volume: "Äänenvoimakkuus", + musicLibrary: "MUSIIKKIKIRJASTO", upFolder: "Yksi kansio ylöspäin", currentFolder: "Nykyinen kansio", + noLibraryConfigured: "Kirjastoa ei ole määritetty.", folderContents: "Kansion sisältö", + nowPlaying: "NYT TOISTETAAN", nothingSelected: "Mitään ei ole valittu", + addTrackHint: "Lisää kappale kirjastosta", playlists: "Soittolistat", + newPlaylist: "Uusi soittolista", playlist: "SOITTOLISTA", clearList: "TYHJENNÄ LISTA", + emptyPlaylist: "Tämä soittolista on tyhjä.", emptyPlaylistHint: "Käytä + kappaleen tai kansion vieressä.", + title: "NIMI", album: "ALBUMI", duration: "KESTO", actions: "Toiminnot", + connecting: "Yhdistetään…", signIn: "Kirjaudu sisään", username: "Käyttäjänimi", + password: "Salasana", noLibrary: "Ei kirjastoa", playNow: "Toista {name} nyt", + addNamed: "Lisää {name}", loadingNamed: "Ladataan {name}…", addingNamed: "Lisätään {name}…", + playlistName: "Soittolistan nimi", removePlaylist: "Poista soittolista", + removeNamed: "Poista {name}", oneTrack: "kappale", manyTracks: "kappaletta", + repeatOff: "Toisto pois", repeatAll: "Toista kaikki", repeatOne: "Toista yksi kappale", + channels: "kanavaa", oneChannel: "kanava", searchingPlayers: "Etsitään verkkosoittimia…", + authUnknown: "Todennuksen tila ei ole tiedossa: {message}", noConnection: "Ei yhteyttä: {message}", + loggedOut: "Olet kirjautunut ulos.", volumePercent: "Säädä äänenvoimakkuudeksi {value} prosenttia", + }, + is: { + output: "ÚTTAK", searchPlayers: "Leita að netspilurum", logout: "SKRÁ ÚT", + rendererLocal: "STAÐBUNDIÐ", defaultPlaylist: "Sjálfgefið", + playbackControls: "Stýringar spilunar", previousTrack: "Fyrra lag", + playOrPause: "Spila eða gera hlé", play: "Spila", pause: "Gera hlé", stop: "Stöðva", + nextTrack: "Næsta lag", playbackPosition: "Staða spilunar", + repeatMode: "Endurtekningarhamur", setVolume: "Stilla hljóðstyrk", volume: "Hljóðstyrkur", + musicLibrary: "TÓNLISTARSAFN", upFolder: "Eina möppu upp", currentFolder: "Núverandi mappa", + noLibraryConfigured: "Ekkert safn er skilgreint.", folderContents: "Innihald möppu", + nowPlaying: "Í SPILUN", nothingSelected: "Ekkert valið", + addTrackHint: "Bættu lagi við úr safninu", playlists: "Spilunarlistar", + newPlaylist: "Nýr spilunarlisti", playlist: "SPILUNARLISTI", clearList: "HREINSA LISTA", + emptyPlaylist: "Þessi spilunarlisti er tómur.", emptyPlaylistHint: "Notaðu + við hlið lags eða möppu.", + title: "TITILL", album: "PLATA", duration: "LENGD", actions: "Aðgerðir", + connecting: "Tengist…", signIn: "Skrá inn", username: "Notandanafn", + password: "Lykilorð", noLibrary: "Ekkert safn", playNow: "Spila {name} núna", + addNamed: "Bæta {name} við", loadingNamed: "Hleður {name}…", addingNamed: "Bætir {name} við…", + playlistName: "Heiti spilunarlista", removePlaylist: "Fjarlægja spilunarlista", + removeNamed: "Fjarlægja {name}", oneTrack: "lag", manyTracks: "lög", + repeatOff: "Endurtekning óvirk", repeatAll: "Endurtaka allt", repeatOne: "Endurtaka eitt lag", + channels: "rásir", oneChannel: "rás", searchingPlayers: "Leita að netspilurum…", + authUnknown: "Staða auðkenningar óþekkt: {message}", noConnection: "Engin tenging: {message}", + loggedOut: "Þú hefur skráð þig út.", volumePercent: "Stilla hljóðstyrk á {value} prósent", + }, }; const supported = Object.keys(translations); const requested = [...(navigator.languages || [navigator.language])] .filter(Boolean) - .map((value) => value.toLowerCase().split("-")[0]); + .map((value) => value.toLowerCase().split("-")[0]) + .map((value) => ({ nb: "no", nn: "no" })[value] || value); let language = requested.find((value) => supported.includes(value)) || "en"; function t(key, values = {}) { diff --git a/scribblings/rkt-web-player.scrbl b/scribblings/rkt-web-player.scrbl index 37a1228..4f13b1c 100644 --- a/scribblings/rkt-web-player.scrbl +++ b/scribblings/rkt-web-player.scrbl @@ -51,8 +51,9 @@ Each username owns an ordered GUID index and separate playlist values. It also owns an independent playback pipeline and a durable interface-language preference. Different outputs can play concurrently. Selecting an output that another user owns stops the previous backend and transfers that output. The web -interface supports Dutch, English, German, French and Spanish; browser language -is the initial default and a manual choice is stored per username. +interface supports Dutch, English, German, French, Spanish, Italian, Swedish, +Norwegian, Finnish and Icelandic; browser language is the initial default and a +manual choice is stored per username. When @racket[users] is non-empty, every browser client must authenticate. Sessions have a sliding idle timeout; an active browser cookie is renewed once half of @racket[session-seconds] has elapsed. Playback-agent endpoints continue @@ -86,8 +87,8 @@ configured RKT Web Player server, downloads assigned tracks over HTTP, and plays them with @tt{racket-audio}. Its configured display name is authoritative and is followed by the server. Importing the module does not start the GUI; the function must be called explicitly. -The GUI and optional tray use Dutch, English, German, French or Spanish based -on the operating-system language, with English as fallback. +The GUI and optional tray support the same ten languages based on the +operating-system language, with English as fallback. } @defproc[(run-player-agent-cli [#:server-url server-url