tl-split: draw the rest of the owl

This commit is contained in:
ed
2025-10-12 22:49:47 +00:00
parent ff01723c6d
commit d099e5e84e
17 changed files with 159 additions and 112 deletions

View File

@@ -39,7 +39,7 @@ if you wanna have a go at coding it up yourself then maybe mention the idea on d
aside from documentation and ideas, some other things that would be cool to have some help with is:
* **translations** -- the copyparty web-UI has translations for english and norwegian at the top of [browser.js](https://github.com/9001/copyparty/blob/hovudstraum/copyparty/web/browser.js); if you'd like to add a translation for another language then that'd be welcome! and if that language has a grammar that doesn't fit into the way the strings are assembled, then we'll fix that as we go :>
* **translations** -- the copyparty web-UI has translations in [copyparty/web/tl](https://github.com/9001/copyparty/tree/hovudstraum/copyparty/web/tl); if you'd like to [add a translation](https://github.com/9001/copyparty/tree/hovudstraum/docs/rice#translations) for another language then that'd be welcome! and if that language has a grammar that doesn't fit into the way the strings are assembled, then we'll fix that as we go :>
* but please note that support for [RTL (Right-to-Left) languages](https://en.wikipedia.org/wiki/Right-to-left_script) is currently not planned, since the javascript is a bit too jank for that

View File

@@ -100,6 +100,25 @@ web/splash.html
web/splash.js
web/svcs.html
web/svcs.js
web/tl/chi.js
web/tl/cze.js
web/tl/deu.js
web/tl/epo.js
web/tl/fin.js
web/tl/fra.js
web/tl/grc.js
web/tl/ita.js
web/tl/kor.js
web/tl/nld.js
web/tl/nno.js
web/tl/nor.js
web/tl/pol.js
web/tl/por.js
web/tl/rus.js
web/tl/spa.js
web/tl/swe.js
web/tl/tur.js
web/tl/ukr.js
web/ui.css
web/up2k.js
web/util.js

View File

@@ -275,7 +275,7 @@ class HttpCli(object):
tpl = self.conn.hsrv.j2[name]
ka["r"] = self.args.SR if self.is_vproxied else ""
ka["ts"] = self.conn.hsrv.cachebuster()
ka["lang"] = self.args.lang
ka["lang"] = self.cookies.get("cplng") or self.args.lang
ka["favico"] = self.args.favico
ka["s_doctitle"] = self.args.doctitle
ka["tcolor"] = self.vn.flags["tcolor"]
@@ -5077,7 +5077,7 @@ class HttpCli(object):
"edit": "edit" in self.uparam,
"title": html_escape(self.vpath, crlf=True),
"lastmod": int(ts_md * 1000),
"lang": self.args.lang,
"lang": self.cookies.get("cplng") or self.args.lang,
"favico": self.args.favico,
"have_emp": int(self.args.emp),
"md_no_br": int(vn.flags.get("md_no_br") or 0),

View File

@@ -2,8 +2,8 @@
# which should help on really slow connections
# but then why are you using copyparty in the first place
pk: $(addsuffix .gz, $(wildcard *.js *.css))
un: $(addsuffix .un, $(wildcard *.gz))
pk: $(addsuffix .gz, $(wildcard tl/*.js *.js *.css))
un: $(addsuffix .un, $(wildcard tl/*.gz *.gz))
%.gz: %
pigz -11 -J 34 -I 573 $<

View File

@@ -145,6 +145,9 @@
document.documentElement.className = (STG && STG.cpp_thm) || dtheme;
</script>
<script src="{{ r }}/.cpr/util.js?_={{ ts }}"></script>
{%- if lang != "eng" %}
<script src="{{ r }}/.cpr/tl/{{ lang }}.js?_={{ ts }}"></script>
{%- endif %}
<script src="{{ r }}/.cpr/baguettebox.js?_={{ ts }}"></script>
<script src="{{ r }}/.cpr/browser.js?_={{ ts }}"></script>
<script src="{{ r }}/.cpr/up2k.js?_={{ ts }}"></script>

View File

@@ -3,10 +3,8 @@
var XHR = XMLHttpRequest,
img_re = /\.(a?png|avif|bmp|gif|heif|jpe?g|jfif|svg|webp|webm|mkv|mp4|m4v|mov)(\?|$)/i;
// please add translations in alphabetic order, but keep "eng" and "nor" first
// (lines ending with //m are machine translations)
var Ls = {
"eng": {
if (1)
Ls.eng = {
"tt": "English",
"cols": {
@@ -26,7 +24,7 @@ var Ls = {
"resw": "horizontal resolution",
"resh": "vertical resolution",
"chs": "audio channels",
"hz": "sample rate"
"hz": "sample rate",
},
"hks": [
@@ -639,18 +637,43 @@ var Ls = {
"lang_set": "refresh to make the change take effect?",
};
var LANGS = ["eng", "nor", "chi", "cze", "deu", "epo", "fin", "fra", "grc", "ita", "kor", "nld", "nno", "pol", "por", "rus", "spa", "swe", "tur", "ukr"];
var LANGN = [
["eng", "English"],
["nor", "Norsk"],
["chi", "中文"],
["cze", "Čeština"],
["deu", "Deutsch"],
["epo", "Esperanto"],
["fin", "Suomi"],
["fra", "français"],
["grc", "Ελληνικά"],
["ita", "Italiano"],
["kor", "한국어"],
["nld", "Nederlands"],
["nno", "Nynorsk"],
["pol", "Polski"],
["por", "Português"],
["rus", "Русский"],
["spa", "Español"],
["swe", "Svenska"],
["tur", "Türkçe"],
["ukr", "Українська"],
];
if (window.langmod)
langmod();
for (var a = LANGS.length; a > 0;)
if (!Ls[LANGS[--a]])
LANGS.splice(a, 1);
var L = Ls[lang] || Ls.eng, LANGS = [];
for (var a = 0; a < LANGN.length; a++)
LANGS.push(LANGN[a][0]);
var L = Ls[sread("cpp_lang", LANGS) || lang] ||
Ls.eng || Ls.nor || Ls.chi;
function langtest() {
var n = LANGS.length - 1;
for (var a = 1; a < LANGS.length; a++)
import_js(SR + '/.cpr/tl/' + LANGS[a] + '.js', function () { if (!--n) langtest2(); });
}
function langtest2() {
for (var a = 0; a < LANGS.length; a++) {
for (var b = a + 1; b < LANGS.length; b++) {
var i1 = Object.keys(Ls[LANGS[a]]).length > Object.keys(Ls[LANGS[b]]).length ? a : b,
@@ -665,8 +688,11 @@ for (var a = 0; a < LANGS.length; a++) {
}
}
}
}
if (!has(LANGS, lang))
if (!Ls[lang])
alert('unsupported --lang "' + lang + '" specified in server args;\nplease use one of these: ' + LANGS);
modal.load();
@@ -6581,9 +6607,7 @@ var treectl = (function () {
bcfg_bind(r, 'csel', 'csel', dgsel);
bcfg_bind(r, 'dots', 'dotfiles', see_dots, function (v) {
r.goto();
var xhr = new XHR();
xhr.open('GET', SR + '/?setck=dots=' + (v ? 'y' : ''), true);
xhr.send();
setck('dots=' + (v ? 'y' : ''));
});
bcfg_bind(r, 'utctid', 'utctid', dutc, function (v) {
window.unix2ui = v ? unix2iso : unix2iso_localtime;
@@ -6620,9 +6644,7 @@ var treectl = (function () {
if (!v == !/\bidxh=y\b/.exec('' + document.cookie))
return;
var xhr = new XHR();
xhr.open('GET', SR + '/?setck=idxh=' + (v ? 'y' : 'n'), true);
xhr.send();
setck('idxh=' + (v ? 'y' : 'n'));
}
setidxh(r.idxh);
@@ -7368,10 +7390,7 @@ var treectl = (function () {
qsr('#bbsw');
srvinf = ebi('srv_info').innerHTML.slice(6, -7);
if (ls0 === null) {
var xhr = new XHR();
xhr.open('GET', SR + '/?setck=js=y', true);
xhr.send();
setck('js=y');
r.ls_cb = showfile.addlinks;
return r.reqls(get_evpath(), false, undefined, true);
}
@@ -8164,11 +8183,9 @@ var setfszf = (function () {
(function () {
function freshen() {
lang = sread("cpp_lang", LANGS) || lang;
var k, cb = ebi('langs'), html = [];
for (var a = 0; a < LANGS.length; a++) {
k = LANGS[a];
html.push('<option value="{0}">{0} ┃ {1}</option>'.format(k, Ls[k].tt));
var cb = ebi('langs'), html = [];
for (var a = 0; a < LANGN.length; a++) {
html.push('<option value="{0}">{0} ┃ {1}</option>'.format(LANGN[a][0], LANGN[a][1]));
}
cb.innerHTML = html.join('');
cb.onchange = setlang;
@@ -8177,11 +8194,10 @@ var setfszf = (function () {
function setlang(e) {
ev(e);
var t = L.lang_set;
lang = ebi('langs').value;
L = Ls[lang];
swrite("cpp_lang", lang);
setck('cplng=' + lang);
freshen();
var t = L.tt == 'English' ? '' : Ls.eng.lang_set;
modal.confirm(L.lang_set + "\n\n" + t, location.reload.bind(location), null);
}

View File

@@ -211,6 +211,9 @@ document.documentElement.className = (STG && STG.cpp_thm) || "{{ this.args.theme
</script>
<script src="{{ r }}/.cpr/util.js?_={{ ts }}"></script>
{%- if lang != "eng" %}
<script src="{{ r }}/.cpr/tl/{{ lang }}.js?_={{ ts }}"></script>
{%- endif %}
<script src="{{ r }}/.cpr/splash.js?_={{ ts }}"></script>
{%- if js %}
<script src="{{ js }}_={{ ts }}"></script>

View File

@@ -1,7 +1,5 @@
// please add translations in alphabetic order, but keep "nor" and "eng" first
// (lines ending with //m are machine translations)
var Ls = {
"eng": {
Ls.eng = {
"splash": {
"d2": "shows the state of all active threads",
"e2": "reload config files (accounts/volumes/volflags),$Nand rescan all e2ds volumes$N$Nnote: any changes to global settings$Nrequire a full restart to take effect",
"lo2": "ends the session on all browsers",
@@ -10,14 +8,13 @@ var Ls = {
"ta1": "fill in your new password first",
"ta2": "repeat to confirm new password:",
"ta3": "found a typo; please try again",
},
}
};
if (window.langmod)
langmod();
var d = Ls[sread("cpp_lang", Object.keys(Ls)) || lang] ||
Ls.eng || Ls.nor || Ls.chi;
var d = (Ls[lang] || Ls.eng).splash;
d.wb = d.w;

View File

@@ -296,6 +296,10 @@ function ignex(all) {
window.onerror = vis_exh;
if (!window.Ls || !window.langmod)
var Ls = {};
function noop() { }
@@ -1307,6 +1311,11 @@ function scfg_bind(obj, oname, cname, defval, cb) {
return v;
}
function setck(v) {
var xhr = new XHR();
xhr.open('GET', SR + '/?setck=' + v, true);
xhr.send();
}
window.unix2ui = (function () {
var v = sread('utctid');

View File

@@ -415,6 +415,7 @@ if you are unable to use `build`, you can use the old setuptools approach instea
```bash
python3 setup.py install --user setuptools wheel jinja2
python3 setup.py build
python3 setup.py bdist_wheel
# you now have a wheel which you can install. or extract and repackage:
python3 setup.py install --skip-build --prefix=/usr --root=$HOME/pe/copyparty
```

View File

@@ -69,23 +69,13 @@ there is also `--html-head-s` and volflag `html_head_s` to add a plain static bi
# translations
add your own translations by using the english or norwegian one from `browser.js` as a template
add your own translations by using [tl.js](https://github.com/9001/copyparty/blob/hovudstraum/scripts/tl.js) as a base, and add a new file in [copyparty/web/tl](https://github.com/9001/copyparty/tree/hovudstraum/copyparty/web/tl) when you're happy with it
> ⚠ Please do not contribute translations to [RTL (Right-to-Left) languages](https://en.wikipedia.org/wiki/Right-to-left_script) for now; the javascript is [not ready](https://github.com/9001/copyparty/blob/hovudstraum/docs/rice/rtl.patch) to deal with it
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
you will be delighted to see inline html in the translation strings; to help prevent syntax errors, there is [a very jank linux script](https://github.com/9001/copyparty/blob/hovudstraum/scripts/tlcheck.sh) which is slightly better than nothing -- just beware the false-positives, so even if it complains it's not necessarily wrong/bad
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
## translations (docker-friendly)
if editing `browser.js` is inconvenient in your setup, for example if you're running in docker, then you can instead do this:
* if you have python, go to the `scripts` folder and run `./tl.py fra Français` to generate a `tl.js` which is perfect for translating to French, using the three-letter language code `fra`
* if you do not have python, you can also just grab `tl.js` from the scripts folder, but I'll probably forget to keep that up to date... and then you'll have to find/replace all `"eng"` and `Ls.eng` to your three-letter language code
to see your translation taking shape in the copyparty ui as you work on it:
* put your `tl.js` inside a folder that is being shared by your copyparty, preferably the webroot
* run copyparty with the argument `--html-head='<script src="/tl.js"></script>'`
* if you placed `tl.js` in the webroot then you're all good, but if you put it somewhere else then change `/tl.js` accordingly
@@ -97,6 +87,4 @@ if editing `browser.js` is inconvenient in your setup, for example if you're run
you can now edit `tl.js` and press CTRL-SHIFT-R in the browser to see your changes take effect as you go
if you want to contribute your translation back to the project (please do!) then you'll want to...
* grab all of the text inside your `var tl_cpanel = {` and add it to the translations inside `copyparty/web/splash.js` in the repo
* and the text inside your `var tl_browser = {` and add that to the translations inside `copyparty/web/browser.js` in the repo
if you want to contribute your translation back to the project (please do!) then grab most of the text inside your `tl.js` , starting from the line that starts with `Ls.` and put it into a new file inside [the translations folder](https://github.com/9001/copyparty/tree/hovudstraum/copyparty/web/tl)

View File

@@ -94,6 +94,8 @@ copyparty = [
"web/*.css",
"web/*.html",
"web/*.xml",
"web/tl/*.js",
"web/tl/*.gz",
"web/a/*.bat",
"web/deps/*.gz",
"web/deps/*.woff*",

View File

@@ -481,10 +481,12 @@ rm -f ftp/pyftpdlib/{__main__,prefork}.py
langs="eng|$langs"
aerr "ERROR: removing english is not supported; will do this instead: $langs"
}
for f in copyparty/web/{browser.js,splash.js}; do
gzip -d "$f.gz" || true
iawk '/^\}/{l=0} !l; /^var Ls =/{l=1;next} !l{next} o; /^\t["}]/{o=0} /^\t"'"$langs"'"/{o=1;print}' $f
done
f=copyparty/web/browser.js
gzip -d "$f.gz" || true
iawk '/^\]/{s=0} !s; /^var LANGN /{s=1;next} !s{next} /"'"$langs"'"/' $f
ls -1 copyparty/web/tl/* >t
grep -vE "/($langs)\." <t | xargs -- rm
rm t
}
[ ! $repack ] && {

View File

@@ -113,6 +113,26 @@ copyparty/web/splash.html,
copyparty/web/splash.js,
copyparty/web/svcs.html,
copyparty/web/svcs.js,
copyparty/web/tl,
copyparty/web/tl/chi.js,
copyparty/web/tl/cze.js,
copyparty/web/tl/deu.js,
copyparty/web/tl/epo.js,
copyparty/web/tl/fin.js,
copyparty/web/tl/fra.js,
copyparty/web/tl/grc.js,
copyparty/web/tl/ita.js,
copyparty/web/tl/kor.js,
copyparty/web/tl/nld.js,
copyparty/web/tl/nno.js,
copyparty/web/tl/nor.js,
copyparty/web/tl/pol.js,
copyparty/web/tl/por.js,
copyparty/web/tl/rus.js,
copyparty/web/tl/spa.js,
copyparty/web/tl/swe.js,
copyparty/web/tl/tur.js,
copyparty/web/tl/ukr.js,
copyparty/web/ui.css,
copyparty/web/up2k.js,
copyparty/web/util.js,

View File

@@ -30,53 +30,48 @@ after editing tl.js, reload your webbrowser by pressing ctrl-shift-r
def generate_javascript(lang3, native_name, tl_browser):
note = "// NOTE: please use tabs for indenting, not spaces :-)"
if lang3 == "eng":
note += """\n
// NOTE: since you are using the tl.js straight from the repo, you'll
// need to find/replace all "eng" with your own three-letter name"""
note1 = ""
note2 = ""
if lang3 == "hmn":
note1 = ";\n// please adjust this (and the \"Ls.hmn\" further down)"
note2 = """
// the three-letter language-code "hmn" and language-name "Hymmnos"
// is used as an example; please replace these with your language
//"""
return f""""use strict";
{note}
// the three-letter name of the language you're translating to
// the three-letter name of the language you're translating to{note1}
var my_lang = "{lang3}";
// and because we don't know these yet...
var SR='', wah='';
// this function is automatically called when the page is loaded:
////////////////////////////////////////////////////////////////////////
// please ignore the next 5 lines:
var Ls={{}}, SR='', wah='';
function langmod() {{
// which page is the javascript currently running on?
// look for some well-known elements to figure it out:
if (QS("h1#cc") && QS("a#k")) {{
// we are running in the control-panel
Ls[my_lang] = tl_cpanel[my_lang];
}}
else if (ebi("op_cfg")) {{
// we are running in the filebrowser
Ls[my_lang] = tl_browser[my_lang];
// inform the settings tab that a new lang is available
LANGS.push(my_lang);
}}
if (window.LANGN)
LANGN.push([my_lang, Ls[my_lang].tt]);
}}
////////////////////////////////////////////////////////////////////////
// alright,
// below this point is where the actual translation happens;
// here is the pairs of "text-identifier": "text-to-translate"
////////////////////////////////////////////////////////////////////////
// translation of splash.js (the control-panel);
//{note2}
// you do not need to translate the TLNotes, those are just for you :-)
//
// when you are happy with this translation and want to submit it,
// copy the text below into a new file in the translations folder;
// https://github.com/9001/copyparty/tree/hovudstraum/copyparty/web/tl
var tl_cpanel = {{
"{lang3}": {{
Ls.{lang3} = {{
"tt": "{native_name}",
{tl_browser}
"splash": {{
"a1": "refresh",
"b1": "howdy stranger &nbsp; <small>(you're not logged in)</small>",
"c1": "logout",
@@ -115,21 +110,9 @@ var tl_cpanel = {{
"ac1": "enable no304",
"ad1": "enabling no304 will disable all caching; try this if k304 wasn't enough. This will waste a huge amount of network traffic!",
"ae1": "active downloads:",
"af1": "show recent uploads",
}},
"af1": "show recent uploads",
}}
}};
////////////////////////////////////////////////////////////////////////
// translation of browser.js (the filebrowser):
var tl_browser = {{
"{lang3}": {{
"tt": "{native_name}",
{tl_browser}
}};
"""
@@ -158,7 +141,8 @@ def main():
browserjs = f.read().decode("utf-8")
_, browserjs = browserjs.split('\n\t\t"tt": "English",\n', 1)
browserjs, _ = browserjs.split('\n\t"nor": {', 1)
browserjs, _ = browserjs.split('\n}', 1)
browserjs = browserjs.replace("\n\t", "\n")
try:
lang3 = sys.argv[1]

View File

@@ -1,13 +1,15 @@
#!/bin/bash
set -e
# usage: ./scripts/tlcheck.sh eng chi copyparty/web/browser.js
[ -f "$1" ] && [ -f "$2" ] && [ $# = 2 ] || {
echo usage: ./scripts/tlcheck.sh scripts/tl.js copyparty/web/tl/nor.js
exit 1
}
awk <"$3" -v lang1=\"$1\": -v lang2=\"$2\": '
/^\t\}/{fa=0;fb=0}
cat "$1" "$2" | awk '
/^\}/{fa=0;fb=0}
/^Ls\./{if(nln++){fb=1}else{fa=1}}
!/":/{next}
$0~lang1{fa=1}
$0~lang2{fb=1}
fa{a[ia++]=$0}
fb{b[ib++]=$0}
END{for (i=0;i<ia;i++) printf "%s\n%s\n\n",a[i],b[i]}

View File

@@ -131,6 +131,7 @@ args = {
"copyparty.stolen.dnslib",
"copyparty.stolen.ifaddr",
"copyparty.web",
"copyparty.web.tl",
"copyparty.web.a",
"copyparty.web.deps",
],