From 8349ca9a0016b8bda44a439712c91981bd662640 Mon Sep 17 00:00:00 2001 From: remittor Date: Sat, 24 Sep 2022 12:35:13 +0300 Subject: [PATCH] Add support translate many HTML files (generate sed patch) --- data/lang_install.sh | 4 + data/lang_patch.sh | 4 + data/lang_uninstall.sh | 1 + install_lang.py | 161 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 170 insertions(+) diff --git a/data/lang_install.sh b/data/lang_install.sh index b2acd49..fe1e6e4 100644 --- a/data/lang_install.sh +++ b/data/lang_install.sh @@ -28,6 +28,10 @@ fi mv -f /tmp/base.*.lmo $DIR_PATCH/ mv -f /tmp/lang_patch.sh $DIR_PATCH/ chmod +x $DIR_PATCH/lang_patch.sh +if [ -e "/tmp/lang_patch1.sh" ]; then + mv -f /tmp/lang_patch1.sh $DIR_PATCH/ + chmod +x $DIR_PATCH/lang_patch1.sh +fi INSTALL_METHOD=1 if [ -e "/usr/lib/os-release" ]; then diff --git a/data/lang_patch.sh b/data/lang_patch.sh index 1c32f5d..2385c13 100644 --- a/data/lang_patch.sh +++ b/data/lang_patch.sh @@ -35,6 +35,10 @@ sed -i 's/ and features\["system"\]\["i18n"\] == "1" //' /usr/lib/lua/luci/view/ # unlock change luci.main.lang sed -i "s/option CHANNEL 'stable'/option CHANNEL 'release'/g" /usr/share/xiaoqiang/xiaoqiang_version +if [ -e "$DIR_PATCH/lang_patch1.sh" ]; then + sh $DIR_PATCH/lang_patch1.sh +fi + echo "lang patched" > /tmp/lang_patch.log MAIN_LANG=$( uci -q get luci.main.lang ) diff --git a/data/lang_uninstall.sh b/data/lang_uninstall.sh index 4edc35e..12b9d4b 100644 --- a/data/lang_uninstall.sh +++ b/data/lang_uninstall.sh @@ -19,6 +19,7 @@ mv /etc/crontabs/root.new /etc/crontabs/root rm -f /etc/rc.lang rm -f /etc/lang_patch.sh rm -f $DIR_PATCH/lang_patch.sh +rm -f $DIR_PATCH/lang_patch1.sh rm -f $DIR_PATCH/base.*.lmo rm -f /tmp/lang_patch.log diff --git a/install_lang.py b/install_lang.py index 80c40ea..853709e 100644 --- a/install_lang.py +++ b/install_lang.py @@ -3,12 +3,122 @@ import os import sys +import types +import re sys.path.append(os.path.dirname(os.path.abspath(__file__))) +import ssh2 import gateway from gateway import die +class www_lmo(): + fn_local = None + fn_remote = None + data = None + out = [] + + def __init__(w, fn_local = None, fn_remote = None): + w.fn_local = fn_local + w.fn_remote = fn_remote + w.data = None + w.out = [] + + def load_file(w): + with open(w.fn_local, "r", encoding="utf-8") as file: + w.data = file.read() + + def parse(w): + if not w.data: + w.load_file() + p = re.compile(r'[^%][>]([^><]*?[\u4e00-\u9fff][^><]*?)[<][^%]') + w.parse1(p) + p = re.compile(r'[\']([^><\n\']*?[\u4e00-\u9fff][^><\n\']*?)[\']') + w.parse1(p) + p = re.compile(r'["]([^><\n"]*?[\u4e00-\u9fff][^><\n"]*?)["]') + w.parse1(p) + + def parse1(w, template): + for m in template.finditer(w.data): + txt = m.group() + if txt.find('<%') > 0 or txt.find('%>') > 0: + continue + if txt.find('// ') > 0: # skip comments + continue + if txt.find('if ') > 0: # skip code + continue + if txt.find('{') > 0: # skip code + continue + if txt.find(' = ') > 0: # skip code + continue + b = m.start() + t1 = m.start(1) + t2 = m.end(1) + e = m.end() + #print(b, t1, t2, e) + prefix = w.data[b:t1] + string = w.data[t1:t2] + postfix = w.data[t2:e] + if len(prefix) == 2 and prefix[1] == '>': + prefix = prefix[1] + txt = txt[1:] + if len(postfix) == 2 and postfix[0] == '<': + postfix = postfix[0] + txt = txt[:-1] + #print('"{}" "{}" "{}"'.format(prefix, string, postfix)) + s = string.strip() + if s == string: + out = prefix + '<%:' + string + '%>' + postfix + msg = string + else: + p = string.find(s) + if p < 0: + continue # fixme + out = prefix + string[:p] + '<%:' + s + '%>' + string[p+len(s):] + postfix + msg = s + #print(b, out) + # check for dup + dup = 0 + for i, v in enumerate(w.out): + if v.txt_orig == txt: + dup = 1 + break + if dup == 0: + v = types.SimpleNamespace() + v.pos = b + v.txt_orig = txt + v.txt_new = out + v.sed = "" + v.msg = msg + w.out.append(v) + + def sed_escape(w, txt): + txt = txt.replace('\\', '\\\\') + txt = txt.replace('\n', r'\n') + txt = txt.replace('\r', r'\r') + txt = txt.replace('\t', r'\t') + txt = txt.replace("'", r"'\''") + txt = txt.replace('[', r'\[') + txt = txt.replace(']', r'\]') + txt = txt.replace('$', r'\$') + txt = txt.replace('*', r'\*') + txt = txt.replace('.', r'\.') + txt = txt.replace('$', r'\$') + txt = txt.replace('^', r'\^') + txt = txt.replace('/', r'\/') + return txt + + def gen_sed(w): + for i, v in enumerate(w.out): + #print(v.pos, v.txt_new) + orig = w.sed_escape(v.txt_orig) + new = w.sed_escape(v.txt_new) + prefix = '' + if v.txt_orig.find('\n') > 0: + prefix = ':a;N;$!ba;' # see: https://stackoverflow.com/questions/1251999/how-can-i-replace-each-newline-n-with-a-space-using-sed + v.sed = "sed -i '{}s/{}/{}/g' {}".format(prefix, orig, new, w.fn_remote) + + gw = gateway.Gateway() fn_dir = 'data/' @@ -18,6 +128,8 @@ fn_local_i = 'data/lang_install.sh' fn_remote_i = '/tmp/lang_install.sh' fn_local_u = 'data/lang_uninstall.sh' fn_remote_u = '/tmp/lang_uninstall.sh' +fn_www_local = 'data/lang_patch1.sh' +fn_www_remote = '/tmp/lang_patch1.sh' action = 'install' if len(sys.argv) > 1: @@ -30,6 +142,19 @@ if action == 'install': gw.upload(fn_local_u, fn_remote_u) +if action == 'install': + patch1_installed = True + fn = 'data/lang_patch.log' + if os.path.exists(fn): + os.remove(fn) + try: + gw.download('/tmp/lang_patch.log', fn, verbose = 0) + except ssh2.exceptions.SCPProtocolError: + patch1_installed = False + if patch1_installed: + print("Uninstall lang_patch...") + gw.run_cmd("sh " + fn_remote_u) + if action == 'install': import po2lmo for filename in [fn for fn in os.listdir(fn_dir) if fn.split(".")[-1] in ['po']]: @@ -42,6 +167,41 @@ if action == 'install': lmo.save_to_bin(fn_dir + lmo_fname) gw.upload(fn_dir + lmo_fname, '/tmp/' + lmo_fname) + dn_www = "tmp/www" + os.makedirs(dn_www, exist_ok = True) + wwwlst = [ "/usr/lib/lua/luci/view/web/index.htm", + "/usr/lib/lua/luci/view/web/apindex.htm", + "/usr/lib/lua/luci/view/web/inc/g.js.htm", + "/usr/lib/lua/luci/view/web/inc/header.htm", + "/usr/lib/lua/luci/view/web/inc/sysinfo.htm", + "/usr/lib/lua/luci/view/web/inc/wanCheck.js.htm", + "/usr/lib/lua/luci/view/web/setting/iptv.htm", + ] + www = [] + for i, www_remote in enumerate(wwwlst): + www_local = dn_www + '/' + www_remote.replace('/', '_') + try: + gw.download(www_remote, www_local, verbose = 0) + except ssh2.exceptions.SCPProtocolError: + print('WARN: file "{}" not found'.format(www_remote)) + continue + w = www_lmo(www_local, www_remote) + www.append(w) + if os.path.exists(fn_www_local): + os.remove(fn_www_local) + file = open(fn_www_local, "wt", encoding='UTF-8', newline = "\n") + file.write('#!/bin/sh\n') + for i, w in enumerate(www): + #print("===== FILE:", w.fn_remote) + w.parse() + w.gen_sed() + file.write('# ======= FILE: {} ======= \n'.format(w.fn_remote)) + for i, v in enumerate(w.out): + if v.sed: + file.write(v.sed + '\n') + file.close() + gw.upload(fn_www_local, fn_www_remote) + print("All files uploaded!") print("Run scripts...") @@ -53,5 +213,6 @@ else: gw.run_cmd("rm -f " + fn_remote) gw.run_cmd("rm -f " + fn_remote_i) gw.run_cmd("rm -f " + fn_remote_u) +gw.run_cmd("rm -f " + fn_www_remote) print("Ready! The language files are installed.")