This commit is contained in:
恍兮惚兮 2024-07-17 03:00:09 +08:00
parent 70942a831e
commit d8f728d410
36 changed files with 396 additions and 256 deletions

View File

@ -462,7 +462,7 @@ def xianshigrid_text(self):
globalconfig, "show_fenci"
),
"",
("词性颜色_需要Mecab"),
("词性颜色"),
D_getIconButton(
callback=lambda: multicolorset(self),
icon="fa.gear",

View File

@ -37,27 +37,18 @@ def getall(l, item="fanyi", name=None):
return grids
def createcheckbtn(self):
btn = QPushButton(_TR("确定"))
btn.clicked.connect(
lambda x: globalconfig.__setitem__("proxy", self.__proxyedit.text())
)
self.__checkproxybtn = btn
_ifusesysproxy(self, globalconfig["usesysproxy"])
return btn
def createproxyedit(self):
proxy = QLineEdit(globalconfig["proxy"])
self.__proxyedit = proxy
proxy.textEdited.connect(
lambda: globalconfig.__setitem__("proxy", self.__proxyedit.text())
)
_ifusesysproxy(self, globalconfig["usesysproxy"])
return proxy
def _ifusesysproxy(self, x):
self.__proxyedit.setEnabled(not x)
self.__checkproxybtn.setEnabled(not x)
def getnotofflines(key):
@ -82,11 +73,7 @@ def makeproxytab(self, basel):
)
),
],
[
("手动设置代理(ip:port)", 5),
(functools.partial(createproxyedit, self), 5),
(functools.partial(createcheckbtn, self), 2),
],
[("手动设置代理(ip:port)", 5), (functools.partial(createproxyedit, self), 5)],
[],
[("使用代理的项目", -1)],
]
@ -184,7 +171,9 @@ def setTab_proxy_lazy(self, basel):
"WebSocket",
(
D_getsimplecombobox(
["winhttp", "libcurl"], globalconfig, "network_websocket"
["winhttp", "libcurl"],
globalconfig,
"network_websocket",
),
5,
),

View File

@ -25,7 +25,28 @@ from hiraparse.basehira import basehira
class mecabwrap:
def testcodec(self, mecabpath):
default = "shift-jis"
dirrc = os.path.join(mecabpath, "dicrc")
if not os.path.exists(dirrc):
return default
with open(dirrc, "rb") as ff:
lines = ff.read().split(b"\n")
for test in ["dictionary-charset", "config-charset"]:
for line in lines:
try:
line = line.decode()
except:
continue
if test in line.lower():
return line.split("=")[1].strip()
return default
def __init__(self, mecabpath) -> None:
if not os.path.exists(mecabpath):
mecabpath = r"C:\Program Files (x86)\MeCab\dic\ipadic"
self.codec = self.testcodec(mecabpath)
print(self.codec)
self.kks = winsharedutils.mecab_init(
mecabpath.encode("utf8"), gobject.GetDllpath("libmecab.dll")
)
@ -33,16 +54,16 @@ class mecabwrap:
def __del__(self):
winsharedutils.mecab_end(self.kks)
def parse(self, text: str, codec: str):
def parse(self, text: str):
res = []
codec = self.codec
def cb(surface: bytes, feature: bytes):
fields = list(csv.reader([feature.decode(codec)]))[0]
res.append((surface.decode(codec), fields))
succ = winsharedutils.mecab_parse(
self.kks, text.encode(codec), CFUNCTYPE(None, c_char_p, c_char_p)(cb)
)
fp = CFUNCTYPE(None, c_char_p, c_char_p)(cb)
succ = winsharedutils.mecab_parse(self.kks, text.encode(codec), fp)
if not succ:
raise Exception # failed
@ -60,8 +81,7 @@ class mecab(basehira):
def parse(self, text):
start = 0
result = []
codec = ["utf8", "shiftjis"][self.config["codec"]]
for node, fields in self.kks.parse(text, codec):
for node, fields in self.kks.parse(text):
kana = ""
origorig = ""
pos1 = fields[0]

View File

@ -164,8 +164,7 @@ class Requester(Requester_common):
url,
headers,
cookies,
dataptr,
datalen,
databytes,
proxy,
stream,
verify,
@ -202,9 +201,9 @@ class Requester(Requester_common):
self._set_verify(curl, verify)
self._set_proxy(curl, proxy)
self._set_allow_redirects(curl, allow_redirects)
if datalen:
curl_easy_setopt(curl, CURLoption.POSTFIELDS, dataptr)
curl_easy_setopt(curl, CURLoption.POSTFIELDSIZE, datalen)
if len(databytes):
curl_easy_setopt(curl, CURLoption.POSTFIELDS, databytes)
curl_easy_setopt(curl, CURLoption.POSTFIELDSIZE, len(databytes))
resp = Response()
resp.keeprefs.append(curl)

View File

@ -151,8 +151,7 @@ class Requester(Requester_common):
url,
_headers,
cookies,
dataptr,
datalen,
databytes,
proxy,
stream,
verify,
@ -161,7 +160,7 @@ class Requester(Requester_common):
):
headers = self._parseheader(_headers, cookies)
flag = WINHTTP_FLAG_SECURE if scheme == "https" else 0
# print(server,port,param,dataptr)
# print(server,port,param,databytes)
headers = "\r\n".join(headers)
hConnect = AutoWinHttpHandle(WinHttpConnect(self.hSession, server, port, 0))
@ -186,7 +185,7 @@ class Requester(Requester_common):
self._set_proxy(hRequest, proxy)
self._set_allow_redirects(hRequest, allow_redirects)
succ = WinHttpSendRequest(
hRequest, headers, -1, dataptr, datalen, datalen, None
hRequest, headers, -1, databytes, len(databytes), len(databytes), None
)
if succ == 0:
raise WinhttpException(GetLastError())

View File

@ -53,17 +53,8 @@ class OCR(baseocr):
"mac": mac,
}
data = (
'--6d94758aed493e27c73620d74ff01fc4\r\nContent-Disposition: form-data; name="image"; filename="2024-05-29 220022.png"\r\nContent-Type: multipart/form-data\r\n\r\n'.encode(
"latin-1"
)
+ imagebinary
+ "\r\n--6d94758aed493e27c73620d74ff01fc4--\r\n".encode("latin-1")
)
headers = {
"content-type": "multipart/form-data; boundary=6d94758aed493e27c73620d74ff01fc4",
}
response = self.proxysession.post(url, params=payload, headers=headers, data=data)
files = {"image": ("image.png", imagebinary, "multipart/form-data")}
response = self.proxysession.post(url, params=payload, files=files)
try:
js = response.json()

View File

@ -11,7 +11,6 @@ class OCR(baseocr):
"accept": "*/*",
"accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
"cache-control": "no-cache",
"content-type": "multipart/form-data; boundary=----WebKitFormBoundaryUjYOv45hug6CFh3t",
"origin": "https://www.zhihu.com",
"pragma": "no-cache",
"referer": "https://www.zhihu.com/",
@ -25,18 +24,11 @@ class OCR(baseocr):
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36",
}
data = (
'------WebKitFormBoundaryUjYOv45hug6CFh3t\r\nContent-Disposition: form-data; name="file"; filename="screenshot.png"\r\nContent-Type: application/octet-stream\r\n\r\n'.encode(
"latin-1"
)
+ imagebinary
+ "\r\n------WebKitFormBoundaryUjYOv45hug6CFh3t--\r\n".encode("latin-1")
)
files = {"file": ("screenshot.png", imagebinary, "application/octet-stream")}
response = self.proxysession.post(
"https://ocrserver.docsumo.com/api/v1/ocr/extract/",
headers=headers,
data=data,
files=files,
)
# print(response.json())
try:

View File

@ -12,24 +12,17 @@ class OCR(baseocr):
timestamp = int(time.time() * 1000)
url = f"https://lens.google.com/v3/upload?stcs={timestamp}"
headers = {
"content-type": "multipart/form-data; boundary=----WebKitFormBoundaryUjYOv45hug6CFh3t",
"User-Agent": "Mozilla/5.0 (Linux; Android 13; RMX3771) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.6167.144 Mobile Safari/537.36",
}
cookies = {"SOCS": "CAESEwgDEgk0ODE3Nzk3MjQaAmVuIAEaBgiA_LyaBg"}
data = (
'------WebKitFormBoundaryUjYOv45hug6CFh3t\r\nContent-Disposition: form-data; name="encoded_image"; filename="screenshot.png"\r\nContent-Type: image/png\r\n\r\n'.encode(
"latin-1"
)
+ imagebinary
+ "\r\n------WebKitFormBoundaryUjYOv45hug6CFh3t--\r\n".encode("latin-1")
)
files = {"encoded_image": ("screenshot.png", imagebinary, "image/png")}
res = self.proxysession.post(
url, data=data, headers=headers, cookies=cookies, timeout=20
url, files=files, headers=headers, cookies=cookies, timeout=20
)
match = regex.search(res.text)
if match == None:
raise Exception(False, "Regex error!")
return
sideChannel = "sideChannel"
null = None
key = "key"

View File

@ -0,0 +1,82 @@
from ocrengines.baseocrclass import baseocr
import uuid, json
class OCR(baseocr):
def langmap(self):
return {"zh": "zh-CHS"}
def ocr(self, imagebinary):
cookies = {
"ABTEST": "0|1716807064|v17",
"SUID": "22005E72BE50A00A0000000066546598",
"wuid": "1716807064590",
"SUV": "1720043144694",
"SNUID": "4A31C2546066423F20E0F4C8609D6C10",
"FQV": "837174c34ee13ac891646aeeec5a8cfa",
"translate.sess": "971ddb4a-0c83-4ea4-8058-271867f48e77",
"SGINPUT_UPSCREEN": "1721149101013",
"NEW_SUV": "1721149407274",
}
headers = {
"Accept": "application/json, text/plain, */*",
"Accept-Language": "zh-CN,zh;q=0.9,ar;q=0.8,sq;q=0.7,ru;q=0.6",
"Connection": "keep-alive",
"Origin": "https://fanyi.sogou.com",
"Referer": "https://fanyi.sogou.com/picture",
"Sec-Fetch-Dest": "empty",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "same-origin",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
"sec-ch-ua": '"Not/A)Brand";v="8", "Chromium";v="126", "Google Chrome";v="126"',
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": '"Windows"',
}
files = {
"fileData": ("blob", imagebinary, "image/jpeg"),
"fuuid": (None, str(uuid.uuid4())),
"extraData": (
None,
json.dumps(
{
"from": self.srclang,
"to": self.tgtlang,
"imageName": str(uuid.uuid4()) + ".png",
}
),
),
}
response = self.proxysession.post(
"https://fanyi.sogou.com/api/transpc/picture/upload",
cookies=cookies,
headers=headers,
files=files,
)
try:
boxes = []
text = []
ts = []
for line in response.json()["data"].get("result", []):
boxes.append(
[
int(_)
for _ in (
line["frame"][0].split(",") + line["frame"][2].split(",")
)
]
)
text.append(line["content"])
ts.append(line["trans_content"])
if self.config["Translate"]:
return "<notrans>" + self.common_solve_text_orientation(boxes, ts)
else:
return self.common_solve_text_orientation(boxes, text)
except:
from traceback import print_exc
print_exc()
raise Exception(response.text)

View File

@ -2,6 +2,7 @@ import gobject, os, uuid, windows
from ocrengines.baseocrclass import baseocr
from ctypes import CDLL, c_void_p, c_wchar_p, c_char_p, CFUNCTYPE, c_bool, c_int
import winsharedutils
from traceback import print_exc
class OCR(baseocr):
@ -13,7 +14,35 @@ class OCR(baseocr):
c_wchar_p,
)
wcocr_init.restype = c_void_p
self.pobj = None
for function in [self.findwechat, self.findqqnt]:
try:
wechatocr_path, wechat_path = function()
except:
print_exc()
if any([not os.path.exists(_) for _ in (wechatocr_path, wechat_path)]):
continue
self.pobj = wcocr_init(wechatocr_path, wechat_path)
if self.pobj:
break
if not self.pobj:
raise Exception("找不到(微信和WeChatOCR)或(QQNT和TencentOCR)")
def findqqnt(self):
default = r"C:\Program Files\Tencent\QQNT"
version = winsharedutils.queryversion(os.path.join(default, "QQ.exe"))
if not version:
raise Exception
mojo = os.path.join(
default,
r"resources\app\versions",
f"{version[0]}.{version[1]}.{version[2]}-{version[3]}",
)
ocr = os.path.join(mojo, r"QQScreenShot\Bin\TencentOCR.exe")
return ocr, mojo
def findwechat(self):
key = windows.RegOpenKeyEx(
windows.HKEY_CURRENT_USER,
"SOFTWARE\Tencent\WeChat",
@ -27,28 +56,17 @@ class OCR(baseocr):
if not version:
raise Exception
except:
from traceback import print_exc
print_exc()
raise Exception("未找到WeChat")
versionf = ".".join((str(_) for _ in version))
wechat_path = os.path.join(base, "[" + versionf + "]")
wechatocr_path = (
os.getenv("APPDATA") + r"\Tencent\WeChat\XPlugin\Plugins\WeChatOCR"
)
try:
wechatocr_path = os.path.join(
wechatocr_path,
os.listdir(wechatocr_path)[0],
r"extracted\WeChatOCR.exe",
)
except:
raise Exception("未找到WeChatOCR")
self.pobj = wcocr_init(wechatocr_path, wechat_path)
if not self.pobj:
raise Exception("加载失败")
return wechatocr_path, wechat_path
def end(self):
@ -69,11 +87,8 @@ class OCR(baseocr):
def cb(x1, y1, x2, y2, text: bytes):
ret.append((x1, y1, x2, y2, text.decode("utf8")))
succ = wcocr_ocr(
self.pobj,
imgfile.encode("utf8"),
CFUNCTYPE(None, c_int, c_int, c_int, c_int, c_char_p)(cb),
)
fp = CFUNCTYPE(None, c_int, c_int, c_int, c_int, c_char_p)(cb)
succ = wcocr_ocr(self.pobj, imgfile.encode("utf8"), fp)
if not succ:
return
os.remove(imgfile)

View File

@ -0,0 +1,39 @@
from ocrengines.baseocrclass import baseocr
from ctypes import CDLL, c_char_p, c_size_t, c_void_p, CFUNCTYPE, sizeof, c_wchar_p
import json, os
youdaosig = CDLL(
os.path.join(os.path.dirname(__file__), f"ydocr{sizeof(c_void_p)*8}.dll")
)
ydocr = youdaosig.ydocr
ydocr.argtypes = c_void_p, c_size_t, c_wchar_p, c_wchar_p, c_void_p
def doocr(image, src, tgt):
ret = []
fp = CFUNCTYPE(None, c_char_p)(ret.append)
ydocr(image, len(image), src, tgt, fp)
boxs = []
texts = []
transs = []
for line in ret:
line = json.loads(line.decode("utf8"))
boxs.append(line[:4])
texts.append(line[4])
transs.append(line[5])
return boxs, transs, texts
class OCR(baseocr):
def langmap(self):
return {"zh": "zh-CHS", "cht": "zh-CHT"}
def ocr(self, imagebinary):
boxs, transs, texts = doocr(imagebinary, self.srclang, self.tgtlang)
if self.config["Translate"]:
return "<notrans>" + self.common_solve_text_orientation(boxs, transs)
else:
return self.common_solve_text_orientation(boxs, texts)

View File

@ -577,9 +577,9 @@ class TextBrowser(QWidget, dataget):
_, fontorig = self._getfh(False)
fha, fonthira = self._getfh(True)
self.textbrowser.move(0, fha)
self.atback_color.move(0, fha)
ldh = max(globalconfig["extra_space"], fha // 2)
self.textbrowser.move(0, int(fha))
self.atback_color.move(0, int(fha))
ldh = max(globalconfig["extra_space"], int(fha / 2))
for i in range(0, self.textbrowser.document().blockCount()):
b = self.textbrowser.document().findBlockByNumber(i)

View File

@ -61,8 +61,11 @@ class base(QLabel):
dx, dy = self.moveoffset()
text = self.text()
isarabic = lambda char: (ord(char) >= 0x0600 and ord(char) <= 0x06E0)
isfirstara = lambda text: len(text) and isarabic(text[0])
isfirstara = lambda text: len(text) and (
isarabic(text[0])
or (any(isarabic(_) for _ in text))
and (isarabic(text[0]) or (ord(text[0]) in (32, 46)))
)
if isfirstara(text):
self.movedx -= self.width()
self.movedx += dx

View File

@ -1,4 +1,4 @@
import json, base64, re
import json, base64, re, string, random
from collections.abc import Mapping, MutableMapping
from collections import OrderedDict
from urllib.parse import urlencode, urlsplit
@ -172,33 +172,6 @@ class Requester_common:
url = scheme + "://" + server + path
return scheme, server, port, path, url
def _parsedata(self, data, headers, js):
if data is None and js is None:
dataptr = None
datalen = 0
else:
if data:
dataptr = self._encode_params(data)
if isinstance(dataptr, str):
dataptr = (dataptr).encode("utf8")
datalen = len(dataptr)
# print('dataptr',dataptr)
if isinstance(data, (str, bytes)):
pass
elif "Content-Type" not in headers:
headers["Content-Type"] = "application/x-www-form-urlencoded"
elif js:
dataptr = json.dumps(js).encode("utf8")
datalen = len(dataptr)
if "Content-Type" not in headers:
headers["Content-Type"] = "application/json"
if datalen:
headers["Content-Length"] = str(datalen)
# print(headers,dataptr,datalen)
return headers, dataptr, datalen
def request(
self,
method,
@ -230,7 +203,18 @@ class Requester_common:
)
scheme, server, port, param, url = self._parseurl(url, params)
headers, dataptr, datalen = self._parsedata(data, headers, json)
databytes = b""
contenttype = None
if files:
contenttype, databytes = self._parsefilesasmultipart(files, headers)
elif data:
contenttype, databytes = self._parsedata(data)
elif json:
contenttype, databytes = self._parsejson(json)
if len(databytes):
headers["Content-Length"] = str(len(databytes))
if contenttype and ("Content-Type" not in headers):
headers["Content-Type"] = contenttype
proxy = proxies.get(scheme, None) if proxies else None
proxy = None if proxy == "" else proxy
if timeout:
@ -251,8 +235,7 @@ class Requester_common:
url,
headers,
cookies,
dataptr,
datalen,
databytes,
proxy,
stream,
verify,
@ -302,6 +285,66 @@ class Requester_common:
header[line[:idx]] = line[idx + 2 :]
return CaseInsensitiveDict(header), cookie
def _parsejson(self, _json):
databytes = json.dumps(_json).encode("utf8")
contenttype = "application/json"
return contenttype, databytes
def _parsedata(self, data):
contenttype = None
databytes = self._encode_params(data)
if isinstance(databytes, str):
databytes = (databytes).encode("utf8")
if isinstance(data, (str, bytes)):
pass
else:
contenttype = "application/x-www-form-urlencoded"
return contenttype, databytes
def _parsefilesasmultipart(self, files: dict, header: dict):
def generate_random_string(length=16):
characters = string.ascii_letters + string.digits
return "".join(random.choices(characters, k=length))
_ct = header.get("Content-Type", None)
_ct_start = "multipart/form-data; boundary="
if _ct and _ct.lower().startswith(_ct_start):
boundary = _ct[len(_ct_start) :]
else:
boundary = "----WebKitFormBoundary" + generate_random_string()
_ct = _ct_start + boundary
boundary = boundary.encode()
items = []
for name, data in files.items():
items.append(b"--" + boundary)
disposition = b'Content-Disposition: form-data; name="'
disposition += name.encode("utf8")
disposition += b'"'
if isinstance(data, tuple) or isinstance(data, list):
if len(data) == 3:
filename, data, type_ = data
elif len(data) == 2:
filename, data = data
type_ = None
else:
filename = None
type_ = None
if filename:
disposition += b'; filename="'
disposition += filename.encode("utf8")
disposition += b'"'
items.append(disposition)
if type_:
Type = b"Content-Type: "
Type += type_.encode("utf8")
items.append(Type)
items.append(b"")
if isinstance(data, str):
data = data.encode("utf8")
items.append(data)
items.append(b"--" + boundary + b"--")
return _ct, b"".join(_ + b"\r\n" for _ in items)
class Session:
cookies = {}

View File

@ -37,4 +37,4 @@ class TS(basetrans):
try:
return response.json()["translation"]
except:
raise Exception(json.dumps(response.json(), ensure_ascii=False))
raise Exception(response.text)

View File

@ -1,42 +0,0 @@
import json
from translator.basetranslator import basetrans
class TS(basetrans):
def langmap(self):
return {"zh": "zh-cn", "en": "en-us", "cht": "zh-tw"}
def translate(self, content):
headers = {
"Accept": "application/json, text/plain, */*",
"Accept-Language": "zh-CN,zh;q=0.9",
"Cache-Control": "no-cache",
"Connection": "keep-alive",
"Origin": "https://online.cloudtranslation.com",
"Pragma": "no-cache",
"Referer": "https://online.cloudtranslation.com/",
"Sec-Fetch-Dest": "empty",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "same-origin",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.42",
"sec-ch-ua": '"Microsoft Edge";v="107", "Chromium";v="107", "Not=A?Brand";v="24"',
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": '"Windows"',
}
response = self.proxysession.post(
"https://online.cloudtranslation.com/api/v1.0/request_translate/try_translate",
data={
"type": "text",
"text": content,
"src_lang": self.srclang,
"tgt_lang": self.tgtlang,
"domain": "general",
},
headers=headers,
)
try:
return json.loads(response.json()["data"]["data"])["translation"]
except:
raise Exception(json.dumps(response.json(), ensure_ascii=False))

View File

@ -90,14 +90,8 @@ def SAPI_Speak(content, v, voiceid, rate, volume):
def _cb(ptr, size):
ret.append(cast(ptr, POINTER(c_char))[:size])
succ = _SAPI_Speak(
content,
v,
voiceid,
int(rate),
int(volume),
CFUNCTYPE(None, c_void_p, c_size_t)(_cb),
)
fp = CFUNCTYPE(None, c_void_p, c_size_t)(_cb)
succ = _SAPI_Speak(content, v, voiceid, int(rate), int(volume), fp)
if not succ:
return None
return ret[0]

View File

@ -466,7 +466,7 @@
"showfanyi": true,
"autoread": false,
"ttsnointerrupt": false,
"show_fenci": false,
"show_fenci": true,
"jiamingcolor": "black",
"ankiconnect": {
"port": 8765,
@ -507,7 +507,7 @@
1200,
600
],
"global_namemap":{},
"global_namemap": {},
"settingfontsize": 12,
"filter_chaos_code": false,
"accept_encoding": [
@ -827,7 +827,7 @@
"showtranexception": true,
"refresh_on_get_trans": false,
"languageuse": 0,
"proxy": "",
"proxy": "127.0.0.1:7890",
"showbold": false,
"showShadow": false,
"shadowcolor": "blue",
@ -1123,11 +1123,11 @@
},
"hirasetting": {
"mecab": {
"use": false,
"use": true,
"name": "MeCab",
"args": {
"path": "",
"codec": 0
"downloadlink": "{main_server}/Resource/dictionary/Mecab.zip"
},
"argstype": {
"path": {
@ -1135,13 +1135,10 @@
"name": "路径",
"dir": true
},
"codec": {
"type": "combo",
"name": "编码",
"list": [
"utf8",
"shiftjis"
]
"downloadlink": {
"type": "label",
"islink": true,
"name": "下载"
}
},
"type": "offline"
@ -1303,7 +1300,7 @@
},
"youdao": {
"use": false,
"name": "有道",
"name": "有道词典",
"useproxy": false
},
"jisho": {
@ -1415,6 +1412,10 @@
"use": false,
"name": "腾讯OCR"
},
"sougou": {
"use": false,
"name": "搜狗"
},
"txocrtrans": {
"use": false,
"name": "腾讯图片翻译"
@ -1451,6 +1452,10 @@
"use": false,
"name": "有道图片翻译"
},
"youdaodictocr": {
"use": false,
"name": "有道词典"
},
"volcengine": {
"use": false,
"name": "火山OCR"
@ -1462,7 +1467,7 @@
},
"weixinocr": {
"use": false,
"name": "WeChatOCR",
"name": "WeChat/QQ OCR",
"type": "offline"
},
"geminiocr": {
@ -1531,7 +1536,7 @@
"youdaodict": {
"use": false,
"color": "#95a5ff",
"name": "YoudaoDict"
"name": "有道词典"
},
"google2": {
"use": false,
@ -1751,7 +1756,7 @@
"huoshan": {
"use": false,
"color": "blue",
"name": "huoshan"
"name": "火山"
},
"caiyunapi": {
"type": "api",
@ -1806,11 +1811,6 @@
"color": "blue",
"name": "有道api"
},
"yunyi2": {
"use": false,
"color": "blue",
"name": "云译_v2"
},
"chatgpt": {
"type": "api",
"use": false,

View File

@ -13,6 +13,28 @@
}
}
},
"sougou": {
"args": {
"Translate": false
},
"argstype": {
"Translate": {
"type": "switch",
"name": "翻译"
}
}
},
"youdaodictocr": {
"args": {
"Translate": false
},
"argstype": {
"Translate": {
"type": "switch",
"name": "翻译"
}
}
},
"windowsocr": {
"args": {
"": ""

View File

@ -768,7 +768,6 @@
"网络设置": "إعدادات الشبكة",
"版本更新": "تحديث النسخة",
"词性颜色": "لون الكلام",
"需要Mecab": "مطلوب ميكاب",
"跟随游戏窗口": "اتبع نافذة اللعبة",
"自动调整高度": "ضبط الارتفاع تلقائيا",
"文本区": "منطقة النص",
@ -778,7 +777,6 @@
"内容": "المحتويات",
"显示内容": "عرض المحتوى",
"界面设置": "إعدادات واجهة",
"主题效果": "تأثير الموضوع",
"其他界面": "واجهة أخرى",
"翻译及OCR": "الترجمة و التعرف الضوئي على الحروف",
"这一设置将会在下一次打开软件时生效": "هذا الإعداد سوف تصبح نافذة المفعول في المرة القادمة التي يتم فتح البرنامج",
@ -820,5 +818,7 @@
"未添加": "لا إضافة",
"在线": "آنلاین",
"行间距": "تباعد الصفوف",
"阴影": "شادو"
"阴影": "شادو",
"火山": "البراكين",
"有道词典": "قاموس تاو"
}

View File

@ -768,7 +768,6 @@
"网络设置": "網路設定",
"版本更新": "版本更新",
"词性颜色": "詞性顏色",
"需要Mecab": "需要 Mecab",
"跟随游戏窗口": "跟隨遊戲視窗",
"自动调整高度": "自動調整高度",
"文本区": "文字區",
@ -778,7 +777,6 @@
"内容": "內容",
"显示内容": "顯示內容",
"界面设置": "介面設定",
"主题效果": "主題效果",
"其他界面": "其他介面",
"翻译及OCR": "翻譯及 OCR",
"这一设置将会在下一次打开软件时生效": "這一設定將會在下一次打開軟體時生效",
@ -820,5 +818,7 @@
"未添加": "未添加",
"在线": "線上",
"行间距": "行間距",
"阴影": "陰影"
"阴影": "陰影",
"火山": "火山",
"有道词典": "有道詞典"
}

View File

@ -767,7 +767,6 @@
"网络设置": "Network Settings",
"版本更新": "Version Update",
"词性颜色": "Colored Parts-of-Speech",
"需要Mecab": " (Requires MeCab)",
"跟随游戏窗口": "Follow Game Window",
"自动调整高度": "Auto Adjust Height",
"文本区": "Text Area",
@ -777,7 +776,6 @@
"内容": "Content",
"显示内容": "Show Content",
"界面设置": "Interface Settings",
"主题效果": "Theme Effects",
"其他界面": "Other Interface",
"翻译及OCR": "Translation and OCR",
"这一设置将会在下一次打开软件时生效": "This setting will take effect the next time the software is opened",
@ -820,5 +818,7 @@
"未添加": "Not added",
"在线": "on-line",
"行间距": "Row spacing",
"阴影": "shadow"
"阴影": "shadow",
"火山": "volcano",
"有道词典": "Youdao Dictionary"
}

View File

@ -768,7 +768,6 @@
"网络设置": "Configuración de la red",
"版本更新": "Actualización de la versión",
"词性颜色": "Color del habla",
"需要Mecab": "Se necesita mecab",
"跟随游戏窗口": "Sigue la ventana del juego",
"自动调整高度": "Ajustar automáticamente la altura",
"文本区": "Área de texto",
@ -778,7 +777,6 @@
"内容": "Contenido",
"显示内容": "Mostrar contenido",
"界面设置": "Configuración de la interfaz",
"主题效果": "Efectos temáticos",
"其他界面": "Otras interfaces",
"翻译及OCR": "Traducción y OCR",
"这一设置将会在下一次打开软件时生效": "Esta configuración entrará en vigor la próxima vez que abra el software",
@ -820,5 +818,7 @@
"未添加": "Sin agregar",
"在线": "En línea",
"行间距": "Distancia entre líneas",
"阴影": "Sombra"
"阴影": "Sombra",
"火山": "Volcán",
"有道词典": "Diccionario youdao"
}

View File

@ -768,7 +768,6 @@
"网络设置": "Paramètres réseau",
"版本更新": "Mise à jour de la version",
"词性颜色": "La couleur des mots",
"需要Mecab": "Mecab est nécessaire",
"跟随游戏窗口": "Suivez la fenêtre du jeu",
"自动调整高度": "Ajustement automatique de la hauteur",
"文本区": "Zone de texte",
@ -778,7 +777,6 @@
"内容": "Contenu",
"显示内容": "Afficher le contenu",
"界面设置": "Paramètres de l'interface",
"主题效果": "Effets thématiques",
"其他界面": "Autres interfaces",
"翻译及OCR": "Traduction et ocr",
"这一设置将会在下一次打开软件时生效": "Ce paramètre prendra effet lors de la prochaine ouverture du logiciel.",
@ -820,5 +818,7 @@
"未添加": "Non ajouté",
"在线": "En ligne",
"行间距": "Espacement des lignes",
"阴影": "Ombre"
"阴影": "Ombre",
"火山": "Le volcan",
"有道词典": "Dictionnaire Tao"
}

View File

@ -768,7 +768,6 @@
"网络设置": "Impostazioni di rete",
"版本更新": "Aggiornamento della versione",
"词性颜色": "Colore di parte del discorso",
"需要Mecab": "Necessità di Mecab",
"跟随游戏窗口": "Segui la finestra del gioco",
"自动调整高度": "Regolazione automatica dell'altezza",
"文本区": "Area testo",
@ -778,7 +777,6 @@
"内容": "contenuto",
"显示内容": "mostra contenuti",
"界面设置": "Impostazioni interfaccia",
"主题效果": "Effetto tema",
"其他界面": "Altre interfacce",
"翻译及OCR": "Traduzione e OCR",
"这一设置将会在下一次打开软件时生效": "Questa impostazione avrà effetto alla prossima apertura del software",
@ -820,5 +818,7 @@
"未添加": "Non aggiunto",
"在线": "on-line",
"行间距": "Spaziatura riga",
"阴影": "ombra"
"阴影": "ombra",
"火山": "vulcano",
"有道词典": "Dizionario Youdao"
}

View File

@ -768,7 +768,6 @@
"网络设置": "ネットワーク設定",
"版本更新": "バージョンの更新",
"词性颜色": "品詞色",
"需要Mecab": "Mecabが必要",
"跟随游戏窗口": "ゲームウィンドウに従う",
"自动调整高度": "高さの自動調整",
"文本区": "テキスト領域",
@ -778,7 +777,6 @@
"内容": "内容",
"显示内容": "コンテンツの表示",
"界面设置": "インタフェースの設定",
"主题效果": "テーマ効果",
"其他界面": "その他のインタフェース",
"翻译及OCR": "翻訳とOCR",
"这一设置将会在下一次打开软件时生效": "この設定は、次回ソフトウェアを開くときに有効になります",
@ -820,5 +818,7 @@
"未添加": "追加されていません",
"在线": "オンライン",
"行间距": "行の間隔",
"阴影": "陰影"
"阴影": "陰影",
"火山": "かざん",
"有道词典": "有道辞典"
}

View File

@ -768,7 +768,6 @@
"网络设置": "네트워크 설정",
"版本更新": "버전 업데이트",
"词性颜色": "단어 색상",
"需要Mecab": "Mecab 필요",
"跟随游戏窗口": "게임 창 따라가기",
"自动调整高度": "자동 높이 조정",
"文本区": "텍스트 영역",
@ -778,7 +777,6 @@
"内容": "내용",
"显示内容": "컨텐트 표시",
"界面设置": "인터페이스 설정",
"主题效果": "테마 효과",
"其他界面": "기타 인터페이스",
"翻译及OCR": "번역 및 OCR",
"这一设置将会在下一次打开软件时生效": "이 설정은 다음에 소프트웨어를 열 때 적용됩니다.",
@ -820,5 +818,7 @@
"未添加": "추가되지 않음",
"在线": "온라인",
"行间距": "행 간격",
"阴影": "그림자"
"阴影": "그림자",
"火山": "화산",
"有道词典": "유도 사전"
}

View File

@ -768,7 +768,6 @@
"网络设置": "Ustawienia sieci",
"版本更新": "Aktualizacja wersji",
"词性颜色": "Część koloru mowy",
"需要Mecab": "Potrzebuję Mecabu.",
"跟随游戏窗口": "Obserwuj okno gry",
"自动调整高度": "Automatyczna regulacja wysokości",
"文本区": "Obszar tekstowy",
@ -778,7 +777,6 @@
"内容": "treść",
"显示内容": "pokaż zawartość",
"界面设置": "Ustawienia interfejsu",
"主题效果": "Efekt motywu",
"其他界面": "Inne interfejsy",
"翻译及OCR": "Tłumaczenia i OCR",
"这一设置将会在下一次打开软件时生效": "To ustawienie wchodzi w życie przy następnym otwarciu oprogramowania",
@ -820,5 +818,7 @@
"未添加": "Nie dodano",
"在线": "on-line",
"行间距": "Odstępy wierszy",
"阴影": "cień"
"阴影": "cień",
"火山": "wulkan",
"有道词典": "Słownik Youdao"
}

View File

@ -768,7 +768,6 @@
"网络设置": "Настройки сети",
"版本更新": "Обновление версии",
"词性颜色": "Цвет слова",
"需要Mecab": "Требуется Mecab",
"跟随游戏窗口": "Следуйте за окном игры",
"自动调整高度": "Автоматическая регулировка высоты",
"文本区": "Текстовая область",
@ -778,7 +777,6 @@
"内容": "Содержание",
"显示内容": "Показать содержимое",
"界面设置": "Параметры интерфейса",
"主题效果": "Тематический эффект",
"其他界面": "Другие интерфейсы",
"翻译及OCR": "Перевод и OCR",
"这一设置将会在下一次打开软件时生效": "Эта настройка вступит в силу при следующем открытии программного обеспечения.",
@ -820,5 +818,7 @@
"未添加": "Не добавлено",
"在线": "Онлайн",
"行间距": "Расстояние между строками",
"阴影": "Тень"
"阴影": "Тень",
"火山": "Вулканы",
"有道词典": "Словарь даосизма"
}

View File

@ -768,7 +768,6 @@
"网络设置": "การตั้งค่าเครือข่าย",
"版本更新": "อัปเดตเวอร์ชัน",
"词性颜色": "สีของคำ",
"需要Mecab": "ต้องการ Mecab",
"跟随游戏窗口": "ติดตามหน้าต่างเกม",
"自动调整高度": "ปรับความสูงอัตโนมัติ",
"文本区": "พื้นที่ข้อความ",
@ -778,7 +777,6 @@
"内容": "เนื้อหา",
"显示内容": "แสดงเนื้อหา",
"界面设置": "การตั้งค่าอินเทอร์เฟซ",
"主题效果": "ผลของธีม",
"其他界面": "อินเตอร์เฟซอื่น ๆ",
"翻译及OCR": "การแปลและ OCR",
"这一设置将会在下一次打开软件时生效": "การตั้งค่านี้จะมีผลในการเปิดซอฟต์แวร์ครั้งต่อไป",
@ -820,5 +818,7 @@
"未添加": "ไม่ได้เพิ่ม",
"在线": "ออนไลน์",
"行间距": "ระยะห่างระหว่างแถว",
"阴影": "เงา"
"阴影": "เงา",
"火山": "ภูเขาไฟ",
"有道词典": "พจนานุกรม Dao"
}

View File

@ -768,7 +768,6 @@
"网络设置": "Ağ Ayarları",
"版本更新": "Sürüm güncelleştirme",
"词性颜色": "Konuşma renginin bir parçası",
"需要Mecab": "Mecabi lazım.",
"跟随游戏窗口": "Oyun penceresini takip et",
"自动调整高度": "Otomatik yükseklik ayarlaması",
"文本区": "Metin alanı",
@ -778,7 +777,6 @@
"内容": "İçeri",
"显示内容": "İçeri göster",
"界面设置": "Arayüz ayarları",
"主题效果": "Tema etkisi",
"其他界面": "Diğer arayüzler",
"翻译及OCR": "Çeviri ve OCR",
"这一设置将会在下一次打开软件时生效": "Bu ayarlar bir sonraki yazılım açıldığında etkisi alacak.",
@ -820,5 +818,7 @@
"未添加": "Eklenmedi",
"在线": "on line",
"行间距": "Satır boşluğu",
"阴影": "gölge"
"阴影": "gölge",
"火山": "vulkan",
"有道词典": "Youdao Sözlük"
}

View File

@ -768,7 +768,6 @@
"网络设置": "Параметри мережі",
"版本更新": "Оновлення версії",
"词性颜色": "Частина кольору мови",
"需要Mecab": "Потрібний Mecab",
"跟随游戏窗口": "Слідувати за вікном гри",
"自动调整高度": "Автоматичне налаштування висоти",
"文本区": "Текстова область",
@ -778,7 +777,6 @@
"内容": "вміст",
"显示内容": "показувати вміст",
"界面设置": "Параметри інтерфейсу",
"主题效果": "Ефект теми",
"其他界面": "Інші інтерфейси",
"翻译及OCR": "Переклад і OCR",
"这一设置将会在下一次打开软件时生效": "Цей параметр діє наступного разу, коли буде відкрито програмне забезпечення",
@ -820,5 +818,7 @@
"未添加": "Не додано",
"在线": "онлайн",
"行间距": "Розділ рядків",
"阴影": "тінь"
"阴影": "тінь",
"火山": "вулкан",
"有道词典": "Словник Youdao"
}

View File

@ -768,7 +768,6 @@
"网络设置": "Thiết lập mạng",
"版本更新": "Cập nhật phiên bản",
"词性颜色": "Màu sắc của từ",
"需要Mecab": "Cần Mecab",
"跟随游戏窗口": "Theo cửa sổ trò chơi",
"自动调整高度": "Tự động điều chỉnh chiều cao",
"文本区": "Vùng văn bản",
@ -778,7 +777,6 @@
"内容": "Nội dung",
"显示内容": "Hiển thị nội dung",
"界面设置": "Thiết lập giao diện",
"主题效果": "Hiệu ứng sắc thái",
"其他界面": "Giao diện khác",
"翻译及OCR": "Biên dịch và OCR",
"这一设置将会在下一次打开软件时生效": "Cài đặt này sẽ có hiệu lực vào lần mở phần mềm tiếp theo.",
@ -820,5 +818,7 @@
"未添加": "Chưa thêm",
"在线": "Trực tuyến",
"行间距": "Khoảng cách dòng",
"阴影": "Bóng"
"阴影": "Bóng",
"火山": "Núi lửa",
"有道词典": "Có một từ điển."
}

View File

@ -772,7 +772,6 @@
"网络设置": "",
"版本更新": "",
"词性颜色": "",
"需要Mecab": "",
"自动调整高度": "",
"文本区": "",
"自动隐藏窗口": "",
@ -819,5 +818,7 @@
"添加语言包": "",
"未添加": "",
"在线": "",
"阴影": ""
"阴影": "",
"火山": "",
"有道词典": ""
}

View File

@ -16,10 +16,10 @@ localeEmulatorFile = "https://github.com/xupefei/Locale-Emulator/releases/downlo
localeEmulatorFileName = "Locale.Emulator.2.5.0.1.zip"
ntleaFile = "https://github.com/zxyacb/ntlea/releases/download/0.46/ntleas046_x64.7z"
ntleaFileName = "ntleas046_x64.7z"
curlFile32 = "https://curl.se/windows/dl-8.7.1_7/curl-8.7.1_7-win32-mingw.zip"
curlFileName32 = "curl-8.7.1_7-win32-mingw.zip"
curlFile64 = "https://curl.se/windows/dl-8.7.1_7/curl-8.7.1_7-win64-mingw.zip"
curlFileName64 = "curl-8.7.1_7-win64-mingw.zip"
curlFile32 = "https://curl.se/windows/dl-8.8.0_3/curl-8.8.0_3-win32-mingw.zip"
curlFileName32 = "curl-8.8.0_3-win32-mingw.zip"
curlFile64 = "https://curl.se/windows/dl-8.8.0_3/curl-8.8.0_3-win64-mingw.zip"
curlFileName64 = "curl-8.8.0_3-win64-mingw.zip"
ocrModelUrl = (

View File

@ -29,7 +29,7 @@ include(generate_product_version)
set(VERSION_MAJOR 5)
set(VERSION_MINOR 13)
set(VERSION_PATCH 2)
set(VERSION_PATCH 3)
add_library(pch pch.cpp)
target_precompile_headers(pch PUBLIC pch.h)