diff --git a/LunaTranslator/LunaTranslator/LunaTranslator.py b/LunaTranslator/LunaTranslator/LunaTranslator.py index a6fe9707..f6a14b92 100644 --- a/LunaTranslator/LunaTranslator/LunaTranslator.py +++ b/LunaTranslator/LunaTranslator/LunaTranslator.py @@ -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() diff --git a/LunaTranslator/LunaTranslator/gui/showword.py b/LunaTranslator/LunaTranslator/gui/showword.py index 234ae6f3..243053e7 100644 --- a/LunaTranslator/LunaTranslator/gui/showword.py +++ b/LunaTranslator/LunaTranslator/gui/showword.py @@ -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) diff --git a/LunaTranslator/LunaTranslator/myutils/ankiconnect.py b/LunaTranslator/LunaTranslator/myutils/ankiconnect.py new file mode 100644 index 00000000..76ca493b --- /dev/null +++ b/LunaTranslator/LunaTranslator/myutils/ankiconnect.py @@ -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"], + # } + ], + ) diff --git a/LunaTranslator/LunaTranslator/myutils/ankiconnect_config.py b/LunaTranslator/LunaTranslator/myutils/ankiconnect_config.py new file mode 100644 index 00000000..fb43e4a2 --- /dev/null +++ b/LunaTranslator/LunaTranslator/myutils/ankiconnect_config.py @@ -0,0 +1,25 @@ + +DeckName="LunaDeck" + +ModelName="LunaModel" + +global_port = 8765 + +model_fileds=["word","explain","image","audio"] + +model_css='' + +model_htmlfront = """ +{{word}} +
+{{explain}} +
+{{image}} + """ +model_htmlback = """ +{{word}} +
+{{explain}} +
+{{image}} + """ diff --git a/LunaTranslator/LunaTranslator/network/libcurl/libcurl.py b/LunaTranslator/LunaTranslator/network/libcurl/libcurl.py index 3826a08c..c8863e47 100644 --- a/LunaTranslator/LunaTranslator/network/libcurl/libcurl.py +++ b/LunaTranslator/LunaTranslator/network/libcurl/libcurl.py @@ -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 diff --git a/LunaTranslator/LunaTranslator/network/requests_common.py b/LunaTranslator/LunaTranslator/network/requests_common.py index 2f9ad763..44c78de1 100644 --- a/LunaTranslator/LunaTranslator/network/requests_common.py +++ b/LunaTranslator/LunaTranslator/network/requests_common.py @@ -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 diff --git a/LunaTranslator/LunaTranslator/network/winhttp/winhttp.py b/LunaTranslator/LunaTranslator/network/winhttp/winhttp.py index 5ce96c5b..0ae1c02e 100644 --- a/LunaTranslator/LunaTranslator/network/winhttp/winhttp.py +++ b/LunaTranslator/LunaTranslator/network/winhttp/winhttp.py @@ -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 diff --git a/LunaTranslator/LunaTranslator/tts/basettsclass.py b/LunaTranslator/LunaTranslator/tts/basettsclass.py index 81ba03db..9a162e2d 100644 --- a/LunaTranslator/LunaTranslator/tts/basettsclass.py +++ b/LunaTranslator/LunaTranslator/tts/basettsclass.py @@ -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 diff --git a/LunaTranslator/LunaTranslator/tts/windowstts.py b/LunaTranslator/LunaTranslator/tts/windowstts.py index 494fffe7..9fe5bdf3 100644 --- a/LunaTranslator/LunaTranslator/tts/windowstts.py +++ b/LunaTranslator/LunaTranslator/tts/windowstts.py @@ -1,4 +1,4 @@ -import time +import time, os import winsharedutils from tts.basettsclass import TTSbase diff --git a/LunaTranslator/files/lang/ar.json b/LunaTranslator/files/lang/ar.json index d2347ab2..cb675a2b 100644 --- a/LunaTranslator/files/lang/ar.json +++ b/LunaTranslator/files/lang/ar.json @@ -775,5 +775,7 @@ "半径": "نصف قطر", "圆角": "فيليه", "合并": "دمج", - "立即应用": "التطبيق الفوري" + "立即应用": "التطبيق الفوري", + "无法连接到anki": "غير قادر على الاتصال انكي", + "追加": "إلحاق" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/cht.json b/LunaTranslator/files/lang/cht.json index dac82ff4..d8dbf143 100644 --- a/LunaTranslator/files/lang/cht.json +++ b/LunaTranslator/files/lang/cht.json @@ -775,5 +775,7 @@ "半径": "半徑", "圆角": "圓角", "合并": "合併", - "立即应用": "立即應用" + "立即应用": "立即應用", + "无法连接到anki": "無法連接到anki", + "追加": "追加" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/en.json b/LunaTranslator/files/lang/en.json index 92f23535..a11991ee 100644 --- a/LunaTranslator/files/lang/en.json +++ b/LunaTranslator/files/lang/en.json @@ -775,5 +775,7 @@ "半径": "radius", "圆角": "fillet", "合并": "merge", - "立即应用": "apply now" + "立即应用": "apply now", + "无法连接到anki": "Unable to connect to Anki", + "追加": "Add" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/es.json b/LunaTranslator/files/lang/es.json index 4ddf8c01..83cb703d 100644 --- a/LunaTranslator/files/lang/es.json +++ b/LunaTranslator/files/lang/es.json @@ -775,5 +775,7 @@ "半径": "Radio", "圆角": "Redondeado", "合并": "Fusión", - "立即应用": "Aplicar de inmediato" + "立即应用": "Aplicar de inmediato", + "无法连接到anki": "No se puede conectar a Anki", + "追加": "Añadido" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/fr.json b/LunaTranslator/files/lang/fr.json index b074d979..a0e892bc 100644 --- a/LunaTranslator/files/lang/fr.json +++ b/LunaTranslator/files/lang/fr.json @@ -775,5 +775,7 @@ "半径": "Rayon", "圆角": "Coins arrondis", "合并": "Consolidation", - "立即应用": "Appliquer maintenant" + "立即应用": "Appliquer maintenant", + "无法连接到anki": "Impossible de se connecter à Anki", + "追加": "Supplémentaire" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/it.json b/LunaTranslator/files/lang/it.json index 1dd8e116..6ac7a71e 100644 --- a/LunaTranslator/files/lang/it.json +++ b/LunaTranslator/files/lang/it.json @@ -775,5 +775,7 @@ "半径": "raggio", "圆角": "filetto", "合并": "fusione", - "立即应用": "Applica ora" + "立即应用": "Applica ora", + "无法连接到anki": "Impossibile connettersi ad Anki", + "追加": "Aggiungi" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/ja.json b/LunaTranslator/files/lang/ja.json index 7080da39..80d251a7 100644 --- a/LunaTranslator/files/lang/ja.json +++ b/LunaTranslator/files/lang/ja.json @@ -775,5 +775,7 @@ "半径": "半径はんけい", "圆角": "フィレット", "合并": "マージ", - "立即应用": "今すぐ適用" + "立即应用": "今すぐ適用", + "无法连接到anki": "ankiに接続できません", + "追加": "追加#ツイカ#" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/ko.json b/LunaTranslator/files/lang/ko.json index 0108abf0..644d7d4e 100644 --- a/LunaTranslator/files/lang/ko.json +++ b/LunaTranslator/files/lang/ko.json @@ -775,5 +775,7 @@ "半径": "반지름", "圆角": "필렛", "合并": "병합", - "立即应用": "지금 적용" + "立即应用": "지금 적용", + "无法连接到anki": "anki에 연결할 수 없음", + "追加": "추가" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/pl.json b/LunaTranslator/files/lang/pl.json index 9877b986..e5f4e5fe 100644 --- a/LunaTranslator/files/lang/pl.json +++ b/LunaTranslator/files/lang/pl.json @@ -775,5 +775,7 @@ "半径": "promień", "圆角": "filet", "合并": "połączenie", - "立即应用": "aplikuj teraz" + "立即应用": "aplikuj teraz", + "无法连接到anki": "Nie można połączyć się z Anki", + "追加": "Dodaj" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/ru.json b/LunaTranslator/files/lang/ru.json index 336cf388..18b80879 100644 --- a/LunaTranslator/files/lang/ru.json +++ b/LunaTranslator/files/lang/ru.json @@ -775,5 +775,7 @@ "半径": "Радиус", "圆角": "Круглый угол", "合并": "Объединение", - "立即应用": "Немедленное применение" + "立即应用": "Немедленное применение", + "无法连接到anki": "Не удалось подключиться к ANKI", + "追加": "Добавить" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/th.json b/LunaTranslator/files/lang/th.json index 715dc76f..2f8922e1 100644 --- a/LunaTranslator/files/lang/th.json +++ b/LunaTranslator/files/lang/th.json @@ -775,5 +775,7 @@ "半径": "รัศมี", "圆角": "มุมกลม", "合并": "การควบรวมกิจการ", - "立即应用": "สมัครตอนนี้" + "立即应用": "สมัครตอนนี้", + "无法连接到anki": "ไม่สามารถเชื่อมต่อกับ anki ได้", + "追加": "เพิ่ม" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/tr.json b/LunaTranslator/files/lang/tr.json index bba87bbc..76ac2119 100644 --- a/LunaTranslator/files/lang/tr.json +++ b/LunaTranslator/files/lang/tr.json @@ -775,5 +775,7 @@ "半径": "radius", "圆角": "fillet", "合并": "birleştir", - "立即应用": "şimdi uygulayın" + "立即应用": "şimdi uygulayın", + "无法连接到anki": "Anki ile bağlanılamadı", + "追加": "Ekle" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/uk.json b/LunaTranslator/files/lang/uk.json index e3c321c2..a164e0fd 100644 --- a/LunaTranslator/files/lang/uk.json +++ b/LunaTranslator/files/lang/uk.json @@ -775,5 +775,7 @@ "半径": "радіус", "圆角": "філет", "合并": "об’ єднати", - "立即应用": "застосовувати зараз" + "立即应用": "застосовувати зараз", + "无法连接到anki": "Неможливо з' єднатися з Anki", + "追加": "Додати" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/vi.json b/LunaTranslator/files/lang/vi.json index c82dd42b..f2442baf 100644 --- a/LunaTranslator/files/lang/vi.json +++ b/LunaTranslator/files/lang/vi.json @@ -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" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/zh.json b/LunaTranslator/files/lang/zh.json index 67e2fd4b..e55ea524 100644 --- a/LunaTranslator/files/lang/zh.json +++ b/LunaTranslator/files/lang/zh.json @@ -775,5 +775,7 @@ "半径": "", "圆角": "", "合并": "", - "立即应用": "" + "立即应用": "", + "追加": "", + "无法连接到anki": "" } \ No newline at end of file diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index f6a77484..fa180162 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -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)