option to add custom UI translations

This commit is contained in:
ed 2024-05-09 23:09:45 +00:00
parent 87c60a1ec9
commit 19d156ff4e
4 changed files with 73 additions and 45 deletions

View file

@ -230,6 +230,7 @@ also see [comparison to similar software](./docs/versus.md)
* ☑ ...of videos using FFmpeg * ☑ ...of videos using FFmpeg
* ☑ ...of audio (spectrograms) using FFmpeg * ☑ ...of audio (spectrograms) using FFmpeg
* ☑ cache eviction (max-age; maybe max-size eventually) * ☑ cache eviction (max-age; maybe max-size eventually)
* ☑ multilingual UI (english, norwegian, [add your own](./docs/rice/#translations)))
* ☑ SPA (browse while uploading) * ☑ SPA (browse while uploading)
* server indexing * server indexing
* ☑ [locate files by contents](#file-search) * ☑ [locate files by contents](#file-search)
@ -1088,7 +1089,7 @@ tweaking the ui
* to sort in music order (album, track, artist, title) with filename as fallback, you could `--sort tags/Cirle,tags/.tn,tags/Artist,tags/Title,href` * to sort in music order (album, track, artist, title) with filename as fallback, you could `--sort tags/Cirle,tags/.tn,tags/Artist,tags/Title,href`
* to sort by upload date, first enable showing the upload date in the listing with `-e2d -mte +.up_at` and then `--sort tags/.up_at` * to sort by upload date, first enable showing the upload date in the listing with `-e2d -mte +.up_at` and then `--sort tags/.up_at`
see [./docs/rice](./docs/rice) for more, including how to add stuff (css/`<meta>`/...) to the html `<head>` tag see [./docs/rice](./docs/rice) for more, including how to add stuff (css/`<meta>`/...) to the html `<head>` tag, or to add your own translation
## opengraph ## opengraph

View file

@ -141,7 +141,7 @@ var Ls = {
"ut_rand": "randomize filenames", "ut_rand": "randomize filenames",
"ut_u2ts": "copy the last-modified timestamp$Nfrom your filesystem to the server", "ut_u2ts": "copy the last-modified timestamp$Nfrom your filesystem to the server",
"ut_mt": "continue hashing other files while uploading$N$Nmaybe disable if your CPU or HDD is a bottleneck", "ut_mt": "continue hashing other files while uploading$N$Nmaybe disable if your CPU or HDD is a bottleneck",
"ut_ask": "ask for confirmation before upload starts", "ut_ask": 'ask for confirmation before upload starts">💭',
"ut_pot": "improve upload speed on slow devices$Nby making the UI less complex", "ut_pot": "improve upload speed on slow devices$Nby making the UI less complex",
"ut_srch": "don't actually upload, instead check if the files already $N exist on the server (will scan all folders you can read)", "ut_srch": "don't actually upload, instead check if the files already $N exist on the server (will scan all folders you can read)",
"ut_par": "pause uploads by setting it to 0$N$Nincrease if your connection is slow / high latency$N$Nkeep it 1 on LAN or if the server HDD is a bottleneck", "ut_par": "pause uploads by setting it to 0$N$Nincrease if your connection is slow / high latency$N$Nkeep it 1 on LAN or if the server HDD is a bottleneck",
@ -194,20 +194,21 @@ var Ls = {
"cl_hpick": "tap on column headers to hide in the table below", "cl_hpick": "tap on column headers to hide in the table below",
"cl_hcancel": "column hiding aborted", "cl_hcancel": "column hiding aborted",
"ct_thumb": "in grid-view, toggle icons or thumbnails$NHotkey: T", "ct_grid": '田 the grid',
"ct_csel": "use CTRL and SHIFT for file selection in grid-view", "ct_thumb": 'in grid-view, toggle icons or thumbnails$NHotkey: T">🖼️ thumbs',
"ct_ihop": "when the image viewer is closed, scroll down to the last viewed file", "ct_csel": 'use CTRL and SHIFT for file selection in grid-view">sel',
"ct_dots": "show hidden files (if server permits)", "ct_ihop": 'when the image viewer is closed, scroll down to the last viewed file">g⮯',
"ct_dir1st": "sort folders before files", "ct_dots": 'show hidden files (if server permits)">dotfiles',
"ct_readme": "show README.md in folder listings", "ct_dir1st": 'sort folders before files">📁 first',
"ct_idxh": "show index.html instead of folder listing", "ct_readme": 'show README.md in folder listings">📜 readme',
"ct_sbars": "show scrollbars", "ct_idxh": 'show index.html instead of folder listing">htm',
"ct_sbars": 'show scrollbars">⟊',
"cut_umod": "if a file already exists on the server, update the server's last-modified timestamp to match your local file (requires write+delete permissions)", "cut_umod": "if a file already exists on the server, update the server's last-modified timestamp to match your local file (requires write+delete permissions)\">re📅",
"cut_turbo": "the yolo button, you probably DO NOT want to enable this:$N$Nuse this if you were uploading a huge amount of files and had to restart for some reason, and want to continue the upload ASAP$N$Nthis replaces the hash-check with a simple <em>&quot;does this have the same filesize on the server?&quot;</em> so if the file contents are different it will NOT be uploaded$N$Nyou should turn this off when the upload is done, and then &quot;upload&quot; the same files again to let the client verify them", "cut_turbo": "the yolo button, you probably DO NOT want to enable this:$N$Nuse this if you were uploading a huge amount of files and had to restart for some reason, and want to continue the upload ASAP$N$Nthis replaces the hash-check with a simple <em>&quot;does this have the same filesize on the server?&quot;</em> so if the file contents are different it will NOT be uploaded$N$Nyou should turn this off when the upload is done, and then &quot;upload&quot; the same files again to let the client verify them\">turbo",
"cut_datechk": "has no effect unless the turbo button is enabled$N$Nreduces the yolo factor by a tiny amount; checks whether the file timestamps on the server matches yours$N$Nshould <em>theoretically</em> catch most unfinished / corrupted uploads, but is not a substitute for doing a verification pass with turbo disabled afterwards", "cut_datechk": "has no effect unless the turbo button is enabled$N$Nreduces the yolo factor by a tiny amount; checks whether the file timestamps on the server matches yours$N$Nshould <em>theoretically</em> catch most unfinished / corrupted uploads, but is not a substitute for doing a verification pass with turbo disabled afterwards\">date-chk",
"cut_flag": "ensure only one tab is uploading at a time $N -- other tabs must have this enabled too $N -- only affects tabs on the same domain", "cut_flag": "ensure only one tab is uploading at a time $N -- other tabs must have this enabled too $N -- only affects tabs on the same domain",
@ -216,7 +217,7 @@ var Ls = {
"cut_nag": "OS notification when upload completes$N(only if the browser or tab is not active)", "cut_nag": "OS notification when upload completes$N(only if the browser or tab is not active)",
"cut_sfx": "audible alert when upload completes$N(only if the browser or tab is not active)", "cut_sfx": "audible alert when upload completes$N(only if the browser or tab is not active)",
"cut_mt": "use multithreading to accelerate file hashing$N$Nthis uses web-workers and requires$Nmore RAM (up to 512 MiB extra)$N$N30% faster https, 4.5x faster http,$Nand 5.3x faster on android phones", "cut_mt": "use multithreading to accelerate file hashing$N$Nthis uses web-workers and requires$Nmore RAM (up to 512 MiB extra)$N$N30% faster https, 4.5x faster http,$Nand 5.3x faster on android phones\">mt",
"cft_text": "favicon text (blank and refresh to disable)", "cft_text": "favicon text (blank and refresh to disable)",
"cft_fg": "foreground color", "cft_fg": "foreground color",
@ -650,7 +651,7 @@ var Ls = {
"ut_rand": "finn opp nye tilfeldige filnavn", "ut_rand": "finn opp nye tilfeldige filnavn",
"ut_u2ts": "gi filen på serveren samme$Ntidsstempel som lokalt hos deg", "ut_u2ts": "gi filen på serveren samme$Ntidsstempel som lokalt hos deg",
"ut_mt": "fortsett å befare køen mens opplastning foregår$N$Nskru denne av dersom du har en$Ntreg prosessor eller harddisk", "ut_mt": "fortsett å befare køen mens opplastning foregår$N$Nskru denne av dersom du har en$Ntreg prosessor eller harddisk",
"ut_ask": "bekreft filutvalg før opplastning starter", "ut_ask": 'bekreft filutvalg før opplastning starter">💭',
"ut_pot": "forbedre ytelsen på trege enheter ved å$Nforenkle brukergrensesnittet", "ut_pot": "forbedre ytelsen på trege enheter ved å$Nforenkle brukergrensesnittet",
"ut_srch": "utfør søk istedenfor å laste opp --$Nleter igjennom alle mappene du har lov til å se", "ut_srch": "utfør søk istedenfor å laste opp --$Nleter igjennom alle mappene du har lov til å se",
"ut_par": "sett til 0 for å midlertidig stanse opplastning$N$Nhøye verdier (4 eller 8) kan gi bedre ytelse,$Nspesielt på trege internettlinjer$N$Nbør ikke være høyere enn 1 på LAN$Neller hvis serveren sin harddisk er treg", "ut_par": "sett til 0 for å midlertidig stanse opplastning$N$Nhøye verdier (4 eller 8) kan gi bedre ytelse,$Nspesielt på trege internettlinjer$N$Nbør ikke være høyere enn 1 på LAN$Neller hvis serveren sin harddisk er treg",
@ -703,20 +704,21 @@ var Ls = {
"cl_hpick": "klikk på overskriften til kolonnene du ønsker å skjule i tabellen nedenfor", "cl_hpick": "klikk på overskriften til kolonnene du ønsker å skjule i tabellen nedenfor",
"cl_hcancel": "kolonne-skjuling avbrutt", "cl_hcancel": "kolonne-skjuling avbrutt",
"ct_thumb": "vis miniatyrbilder istedenfor ikoner$NSnarvei: T", "ct_grid": '田 ikoner',
"ct_csel": "bruk tastene CTRL og SHIFT for markering av filer i ikonvisning", "ct_thumb": 'vis miniatyrbilder istedenfor ikoner$NSnarvei: T">🖼️ bilder',
"ct_ihop": "bla ned til sist viste bilde når bildeviseren lukkes", "ct_csel": 'bruk tastene CTRL og SHIFT for markering av filer i ikonvisning">merk',
"ct_dots": "vis skjulte filer (gitt at serveren tillater det)", "ct_ihop": 'bla ned til sist viste bilde når bildeviseren lukkes">g⮯',
"ct_dir1st": "sorter slik at mapper kommer foran filer", "ct_dots": 'vis skjulte filer (gitt at serveren tillater det)">.synlig',
"ct_readme": "vis README.md nedenfor filene", "ct_dir1st": 'sorter slik at mapper kommer foran filer">📁 først',
"ct_idxh": "vis index.html istedenfor fil-liste", "ct_readme": 'vis README.md nedenfor filene">📜 readme',
"ct_sbars": "vis rullgardiner / skrollefelt", "ct_idxh": 'vis index.html istedenfor fil-liste">htm',
"ct_sbars": 'vis rullgardiner / skrollefelt">⟊',
"cut_umod": "i tilfelle en fil du laster opp allerede finnes på serveren, så skal serverens tidsstempel oppdateres slik at det stemmer overens med din lokale fil (krever rettighetene write+delete)", "cut_umod": 'i tilfelle en fil du laster opp allerede finnes på serveren, så skal serverens tidsstempel oppdateres slik at det stemmer overens med din lokale fil (krever rettighetene write+delete)">re📅',
"cut_turbo": "forenklet befaring ved opplastning; bør sannsynlig <em>ikke</em> skrus på:$N$Nnyttig dersom du var midt i en svær opplastning som måtte restartes av en eller annen grunn, og du vil komme igang igjen så raskt som overhodet mulig.$N$Nnår denne er skrudd på så forenkles befaringen kraftig; istedenfor å utføre en trygg sjekk på om filene finnes på serveren i god stand, så sjekkes kun om <em>filstørrelsen</em> stemmer. Så dersom en korrupt fil skulle befinne seg på serveren allerede, på samme sted med samme størrelse og navn, så blir det <em>ikke oppdaget</em>.$N$Ndet anbefales å kun benytte denne funksjonen for å komme seg raskt igjennom selve opplastningen, for så å skru den av, og til slutt &quot;laste opp&quot; de samme filene én gang til -- slik at integriteten kan verifiseres", "cut_turbo": "forenklet befaring ved opplastning; bør sannsynlig <em>ikke</em> skrus på:$N$Nnyttig dersom du var midt i en svær opplastning som måtte restartes av en eller annen grunn, og du vil komme igang igjen så raskt som overhodet mulig.$N$Nnår denne er skrudd på så forenkles befaringen kraftig; istedenfor å utføre en trygg sjekk på om filene finnes på serveren i god stand, så sjekkes kun om <em>filstørrelsen</em> stemmer. Så dersom en korrupt fil skulle befinne seg på serveren allerede, på samme sted med samme størrelse og navn, så blir det <em>ikke oppdaget</em>.$N$Ndet anbefales å kun benytte denne funksjonen for å komme seg raskt igjennom selve opplastningen, for så å skru den av, og til slutt &quot;laste opp&quot; de samme filene én gang til -- slik at integriteten kan verifiseres\">turbo",
"cut_datechk": "har ingen effekt dersom turbo er avslått$N$Ngjør turbo bittelitt tryggere ved å sjekke datostemplingen på filene (i tillegg til filstørrelse)$N$N<em>burde</em> oppdage og gjenoppta de fleste ufullstendige opplastninger, men er <em>ikke</em> en fullverdig erstatning for å deaktivere turbo og gjøre en skikkelig sjekk", "cut_datechk": "har ingen effekt dersom turbo er avslått$N$Ngjør turbo bittelitt tryggere ved å sjekke datostemplingen på filene (i tillegg til filstørrelse)$N$N<em>burde</em> oppdage og gjenoppta de fleste ufullstendige opplastninger, men er <em>ikke</em> en fullverdig erstatning for å deaktivere turbo og gjøre en skikkelig sjekk\">date-chk",
"cut_flag": "samkjører nettleserfaner slik at bare én $N kan holde på med befaring / opplastning $N -- andre faner må også ha denne skrudd på $N -- fungerer kun innenfor samme domene", "cut_flag": "samkjører nettleserfaner slik at bare én $N kan holde på med befaring / opplastning $N -- andre faner må også ha denne skrudd på $N -- fungerer kun innenfor samme domene",
@ -725,7 +727,7 @@ var Ls = {
"cut_nag": "meldingsvarsel når opplastning er ferdig$N(kun on nettleserfanen ikke er synlig)", "cut_nag": "meldingsvarsel når opplastning er ferdig$N(kun on nettleserfanen ikke er synlig)",
"cut_sfx": "lydvarsel når opplastning er ferdig$N(kun on nettleserfanen ikke er synlig)", "cut_sfx": "lydvarsel når opplastning er ferdig$N(kun on nettleserfanen ikke er synlig)",
"cut_mt": "raskere befaring ved å bruke hele CPU'en$N$Ndenne funksjonen anvender web-workers$Nog krever mer RAM (opptil 512 MiB ekstra)$N$N30% raskere https, 4.5x raskere http,$Nog 5.3x raskere på android-telefoner", "cut_mt": "raskere befaring ved å bruke hele CPU'en$N$Ndenne funksjonen anvender web-workers$Nog krever mer RAM (opptil 512 MiB ekstra)$N$N30% raskere https, 4.5x raskere http,$Nog 5.3x raskere på android-telefoner\">mt",
"cft_text": "ikontekst (blank ut og last siden på nytt for å deaktivere)", "cft_text": "ikontekst (blank ut og last siden på nytt for å deaktivere)",
"cft_fg": "farge", "cft_fg": "farge",
@ -1022,8 +1024,13 @@ var Ls = {
"lang_set": "passer det å laste siden på nytt?", "lang_set": "passer det å laste siden på nytt?",
}, },
}; };
var LANGS = ["eng", "nor"],
L = Ls[sread("cpp_lang", LANGS) || lang] || Ls.eng || Ls.nor; var LANGS = ["eng", "nor"];
if (window.langmod)
langmod();
var L = Ls[sread("cpp_lang", LANGS) || lang] || Ls.eng || Ls.nor;
for (var a = 0; a < LANGS.length; a++) { for (var a = 0; a < LANGS.length; a++) {
for (var b = a + 1; b < LANGS.length; b++) { for (var b = a + 1; b < LANGS.length; b++) {
@ -1210,15 +1217,15 @@ ebi('op_cfg').innerHTML = (
' <h3>' + L.cl_opts + '</h3>\n' + ' <h3>' + L.cl_opts + '</h3>\n' +
' <div>\n' + ' <div>\n' +
' <a id="tooltips" class="tgl btn" href="#" tt="◔ ◡ ◔"> tooltips</a>\n' + ' <a id="tooltips" class="tgl btn" href="#" tt="◔ ◡ ◔"> tooltips</a>\n' +
' <a id="griden" class="tgl btn" href="#" tt="' + L.wt_grid + '">田 the grid</a>\n' + ' <a id="griden" class="tgl btn" href="#" tt="' + L.wt_grid + '">' + L.ct_grid + '</a>\n' +
' <a id="thumbs" class="tgl btn" href="#" tt="' + L.ct_thumb + '">🖼️ thumbs</a>\n' + ' <a id="thumbs" class="tgl btn" href="#" tt="' + L.ct_thumb + '</a>\n' +
' <a id="csel" class="tgl btn" href="#" tt="' + L.ct_csel + '">sel</a>\n' + ' <a id="csel" class="tgl btn" href="#" tt="' + L.ct_csel + '</a>\n' +
' <a id="ihop" class="tgl btn" href="#" tt="' + L.ct_ihop + '">g⮯</a>\n' + ' <a id="ihop" class="tgl btn" href="#" tt="' + L.ct_ihop + '</a>\n' +
' <a id="dotfiles" class="tgl btn" href="#" tt="' + L.ct_dots + '">dotfiles</a>\n' + ' <a id="dotfiles" class="tgl btn" href="#" tt="' + L.ct_dots + '</a>\n' +
' <a id="dir1st" class="tgl btn" href="#" tt="' + L.ct_dir1st + '">📁 first</a>\n' + ' <a id="dir1st" class="tgl btn" href="#" tt="' + L.ct_dir1st + '</a>\n' +
' <a id="ireadme" class="tgl btn" href="#" tt="' + L.ct_readme + '">📜 readme</a>\n' + ' <a id="ireadme" class="tgl btn" href="#" tt="' + L.ct_readme + '</a>\n' +
' <a id="idxh" class="tgl btn" href="#" tt="' + L.ct_idxh + '">htm</a>\n' + ' <a id="idxh" class="tgl btn" href="#" tt="' + L.ct_idxh + '</a>\n' +
' <a id="sbars" class="tgl btn" href="#" tt="' + L.ct_sbars + '">⟊</a>\n' + ' <a id="sbars" class="tgl btn" href="#" tt="' + L.ct_sbars + '</a>\n' +
' </div>\n' + ' </div>\n' +
'</div>\n' + '</div>\n' +
'<div>\n' + '<div>\n' +
@ -1237,11 +1244,11 @@ ebi('op_cfg').innerHTML = (
'<div>\n' + '<div>\n' +
' <h3>' + L.cl_uopts + '</h3>\n' + ' <h3>' + L.cl_uopts + '</h3>\n' +
' <div>\n' + ' <div>\n' +
' <a id="ask_up" class="tgl btn" href="#" tt="' + L.ut_ask + '">💭</a>\n' + ' <a id="ask_up" class="tgl btn" href="#" tt="' + L.ut_ask + '</a>\n' +
' <a id="umod" class="tgl btn" href="#" tt="' + L.cut_umod + '">re📅</a>\n' + ' <a id="umod" class="tgl btn" href="#" tt="' + L.cut_umod + '</a>\n' +
' <a id="hashw" class="tgl btn" href="#" tt="' + L.cut_mt + '">mt</a>\n' + ' <a id="hashw" class="tgl btn" href="#" tt="' + L.cut_mt + '</a>\n' +
' <a id="u2turbo" class="tgl btn ttb" href="#" tt="' + L.cut_turbo + '">turbo</a>\n' + ' <a id="u2turbo" class="tgl btn ttb" href="#" tt="' + L.cut_turbo + '</a>\n' +
' <a id="u2tdate" class="tgl btn ttb" href="#" tt="' + L.cut_datechk + '">date-chk</a>\n' + ' <a id="u2tdate" class="tgl btn ttb" href="#" tt="' + L.cut_datechk + '</a>\n' +
' <a id="flag_en" class="tgl btn" href="#" tt="' + L.cut_flag + '">💤</a>\n' + ' <a id="flag_en" class="tgl btn" href="#" tt="' + L.cut_flag + '">💤</a>\n' +
' <a id="u2sort" class="tgl btn" href="#" tt="' + L.cut_az + '">az</a>\n' + ' <a id="u2sort" class="tgl btn" href="#" tt="' + L.cut_az + '">az</a>\n' +
' <a id="upnag" class="tgl btn" href="#" tt="' + L.cut_nag + '">🔔</a>\n' + ' <a id="upnag" class="tgl btn" href="#" tt="' + L.cut_nag + '">🔔</a>\n' +

View file

@ -34,8 +34,14 @@ var Ls = {
"u2": "time since the last server write$N( upload / rename / ... )$N$N17d = 17 days$N1h23 = 1 hour 23 minutes$N4m56 = 4 minutes 56 seconds", "u2": "time since the last server write$N( upload / rename / ... )$N$N17d = 17 days$N1h23 = 1 hour 23 minutes$N4m56 = 4 minutes 56 seconds",
"v2": "use this server as a local HDD$N$NWARNING: this will show your password!", "v2": "use this server as a local HDD$N$NWARNING: this will show your password!",
} }
}, };
d = Ls[sread("cpp_lang", ["eng", "nor"]) || lang] || Ls.eng || Ls.nor;
var LANGS = ["eng", "nor"];
if (window.langmod)
langmod();
var d = Ls[sread("cpp_lang", LANGS) || lang] || Ls.eng || Ls.nor;
for (var k in (d || {})) { for (var k in (d || {})) {
var f = k.slice(-1), var f = k.slice(-1),

View file

@ -55,3 +55,17 @@ to add stuff to the html `<head>`, for example a css `<link>` or `<meta>` tags,
if you give it the value `@ASDF` it will try to open a file named ASDF and send the text within if you give it the value `@ASDF` it will try to open a file named ASDF and send the text within
if the value starts with `%` it will assume a jinja2 template and expand it; the template has access to the `HttpCli` object through a property named `this` as well as everything in `j2a` and the stuff added by `self.j2s`; see [browser.html](https://github.com/9001/copyparty/blob/hovudstraum/copyparty/web/browser.html) for inspiration or look under the hood in [httpcli.py](https://github.com/9001/copyparty/blob/hovudstraum/copyparty/httpcli.py) if the value starts with `%` it will assume a jinja2 template and expand it; the template has access to the `HttpCli` object through a property named `this` as well as everything in `j2a` and the stuff added by `self.j2s`; see [browser.html](https://github.com/9001/copyparty/blob/hovudstraum/copyparty/web/browser.html) for inspiration or look under the hood in [httpcli.py](https://github.com/9001/copyparty/blob/hovudstraum/copyparty/httpcli.py)
# translations
add your own translations by using the english or norwegian one from `browser.js` as a template
the easy way is to open up and modify `browser.js` in your own installation; depending on how you installed copyparty it might be named `browser.js.gz` instead, in which case just decompress it, restart copyparty, and start editing it anyways
if you're running `copyparty-sfx.py` then you'll find it at `/tmp/pe-copyparty.1000/copyparty/web` (on linux) or `%TEMP%\pe-copyparty\copyparty\web` (on windows)
* make sure to keep backups of your work religiously! since that location is volatile af
if editing `browser.js` is inconvenient in your setup then you can instead do this:
* add your translation to a separate javascript file (`tl.js`) and make it load before `browser.js` with the help of `--html-head='<script src="/tl.js"></script>'`
* as the page loads, `browser.js` will look for a function named `langmod` so define that function and make it insert your translation into the `Ls` and `LANGS` variables so it'll take effect