mirror of
https://github.com/HIllya51/LunaTranslator.git
synced 2024-12-28 08:04:13 +08:00
update
This commit is contained in:
parent
20e7106d60
commit
a001ba38c7
@ -415,7 +415,7 @@ class MAINUI:
|
||||
text, savehook_new_data[self.textsource.pname]
|
||||
)
|
||||
except:
|
||||
print_exc()
|
||||
pass
|
||||
self.reader.read(text, force)
|
||||
except:
|
||||
print_exc()
|
||||
|
@ -5,16 +5,146 @@ from PyQt5.QtWidgets import (
|
||||
QVBoxLayout,
|
||||
QTextBrowser,
|
||||
QLineEdit,
|
||||
QMenu,
|
||||
QAction,
|
||||
QPushButton,
|
||||
QTextEdit,
|
||||
QTabWidget,
|
||||
QDialog,
|
||||
QLabel,
|
||||
)
|
||||
from traceback import print_exc
|
||||
import requests
|
||||
from PyQt5.QtCore import Qt, pyqtSignal
|
||||
import qtawesome, functools
|
||||
import threading, gobject
|
||||
from PyQt5.QtGui import QCursor
|
||||
import qtawesome, functools, os
|
||||
import threading, gobject, uuid
|
||||
from myutils.config import globalconfig
|
||||
from myutils.config import globalconfig, _TR, _TRL
|
||||
import myutils.ankiconnect as anki
|
||||
from gui.usefulwidget import closeashidewindow, getQMessageBox, getboxlayout
|
||||
|
||||
from gui.usefulwidget import closeashidewindow
|
||||
from myutils.ocrutil import imageCut
|
||||
from gui.rangeselect import rangeselct_function
|
||||
|
||||
|
||||
class AnkiWindow(QDialog):
|
||||
setcurrenttext = pyqtSignal(str)
|
||||
appenddictionary = pyqtSignal(str)
|
||||
|
||||
def langdu(self):
|
||||
if gobject.baseobject.reader:
|
||||
self.audiofile = gobject.baseobject.reader.syncttstofile(
|
||||
self.wordedit.text()
|
||||
)
|
||||
|
||||
def crop(self):
|
||||
def ocroncefunction(rect):
|
||||
img = imageCut(0, rect[0][0], rect[0][1], rect[1][0], rect[1][1])
|
||||
fname = "./cache/ocr/cropforanki.png"
|
||||
os.makedirs("./cache/ocr", exist_ok=True)
|
||||
img.save(fname)
|
||||
self.cropedimagepath = os.path.abspath(fname)
|
||||
|
||||
rangeselct_function(self, ocroncefunction, False, False)
|
||||
|
||||
def __init__(self, parent) -> None:
|
||||
super().__init__(parent, Qt.WindowCloseButtonHint)
|
||||
self.setWindowTitle("Anki Connect")
|
||||
self.audiofile = None
|
||||
self.cropedimagepath = None
|
||||
layout = QVBoxLayout()
|
||||
self.setLayout(layout)
|
||||
soundbutton = QPushButton(qtawesome.icon("fa.music"), "")
|
||||
soundbutton.clicked.connect(self.langdu)
|
||||
cropbutton = QPushButton(qtawesome.icon("fa.crop"), "")
|
||||
cropbutton.clicked.connect(self.crop)
|
||||
self.wordedit = QLineEdit()
|
||||
layout.addLayout(
|
||||
getboxlayout([QLabel(_TR("Word")), self.wordedit, soundbutton, cropbutton])
|
||||
)
|
||||
self.textedit = QTextEdit()
|
||||
layout.addWidget(self.textedit)
|
||||
|
||||
btn = QPushButton(_TR("添加"))
|
||||
btn.clicked.connect(self.errorwrap)
|
||||
layout.addWidget(btn)
|
||||
self.setcurrenttext.connect(self.reset)
|
||||
self.appenddictionary.connect(self.textedit.append)
|
||||
|
||||
def reset(self, text):
|
||||
self.wordedit.setText(text)
|
||||
self.textedit.clear()
|
||||
self.cropedimagepath = None
|
||||
self.audiofile = None
|
||||
|
||||
def errorwrap(self):
|
||||
try:
|
||||
self.addanki()
|
||||
getQMessageBox(self, _TR("成功"), _TR("成功"))
|
||||
except requests.NetWorkException:
|
||||
getQMessageBox(self, _TR("错误"), _TR("无法连接到anki"))
|
||||
except anki.AnkiException as e:
|
||||
getQMessageBox(self, _TR("错误"), str(e))
|
||||
except:
|
||||
print_exc()
|
||||
|
||||
def addanki(self):
|
||||
word = self.wordedit.text()
|
||||
explain = self.textedit.toHtml()
|
||||
anki.Deck.create(anki.DeckName)
|
||||
try:
|
||||
model = anki.Model.create(
|
||||
anki.ModelName,
|
||||
anki.model_fileds,
|
||||
anki.model_css,
|
||||
False,
|
||||
[
|
||||
{
|
||||
"Name": "LUNACARDTEMPLATE1",
|
||||
"Front": anki.model_htmlfront,
|
||||
"Back": anki.model_htmlback,
|
||||
}
|
||||
],
|
||||
)
|
||||
except anki.AnkiModelExists:
|
||||
model = anki.Model(anki.ModelName)
|
||||
model.updateStyling(anki.model_css)
|
||||
model.updateTemplates(
|
||||
{
|
||||
"LUNACARDTEMPLATE1": {
|
||||
"Front": anki.model_htmlfront,
|
||||
"Back": anki.model_htmlback,
|
||||
}
|
||||
}
|
||||
)
|
||||
media = []
|
||||
for k, _ in [("audio", self.audiofile), ("image", self.cropedimagepath)]:
|
||||
if _:
|
||||
media.append(
|
||||
[
|
||||
{
|
||||
"path": _,
|
||||
"filename": str(uuid.uuid4()) + os.path.basename(_),
|
||||
"fields": [k],
|
||||
}
|
||||
]
|
||||
)
|
||||
else:
|
||||
media.append([])
|
||||
|
||||
anki.Note.add(
|
||||
anki.DeckName,
|
||||
anki.ModelName,
|
||||
{
|
||||
"word": word,
|
||||
"explain": explain,
|
||||
},
|
||||
False,
|
||||
[],
|
||||
media[0],
|
||||
media[1],
|
||||
)
|
||||
|
||||
|
||||
class searchwordW(closeashidewindow):
|
||||
@ -24,6 +154,7 @@ class searchwordW(closeashidewindow):
|
||||
|
||||
def __init__(self, parent):
|
||||
super(searchwordW, self).__init__(parent, globalconfig, "sw_geo")
|
||||
self.ankiwindow = AnkiWindow(self)
|
||||
self.setupUi()
|
||||
# self.setWindowFlags(self.windowFlags()&~Qt.WindowMinimizeButtonHint)
|
||||
self.getnewsentencesignal.connect(self.getnewsentence)
|
||||
@ -55,16 +186,18 @@ class searchwordW(closeashidewindow):
|
||||
self.searchtext = QLineEdit()
|
||||
# self.searchtext.setFont(font)
|
||||
self.searchlayout.addWidget(self.searchtext)
|
||||
self.searchbutton = QPushButton(qtawesome.icon("fa.search"), "") # _TR("搜索"))
|
||||
searchbutton = QPushButton(qtawesome.icon("fa.search"), "") # _TR("搜索"))
|
||||
|
||||
# self.searchbutton.setFont(font)
|
||||
self.searchbutton.clicked.connect(lambda: self.search((self.searchtext.text())))
|
||||
self.searchlayout.addWidget(self.searchbutton)
|
||||
searchbutton.clicked.connect(lambda: self.search((self.searchtext.text())))
|
||||
self.searchlayout.addWidget(searchbutton)
|
||||
|
||||
self.soundbutton = QPushButton(qtawesome.icon("fa.music"), "")
|
||||
# self.searchbutton.setFont(font)
|
||||
self.soundbutton.clicked.connect(self.langdu)
|
||||
self.searchlayout.addWidget(self.soundbutton)
|
||||
soundbutton = QPushButton(qtawesome.icon("fa.music"), "")
|
||||
soundbutton.clicked.connect(self.langdu)
|
||||
self.searchlayout.addWidget(soundbutton)
|
||||
|
||||
ankiconnect = QPushButton(qtawesome.icon("fa.adn"), "")
|
||||
ankiconnect.clicked.connect(self.ankiwindow.show)
|
||||
self.searchlayout.addWidget(ankiconnect)
|
||||
|
||||
self.tab = QTabWidget(self)
|
||||
|
||||
@ -86,7 +219,6 @@ class searchwordW(closeashidewindow):
|
||||
|
||||
textOutput = QTextBrowser(self)
|
||||
# textOutput.setFont(font)
|
||||
textOutput.setContextMenuPolicy(Qt.CustomContextMenu)
|
||||
textOutput.setUndoRedoEnabled(False)
|
||||
textOutput.setReadOnly(True)
|
||||
textOutput.setOpenLinks(False)
|
||||
@ -94,9 +226,10 @@ class searchwordW(closeashidewindow):
|
||||
self.tab.setTabVisible(i, False)
|
||||
|
||||
self.textbs[self._k[i]] = textOutput
|
||||
|
||||
textOutput.setContextMenuPolicy(Qt.CustomContextMenu)
|
||||
|
||||
textOutput.customContextMenuRequested.connect(
|
||||
functools.partial(self.showmenu, textOutput)
|
||||
)
|
||||
self.hiding = True
|
||||
self.searchthreadsignal.connect(self.searchthread)
|
||||
|
||||
@ -104,6 +237,15 @@ class searchwordW(closeashidewindow):
|
||||
if gobject.baseobject.reader:
|
||||
gobject.baseobject.reader.read(self.searchtext.text(), True)
|
||||
|
||||
def showmenu(self, tb, point):
|
||||
menu = QMenu(tb)
|
||||
append = QAction(_TR("追加"))
|
||||
menu.addAction(append)
|
||||
print(point, (tb.pos()), self.mapToGlobal(tb.pos()))
|
||||
action = menu.exec(QCursor.pos())
|
||||
if action == append:
|
||||
self.ankiwindow.appenddictionary.emit(tb.toHtml())
|
||||
|
||||
def getnewsentence(self, sentence, append):
|
||||
self.showNormal()
|
||||
if append:
|
||||
@ -120,7 +262,7 @@ class searchwordW(closeashidewindow):
|
||||
def search(self, sentence):
|
||||
if sentence == "":
|
||||
return
|
||||
|
||||
self.ankiwindow.setcurrenttext.emit(sentence)
|
||||
_mp = {}
|
||||
_mp.update(gobject.baseobject.cishus)
|
||||
|
||||
|
230
LunaTranslator/LunaTranslator/myutils/ankiconnect.py
Normal file
230
LunaTranslator/LunaTranslator/myutils/ankiconnect.py
Normal file
@ -0,0 +1,230 @@
|
||||
import requests
|
||||
from .ankiconnect_config import *
|
||||
|
||||
|
||||
class AnkiException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class AnkiModelExists(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def invoke(action, **params):
|
||||
response = requests.get(
|
||||
f"http://127.0.0.1:{global_port}",
|
||||
json={"action": action, "params": params, "version": 6},
|
||||
).json()
|
||||
if len(response) != 2:
|
||||
raise AnkiException("response has an unexpected number of fields")
|
||||
if "error" not in response:
|
||||
raise AnkiException("response is missing required error field")
|
||||
if "result" not in response:
|
||||
raise AnkiException("response is missing required result field")
|
||||
if response["error"] is not None:
|
||||
if response["error"] == "Model name already exists":
|
||||
raise AnkiModelExists()
|
||||
else:
|
||||
raise AnkiException(response["error"])
|
||||
return response["result"]
|
||||
|
||||
|
||||
class Deck:
|
||||
@staticmethod
|
||||
def create(name):
|
||||
invoke("createDeck", deck=name)
|
||||
return Deck(name)
|
||||
|
||||
@staticmethod
|
||||
def NamesAndIds():
|
||||
return [Deck(k, v) for k, v in invoke("deckNamesAndIds").items()]
|
||||
|
||||
def __init__(self, name, did=None):
|
||||
self.name = name
|
||||
self.did = did
|
||||
|
||||
def __repr__(self):
|
||||
return f"(Deck {self.name},{self.did})"
|
||||
|
||||
def delete(self):
|
||||
return invoke("deleteDecks", decks=[self.name], cardsToo=True)
|
||||
|
||||
@property
|
||||
def Config(self):
|
||||
return invoke("getDeckConfig", deck=self.name)
|
||||
|
||||
@Config.setter
|
||||
def Config(self, config):
|
||||
return invoke("saveDeckConfig", config=config)
|
||||
|
||||
|
||||
class Card:
|
||||
def __repr__(self):
|
||||
return f"(Card {self.cardId})"
|
||||
|
||||
def __init__(self, cardId):
|
||||
self.cardId = cardId
|
||||
|
||||
def forget(self):
|
||||
return invoke("forgetCards", cards=[self.cardId])
|
||||
|
||||
def relearn(self):
|
||||
return invoke("relearnCards", cards=[self.cardId])
|
||||
|
||||
def answer(self):
|
||||
return invoke("answerCards", cards=[self.cardId])
|
||||
|
||||
@property
|
||||
def Info(self):
|
||||
return invoke("cardsInfo", cards=[self.cardId])[0]
|
||||
|
||||
@staticmethod
|
||||
def find(query="deck:current"):
|
||||
return [Card(_) for _ in invoke("findCards", query=query)]
|
||||
|
||||
@property
|
||||
def Deck(self):
|
||||
return Deck(list(invoke("getDecks", cards=[self.cardId]).keys())[0])
|
||||
|
||||
|
||||
class Model:
|
||||
@staticmethod
|
||||
def create(modelName, inOrderFields: list, css, isCloze, cardTemplates):
|
||||
try:
|
||||
print(
|
||||
invoke(
|
||||
"createModel",
|
||||
modelName=modelName,
|
||||
inOrderFields=inOrderFields,
|
||||
css=css,
|
||||
isCloze=isCloze,
|
||||
cardTemplates=cardTemplates,
|
||||
)
|
||||
)
|
||||
except AnkiException as e:
|
||||
if str(e) == "Model name already exists":
|
||||
pass
|
||||
else:
|
||||
raise e
|
||||
return Model(modelName)
|
||||
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
||||
def updateStyling(self, css):
|
||||
return invoke("updateModelStyling", model={"name": self.name, "css": css})
|
||||
|
||||
def updateTemplates(self, templates):
|
||||
return invoke(
|
||||
"updateModelTemplates", model={"name": self.name, "templates": templates}
|
||||
)
|
||||
|
||||
|
||||
class AnkiConnect:
|
||||
@staticmethod
|
||||
def version() -> int:
|
||||
return invoke("version")
|
||||
|
||||
@staticmethod
|
||||
def createDeck(deck):
|
||||
return invoke("createDeck", deck=deck)
|
||||
|
||||
@staticmethod
|
||||
def findCards(query="deck:current"):
|
||||
return Card.find(query)
|
||||
|
||||
|
||||
class Note:
|
||||
@staticmethod
|
||||
def add(
|
||||
deckName,
|
||||
modelName,
|
||||
fields: dict,
|
||||
allowDuplicate: bool,
|
||||
tags: list,
|
||||
audio: list,
|
||||
picture: list,
|
||||
):
|
||||
invoke(
|
||||
"addNote",
|
||||
note={
|
||||
"deckName": deckName,
|
||||
"modelName": modelName,
|
||||
"fields": fields,
|
||||
"options": {
|
||||
"allowDuplicate": allowDuplicate,
|
||||
"duplicateScope": "deck",
|
||||
"duplicateScopeOptions": {
|
||||
"deckName": "Default",
|
||||
"checkChildren": False,
|
||||
"checkAllModels": False,
|
||||
},
|
||||
},
|
||||
"tags": tags,
|
||||
"audio": audio,
|
||||
"picture": picture,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(AnkiConnect.version())
|
||||
print(AnkiConnect.createDeck("shit2"))
|
||||
# print(AnkiConnect.findCards()[0].Info['cardId'])
|
||||
# print(Card(1504404537724).Info)
|
||||
# print(AnkiConnect.findCards()[0].Deck)
|
||||
print(Deck.NamesAndIds())
|
||||
deck = Deck.NamesAndIds()[0]
|
||||
print(deck)
|
||||
Deck.create("test1111")
|
||||
# print(deck.Config)
|
||||
# deck.Config=deck.Config
|
||||
# print(deck.delete())
|
||||
# print(AnkiConnect.findCards()[0].Deck.delete())
|
||||
|
||||
model = Model.create(
|
||||
"newModelName3111",
|
||||
["expression", "sentence", "audio-text", "image"],
|
||||
"Optional CSS with default to builtin css",
|
||||
False,
|
||||
[{"Name": "My Card 1", "Front": html, "Back": html}],
|
||||
)
|
||||
|
||||
model.updateStyling("shitcss")
|
||||
model.updateTemplates(
|
||||
{
|
||||
"My Card 1": {
|
||||
"Front": html + "shit",
|
||||
"Back": html + "shit",
|
||||
}
|
||||
}
|
||||
)
|
||||
Note.add(
|
||||
"test1111",
|
||||
"newModelName3111",
|
||||
{
|
||||
"expression": "shit122",
|
||||
"sentence": "hahaa",
|
||||
"meaning": "meaning",
|
||||
"glossary-brief": "ss",
|
||||
# "audio-text": Media(
|
||||
# r"C:\dataH\LunaTranslator\cache\tts\1714228732.8068416.mp3"
|
||||
# ).audio,
|
||||
},
|
||||
False,
|
||||
[],
|
||||
[
|
||||
# {
|
||||
# "path": r"C:\dataH\LunaTranslator\cache\tts\1714228732.8068416.mp3",
|
||||
# "filename": str(uuid.uuid4()) + "1714228732.8068416.mp3",
|
||||
# "fields": ["audio-text"],
|
||||
# }
|
||||
],
|
||||
[
|
||||
# {
|
||||
# "path": r"C:\Users\11737\Documents\GitHub\LunaTranslator\LunaTranslator\cache\ocr\1709362617.9424458.png",
|
||||
# "filename": str(uuid.uuid4()) + "1714228732.8068416.png",
|
||||
# "fields": ["image"],
|
||||
# }
|
||||
],
|
||||
)
|
25
LunaTranslator/LunaTranslator/myutils/ankiconnect_config.py
Normal file
25
LunaTranslator/LunaTranslator/myutils/ankiconnect_config.py
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
DeckName="LunaDeck"
|
||||
|
||||
ModelName="LunaModel"
|
||||
|
||||
global_port = 8765
|
||||
|
||||
model_fileds=["word","explain","image","audio"]
|
||||
|
||||
model_css=''
|
||||
|
||||
model_htmlfront = """
|
||||
{{word}}
|
||||
<br>
|
||||
{{explain}}
|
||||
<br>
|
||||
{{image}}
|
||||
"""
|
||||
model_htmlback = """
|
||||
{{word}}
|
||||
<br>
|
||||
{{explain}}
|
||||
<br>
|
||||
{{image}}
|
||||
"""
|
@ -1,4 +1,5 @@
|
||||
import gobject, os
|
||||
from network.requests_common import NetWorkException
|
||||
from ctypes import (
|
||||
CDLL,
|
||||
c_void_p,
|
||||
@ -316,7 +317,7 @@ class AutoCURLHandle(CURL):
|
||||
curl_easy_cleanup(self)
|
||||
|
||||
|
||||
class CURLException(Exception):
|
||||
class CURLException(NetWorkException):
|
||||
def __init__(self, code) -> None:
|
||||
if isinstance(code, CURLcode):
|
||||
self.errorcode = code.value
|
||||
|
@ -4,8 +4,10 @@ from collections import OrderedDict
|
||||
from urllib.parse import urlencode, urlsplit
|
||||
from functools import partial
|
||||
|
||||
class NetWorkException(Exception):
|
||||
pass
|
||||
|
||||
class Timeout(Exception):
|
||||
class Timeout(NetWorkException):
|
||||
pass
|
||||
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
from ctypes import windll, POINTER, pointer, Structure, sizeof
|
||||
from ctypes.wintypes import LPCWSTR, DWORD, LPVOID, WORD, BOOL, LPCVOID, LPWSTR, USHORT
|
||||
from network.requests_common import NetWorkException
|
||||
|
||||
|
||||
class WinhttpException(Exception):
|
||||
class WinhttpException(NetWorkException):
|
||||
ERROR_INVALID_PARAMETER = 87
|
||||
ERROR_INVALID_OPERATION = 4317
|
||||
WINHTTP_ERROR_BASE = 12000
|
||||
|
@ -51,7 +51,15 @@ class TTSbase:
|
||||
threading.Thread(target=_).start()
|
||||
|
||||
def read(self, content, force=False):
|
||||
def _(content, force):
|
||||
fname = self.syncttstofile(content)
|
||||
volume = globalconfig["ttscommon"]["volume"]
|
||||
if fname:
|
||||
self.mp3playsignal.emit(fname, volume, force)
|
||||
|
||||
threading.Thread(target=_, args=(content, force)).start()
|
||||
|
||||
def syncttstofile(self, content):
|
||||
if self.loadok == False:
|
||||
return
|
||||
if len(content) == 0:
|
||||
@ -60,13 +68,7 @@ class TTSbase:
|
||||
return
|
||||
|
||||
rate = globalconfig["ttscommon"]["rate"]
|
||||
volume = globalconfig["ttscommon"]["volume"]
|
||||
voice = globalconfig["reader"][self.typename]["voice"]
|
||||
voice_index = self.voicelist.index(voice)
|
||||
|
||||
def _():
|
||||
fname = self.speak(content, rate, voice, voice_index)
|
||||
if fname:
|
||||
self.mp3playsignal.emit(fname, volume, force)
|
||||
|
||||
threading.Thread(target=_).start()
|
||||
fname = self.speak(content, rate, voice, voice_index)
|
||||
return fname
|
||||
|
@ -1,4 +1,4 @@
|
||||
import time
|
||||
import time, os
|
||||
import winsharedutils
|
||||
|
||||
from tts.basettsclass import TTSbase
|
||||
|
@ -775,5 +775,7 @@
|
||||
"半径": "نصف قطر",
|
||||
"圆角": "فيليه",
|
||||
"合并": "دمج",
|
||||
"立即应用": "التطبيق الفوري"
|
||||
"立即应用": "التطبيق الفوري",
|
||||
"无法连接到anki": "غير قادر على الاتصال انكي",
|
||||
"追加": "إلحاق"
|
||||
}
|
@ -775,5 +775,7 @@
|
||||
"半径": "半徑",
|
||||
"圆角": "圓角",
|
||||
"合并": "合併",
|
||||
"立即应用": "立即應用"
|
||||
"立即应用": "立即應用",
|
||||
"无法连接到anki": "無法連接到anki",
|
||||
"追加": "追加"
|
||||
}
|
@ -775,5 +775,7 @@
|
||||
"半径": "radius",
|
||||
"圆角": "fillet",
|
||||
"合并": "merge",
|
||||
"立即应用": "apply now"
|
||||
"立即应用": "apply now",
|
||||
"无法连接到anki": "Unable to connect to Anki",
|
||||
"追加": "Add"
|
||||
}
|
@ -775,5 +775,7 @@
|
||||
"半径": "Radio",
|
||||
"圆角": "Redondeado",
|
||||
"合并": "Fusión",
|
||||
"立即应用": "Aplicar de inmediato"
|
||||
"立即应用": "Aplicar de inmediato",
|
||||
"无法连接到anki": "No se puede conectar a Anki",
|
||||
"追加": "Añadido"
|
||||
}
|
@ -775,5 +775,7 @@
|
||||
"半径": "Rayon",
|
||||
"圆角": "Coins arrondis",
|
||||
"合并": "Consolidation",
|
||||
"立即应用": "Appliquer maintenant"
|
||||
"立即应用": "Appliquer maintenant",
|
||||
"无法连接到anki": "Impossible de se connecter à Anki",
|
||||
"追加": "Supplémentaire"
|
||||
}
|
@ -775,5 +775,7 @@
|
||||
"半径": "raggio",
|
||||
"圆角": "filetto",
|
||||
"合并": "fusione",
|
||||
"立即应用": "Applica ora"
|
||||
"立即应用": "Applica ora",
|
||||
"无法连接到anki": "Impossibile connettersi ad Anki",
|
||||
"追加": "Aggiungi"
|
||||
}
|
@ -775,5 +775,7 @@
|
||||
"半径": "半径はんけい",
|
||||
"圆角": "フィレット",
|
||||
"合并": "マージ",
|
||||
"立即应用": "今すぐ適用"
|
||||
"立即应用": "今すぐ適用",
|
||||
"无法连接到anki": "ankiに接続できません",
|
||||
"追加": "追加#ツイカ#"
|
||||
}
|
@ -775,5 +775,7 @@
|
||||
"半径": "반지름",
|
||||
"圆角": "필렛",
|
||||
"合并": "병합",
|
||||
"立即应用": "지금 적용"
|
||||
"立即应用": "지금 적용",
|
||||
"无法连接到anki": "anki에 연결할 수 없음",
|
||||
"追加": "추가"
|
||||
}
|
@ -775,5 +775,7 @@
|
||||
"半径": "promień",
|
||||
"圆角": "filet",
|
||||
"合并": "połączenie",
|
||||
"立即应用": "aplikuj teraz"
|
||||
"立即应用": "aplikuj teraz",
|
||||
"无法连接到anki": "Nie można połączyć się z Anki",
|
||||
"追加": "Dodaj"
|
||||
}
|
@ -775,5 +775,7 @@
|
||||
"半径": "Радиус",
|
||||
"圆角": "Круглый угол",
|
||||
"合并": "Объединение",
|
||||
"立即应用": "Немедленное применение"
|
||||
"立即应用": "Немедленное применение",
|
||||
"无法连接到anki": "Не удалось подключиться к ANKI",
|
||||
"追加": "Добавить"
|
||||
}
|
@ -775,5 +775,7 @@
|
||||
"半径": "รัศมี",
|
||||
"圆角": "มุมกลม",
|
||||
"合并": "การควบรวมกิจการ",
|
||||
"立即应用": "สมัครตอนนี้"
|
||||
"立即应用": "สมัครตอนนี้",
|
||||
"无法连接到anki": "ไม่สามารถเชื่อมต่อกับ anki ได้",
|
||||
"追加": "เพิ่ม"
|
||||
}
|
@ -775,5 +775,7 @@
|
||||
"半径": "radius",
|
||||
"圆角": "fillet",
|
||||
"合并": "birleştir",
|
||||
"立即应用": "şimdi uygulayın"
|
||||
"立即应用": "şimdi uygulayın",
|
||||
"无法连接到anki": "Anki ile bağlanılamadı",
|
||||
"追加": "Ekle"
|
||||
}
|
@ -775,5 +775,7 @@
|
||||
"半径": "радіус",
|
||||
"圆角": "філет",
|
||||
"合并": "об’ єднати",
|
||||
"立即应用": "застосовувати зараз"
|
||||
"立即应用": "застосовувати зараз",
|
||||
"无法连接到anki": "Неможливо з' єднатися з Anki",
|
||||
"追加": "Додати"
|
||||
}
|
@ -775,5 +775,7 @@
|
||||
"半径": "Bán kính",
|
||||
"圆角": "Góc tròn",
|
||||
"合并": "Hợp nhất",
|
||||
"立即应用": "Áp dụng ngay"
|
||||
"立即应用": "Áp dụng ngay",
|
||||
"无法连接到anki": "Không thể kết nối với Anki",
|
||||
"追加": "Thêm"
|
||||
}
|
@ -775,5 +775,7 @@
|
||||
"半径": "",
|
||||
"圆角": "",
|
||||
"合并": "",
|
||||
"立即应用": ""
|
||||
"立即应用": "",
|
||||
"追加": "",
|
||||
"无法连接到anki": ""
|
||||
}
|
@ -29,7 +29,7 @@ include(generate_product_version)
|
||||
|
||||
set(VERSION_MAJOR 2)
|
||||
set(VERSION_MINOR 50)
|
||||
set(VERSION_PATCH 2)
|
||||
set(VERSION_PATCH 3)
|
||||
|
||||
add_library(pch pch.cpp)
|
||||
target_precompile_headers(pch PUBLIC pch.h)
|
||||
|
Loading…
x
Reference in New Issue
Block a user