This commit is contained in:
恍兮惚兮 2024-05-16 01:36:03 +08:00
parent b43545bacb
commit 022e1553fb
46 changed files with 658 additions and 458 deletions

View File

@ -492,12 +492,13 @@ class MAINUI:
== False
):
continue
_hira = importlib.import_module("hiraparse." + name).hira
_hira = importlib.import_module("hiraparse." + name)
_hira = getattr(_hira, name)
break
try:
if _hira:
self.hira_ = _hira()
self.hira_ = _hira(name)
else:
self.hira_ = None
except:
@ -583,22 +584,7 @@ class MAINUI:
except:
return
class cishuwrapper:
def __init__(self, _type) -> None:
self._ = _type()
@threader
def search(self, sentence):
try:
res = self._.search(sentence)
if res is None or res == "":
return
self.callback(res)
except:
pass
_ = cishuwrapper(aclass)
return _
return aclass(type_)
def onwindowloadautohook(self):
textsourceusing = globalconfig["sourcestatus2"]["texthook"]["use"]

View File

@ -0,0 +1,41 @@
from myutils.config import globalconfig
from myutils.wrapper import threader
class cishubase:
def init(self):
pass
def search(self, word):
return word
def __init__(self, typename) -> None:
self.typename = typename
self.callback = print
self.needinit = True
try:
self.init()
self.needinit = False
except:
pass
@threader
def safesearch(self, sentence):
try:
if self.needinit:
self.init()
self.needinit = False
try:
res = self.search(sentence)
except:
self.needinit = True
if res is None or res == "":
return
self.callback(res)
except:
pass
@property
def config(self):
return globalconfig["cishu"][self.typename]["args"]

View File

@ -1,14 +1,14 @@
from myutils.config import globalconfig
import sqlite3, os
import winsharedutils, re
from myutils.utils import argsort, autosql
from cishu.cishubase import cishubase
class edict:
def __init__(self):
class edict(cishubase):
def init(self):
self.sql = None
try:
path = globalconfig["cishu"]["edict"]["path"]
path = self.config["path"]
if os.path.exists(path):
self.sql = autosql(sqlite3.connect(path, check_same_thread=False))
except:

View File

@ -1,15 +1,15 @@
from myutils.config import globalconfig
import winsharedutils, os
import re
from myutils.utils import argsort
from traceback import print_exc
from cishu.cishubase import cishubase
class edict2:
def __init__(self):
class edict2(cishubase):
def init(self):
self.sql = None
try:
path = globalconfig["cishu"]["edict2"]["path"]
path = self.config["path"]
if os.path.exists(path):
with open(path, "r", encoding="euc-jp") as ff:
_ = ff.read()

View File

@ -2,9 +2,10 @@ import requests
from urllib.parse import quote
import re
from myutils.proxy import getproxy
from cishu.cishubase import cishubase
class goo:
class goo(cishubase):
def search(self, word):
url = "https://dictionary.goo.ne.jp/srch/all/{}/m1u/".format(quote(word))

View File

@ -1,35 +1,28 @@
from myutils.config import globalconfig
from myutils.utils import autosql
import sqlite3
import winsharedutils
import os
from cishu.cishubase import cishubase
class linggesi:
def __init__(self):
class linggesi(cishubase):
def init(self):
self.sql = None
try:
if (
os.path.exists(
os.path.join(globalconfig["cishu"]["linggesi"]["path"], "ja-zh.db")
)
== False
or os.path.exists(
os.path.join(
globalconfig["cishu"]["linggesi"]["path"], "ja-zh-gbk.db"
)
)
os.path.exists(os.path.join(self.config["path"], "ja-zh.db")) == False
or os.path.exists(os.path.join(self.config["path"], "ja-zh-gbk.db"))
== False
):
return
self.sql = autosql(
sqlite3.connect(
os.path.join(globalconfig["cishu"]["linggesi"]["path"], "ja-zh.db"),
os.path.join(self.config["path"], "ja-zh.db"),
check_same_thread=False,
)
)
self.sql2 = sqlite3.connect(
os.path.join(globalconfig["cishu"]["linggesi"]["path"], "ja-zh-gbk.db"),
os.path.join(self.config["path"], "ja-zh-gbk.db"),
check_same_thread=False,
)
except:

View File

@ -1,8 +1,10 @@
import requests
from myutils.proxy import getproxy
from cishu.cishubase import cishubase
class mojidict:
class mojidict(cishubase):
def search(self, word):
try:
response = requests.post(

View File

@ -1,11 +1,12 @@
import requests
from urllib.parse import quote
from cishu.cishubase import cishubase
from myutils.proxy import getproxy
import re
class weblio:
class weblio(cishubase):
def search(self, word):
url = "https://www.weblio.jp/content/" + quote(word)

View File

@ -1,14 +1,15 @@
from myutils.config import globalconfig
import sqlite3, os
import winsharedutils
from myutils.utils import argsort, autosql
from cishu.cishubase import cishubase
class xiaoxueguan:
def __init__(self):
class xiaoxueguan(cishubase):
def init(self):
self.sql = None
try:
path = globalconfig["cishu"]["xiaoxueguan"]["path"]
path = self.config["path"]
if os.path.exists(path):
self.sql = autosql(sqlite3.connect(path, check_same_thread=False))
except:

View File

@ -3,9 +3,10 @@ import requests
from urllib.parse import quote
import re
from myutils.proxy import getproxy
from cishu.cishubase import cishubase
class youdao:
class youdao(cishubase):
@property
def srclang(self):

View File

@ -310,6 +310,7 @@ class tagitem(QWidget):
super().__init__()
tagLayout = QHBoxLayout()
tagLayout.setContentsMargins(0, 0, 0, 0)
tagLayout.setSpacing(0)
self._type = _type
key = (tag, _type, refdata)
self.setLayout(tagLayout)

View File

@ -520,7 +520,7 @@ class hookselect(closeashidewindow):
savehook_new_data[gobject.baseobject.textsource.pname][
"hooktypeasname"
].__setitem__,
json.dumps(key),
json.dumps(gobject.baseobject.textsource.serialkey(key)),
),
),
)

View File

@ -1,6 +1,6 @@
import functools, os
from myutils.config import globalconfig, _TRL
from gui.inputdialog import getsomepath1, autoinitdialog
from gui.inputdialog import autoinitdialog, autoinitdialog_items
from gui.usefulwidget import (
getcolorbutton,
yuitsu_switch,
@ -18,83 +18,54 @@ def gethiragrid(self):
grids = []
i = 0
self.ocrswitchs = {}
self.hiraswitchs = {}
line = []
for name in globalconfig["hirasetting"]:
_f = "./LunaTranslator/hiraparse/{}.py".format(name)
if os.path.exists(_f) == False:
continue
line += [
((globalconfig["hirasetting"][name]["name"]), 5),
getsimpleswitch(
globalconfig["hirasetting"][name],
"use",
parent=self,
name=name,
if "args" in globalconfig["hirasetting"][name]:
items = autoinitdialog_items(globalconfig["hirasetting"][name])
_3 = getcolorbutton(
globalconfig,
"",
callback=functools.partial(
yuitsu_switch,
autoinitdialog,
self,
globalconfig["hirasetting"],
"hiraswitchs",
name,
gobject.baseobject.starthira,
globalconfig["hirasetting"][name]["name"],
800,
items,
),
pair="hiraswitchs",
),
]
items = []
for key in globalconfig["hirasetting"][name]:
if key == "path":
items.append(
{
"t": "file",
"l": globalconfig["hirasetting"][name]["name"],
"d": globalconfig["hirasetting"][name],
"k": "path",
"dir": True,
}
)
elif key == "token":
items.append(
{
"t": "lineedit",
"l": globalconfig["hirasetting"][name]["token_name"],
"d": globalconfig["hirasetting"][name],
"k": "token",
}
)
elif key == "codec":
items.append(
{
"t": "combo",
"l": "codec",
"d": globalconfig["hirasetting"][name],
"k": "codec",
"list": ["utf8", "shiftjis"],
}
)
if len(items):
items.append({"t": "okcancel", "callback": gobject.baseobject.starthira})
line += [
getcolorbutton(
globalconfig,
"",
callback=functools.partial(
autoinitdialog,
self,
globalconfig["hirasetting"][name]["name"],
800,
items,
),
icon="fa.gear",
constcolor="#FF69B4",
)
]
icon="fa.gear",
constcolor="#FF69B4",
)
else:
line += [""]
_3 = ""
line += [
((globalconfig["hirasetting"][name]["name"]), 6),
(
getsimpleswitch(
globalconfig["hirasetting"][name],
"use",
name=name,
parent=self,
callback=functools.partial(
yuitsu_switch,
self,
globalconfig["hirasetting"],
"hiraswitchs",
name,
gobject.baseobject.starthira,
),
pair="hiraswitchs",
),
1,
),
_3,
]
if i % 3 == 2:
grids.append(line)
line = []
@ -112,7 +83,7 @@ def setTabcishu_l(self):
[
[("分词&假名分析器", 10)],
[
("日语注音方案", 5),
("日语注音方案", 6),
(
getsimplecombobox(
_TRL(["平假名", "片假名", "罗马音"]),
@ -128,7 +99,7 @@ def setTabcishu_l(self):
[],
[],
[
("点击单词查词", 5),
("点击单词查词", 6),
(getsimpleswitch(globalconfig, "usesearchword"), 1),
getcolorbutton(
globalconfig,
@ -138,11 +109,11 @@ def setTabcishu_l(self):
constcolor="#FF69B4",
),
"",
("点击单词复制", 5),
("点击单词复制", 6),
(getsimpleswitch(globalconfig, "usecopyword"), 1),
],
[
("使用原型查询", 5),
("使用原型查询", 6),
(getsimpleswitch(globalconfig, "usewordorigin"), 1),
],
[],
@ -156,33 +127,28 @@ def setTabcishu_l(self):
_f = "./LunaTranslator/cishu/{}.py".format(cishu)
if os.path.exists(_f) == False:
continue
items = autoinitdialog_items(globalconfig["cishu"][cishu])
line += [
(globalconfig["cishu"][cishu]["name"], 5),
(globalconfig["cishu"][cishu]["name"], 6),
getsimpleswitch(
globalconfig["cishu"][cishu],
"use",
callback=functools.partial(gobject.baseobject.startxiaoxueguan, cishu),
),
(
getcolorbutton(
globalconfig,
"",
callback=functools.partial(
getsomepath1,
self,
globalconfig["cishu"][cishu]["name"],
globalconfig["cishu"][cishu],
"path",
globalconfig["cishu"][cishu]["name"],
functools.partial(gobject.baseobject.startxiaoxueguan, cishu),
globalconfig["cishu"][cishu]["isdir"],
globalconfig["cishu"][cishu]["filter"],
),
icon="fa.gear",
constcolor="#FF69B4",
)
if "path" in globalconfig["cishu"][cishu]
else ""
getcolorbutton(
globalconfig,
"",
callback=functools.partial(
autoinitdialog,
self,
globalconfig["cishu"][cishu]["name"],
800,
items,
),
icon="fa.gear",
constcolor="#FF69B4",
),
]

View File

@ -16,7 +16,6 @@ def getocrgrid(self):
grids = []
i = 0
lendict = len(list(globalconfig["ocr"].keys()))
self.ocrswitchs = {}
line = []

View File

@ -65,4 +65,6 @@ class showocrimage(closeashidewindow):
self.originimage = originimage
self.img1 = QPixmap.fromImage(originimage)
self.img2 = QPixmap.fromImage(solved)
self.img1.setDevicePixelRatio(self.devicePixelRatioF())
self.img2.setDevicePixelRatio(self.devicePixelRatioF())
self.showimg()

View File

@ -1,4 +1,3 @@
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (
QWidget,
QHBoxLayout,
@ -7,24 +6,21 @@ from PyQt5.QtWidgets import (
QLineEdit,
QPlainTextEdit,
QFormLayout,
QAction,
QSizePolicy,
QStylePainter,
QStyleOptionTab,
QStyle,
QPushButton,
QTextEdit,
QTabWidget,QFileDialog,
QTabWidget,
QFileDialog,
QTabBar,
QLabel,
)
from PyQt5.QtGui import QPixmap, QImage
from traceback import print_exc
import requests, json
from PyQt5.QtCore import Qt, pyqtSignal
from PyQt5.QtGui import QCursor
import qtawesome, functools, os, re, base64
import threading, gobject, uuid
from myutils.config import globalconfig, _TR, _TRL, static_data
from PyQt5.QtCore import pyqtSignal, Qt
import qtawesome, functools, os, base64
import gobject, uuid
from myutils.config import globalconfig, _TR, static_data
import myutils.ankiconnect as anki
from gui.usefulwidget import (
closeashidewindow,
@ -33,8 +29,8 @@ from gui.usefulwidget import (
getboxlayout,
getspinbox,
getlineedit,
saveposwindow,
getsimpleswitch,getcolorbutton,
getsimpleswitch,
getcolorbutton,
tabadd_lazy,
)
from myutils.wrapper import threader
@ -42,16 +38,22 @@ from myutils.ocrutil import imageCut, ocr_run
from gui.rangeselect import rangeselct_function
class AnkiWindow(closeashidewindow):
class AnkiWindow(QWidget):
setcurrenttext = pyqtSignal(str)
__ocrsettext = pyqtSignal(str)
refreshhtml = pyqtSignal()
def langdu(self):
if gobject.baseobject.reader:
self.audiopath.setText(gobject.baseobject.reader.syncttstofile(
self.wordedit.text()
))
self.audiopath.setText(
gobject.baseobject.reader.syncttstofile(self.currentword)
)
def langdu2(self):
if gobject.baseobject.reader:
self.audiopath_sentence.setText(
gobject.baseobject.reader.syncttstofile(self.example.toPlainText())
)
@threader
def asyncocr(self, fname):
@ -63,20 +65,26 @@ class AnkiWindow(closeashidewindow):
fname = "./cache/ocr/cropforanki.png"
os.makedirs("./cache/ocr", exist_ok=True)
img.save(fname)
self.editpath.setText("")
self.editpath.setText(os.path.abspath(fname))
self.asyncocr(fname)
rangeselct_function(self, ocroncefunction, False, False)
def __init__(self, parent) -> None:
super().__init__(parent, globalconfig, "ankiwindow")
def __init__(self) -> None:
super().__init__()
self.setWindowTitle("Anki Connect")
self.currentword = ""
self.tabs = QTabWidget()
self.tabs.addTab(self.createaddtab(), _TR("添加"))
tabadd_lazy(self.tabs, "设置", self.creatsetdtab)
tabadd_lazy(self.tabs, "模板", self.creattemplatetab)
self.setCentralWidget(self.tabs)
l = QHBoxLayout()
l.setContentsMargins(0, 0, 0, 0)
l.setSpacing(0)
l.addWidget(self.tabs)
self.setLayout(l)
self.refreshhtml.connect(self.refreshhtmlfunction)
self.tabs.currentChanged.connect(self.ifshowrefresh)
@ -127,6 +135,7 @@ class AnkiWindow(closeashidewindow):
layout = QHBoxLayout()
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(0)
wid = QWidget()
wid.setLayout(layout)
@ -139,7 +148,6 @@ class AnkiWindow(closeashidewindow):
layout.addLayout(
getboxlayout(
[
QLabel(_TR("编辑")),
edittemptab,
getboxlayout([revertbtn, savebtn], makewidget=True),
],
@ -152,7 +160,7 @@ class AnkiWindow(closeashidewindow):
self.htmlbrowser.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
layout.addLayout(
getboxlayout(
[QLabel(_TR("预览")), self.previewtab, self.htmlbrowser],
[self.previewtab, self.htmlbrowser],
lc=QVBoxLayout,
margin0=True,
)
@ -179,7 +187,7 @@ class AnkiWindow(closeashidewindow):
object.setPlainText(text)
def loadfileds(self):
word = self.wordedit.text()
word = self.currentword
explain = json.dumps(gobject.baseobject.searchwordW.generate_explains())
remarks = self.remarks.toHtml()
example = self.example.toPlainText()
@ -205,12 +213,24 @@ class AnkiWindow(closeashidewindow):
if len(self.audiopath.text()):
with open(self.audiopath.text(), "rb") as image_file:
encoded_string2 = base64.b64encode(image_file.read()).decode("utf-8")
encoded_string2 = '<audio controls><source src="data:audio/mpeg;base64,{}"></audio>'.format(
encoded_string2 = """<button onclick='document.getElementById("audio1111").play()'>play audio<audio controls id="audio1111" style="display: none"><source src="data:audio/mpeg;base64,{}"></audio></button>""".format(
encoded_string2
)
else:
encoded_string2 = ""
fields = {"audio": encoded_string2, "image": encoded_string}
if len(self.audiopath_sentence.text()):
with open(self.audiopath_sentence.text(), "rb") as image_file:
encoded_string3 = base64.b64encode(image_file.read()).decode("utf-8")
encoded_string3 = """<button onclick='document.getElementById("audio2222").play()'>play audio_sentence<audio controls id="audio2222" style="display: none"><source src="data:audio/mpeg;base64,{}"></audio></button>""".format(
encoded_string3
)
else:
encoded_string3 = ""
fields = {
"audio": encoded_string2,
"audio_sentence": encoded_string3,
"image": encoded_string,
}
return fields
def saveedits(self):
@ -236,13 +256,17 @@ class AnkiWindow(closeashidewindow):
_TR("DeckName"), getlineedit(globalconfig["ankiconnect"], "DeckName")
)
layout.addRow(
_TR("ModelName"), getlineedit(globalconfig["ankiconnect"], "ModelName")
_TR("ModelName"), getlineedit(globalconfig["ankiconnect"], "ModelName2")
)
layout.addRow(
_TR("allowDuplicate"),
getsimpleswitch(globalconfig["ankiconnect"], "allowDuplicate"),
)
layout.addRow(
_TR("autoUpdateModel"),
getsimpleswitch(globalconfig["ankiconnect"], "autoUpdateModel"),
)
return wid
@ -252,42 +276,94 @@ class AnkiWindow(closeashidewindow):
wid.setLayout(layout)
soundbutton = QPushButton(qtawesome.icon("fa.music"), "")
soundbutton.clicked.connect(self.langdu)
soundbutton2 = QPushButton(qtawesome.icon("fa.music"), "")
soundbutton2.clicked.connect(self.langdu2)
cropbutton = QPushButton(qtawesome.icon("fa.crop"), "")
cropbutton.clicked.connect(self.crop)
self.wordedit = QLineEdit()
self.wordedit.textEdited.connect(self.reset)
layout.addLayout(
getboxlayout([QLabel(_TR("Word")), self.wordedit])
)
self.audiopath = QLineEdit()
self.audiopath.setReadOnly(True)
self.audiopath_sentence = QLineEdit()
self.audiopath_sentence.setReadOnly(True)
self.editpath = QLineEdit()
self.editpath.setReadOnly(True)
self.viewimagelabel = QLabel()
self.editpath.textChanged.connect(self.wrappedpixmap)
self.example = QPlainTextEdit()
layout.addWidget(QLabel(_TR("例句")))
layout.addWidget(self.example)
self.remarks = QTextEdit()
layout.addWidget(QLabel(_TR("备注")))
layout.addWidget(self.remarks)
layout.addLayout(
getboxlayout(
[
getboxlayout(
[
getboxlayout(
[QLabel(_TR("例句")), self.example],
QVBoxLayout,
margin0=True,
),
getboxlayout(
[QLabel(_TR("备注")), self.remarks],
QVBoxLayout,
margin0=True,
),
],
QVBoxLayout,
),
getboxlayout(
[
getboxlayout(
[
QLabel(_TR("语音")),
self.audiopath,
soundbutton,
getcolorbutton(
"",
"",
functools.partial(self.selectaudio),
icon="fa.gear",
constcolor="#FF69B4",
),
]
),
getboxlayout(
[
QLabel(_TR("语音_例句")),
self.audiopath_sentence,
soundbutton2,
getcolorbutton(
"",
"",
functools.partial(self.selectaudio2),
icon="fa.gear",
constcolor="#FF69B4",
),
]
),
getboxlayout(
[
QLabel(_TR("截图")),
self.editpath,
cropbutton,
getcolorbutton(
"",
"",
functools.partial(self.selectimage),
icon="fa.gear",
constcolor="#FF69B4",
),
]
),
self.viewimagelabel,
],
QVBoxLayout,
),
]
)
)
self.tagsedit = QLineEdit()
layout.addLayout(getboxlayout([QLabel(_TR("Tags(split by |)")), self.tagsedit]))
self.audiopath = QLineEdit()
self.audiopath.setReadOnly(True)
layout.addLayout(getboxlayout([QLabel(_TR("语音")),self.audiopath,soundbutton,getcolorbutton(
"",
"",
functools.partial(self.selectaudio),
icon="fa.gear",
constcolor="#FF69B4",
)]))
self.editpath = QLineEdit()
self.editpath.setReadOnly(True)
layout.addLayout(getboxlayout([QLabel(_TR("截图")),self.editpath,cropbutton,getcolorbutton(
"",
"",
functools.partial(self.selectimage),
icon="fa.gear",
constcolor="#FF69B4",
)]))
btn = QPushButton(_TR("添加"))
btn.clicked.connect(self.errorwrap)
layout.addWidget(btn)
@ -298,24 +374,46 @@ class AnkiWindow(closeashidewindow):
self.reset("")
return wid
def wrappedpixmap(self, src):
pix = QPixmap.fromImage(QImage(src))
rate = self.devicePixelRatioF()
pix.setDevicePixelRatio(rate)
if (
pix.width() > self.viewimagelabel.width()
or pix.height() > self.viewimagelabel.height()
):
pix = pix.scaled(self.viewimagelabel.size() * rate, Qt.KeepAspectRatio)
self.viewimagelabel.setPixmap(pix)
def selectimage(self):
f = QFileDialog.getOpenFileName()
res = f[0]
if res != "":
self.editpath.setText(res)
def selectaudio(self):
f = QFileDialog.getOpenFileName()
res = f[0]
if res != "":
self.audiopath.setText(res)
def selectaudio2(self):
f = QFileDialog.getOpenFileName()
res = f[0]
if res != "":
self.audiopath_sentence.setText(res)
def reset(self, text):
self.wordedit.setText(text)
self.currentword = text
if text and len(text):
self.ruby = json.dumps(gobject.baseobject.translation_ui.parsehira(text))
else:
self.ruby = ""
self.editpath.clear()
self.audiopath.clear()
self.audiopath_sentence.clear()
def errorwrap(self):
try:
self.addanki()
@ -345,9 +443,10 @@ class AnkiWindow(closeashidewindow):
return model_htmlfront, model_htmlback, model_css
def addanki(self):
autoUpdateModel = globalconfig["ankiconnect"]["autoUpdateModel"]
allowDuplicate = globalconfig["ankiconnect"]["allowDuplicate"]
anki.global_port = globalconfig["ankiconnect"]["port"]
ModelName = globalconfig["ankiconnect"]["ModelName"]
ModelName = globalconfig["ankiconnect"]["ModelName2"]
DeckName = globalconfig["ankiconnect"]["DeckName"]
model_htmlfront, model_htmlback, model_css = self.tryloadankitemplates()
try:
@ -370,19 +469,24 @@ class AnkiWindow(closeashidewindow):
],
)
except anki.AnkiModelExists:
model = anki.Model(ModelName)
model.updateStyling(model_css)
model.updateTemplates(
{
"LUNACARDTEMPLATE1": {
"Front": model_htmlfront,
"Back": model_htmlback,
if autoUpdateModel:
model = anki.Model(ModelName)
model.updateStyling(model_css)
model.updateTemplates(
{
"LUNACARDTEMPLATE1": {
"Front": model_htmlfront,
"Back": model_htmlback,
}
}
}
)
)
media = []
tempfiles = []
for k, _ in [("audio", self.audiopath.text()), ("image", self.editpath.text())]:
for k, _ in [
("audio", self.audiopath.text()),
("audio_sentence", self.audiopath_sentence.text()),
("image", self.editpath.text()),
]:
if len(_):
media.append(
[
@ -403,49 +507,47 @@ class AnkiWindow(closeashidewindow):
self.loadfileds(),
allowDuplicate,
tags,
media[0],
media[1],
media[0] + media[1],
media[2],
)
class searchwordW(closeashidewindow):
getnewsentencesignal = pyqtSignal(str, bool)
searchthreadsignal = pyqtSignal(str, dict, str)
showtabsignal = pyqtSignal(str, str)
def __init__(self, parent):
super(searchwordW, self).__init__(parent, globalconfig, "sw_geo")
self.ankiwindow = AnkiWindow(self)
self.ankiwindow = AnkiWindow()
self.setupUi()
# self.setWindowFlags(self.windowFlags()&~Qt.WindowMinimizeButtonHint)
self.getnewsentencesignal.connect(self.getnewsentence)
self.setWindowTitle(_TR("查词"))
def showresfun(self, k, res):
first = res.split("<hr>")[0]
self.cache_results[k] = res
self.textbs[k].insertHtml(first)
self.textbs[k].firsttext = self.textbs[k].toPlainText()
self.textbs[k].insertHtml(res[len(first) :])
scrollbar = self.textbs[k].verticalScrollBar()
scrollbar.setValue(0)
self.tab.setTabVisible(self._k.index(k), True)
thisp = globalconfig["cishu"][k]["args"]["priority"]
idx = 0
for kk in self.tabks:
if globalconfig["cishu"][kk]["args"]["priority"] >= thisp:
idx += 1
self.tabks.insert(idx, k)
self.tab.insertTab(idx, _TR(globalconfig["cishu"][k]["name"]))
def setupUi(self):
self.setWindowIcon(qtawesome.icon("fa.search"))
self.showtabsignal.connect(self.showresfun)
self.centralWidget = QWidget(self)
ww = QWidget(self)
self.setWindowIcon(qtawesome.icon("fa.gear"))
self.hboxlayout = QHBoxLayout(self.centralWidget)
self.vboxlayout = QVBoxLayout()
ww.setLayout(self.vboxlayout)
self.searchlayout = QHBoxLayout()
self.vboxlayout.addLayout(self.searchlayout)
self.searchtext = QLineEdit()
# self.searchtext.setFont(font)
self.searchtext.textChanged.connect(self.ankiwindow.reset)
self.searchlayout.addWidget(self.searchtext)
searchbutton = QPushButton(qtawesome.icon("fa.search"), "") # _TR("搜索"))
@ -457,38 +559,41 @@ class searchwordW(closeashidewindow):
self.searchlayout.addWidget(soundbutton)
ankiconnect = QPushButton(qtawesome.icon("fa.adn"), "")
ankiconnect.clicked.connect(self.ankiwindow.show)
ankiconnect.clicked.connect(self.onceaddankiwindow)
self.searchlayout.addWidget(ankiconnect)
self.tab = QTabWidget(self)
self.tab = QTabBar(self)
self.tab.currentChanged.connect(
lambda idx: self.textOutput.setHtml(self.cache_results[self.tabks[idx]])
)
self.tabks = []
self.setCentralWidget(ww)
self.vboxlayout.addWidget(self.tab)
self.hboxlayout.addLayout(self.vboxlayout)
self.setCentralWidget(self.centralWidget)
self.textbs = {}
_k = []
_name = []
for cishu in globalconfig["cishu"]:
_name.append(globalconfig["cishu"][cishu]["name"])
_k.append(cishu)
self._k = _k
_name = _TRL(_name)
for i in range(len(_name)):
textOutput = QTextBrowser(self)
# textOutput.setFont(font)
textOutput.setUndoRedoEnabled(False)
textOutput.setReadOnly(True)
textOutput.setOpenLinks(False)
self.tab.addTab(textOutput, _name[i])
self.tab.setTabVisible(i, False)
self.textbs[self._k[i]] = textOutput
textOutput = QTextBrowser(self)
textOutput.setUndoRedoEnabled(False)
textOutput.setReadOnly(True)
textOutput.setOpenLinks(False)
self.textOutput = textOutput
self.cache_results = {}
self.hiding = True
self.searchthreadsignal.connect(self.searchthread)
self.addankiwindowidx = 0
tablayout = QVBoxLayout()
tablayout.addWidget(self.tab)
tablayout.addWidget(textOutput)
tablayout.setContentsMargins(0, 0, 0, 0)
tablayout.setSpacing(0)
self.vboxlayout.addLayout(tablayout)
def onceaddankiwindow(self):
if self.addankiwindowidx == 0:
self.vboxlayout.addWidget(self.ankiwindow)
else:
if self.addankiwindowidx % 2 == 0:
self.ankiwindow.show()
else:
self.ankiwindow.hide()
self.addankiwindowidx += 1
def langdu(self):
if gobject.baseobject.reader:
@ -496,13 +601,18 @@ class searchwordW(closeashidewindow):
def generate_explains(self):
res = []
for i in range(len(self._k)):
if len(self.textbs[self._k[i]].toPlainText()) == 0:
tabks = []
for k, v in self.cache_results.items():
if len(v) == 0:
continue
res.append(
{"source": self._k[i], "content": self.textbs[self._k[i]].toHtml()}
)
thisp = globalconfig["cishu"][k]["args"]["priority"]
idx = 0
for i in tabks:
if i >= thisp:
idx += 1
k = _TR(globalconfig["cishu"][k]["name"])
tabks.append(thisp)
res.insert(idx, {"source": k, "content": v})
return res
def getnewsentence(self, sentence, append):
@ -513,22 +623,14 @@ class searchwordW(closeashidewindow):
self.search(sentence)
def searchthread(self, k, _mp, sentence):
_mp[k].callback = functools.partial(self.showtabsignal.emit, k)
_mp[k].search(sentence)
def search(self, sentence):
if sentence == "":
return
self.ankiwindow.setcurrenttext.emit(sentence)
_mp = {}
_mp.update(gobject.baseobject.cishus)
for k in self._k:
self.tab.setTabVisible(self._k.index(k), False)
self.textbs[k].clear()
if k in _mp:
threading.Thread(
target=self.searchthreadsignal.emit, args=(k, _mp, sentence)
).start()
for i in range(self.tab.count()):
self.tab.removeTab(0)
self.tabks.clear()
self.cache_results.clear()
for k, cishu in gobject.baseobject.cishus.items():
cishu.callback = functools.partial(self.showtabsignal.emit, k)
cishu.safesearch(sentence)

View File

@ -2,13 +2,12 @@ import time
import functools
import threading
import os, sys
from PyQt5.QtCore import QT_VERSION_STR
import windows, importlib
from traceback import print_exc
from PyQt5.QtCore import Qt, pyqtSignal
import qtawesome
from PyQt5.QtCore import pyqtSignal, Qt, QSize
from PyQt5.QtGui import QCursor, QColor
from PyQt5.QtGui import QCursor
from PyQt5.QtWidgets import QLabel, QPushButton, QSystemTrayIcon
import gobject
from myutils.wrapper import threader, trypass
@ -152,25 +151,8 @@ class QUnFrameWindow(resizableframeless):
hira = []
try:
if gobject.baseobject.hira_:
hira = gobject.baseobject.hira_.fy(text)
for _1 in range(len(hira)):
_ = len(hira) - 1 - _1
if globalconfig["hira_vis_type"] == 0:
hira[_]["hira"] = hira[_]["hira"].translate(self.castkata2hira)
elif globalconfig["hira_vis_type"] == 1:
hira[_]["hira"] = hira[_]["hira"].translate(self.casthira2kata)
elif globalconfig["hira_vis_type"] == 2:
__kanas = [
static_data["hira"] + [""],
static_data["kata"] + [""],
]
target = static_data["roma"] + ["-"]
for _ka in __kanas:
for __idx in range(len(_ka)):
_reverse_idx = len(_ka) - 1 - __idx
hira[_]["hira"] = hira[_]["hira"].replace(
_ka[_reverse_idx], target[_reverse_idx]
)
hira = gobject.baseobject.hira_.parseparse(text)
except:
print_exc()
return hira
@ -624,8 +606,7 @@ class QUnFrameWindow(resizableframeless):
self.tray.setIcon(icon)
showintab(int(self.winId()), globalconfig["showintab"])
self.isfirstshow = True
if QT_VERSION_STR != "5.5.1":
self.setAttribute(Qt.WA_TranslucentBackground)
self.setAttribute(Qt.WA_TranslucentBackground)
self.setAttribute(Qt.WA_ShowWithoutActivating, True)
self.showintab = globalconfig["showintab"]
self.setWindowTitle("LunaTranslator")
@ -655,12 +636,6 @@ class QUnFrameWindow(resizableframeless):
self.quitf_signal.connect(self.close)
self.fullsgame_signal.connect(self._fullsgame)
self.castkata2hira = str.maketrans(
static_data["allkata"], static_data["allhira"]
)
self.casthira2kata = str.maketrans(
static_data["allhira"], static_data["allkata"]
)
self.fullscreenmanager_busy = False
self.isletgamefullscreened = False
self.fullscreenmanager = None

View File

@ -9,6 +9,7 @@ from PyQt5.QtWidgets import (
QSizePolicy,
QHBoxLayout,
QWidget,
QLayout,
)
from webviewpy import (
@ -507,7 +508,10 @@ def selectcolor(
def getboxlayout(widgets, lc=QHBoxLayout, margin0=False, makewidget=False):
cp_layout = lc()
for w in widgets:
cp_layout.addWidget(w)
if isinstance(w, QWidget):
cp_layout.addWidget(w)
elif isinstance(w, QLayout):
cp_layout.addLayout(w)
if margin0:
cp_layout.setContentsMargins(0, 0, 0, 0)
if makewidget:

View File

@ -0,0 +1,59 @@
from myutils.config import globalconfig, static_data
from traceback import print_exc
class basehira:
def init(self):
pass
def parse(self, text):
return []
def __init__(self, typename) -> None:
self.typename = typename
self.castkata2hira = str.maketrans(
static_data["allkata"], static_data["allhira"]
)
self.casthira2kata = str.maketrans(
static_data["allhira"], static_data["allkata"]
)
self.needinit = True
self.init()
self.needinit = False
@property
def config(self):
return globalconfig["hirasetting"][self.typename]["args"]
def parseparse(self, text):
hira = []
try:
if self.needinit:
self.init()
self.needinit = False
try:
hira = self.parse(text)
except Exception as e:
self.needinit = True
raise e
for _1 in range(len(hira)):
_ = len(hira) - 1 - _1
if globalconfig["hira_vis_type"] == 0:
hira[_]["hira"] = hira[_]["hira"].translate(self.castkata2hira)
elif globalconfig["hira_vis_type"] == 1:
hira[_]["hira"] = hira[_]["hira"].translate(self.casthira2kata)
elif globalconfig["hira_vis_type"] == 2:
__kanas = [
static_data["hira"] + [""],
static_data["kata"] + [""],
]
target = static_data["roma"] + ["-"]
for _ka in __kanas:
for __idx in range(len(_ka)):
_reverse_idx = len(_ka) - 1 - __idx
hira[_]["hira"] = hira[_]["hira"].replace(
_ka[_reverse_idx], target[_reverse_idx]
)
except:
print_exc()
return hira

View File

@ -1,8 +1,9 @@
class hira:
def __init__(self) -> None:
pass
from hiraparse.basehira import basehira
def fy(self, text):
class latin(basehira):
def parse(self, text):
_x = []
i = 0
for _ in text.split(" "):

View File

@ -1,22 +1,21 @@
from myutils.config import globalconfig
import winsharedutils
import os
from hiraparse.basehira import basehira
class hira:
def __init__(self) -> None:
hirasettingbase = globalconfig["hirasetting"]
mecabpath = hirasettingbase["mecab"]["path"]
class mecab(basehira):
def init(self) -> None:
mecabpath = self.config["path"]
if os.path.exists(mecabpath):
self.kks = winsharedutils.mecabwrap(
mecabpath
) # fugashi.Tagger('-r nul -d "{}" -Owakati'.format(mecabpath))
def fy(self, text):
def parse(self, text):
start = 0
result = []
codec = ["utf8", "shiftjis"][globalconfig["hirasetting"]["mecab"]["codec"]]
codec = ["utf8", "shiftjis"][self.config["codec"]]
for node, fields in self.kks.parse(
text, codec
): # self.kks.parseToNodeList(text):
@ -49,7 +48,6 @@ class hira:
if origorig is None:
origorig = orig
start += l
hira = kana # .translate(self.h2k)

View File

@ -1,14 +1,10 @@
from myutils.config import globalconfig
from myutils.proxy import getproxy
import requests
from hiraparse.basehira import basehira
class hira:
def __init__(self) -> None:
pass
def fy(self, text):
class mojinlt(basehira):
def parse(self, text):
def nlt(text, token):
try:
@ -37,4 +33,4 @@ class hira:
except:
return []
return nlt(text, globalconfig["hirasetting"]["mojinlt"]["token"])
return nlt(text, self.config["Moji NLT Token"])

View File

@ -460,10 +460,14 @@ class texthook(basetext):
return True
def serialkey(self, key):
hc, hn, tp = key
return (tp.processId, tp.addr, tp.ctx, tp.ctx2, hn, hc)
def serialselectedhook(self):
xx = []
for hc, hn, tp in self.selectedhook:
xx.append((tp.processId, tp.addr, tp.ctx, tp.ctx2, hn, hc))
for key in self.selectedhook:
xx.append(self.serialkey(key))
return xx
def checkisusingembed(self, address, ctx1, ctx2):

View File

@ -1,5 +1,4 @@
from translator.basetranslator_dev import basetransdev
from urllib.parse import quote
class TS(basetransdev):
@ -18,15 +17,12 @@ class TS(basetransdev):
def translate(self, content):
self.Runtime_evaluate(
"document.getElementsByClassName('textarea-clear-btn')[0].click()"
"""document.querySelector("#editor-text > div.AZLVLJHb > div.Ssl84aLh > span").click()"""
)
self.Page_navigate(
"https://fanyi.baidu.com/#{}/{}/{}".format(
self.srclang, self.tgtlang, quote(content)
)
self.Runtime_evaluate(
"""document.querySelector("#editor-text > div.AZLVLJHb > div.Ssl84aLh > div > div > div").click()"""
)
self.send_keys(content)
return self.wait_for_result(
"""document.querySelector("#trans-selection").innerText"""
)
res = self.wait_for_result(
"document.querySelector('div.output-bd')===null?'':document.querySelector('div.output-bd').innerText"
).replace("\n\n", "\n")
return res

View File

@ -40,28 +40,21 @@ class basetransdev(basetrans):
if self.using == False:
return
self._id += 1
try:
if ws is None:
ws = self.ws
ws.send(json.dumps({"id": self._id, "method": method, "params": params}))
res = ws.recv()
except:
print_exc()
self._createtarget()
time.sleep(1)
return self._SendRequest(method, params, ws)
if ws is None:
ws = self.ws
ws.send(json.dumps({"id": self._id, "method": method, "params": params}))
res = ws.recv()
res = json.loads(res)
try:
return res["result"]
except:
print(res)
if (
res["method"] == "Inspector.detached"
and res["params"]["reason"] == "target_closed"
):
self._createtarget()
return self._SendRequest(method, params, ws)
if res['error']['code']==-32600:
self._id+=1
self._SendRequest(method,params,ws)
else:
raise
def _createtarget(self):
if self.using == False:
return

View File

@ -1,28 +0,0 @@
from translator.basetranslator_dev import basetransdev
class TS(basetransdev):
target_url = "https://fanyi.baidu.com/mtpe-individual/multimodal#/"
def langmap(self):
return {
"es": "spa",
"ko": "kor",
"fr": "fra",
"ja": "jp",
"cht": "cht",
"vi": "vie",
"uk": "ukr",
}
def translate(self, content):
self.Runtime_evaluate(
"""document.querySelector("#editor-text > div.AZLVLJHb > div.Ssl84aLh > span").click()"""
)
self.Runtime_evaluate(
"""document.querySelector("#editor-text > div.AZLVLJHb > div.Ssl84aLh > div > div > div").click()"""
)
self.send_keys(content)
return self.wait_for_result(
"""document.querySelector("#trans-selection").innerText"""
)

View File

@ -1,6 +1,9 @@
<div class="hide-style">{{audio}}</div>
<div class="hide-style">
<div id="audio">{{audio}}</div>
<div id="audio_sentence">{{audio_sentence}}</div>
</div>
<div class="centerdiv">
<div id="rubyword" class="ruby-div"></div>
<div id="rubyword" class="ruby-div" onclick='playAudio("audio")'></div>
</div>
<script>
@ -13,17 +16,13 @@
</script>
<div id="example_sentence" class="centerdiv example-div">
<div id="example_sentence" class="centerdiv example-div" onclick='playAudio("audio_sentence")'>
{{example_sentence}}
</div>
<div id="image" class="centerdiv">
{{image}}
</div>
<div id="remarks" class="centerdiv remark-div">
{{remarks}}
</div>
<div class="tab-widget">
<div class="centerdiv">
<div class="tab-buttons" id="tab_buttons">
@ -46,11 +45,22 @@
<script>
explains = {{ explain }}
function safehtml(html) {
var tempParent = document.createElement('div');
tempParent.innerHTML = html;
var fragment = document.createElement('div');
while (tempParent.firstChild) {
fragment.appendChild(tempParent.firstChild);
}
return fragment.innerHTML
}
htmltabbuttons = ''
htmlcontents = ''
for (i = 0; i < explains.length; i++) {
htmltabbuttons += '<button type="button" class="tab-button" data-tab="tab' + (i + 0).toString() + '">' + explains[i]['source'] + '</button>'
htmlcontents += '<div id="tab' + (i + 0).toString() + '" class="tab-pane">' + explains[i]['content'] + '</div>'
htmlcontents += '<div id="tab' + (i + 0).toString() + '" class="tab-pane">' + safehtml(explains[i]['content']) + '</div>'
}
document.getElementById('tab_buttons').innerHTML = htmltabbuttons
document.getElementById('tab_contents').innerHTML = htmlcontents
@ -78,6 +88,13 @@
</script>
<script>
function playAudio(audioId) {
var audioDiv = document.getElementById(audioId);
var audio = audioDiv.getElementsByTagName('*');
if (audio.length > 0) {
audio[0].click();
}
}
function checkhide(eid) {
var emptyDiv = document.getElementById(eid);
if (emptyDiv && emptyDiv.innerText.trim() === "") {

View File

@ -1,6 +1,9 @@
<div class="hide-style">{{audio}}</div>
<div class="hide-style">
<div id="audio">{{audio}}</div>
<div id="audio_sentence">{{audio_sentence}}</div>
</div>
<div class="centerdiv">
<div id="rubyword" class="ruby-div"></div>
<div id="rubyword" class="ruby-div" onclick='playAudio("audio")'></div>
</div>
<script>
@ -13,7 +16,7 @@
</script>
<div id="example_sentence" class="centerdiv example-div">
<div id="example_sentence" class="centerdiv example-div" onclick='playAudio("audio_sentence")'>
{{example_sentence}}
</div>
<div id="image" class="centerdiv">
@ -22,6 +25,13 @@
<script>
function playAudio(audioId) {
var audioDiv = document.getElementById(audioId);
var audio = audioDiv.getElementsByTagName('*');
if (audio.length > 0) {
audio[0].click();
}
}
function checkhide(eid) {
var emptyDiv = document.getElementById(eid);
if (emptyDiv && emptyDiv.innerText.trim() === "") {

View File

@ -179,9 +179,9 @@
"ankiconnect": {
"port": 8765,
"DeckName": "lunadeck",
"ModelName": "lunamodel",
"allowDuplicate":true
"ModelName2": "lunamodel2",
"allowDuplicate": true,
"autoUpdateModel": true
},
"ankiwindow": [
100,
@ -678,15 +678,31 @@
"hirasetting": {
"mecab": {
"use": false,
"path": "",
"name": "MeCab",
"codec": 0
"args": {
"path": "",
"codec": 0
},
"argstype": {
"path": {
"type": "file",
"dir": true
},
"codec": {
"type": "combo",
"list": [
"utf8",
"shiftjis"
]
}
}
},
"mojinlt": {
"use": false,
"token": "",
"token_name": "Moji NLT Token",
"name": "mojinlt"
"name": "mojinlt",
"args": {
"Moji NLT Token": ""
}
},
"latin": {
"use": false,
@ -695,48 +711,146 @@
},
"cishu": {
"xiaoxueguan": {
"args": {
"path": "",
"priority": 100
},
"argstype": {
"path": {
"type": "file",
"dir": false,
"filter": "*.db"
},
"priority": {
"type": "intspin",
"min": 0,
"max": 10000,
"step": 1
}
},
"use": false,
"path": "",
"name": "小学馆",
"filter": "*.db",
"isdir": false
"name": "小学馆"
},
"edict": {
"use": false,
"path": "",
"name": "EDICT",
"filter": "*.db",
"isdir": false
"args": {
"path": "",
"priority": 100
},
"argstype": {
"path": {
"type": "file",
"dir": false,
"filter": "*.db"
},
"priority": {
"type": "intspin",
"min": 0,
"max": 10000,
"step": 1
}
}
},
"edict2": {
"use": false,
"path": "",
"name": "EDICT2",
"filter": "",
"isdir": false
"args": {
"path": "",
"priority": 100
},
"argstype": {
"path": {
"type": "file",
"dir": false
},
"priority": {
"type": "intspin",
"min": 0,
"max": 10000,
"step": 1
}
}
},
"linggesi": {
"use": false,
"path": "",
"name": "灵格斯词典",
"filter": "",
"isdir": true
"args": {
"path": "",
"priority": 100
},
"argstype": {
"path": {
"type": "file",
"dir": true
},
"priority": {
"type": "intspin",
"min": 0,
"max": 10000,
"step": 1
}
}
},
"mojidict": {
"use": false,
"name": "Moji辞书"
"name": "Moji辞书",
"args": {
"priority": 100
},
"argstype": {
"priority": {
"type": "intspin",
"min": 0,
"max": 10000,
"step": 1
}
}
},
"youdao": {
"use": false,
"name": "youdao"
"name": "有道",
"args": {
"priority": 100
},
"argstype": {
"priority": {
"type": "intspin",
"min": 0,
"max": 10000,
"step": 1
}
}
},
"weblio": {
"use": false,
"name": "weblio"
"name": "weblio",
"args": {
"priority": 100
},
"argstype": {
"priority": {
"type": "intspin",
"min": 0,
"max": 10000,
"step": 1
}
}
},
"goo": {
"use": false,
"name": "goo"
"name": "goo",
"args": {
"priority": 100
},
"argstype": {
"priority": {
"type": "intspin",
"min": 0,
"max": 10000,
"step": 1
}
}
}
},
"darklight": 0,
@ -951,12 +1065,6 @@
"type": "dev",
"name": "百度"
},
"dev_baidu_ai": {
"use": false,
"color": "blue",
"type": "dev",
"name": "百度_ai"
},
"google_dev": {
"use": false,
"color": "blue",

View File

@ -1625,6 +1625,7 @@
"explain",
"image",
"audio",
"audio_sentence",
"example_sentence",
"rubytext",
"remarks"

View File

@ -777,12 +777,10 @@
"合并": "دمج",
"立即应用": "التطبيق الفوري",
"无法连接到anki": "غير قادر على الاتصال انكي",
"追加": "إلحاق",
"例句": "على سبيل المثال",
"正面": "أمامي",
"背面": "ظهر",
"样式": "نمط",
"预览": "معاينة",
"恢复": "استعاد",
"模板": "قالب .",
"截图": "لقطة"

View File

@ -777,12 +777,10 @@
"合并": "合併",
"立即应用": "立即應用",
"无法连接到anki": "無法連接到anki",
"追加": "追加",
"例句": "例句",
"正面": "正面",
"背面": "背面",
"样式": "樣式",
"预览": "預覽",
"恢复": "恢復",
"模板": "範本",
"截图": "截圖"

View File

@ -777,12 +777,10 @@
"合并": "merge",
"立即应用": "apply now",
"无法连接到anki": "Unable to connect to Anki",
"追加": "Add",
"例句": "Example sentence",
"正面": "front",
"背面": "Back",
"样式": "style",
"预览": "preview",
"恢复": "recovery",
"模板": "Template",
"截图": "screenshot"

View File

@ -777,12 +777,10 @@
"合并": "Fusión",
"立即应用": "Aplicar de inmediato",
"无法连接到anki": "No se puede conectar a Anki",
"追加": "Añadido",
"例句": "Ejemplo",
"正面": "Frontal",
"背面": "Parte posterior",
"样式": "Estilo",
"预览": "Vista previa",
"恢复": "Recuperación",
"模板": "Plantilla",
"截图": "Captura de pantalla"

View File

@ -777,12 +777,10 @@
"合并": "Consolidation",
"立即应用": "Appliquer maintenant",
"无法连接到anki": "Impossible de se connecter à Anki",
"追加": "Supplémentaire",
"例句": "Phrases d'exemple",
"正面": "Le Front",
"背面": "Arrière",
"样式": "Style",
"预览": "Preview",
"恢复": "Récupération",
"模板": "Modèle",
"截图": "Capture d'écran"

View File

@ -777,12 +777,10 @@
"合并": "fusione",
"立即应用": "Applica ora",
"无法连接到anki": "Impossibile connettersi ad Anki",
"追加": "Aggiungi",
"例句": "Esempio di frase",
"正面": "anteriore",
"背面": "Indietro",
"样式": "stile",
"预览": "anteprima",
"恢复": "recupero",
"模板": "Modello",
"截图": "screenshot"

View File

@ -777,12 +777,10 @@
"合并": "マージ",
"立即应用": "今すぐ適用",
"无法连接到anki": "ankiに接続できません",
"追加": "追加#ツイカ#",
"例句": "例文",
"正面": "前面",
"背面": "背面",
"样式": "スタイル",
"预览": "プレビュー",
"恢复": "リカバリ",
"模板": "テンプレート",
"截图": "スクリーンショット"

View File

@ -777,12 +777,10 @@
"合并": "병합",
"立即应用": "지금 적용",
"无法连接到anki": "anki에 연결할 수 없음",
"追加": "추가",
"例句": "예문",
"正面": "정면",
"背面": "뒷면",
"样式": "스타일",
"预览": "미리 보기",
"恢复": "복구",
"模板": "템플릿",
"截图": "캡처"

View File

@ -777,12 +777,10 @@
"合并": "połączenie",
"立即应用": "aplikuj teraz",
"无法连接到anki": "Nie można połączyć się z Anki",
"追加": "Dodaj",
"例句": "Zdanie przykładowe",
"正面": "z przodu",
"背面": "Z powrotem",
"样式": "styl",
"预览": "podgląd",
"恢复": "odzyskiwanie",
"模板": "Szablon",
"截图": "zrzut ekranu"

View File

@ -777,12 +777,10 @@
"合并": "Объединение",
"立即应用": "Немедленное применение",
"无法连接到anki": "Не удалось подключиться к ANKI",
"追加": "Добавить",
"例句": "Примеры",
"正面": "Положительный",
"背面": "Задняя сторона",
"样式": "Стиль",
"预览": "Предварительный просмотр",
"恢复": "Восстановление",
"模板": "Шаблоны:",
"截图": "Снимок экрана"

View File

@ -777,12 +777,10 @@
"合并": "การควบรวมกิจการ",
"立即应用": "สมัครตอนนี้",
"无法连接到anki": "ไม่สามารถเชื่อมต่อกับ anki ได้",
"追加": "เพิ่ม",
"例句": "ตัวอย่างประโยค",
"正面": "ด้านหน้า",
"背面": "ด้านหลัง",
"样式": "สไตล์",
"预览": "แสดงตัวอย่าง",
"恢复": "การกู้คืน",
"模板": "เทมเพลต",
"截图": "ภาพหน้าจอ"

View File

@ -777,12 +777,10 @@
"合并": "birleştir",
"立即应用": "şimdi uygulayın",
"无法连接到anki": "Anki ile bağlanılamadı",
"追加": "Ekle",
"例句": "Örnek cümle",
"正面": "ön",
"背面": "Geri",
"样式": "stil",
"预览": "önizleme",
"恢复": "iyileştirme",
"模板": "Şablon",
"截图": "ekran fotoğrafı"

View File

@ -777,12 +777,10 @@
"合并": "об єднати",
"立即应用": "застосовувати зараз",
"无法连接到anki": "Неможливо з' єднатися з Anki",
"追加": "Додати",
"例句": "Приклад речення",
"正面": "передній",
"背面": "Назад",
"样式": "стиль",
"预览": "перегляд",
"恢复": "відновлення",
"模板": "Шаблон",
"截图": "знімок екрана"

View File

@ -777,12 +777,10 @@
"合并": "Hợp nhất",
"立即应用": "Áp dụng ngay",
"无法连接到anki": "Không thể kết nối với Anki",
"追加": "Thêm",
"例句": "Câu ví dụ",
"正面": "Mặt trước",
"背面": "Mặt sau",
"样式": "Kiểu dáng",
"预览": "Xem thử",
"恢复": "Phục hồi",
"模板": "Mẫu",
"截图": "Ảnh chụp màn hình"

View File

@ -776,13 +776,11 @@
"圆角": "",
"合并": "",
"立即应用": "",
"追加": "",
"无法连接到anki": "",
"例句": "",
"正面": "",
"背面": "",
"样式": "",
"预览": "",
"恢复": "",
"模板": "",
"截图": ""

View File

@ -28,8 +28,8 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/version)
include(generate_product_version)
set(VERSION_MAJOR 2)
set(VERSION_MINOR 50)
set(VERSION_PATCH 4)
set(VERSION_MINOR 51)
set(VERSION_PATCH 0)
add_library(pch pch.cpp)
target_precompile_headers(pch PUBLIC pch.h)