This commit is contained in:
恍兮惚兮 2024-10-30 15:32:11 +08:00
parent aac082cf45
commit 70aa8e78dc
57 changed files with 435 additions and 196 deletions

View File

@ -29,13 +29,3 @@ body:
尽可能详细描述错误产生的细节。
validations:
required: true
- type: textarea
attributes:
label: Log file 日志文件
description: >
Run LunaTranslator_debug.exe to reproduce the error, and then upload the generated log_*.txt file.
运行LunaTranslator_debug.exe复现错误然后上传产生的log_*.txt文件。
validations:
required: true

View File

@ -60,10 +60,12 @@ Some buttons have two icons to indicate two different states. Some buttons only
However, the select text window will automatically pop up after selecting the process, and this button is actually used to replace the selected text or modify some settings.
1. #### <i class="fa fa-crop"></i> <i class="fa fa-icon fa-rotate-right"></i> Select OCR Range
**This button is only available in OCR mode**<br>
In OCR mode, select the OCR area, or change the OCR area, or when activating `OCR Settings` -> `Other` -> `Multiple Area Mode`, add a new OCR area
In OCR mode, select the OCR area, or change the OCR area, or when activating `OCR Settings` -> `Other` -> `Multiple Area Mode`, add a new OCR area<br>
When the right button is pressed, all selected ranges will be cleared before adding new areas.
1. #### <i class="fa fa-square"></i> <i class="fa fa-icon fa-rotate-right"></i> Show/Hide Range Box
**This button is only available in OCR mode**<br>
When no OCR range is selected, use this button to display the OCR range, which will automatically set the OCR range to the last selected OCR.
When no OCR range is selected, use this button to display the OCR range, which will automatically set the OCR range to the last selected OCR.<br>
When the right button is pressed, all selected ranges will be cleared
1. #### <i class="fa fa-crop"></i> <i class="fa fa-icon fa-rotate-right"></i> Perform OCR Once
This button is similar to `Read Clipboard`, regardless of the current default text input source, it will first select the OCR range, then perform OCR once, and then proceed with the translation process.<br>
This button is generally used in HOOK mode, when encountering choices, to temporarily use OCR for translation of choices. Or in OCR mode, to temporarily recognize a new position that occasionally appears.<br>

View File

@ -57,15 +57,19 @@
### **OCR**
1. #### Select OCR Range
**Available only in OCR mode**
**Available only in OCR mode**<br>
In OCR mode, selects the OCR area, or changes the OCR area, or when `OCR Settings` -> `Other` -> `Multi-region Mode` is activated, adds a new OCR area.
1. #### Show/Hide Range Box
**Available only in OCR mode**
**Available only in OCR mode**<br>
When no OCR range is selected, using this shortcut key will display the OCR range and automatically set the OCR range to the last selected OCR.
1. ###### Clear OCR range
**Only available in OCR mode**<br>
Clear all selected ranges
1. #### Select OCR Range - Immediate
**Available only in OCR mode**
**Available only in OCR mode**<br>
The difference from `Select OCR Range` is that it requires one less mouse click.
1. #### Perform OCR Once

View File

@ -157,14 +157,14 @@ Replace `{endpoint}` and `{deployName}` with your endpoint and deployName.
>Some large model platforms are not fully compatible with the ChatGPT interface, please fill in the parameters to use in the dedicated interface.
#### Foreign Large Model Interfaces
<!-- tabs:start -->
### **gemini**
<a id="gemini"></a>
**BASE_URL** `https://generativelanguage.googleapis.com`
**model** https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models
**API Key** https://aistudio.google.com/app/apikey
@ -183,12 +183,6 @@ Replace `{endpoint}` and `{deployName}` with your endpoint and deployName.
**model** https://docs.cohere.com/docs/models
<!-- tabs:end -->
#### Domestic Large Model Interfaces
<!-- tabs:start -->
### **Tencent Hunyuan Large Model**
**SecretId** & **SecretKey** https://console.cloud.tencent.com/cam/capi

View File

@ -15,7 +15,7 @@ Make sure not to download the source code by mistake!
**LunaTranslator_admin.exe** will start with administrator privileges. Some games require administrator privileges to HOOK, so use this only when necessary; otherwise, start in normal mode.
**LunaTranslator_debug.exe** will generate log file. When submitting bug feedback, please be sure to run the program and reproduce the bug, and then submit the generated log file.
**LunaTranslator_debug.exe** will display a command line window
#### Note

View File

@ -63,12 +63,12 @@
1. #### <i class="fa fa-crop"></i> <i class="fa fa-icon fa-rotate-right"></i> Выбор области OCR
**Эта кнопка доступна только в режиме OCR**<br>
В режиме OCR выбирать область OCR, изменять область OCR или добавлять новую область OCR при активации `OCR настройки` -> `Другие` -> `Многообластный режим`.
В режиме OCR выбирать область OCR, изменять область OCR или добавлять новую область OCR при активации `OCR настройки` -> `Другие` -> `Многообластный режим`.<br>
При нажатии правой кнопки мыши все выбранные области сначала будут очищены, а затем добавлены новые.
1. #### <i class="fa fa-square"></i> <i class="fa fa-icon fa-rotate-right"></i> Показать/Скрыть рамку области
**Эта кнопка доступна только в режиме OCR**<br>
Когда никакая область OCR не выбрана, используйте эту кнопку, чтобы отобразить область OCR, автоматически устанавливая область OCR в последний выбранный OCR.
Когда никакая область OCR не выбрана, используйте эту кнопку, чтобы отобразить область OCR, автоматически устанавливая область OCR в последний выбранный OCR.<br>
При нажатии правой кнопки будет очищен весь выбранный диапазон
1. #### <i class="fa fa-crop"></i> <i class="fa fa-icon fa-rotate-right"></i> Выполнить одинOCR
Эта кнопка аналогична кнопке `Прочитать буфер обмена`, независимо от текущего источника текстового ввода, сначала выбирается область OCR, затем выполняется один OCR, а затем процесс перевода.<br>
Обычно эта кнопка используется в режиме HOOK, когда при выборе ветвей, временно используется OCR для перевода ветвей. Или в режиме OCR, чтобы временно распознать новый случайный появляющийся раз в другом месте.<br>

View File

@ -63,6 +63,10 @@
**Доступно только в режиме OCR**<br>
Если никакая область OCR не выбрана, при использовании этого горячего клавиша для отображения области OCR, автоматически устанавливается область OCR в последний выбранный OCR.
1. #### Очистить диапазон OCR
**Доступно только в режиме OCR**<br>
Очистить все выбранные диапазоны
1. #### Выбор области OCR — немедленно
**Доступно только в режиме OCR**<br>
Разница от `Выбор области OCR` заключается только в том, что требуется нажатие мыши меньше раз.

View File

@ -157,14 +157,14 @@
>Некоторые платформы больших моделей не полностью совместимы с интерфейсом ChatGPT, пожалуйста, заполните параметры в специальном интерфейсе для использования.
#### Зарубежные интерфейсы больших моделей
<!-- tabs:start -->
### **gemini**
<a id="gemini"></a>
**BASE_URL** `https://generativelanguage.googleapis.com`
**model** https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models
**API Key** https://aistudio.google.com/app/apikey
@ -183,12 +183,6 @@
**model** https://docs.cohere.com/docs/models
<!-- tabs:end -->
#### Китайские интерфейсы больших моделей
<!-- tabs:start -->
### **Tencent Hunyuan Large Model**
**SecretId** & **SecretKey** https://console.cloud.tencent.com/cam/capi

View File

@ -15,7 +15,7 @@
**LunaTranslator_admin.exe** запускается с правами администратора, некоторые игры требуют прав администратора для HOOK, используйте его только в этом случае, в остальных случаях запускайте в обычном режиме.
**LunaTranslator_debug.exe** создаст файлы журналов. Отправляя отзыв об ошибке, обязательно используйте эту программу для запуска и воспроизведения ошибки, а затем отправьте созданный файл журнала.
**LunaTranslator_debug.exe** Показать окно командной строки
#### Внимание

View File

@ -60,10 +60,12 @@
不过,选择文本窗口在选择进程后会自动弹出,这个按钮实际上是用来更换选择的文本,或修改一些设置用的。
1. #### <i class="fa fa-crop"></i> <i class="fa fa-icon fa-rotate-right"></i> 选取OCR范围
**该按钮仅在OCR模式下可用**<br>
OCR模式下选取OCR区域或者更换OCR区域或者当激活`OCR设置`->`其他`->`多重区域模式`时增加新的OCR区域
OCR模式下选取OCR区域或者更换OCR区域或者当激活`OCR设置`->`其他`->`多重区域模式`时增加新的OCR区域<br>
当按下右键时,会先清除所有已选取范围,再添加新的区域。
1. #### <i class="fa fa-square"></i> <i class="fa fa-icon fa-rotate-right"></i> 显示/隐藏范围框
**该按钮仅在OCR模式下可用**<br>
当未选择任何OCR范围时使用该按钮显示OCR范围会自动设置OCR范围为上一次选择的OCR。
当未选择任何OCR范围时使用该按钮显示OCR范围会自动设置OCR范围为上一次选择的OCR。<br>
当按下右键时,会清除所有已选取范围
1. #### <i class="fa fa-crop"></i> <i class="fa fa-icon fa-rotate-right"></i> 进行一次OCR
该按钮和`读取剪贴板`类似不管当前的默认文本输入源是什么都会先进行OCR范围选择然后进行一次OCR然后进行翻译流程。<br>
该按钮一般用于在HOOK模式下遇到选择支时临时使用一次OCR进行翻译选择支。或者在OCR模式下临时去识别一次其他偶尔出现的新的位置。<br>

View File

@ -65,6 +65,10 @@
**仅在OCR模式下可用**<br>
当未选择任何OCR范围时使用该快捷键显示OCR范围会自动设置OCR范围为上一次选择的OCR。
1. #### 清除OCR范围
**仅在OCR模式下可用**<br>
清除所有已选取范围
1. #### 选取OCR范围——立即
**仅在OCR模式下可用**<br>
和`选取OCR范围`的区别仅是少按一次鼠标

View File

@ -162,15 +162,14 @@
>部分大模型平台不完全兼容ChatGPT接口请在专用接口中填写参数使用。
#### 外国大模型接口
<!-- tabs:start -->
### **gemini**
<a id="gemini"></a>
**BASE_URL** `https://generativelanguage.googleapis.com`
**model** https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models
**API Key** https://aistudio.google.com/app/apikey
@ -189,14 +188,6 @@
**model** https://docs.cohere.com/docs/models
<!-- tabs:end -->
#### 国产大模型接口
<!-- tabs:start -->
### **腾讯混元大模型**
**SecretId** & **SecretKey** https://console.cloud.tencent.com/cam/capi

View File

@ -24,7 +24,7 @@
**LunaTranslator_admin.exe** 会以管理员权限启动部分游戏需要管理员权限才能HOOK仅这时需要使用这个其他时候普通模式启动即可。
**LunaTranslator_debug.exe** 会生成log文件。提交bug反馈时务必请使用该程序运行并复现bug然后提交生成的log文件。
**LunaTranslator_debug.exe** 会显示命令行窗口

View File

@ -44,7 +44,7 @@ import windows
import winsharedutils
from winsharedutils import collect_running_pids
from myutils.post import POSTSOLVE
from myutils.utils import nowisdark
from myutils.utils import nowisdark, dynamicapiname
from myutils.traceplaytime import playtimemanager
from myutils.audioplayer import series_audioplayer
from gui.dynalang import LAction, LMenu
@ -516,7 +516,7 @@ class MAINUI:
if iserror:
if currentsignature == self.currentsignature:
self.translation_ui.displaystatus.emit(
globalconfig["fanyi"][classname]["name"] + " " + res,
dynamicapiname(classname) + " " + res,
True,
False,
)
@ -540,7 +540,7 @@ class MAINUI:
iter_res_status in (0, 1)
):
displayreskwargs = dict(
name=globalconfig["fanyi"][classname]["name"],
name=dynamicapiname(classname),
color=globalconfig["fanyi"][classname]["color"],
res=res,
iter_context=(iter_res_status, classname),
@ -548,9 +548,7 @@ class MAINUI:
self.translation_ui.displayres.emit(displayreskwargs)
if iter_res_status in (0, 2): # 0为普通1为iter2为iter终止
self.transhis.getnewtranssignal.emit(
globalconfig["fanyi"][classname]["name"], res
)
self.transhis.getnewtranssignal.emit(dynamicapiname(classname), res)
if not waitforresultcallback:
if (
globalconfig["read_trans"]
@ -822,7 +820,7 @@ class MAINUI:
return aclass(classname)
except Exception as e:
self.displayinfomessage(
globalconfig["fanyi"][classname]["name"]
dynamicapiname(classname)
+ " import failed : "
+ str(stringfyerror(e)),
"<msg_error_not_refresh>",

View File

@ -2,7 +2,7 @@ from qtsymbols import *
import gobject, os
from myutils.config import globalconfig, uid2gamepath
from myutils.wrapper import Singleton_close
from myutils.utils import getfilemd5
from myutils.utils import getfilemd5, getimagefilefilter
from gui.usefulwidget import saveposwindow
from gui.dynalang import LPushButton
@ -15,7 +15,7 @@ class dialog_memory(saveposwindow):
ff.write(self.showtext.toHtml())
def insertpic(self):
f = QFileDialog.getOpenFileName()
f = QFileDialog.getOpenFileName(filter=getimagefilefilter())
res = f[0]
if res != "":
self.showtext.insertHtml('<img src="{}">'.format(res))

View File

@ -11,7 +11,7 @@ from myutils.config import (
globalconfig,
)
from myutils.hwnd import clipboard_set_image
from myutils.utils import str2rgba, get_time_stamp, loopbackrecorder
from myutils.utils import str2rgba, get_time_stamp, loopbackrecorder, getimagefilefilter
from myutils.audioplayer import playonce
from gui.inputdialog import autoinitdialog
from gui.specialwidget import stackedlist, shrinkableitem, shownumQPushButton
@ -613,7 +613,7 @@ class pixwrapper(QWidget):
("画廊"),
savehook_new_data[self.k]["imagepath_all"],
closecallback=lambda: self.setpix(self.k),
ispathsedit=dict(),
ispathsedit=dict(filter1=getimagefilefilter()),
)
elif action == setimage:
savehook_new_data[self.k]["currentmainimage"] = curr

View File

@ -2,7 +2,7 @@ from qtsymbols import *
import threading, windows
import gobject, qtawesome, os, json
from myutils.config import globalconfig, savehook_new_data, translatorsetting
from myutils.utils import translate_exits
from myutils.utils import translate_exits, dynamicapiname
from myutils.wrapper import Singleton_close
from gui.usefulwidget import saveposwindow, getsimplecombobox
from gui.dynalang import LPushButton, LMainWindow
@ -160,7 +160,7 @@ class edittrans(LMainWindow):
if not translate_exits(fanyi):
continue
inter.append(fanyi)
vis.append(globalconfig["fanyi"][fanyi]["name"])
vis.append(dynamicapiname(fanyi))
qv.addWidget(self.textOutput)
qv.addWidget(
getsimplecombobox(

View File

@ -2,7 +2,7 @@ from qtsymbols import *
import sqlite3, os, json, functools
from traceback import print_exc
from myutils.config import globalconfig, _TR
from myutils.utils import autosql
from myutils.utils import autosql, dynamicapiname
from gui.usefulwidget import getQMessageBox, LFocusCombo
from gui.dynalang import LFormLayout, LPushButton, LDialog
from textsource.texthook import splitembedlines
@ -51,7 +51,7 @@ def sqlite2json2(
dialog.setLayout(formLayout)
combo = LFocusCombo()
combo.addItems([globalconfig["fanyi"][_]["name"] for _ in collect])
combo.addItems([dynamicapiname(_) for _ in collect])
formLayout.addRow("首选翻译", combo)
e = QLineEdit(sqlitefile[: -(len(".sqlite"))])

View File

@ -1,5 +1,5 @@
from qtsymbols import *
import functools, json, subprocess, os, time, binascii
import functools, binascii
from collections import OrderedDict
from traceback import print_exc
import qtawesome, windows, winsharedutils, gobject
@ -125,6 +125,33 @@ class dialog_showinfo(QDialog):
self.show()
class HexValidator(QValidator):
def validate(self, input_str, pos):
# 检查输入是否是有效的16进制数
if all(c in "0123456789abcdefABCDEF" for c in input_str):
return QValidator.State.Acceptable, input_str, pos
elif input_str == "" or (
len(input_str) == 1 and input_str in "0123456789abcdefABCDEF"
):
return QValidator.State.Intermediate, input_str, pos
else:
return QValidator.State.Invalid, input_str, pos
class PatternValidator(QValidator):
def validate(self, input_str, pos):
# 检查输入是否是有效的16进制数
if all(c in "0123456789abcdefABCDEF ?" for c in input_str):
return QValidator.State.Acceptable, input_str, pos
elif input_str == "" or (
len(input_str) == 1 and input_str in "0123456789abcdefABCDEF ?"
):
return QValidator.State.Intermediate, input_str, pos
else:
return QValidator.State.Invalid, input_str, pos
class searchhookparam(LDialog):
def safehex(self, string, default):
try:
@ -149,11 +176,11 @@ class searchhookparam(LDialog):
elif idx == 2:
dumpvalues = {}
for k, widget in self.regists.items():
if type(widget) == QLineEdit:
if isinstance(widget, QLineEdit):
dumpvalues[k] = widget.text()
if type(widget) == FocusSpin:
elif isinstance(widget, QSpinBox):
dumpvalues[k] = widget.value()
if callable(widget):
elif callable(widget):
dumpvalues[k] = widget()
pattern = dumpvalues["pattern"]
if "." in pattern:
@ -161,9 +188,11 @@ class searchhookparam(LDialog):
usestruct.exportModule = pattern[:120]
else:
try:
bs = bytes.fromhex(
pattern.replace(" ", "").replace("0x", "").replace("??", "11")
)
p = pattern.replace(" ", "").replace("??", "11")
if ("?" in p) or (len(p) % 2 != 0):
getQMessageBox(self, "警告", "无效", True)
raise
bs = bytes.fromhex(p)
usestruct.pattern = bs[:30]
usestruct.length = len(bs)
except:
@ -186,7 +215,7 @@ class searchhookparam(LDialog):
usestruct.maxAddress = self.safehex(
dumpvalues["offstopaddr"], usestruct.maxAddress
)
usestruct.padding = 0 # self.safehex(dumpvalues[4], usestruct.padding)
usestruct.padding = dumpvalues["stroffset"]
usestruct.offset = dumpvalues["offset"]
usestruct.codepage = static_data["codepage_real"][
self.codepagesave["spcp"]
@ -266,7 +295,19 @@ class searchhookparam(LDialog):
):
if _type == 0:
line = QLineEdit(_val)
line.setValidator(HexValidator())
regwid = addwid = line
elif _type == -2:
line = QLineEdit(_val)
line.setValidator(PatternValidator())
regwid = addwid = line
elif _type == -1:
sp = FocusSpin()
sp.setDisplayIntegerBase(16)
sp.setMaximum(0x7FFFFFFF)
sp.setMinimum(-0x7FFFFFFF)
sp.setValue(_val)
regwid = addwid = sp
elif _type == 1:
sp = FocusSpin()
sp.setMaximum(10000000)
@ -364,13 +405,14 @@ class searchhookparam(LDialog):
"pattern",
"搜索匹配的特征(hex)",
self.hex2str(usestruct.pattern),
0,
-2,
uselayout=patternWl,
)
autoaddline(
"offset", "相对特征地址的偏移", usestruct.offset, 1, uselayout=patternWl
)
autoaddline("stroffset", "字符串地址偏移", usestruct.padding, -1)
autoaddline("time", "搜索持续时间(s)", usestruct.searchTime // 1000, 1)
autoaddline("maxrecords", "搜索结果数上限", usestruct.maxRecords, 1)

View File

@ -4,7 +4,7 @@ import gobject, os, zipfile
from myutils.config import globalconfig, static_data
from gui.inputdialog import multicolorset, autoinitdialog
from myutils.wrapper import tryprint
from myutils.utils import dynamiclink, translate_exits, copytree
from myutils.utils import dynamiclink, translate_exits, copytree, dynamicapiname
from gui.usefulwidget import (
D_getsimplecombobox,
getsimplecombobox,
@ -333,7 +333,7 @@ def vistranslate_rank(self):
("显示顺序"),
globalconfig["fix_translate_rank_rank"],
isrankeditor=True,
namemapfunction=lambda k: globalconfig["fanyi"][k]["name"],
namemapfunction=lambda k: dynamicapiname(k),
)

View File

@ -62,6 +62,7 @@ def registrhotkeys(self):
"_12": lambda: gobject.baseobject.hookselectdialog.showsignal.emit(),
"_13": lambda: gobject.baseobject.translation_ui.clickRange_signal.emit(False),
"_14": gobject.baseobject.translation_ui.showhide_signal.emit,
"_14_1": gobject.baseobject.translation_ui.clear_signal_1.emit,
"_15": gobject.baseobject.translation_ui.bindcropwindow_signal.emit,
"_16": gobject.baseobject.translation_ui.showhideuisignal.emit,
"_17": gobject.baseobject.translation_ui.quitf_signal.emit,

View File

@ -1,7 +1,7 @@
from qtsymbols import *
import functools, os, json
import windows, gobject
from myutils.utils import translate_exits
from myutils.utils import translate_exits, dynamicapiname
from myutils.config import (
globalconfig,
_TR,
@ -272,7 +272,7 @@ def loadvalidtss():
for x in globalconfig["fanyi"]:
if not translate_exits(x):
continue
alltransvis.append(globalconfig["fanyi"][x]["name"])
alltransvis.append(dynamicapiname(x))
alltrans.append(x)
return alltrans, alltransvis

View File

@ -1,7 +1,7 @@
from qtsymbols import *
import functools, os
from myutils.config import globalconfig, ocrsetting, ocrerrorfix, static_data
from myutils.utils import splitocrtypes, dynamiclink
from myutils.utils import splitocrtypes, dynamiclink, getimagefilefilter
from gui.inputdialog import autoinitdialogx, postconfigdialog, autoinitdialog_items
from gui.usefulwidget import (
D_getsimplecombobox,
@ -297,13 +297,7 @@ class showocrimage(saveposwindow):
super().closeEvent(e)
def openff(self):
f = QFileDialog.getOpenFileName(
filter="image ("
+ " ".join(
["*" + _.data().decode() for _ in QImageWriter.supportedImageFormats()]
)
+ ")"
)
f = QFileDialog.getOpenFileName(filter=getimagefilefilter())
res = f[0]
if not res:
return
@ -531,7 +525,11 @@ def getocrgrid(self):
grid=[
[
"多重区域模式",
D_getsimpleswitch(globalconfig, "multiregion"),
D_getsimpleswitch(
globalconfig,
"multiregion",
callback=lambda _: gobject.baseobject.textsource.leaveone(),
),
],
[
"范围框颜色",

View File

@ -7,6 +7,7 @@ from myutils.utils import (
splittranslatortypes,
dynamiclink,
translate_exits,
dynamicapiname,
)
from gui.pretransfile import sqlite2json
from gui.inputdialog import autoinitdialog, autoinitdialog_items, autoinitdialogx
@ -14,6 +15,7 @@ from gui.usefulwidget import (
D_getspinbox,
getIconButton,
D_getcolorbutton,
Prompt_dialog,
getcolorbutton,
getsimpleswitch,
D_getIconButton,
@ -25,7 +27,7 @@ from gui.usefulwidget import (
getvboxwidget,
)
from traceback import print_exc
from gui.dynalang import LPushButton, LLabel
from gui.dynalang import LPushButton, LLabel, LAction, LMenu
def deepcopydict(d):
@ -74,7 +76,7 @@ def loadvisinternal(btnplus, copy):
else:
if not translate_exits(_):
continue
__vis.append(globalconfig["fanyi"][_]["name"])
__vis.append(dynamicapiname(_))
__uid.append(_)
return __vis, __uid
@ -123,6 +125,39 @@ def getalistname(parent, copy, btnplus, callback):
)
def renameapi(qlabel: QLabel, apiuid, _):
menu = QMenu(qlabel)
editname = LAction("重命名")
menu.addAction(editname)
action = menu.exec(qlabel.mapToGlobal(_))
if action == editname:
before = dynamicapiname(apiuid)
_dia = Prompt_dialog(
qlabel,
"重命名",
"",
[
[
"名称",
before,
],
],
)
if _dia.exec():
title = _dia.text[0].text()
if title not in ("", before):
globalconfig["fanyi"][apiuid]["name_self_set"] = title
qlabel.setText(title)
def getrenameablellabel(uid):
name = LLabel(dynamicapiname(uid))
name.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
name.customContextMenuRequested.connect(functools.partial(renameapi, name, uid))
return name
def selectllmcallback(self, countnum, btnplus, fanyi, name):
uid = str(uuid.uuid4())
_f11 = "./Lunatranslator/translator/{}.py".format(fanyi)
@ -153,7 +188,7 @@ def selectllmcallback(self, countnum, btnplus, fanyi, name):
autoinitdialogx,
self,
translatorsetting[uid]["args"],
(globalconfig["fanyi"][uid]["name"]),
dynamicapiname(uid),
800,
items,
"userconfig.copyed." + uid,
@ -162,7 +197,7 @@ def selectllmcallback(self, countnum, btnplus, fanyi, name):
icon="fa.gear",
)
name = LLabel(globalconfig["fanyi"][uid]["name"])
name = getrenameablellabel(uid)
swc = getsimpleswitch(
globalconfig["fanyi"][uid],
"use",
@ -329,7 +364,7 @@ def initsome11(self, l, label=None, btnplus=False):
autoinitdialogx,
self,
translatorsetting[fanyi]["args"],
globalconfig["fanyi"][fanyi]["name"],
dynamicapiname(fanyi),
800,
items,
aclass,
@ -345,7 +380,7 @@ def initsome11(self, l, label=None, btnplus=False):
else:
last = ""
line += [
globalconfig["fanyi"][fanyi]["name"],
functools.partial(getrenameablellabel, fanyi),
D_getsimpleswitch(
globalconfig["fanyi"][fanyi],
"use",

View File

@ -5,8 +5,13 @@ from traceback import print_exc
import qtawesome, requests, gobject, windows, winsharedutils
import myutils.ankiconnect as anki
from myutils.hwnd import grabwindow
from myutils.config import globalconfig, _TR, static_data
from myutils.utils import loopbackrecorder, parsekeystringtomodvkcode
from myutils.config import globalconfig, static_data
from myutils.utils import (
loopbackrecorder,
parsekeystringtomodvkcode,
getimageformatlist,
getimagefilefilter,
)
from myutils.wrapper import threader, tryprint
from myutils.ocrutil import imageCut, ocr_run
from gui.rangeselect import rangeselct_function
@ -42,15 +47,7 @@ from gui.dynalang import (
)
def getimageformatlist():
_ = [_.data().decode() for _ in QImageWriter.supportedImageFormats()]
if globalconfig["imageformat"] == -1 or globalconfig["imageformat"] >= len(_):
globalconfig["imageformat"] = _.index("png")
return _
def getimageformat():
return getimageformatlist()[globalconfig["imageformat"]]
@ -496,7 +493,7 @@ class AnkiWindow(QWidget):
functools.partial(self.selecfile, self.audiopath_sentence)
)
folder_open3 = QPushButton(qtawesome.icon("fa.folder-open"), "")
folder_open3.clicked.connect(functools.partial(self.selecfile, self.editpath))
folder_open3.clicked.connect(functools.partial(self.selecfile2, self.editpath))
layout.addLayout(
getboxlayout(
[
@ -622,6 +619,12 @@ class AnkiWindow(QWidget):
pix = QPixmap.fromImage(QImage(src))
self.viewimagelabel.showpixmap(pix)
def selecfile2(self, item):
f = QFileDialog.getOpenFileName(filter=getimagefilefilter())
res = f[0]
if res != "":
item.setText(res)
def selecfile(self, item):
f = QFileDialog.getOpenFileName()
res = f[0]

View File

@ -247,6 +247,7 @@ class TranslatorWindow(resizableframeless):
showsavegame_signal = pyqtSignal()
clickRange_signal = pyqtSignal(bool)
showhide_signal = pyqtSignal()
clear_signal_1 = pyqtSignal()
bindcropwindow_signal = pyqtSignal()
fullsgame_signal = pyqtSignal()
quitf_signal = pyqtSignal()
@ -627,8 +628,20 @@ class TranslatorWindow(resizableframeless):
"selecttext",
lambda: gobject.baseobject.hookselectdialog.showsignal.emit(),
),
("selectocrrange", lambda: self.clickRange(False)),
("hideocrrange", self.showhideocrrange, None, lambda: self.showhidestate),
(
"selectocrrange",
lambda: self.clickRange(False),
None,
None,
lambda: self.clickRangeclear(False),
),
(
"hideocrrange",
self.showhideocrrange,
None,
lambda: self.showhidestate,
self.clear_signal_1.emit,
),
(
"bindwindow",
self.bindcropwindow_signal.emit,
@ -877,6 +890,9 @@ class TranslatorWindow(resizableframeless):
)
self.clickRange_signal.connect(self.clickRange)
self.showhide_signal.connect(self.showhideocrrange)
self.clear_signal_1.connect(
lambda: self.clearstate() or gobject.baseobject.textsource.clearrange()
)
self.bindcropwindow_signal.connect(
functools.partial(mouseselectwindow, self.bindcropwindowcallback)
)
@ -1127,6 +1143,13 @@ class TranslatorWindow(resizableframeless):
except:
pass
def clearstate(self):
try:
self.showhidestate = False
self.refreshtoolicon()
except:
pass
def bindcropwindowcallback(self, pid, hwnd):
_pid = os.getpid()
gobject.baseobject.hwnd = hwnd if pid != _pid else None
@ -1197,10 +1220,18 @@ class TranslatorWindow(resizableframeless):
return
self.showhidestate = False
rangeselct_function(self.afterrange, auto)
rangeselct_function(functools.partial(self.afterrange, False), auto)
def clickRangeclear(self, auto):
if globalconfig["sourcestatus2"]["ocr"]["use"] == False:
return
self.showhidestate = False
rangeselct_function(functools.partial(self.afterrange, True), auto)
@tryprint
def afterrange(self, rect):
def afterrange(self, clear, rect):
if clear or not globalconfig["multiregion"]:
gobject.baseobject.textsource.clearrange()
gobject.baseobject.textsource.newrangeadjustor()
gobject.baseobject.textsource.setrect(rect)
self.showhideocrrange()

View File

@ -1025,3 +1025,20 @@ def get_element_by(attr, attrv, html):
if res is None:
return ""
return res
def getimageformatlist():
_ = [_.data().decode() for _ in QImageWriter.supportedImageFormats()]
if globalconfig["imageformat"] == -1 or globalconfig["imageformat"] >= len(_):
globalconfig["imageformat"] = _.index("png")
return _
def getimagefilefilter():
return " ".join(("*." + _ for _ in getimageformatlist()))
def dynamicapiname(apiuid):
return globalconfig["fanyi"][apiuid].get(
"name_self_set", globalconfig["fanyi"][apiuid]["name"]
)

View File

@ -1,7 +1,7 @@
try:
from PyQt5 import QtSvg
from PyQt5.QtWidgets import QFrame,QListView,QCheckBox,QAbstractItemView,QTextEdit,QTableView,QHeaderView,QColorDialog,QSpinBox,QDoubleSpinBox,QComboBox,QDialogButtonBox,QMainWindow,QMessageBox,QDialog,QGridLayout,QTextBrowser,QGraphicsDropShadowEffect,QWidget,QSizePolicy,QScrollArea,QApplication,QPushButton,QSystemTrayIcon,QPlainTextEdit,QAction,QMenu,QFileDialog,QKeySequenceEdit,QLabel,QSpacerItem,QWidgetItem,QLayout,QTextBrowser,QLineEdit,QFormLayout,QSizePolicy,QTabWidget,QTabBar,QSplitter,QListWidget,QListWidgetItem,QHBoxLayout,QVBoxLayout,QSizeGrip,QFontComboBox,QProgressBar,QRadioButton,QButtonGroup,QSlider,QToolTip,QGroupBox,QGraphicsOpacityEffect,QStackedWidget,QStyledItemDelegate,QStyleOptionViewItem,QFontDialog,QTreeView
from PyQt5.QtGui import QIconEngine,QIntValidator,QStandardItem,QStandardItemModel,QImageWriter,QIcon,QTextCharFormat,QTextBlockFormat,QResizeEvent,QTextCursor,QFontMetricsF,QMouseEvent,QImage,QPainter,QRegion,QCloseEvent,QFontDatabase,QKeySequence,QPixmap,QCursor,QColor,QFont,QPen,QPainterPath,QBrush,QFontMetrics,QShowEvent,QWheelEvent,QPaintEvent,QTextLayout, QTextOption,QDragEnterEvent, QDropEvent,QTransform,QKeyEvent,QInputMethodEvent
from PyQt5.QtGui import QIconEngine,QIntValidator,QStandardItem,QStandardItemModel,QImageWriter,QIcon,QTextCharFormat,QTextBlockFormat,QResizeEvent,QTextCursor,QFontMetricsF,QMouseEvent,QImage,QPainter,QRegion,QCloseEvent,QFontDatabase,QKeySequence,QPixmap,QCursor,QColor,QFont,QPen,QPainterPath,QBrush,QFontMetrics,QShowEvent,QWheelEvent,QPaintEvent,QTextLayout, QTextOption,QDragEnterEvent, QDropEvent,QTransform,QKeyEvent,QInputMethodEvent,QValidator
from PyQt5.QtCore import QObject,pyqtSignal,Qt,QSize,QByteArray,QBuffer,QPointF,QPoint,QRect,QEvent,QModelIndex,QTimer,QRectF,QVariantAnimation,QUrl,QPropertyAnimation,QLocale,QSignalBlocker
isqt5 = True
class LineHeightTypes:
@ -12,7 +12,7 @@ except:
#print_exc()
from PyQt6 import QtSvg
from PyQt6.QtWidgets import QFrame,QListView,QCheckBox,QAbstractItemView,QTextEdit,QTableView,QHeaderView,QColorDialog,QSpinBox,QDoubleSpinBox,QComboBox,QDialogButtonBox,QMainWindow,QMessageBox,QDialog,QGridLayout,QTextBrowser,QGraphicsDropShadowEffect,QWidget,QSizePolicy,QScrollArea,QApplication,QPushButton,QSystemTrayIcon,QPlainTextEdit,QMenu,QFileDialog,QKeySequenceEdit,QLabel,QSpacerItem,QWidgetItem,QLayout,QTextBrowser,QLineEdit,QFormLayout,QSizePolicy,QTabWidget,QTabBar,QSplitter,QListWidget,QListWidgetItem,QHBoxLayout,QVBoxLayout,QSizeGrip,QFontComboBox,QProgressBar,QRadioButton,QButtonGroup,QSlider,QToolTip,QGroupBox,QGraphicsOpacityEffect,QStackedWidget,QTreeView
from PyQt6.QtGui import QIconEngine,QIntValidator,QAction,QStandardItem,QStandardItemModel,QImageWriter,QIcon,QTextCharFormat,QTextBlockFormat,QResizeEvent,QTextCursor,QFontMetricsF,QMouseEvent,QImage,QPainter,QRegion,QCloseEvent,QFontDatabase,QKeySequence,QPixmap,QCursor,QColor,QFont,QPen,QPainterPath,QBrush,QFontMetrics,QShowEvent,QWheelEvent,QPaintEvent,QTextLayout, QTextOption,QKeyEvent,QInputMethodEvent
from PyQt6.QtGui import QIconEngine,QIntValidator,QAction,QStandardItem,QStandardItemModel,QImageWriter,QIcon,QTextCharFormat,QTextBlockFormat,QResizeEvent,QTextCursor,QFontMetricsF,QMouseEvent,QImage,QPainter,QRegion,QCloseEvent,QFontDatabase,QKeySequence,QPixmap,QCursor,QColor,QFont,QPen,QPainterPath,QBrush,QFontMetrics,QShowEvent,QWheelEvent,QPaintEvent,QTextLayout, QTextOption,QKeyEvent,QInputMethodEvent,QValidator
from PyQt6.QtCore import QObject,pyqtSignal,Qt,QSize,QByteArray,QBuffer,QPointF,QPoint,QRect,QEvent,QModelIndex,QTimer,QRectF,QVariantAnimation,QUrl,QPropertyAnimation,QLocale
isqt5 = False

View File

@ -35,6 +35,24 @@ class ocrtext(basetext):
self.range_ui = []
self.gettextthread()
def clearrange(self):
for _ in self.range_ui:
_.close()
self.range_ui.clear()
self.savelastimg.clear()
self.savelastrecimg.clear()
self.lastocrtime.clear()
self.savelasttext.clear()
def leaveone(self):
for _ in self.range_ui[:-1]:
_.close()
self.range_ui = self.range_ui[-1:]
self.savelastimg = self.savelastimg[-1:]
self.savelastrecimg = self.savelastrecimg[-1:]
self.lastocrtime = self.lastocrtime[-1:]
self.savelasttext = self.savelasttext[-1:]
def newrangeadjustor(self):
if len(self.range_ui) == 0 or globalconfig["multiregion"]:
self.range_ui.append(rangeadjust(gobject.baseobject.settin_ui))

View File

@ -35,6 +35,7 @@ from ctypes import (
c_char_p,
c_wchar_p,
c_uint64,
c_int64,
c_void_p,
cast,
c_wchar,
@ -79,7 +80,7 @@ class SearchParam(Structure):
("searchTime", c_int),
("maxRecords", c_int),
("codepage", c_int),
("padding", c_uint64),
("padding", c_int64),
("minAddress", c_uint64),
("maxAddress", c_uint64),
("boundaryModule", c_wchar * 120),

View File

@ -6,7 +6,13 @@ import zhconv, gobject
import sqlite3, json
import functools
from myutils.config import globalconfig, translatorsetting
from myutils.utils import stringfyerror, autosql, PriorityQueue, SafeFormatter
from myutils.utils import (
stringfyerror,
autosql,
PriorityQueue,
SafeFormatter,
dynamicapiname,
)
from myutils.commonbase import ArgsEmptyExc, commonbase
from myutils.languageguesser import guess
@ -86,6 +92,7 @@ class basetrans(commonbase):
_globalconfig_key = "fanyi"
_setting_dict = translatorsetting
using_gpt_dict = False
_compatible_flag_is_sakura_less_than_5_52_3 = True
def level2init(self):
if (self.transtype == "offline") and (not self.is_gpt_like):
@ -97,7 +104,7 @@ class basetrans(commonbase):
self._private_init()
except Exception as e:
gobject.baseobject.displayinfomessage(
globalconfig["fanyi"][self.typename]["name"]
dynamicapiname(self.typename)
+ " init translator failed : "
+ str(stringfyerror(e)),
"<msg_error_not_refresh>",
@ -245,12 +252,6 @@ class basetrans(commonbase):
return res
return None
def maybecachetranslate(self, contentsolved, is_auto_run):
res = self.shortorlongcacheget(contentsolved, is_auto_run)
if res:
return res
return self.intervaledtranslate(contentsolved)
def intervaledtranslate(self, content):
interval = globalconfig["requestinterval"]
current = time.time()
@ -298,33 +299,48 @@ class basetrans(commonbase):
messages.append(context[i * 2])
messages.append(context[i * 2 + 1])
def reinitandtrans(self, contentsolved, is_auto_run):
if self.needreinit or self.initok == False:
self.needreinit = False
self.renewsesion()
try:
self._private_init()
except Exception as e:
raise Exception("init translator failed : " + str(stringfyerror(e)))
return self.maybecachetranslate(contentsolved, is_auto_run)
def maybeneedreinit(self):
if not (self.needreinit or not self.initok):
return
self.needreinit = False
self.renewsesion()
try:
self._private_init()
except Exception as e:
raise Exception("init translator failed : " + str(stringfyerror(e)))
def translate_and_collect(
self,
contentsolved,
is_auto_run,
callback,
):
def maybezhconvwrapper(self, callback):
def __maybeshow(callback, res, is_iter_res):
if self.needzhconv:
res = zhconv.convert(res, "zh-tw")
callback(res, is_iter_res)
callback = functools.partial(__maybeshow, callback)
return functools.partial(__maybeshow, callback)
res = self.reinitandtrans(contentsolved, is_auto_run)
def translate_and_collect(
self,
contentsolved: str | dict,
is_auto_run,
callback,
):
if isinstance(contentsolved, dict):
if self._compatible_flag_is_sakura_less_than_5_52_3:
query_use = json.dumps(contentsolved)
cache_use = contentsolved["text"]
else:
query_use = contentsolved
cache_use = contentsolved["contentraw"]
else:
cache_use = query_use = contentsolved
res = self.shortorlongcacheget(cache_use, is_auto_run)
if not res:
res = self.intervaledtranslate(query_use)
# 不能因为被打断而放弃后面的操作,发出的请求不会因为不再处理而无效,所以与其浪费不如存下来
# gettranslationcallback里已经有了是否为当前请求的校验这里无脑输出就行了
callback = self.maybezhconvwrapper(callback)
if isinstance(res, types.GeneratorType):
collectiterres = ""
for _res in res:
@ -348,8 +364,25 @@ class basetrans(commonbase):
# 不管是否使用翻译缓存,都存下来
if self.transtype == "pre":
return
self.shorttermcacheset(contentsolved, res)
self.longtermcacheset(contentsolved, res)
self.shorttermcacheset(cache_use, res)
self.longtermcacheset(cache_use, res)
def __parse_gpt_dict(self, contentsolved, optimization_params):
gpt_dict = None
contentraw = contentsolved
for _ in optimization_params:
if isinstance(_, dict):
_gpt_dict = _.get("gpt_dict", None)
if _gpt_dict is None:
continue
gpt_dict = _gpt_dict
contentraw = _.get("gpt_dict_origin")
return {
"text": contentsolved,
"gpt_dict": gpt_dict,
"contentraw": contentraw,
}
def _fythread(self):
self.needreinit = False
@ -376,23 +409,12 @@ class basetrans(commonbase):
if not checktutukufunction():
# 检查请求队列是否空,请求队列有新的请求,则放弃当前请求。但对于内嵌翻译请求,不可以放弃。
continue
if self.transtype == "pre" or self.using_gpt_dict:
gpt_dict = None
contentraw = contentsolved
for _ in optimization_params:
if isinstance(_, dict):
_gpt_dict = _.get("gpt_dict", None)
if _gpt_dict is None:
continue
gpt_dict = _gpt_dict
contentraw = _.get("gpt_dict_origin")
contentsolved = json.dumps(
{
"text": contentsolved,
"gpt_dict": gpt_dict,
"contentraw": contentraw,
}
self.maybeneedreinit()
if self.using_gpt_dict:
contentsolved = self.__parse_gpt_dict(
contentsolved, optimization_params
)
func = functools.partial(

View File

@ -5,6 +5,6 @@ class TS(commonllmdev):
target_url = "https://chatgpt.com/"
jsfile = "commonhookfetchstream.js"
function1 = 'url.includes("conversation")'
function2 = r"""thistext = chunk.message.content.parts[0]"""
function2 = r"""thistext += typeof(chunk.v)=='string'?chunk.v:(chunk.v[0]?(chunk.v[0].o=='append'?chunk.v[0].v:''):'')"""
textarea_selector = "#prompt-textarea"
button_selector = 'button[data-testid="send-button"]'

View File

@ -8,7 +8,11 @@ from myutils.utils import urlpathjoin
class TS(basetrans):
using_gpt_dict = True
_compatible_flag_is_sakura_less_than_5_52_3 = False
@property
def using_gpt_dict(self):
return self.config["prompt_version"] in [1, 2]
def langmap(self):
return {"zh": "zh-CN"}
@ -31,8 +35,6 @@ class TS(basetrans):
# self.client = OpenAI(api_key="114514", base_url=api_url)
def make_gpt_dict_text(self, gpt_dict):
if gpt_dict is None:
return ""
gpt_dict_text_list = []
for gpt in gpt_dict:
src = gpt["src"]
@ -112,11 +114,10 @@ class TS(basetrans):
}
]
self._gpt_common_parse_context_2(messages, self.context, contextnum, True)
gpt_dict_raw_text = self.make_gpt_dict_text(gpt_dict)
if gpt_dict_raw_text:
if gpt_dict:
content = (
"根据以下术语表(可以为空):\n"
+ gpt_dict_raw_text
+ self.make_gpt_dict_text(gpt_dict)
+ "\n"
+ "将下面的日文文本根据对应关系和备注翻译成中文:"
+ query
@ -211,17 +212,16 @@ class TS(basetrans):
yield res
def translate(self, query):
query = json.loads(query)
gpt_dict = query["gpt_dict"]
contentraw = query["contentraw"]
query = query["text"]
if (
(gpt_dict is not None)
and len(gpt_dict)
and self.config["prompt_version"] in [1, 2]
):
query = contentraw
def translate(self, query: str | dict):
if isinstance(query, dict):
gpt_dict = query["gpt_dict"]
contentraw = query["contentraw"]
query = query["text"]
if gpt_dict and self.using_gpt_dict:
query = contentraw
else:
gpt_dict = None
contentraw = query
self.checkempty(["API接口地址"])
self.get_client(self.config["API接口地址"])
frequency_penalty = float(self.config["frequency_penalty"])

View File

@ -985,6 +985,11 @@
"name": "显示/隐藏范围框",
"keystring": ""
},
"_14_1": {
"use": false,
"name": "清除OCR范围",
"keystring": ""
},
"_15": {
"use": false,
"name": "绑定窗口_点击自己取消",

View File

@ -2056,6 +2056,7 @@
[
"_13",
"_14",
"_14_1",
"_23",
"_26",
"_26_1"

View File

@ -804,5 +804,9 @@
"日志": "سجل .",
"查看": "عرض .",
"标记": "علامة",
"当前OCR引擎不支持设置语言为自动": "التعرف الضوئي على الحروف المحرك الحالي لا يدعم وضع اللغة التلقائي"
"当前OCR引擎不支持设置语言为自动": "التعرف الضوئي على الحروف المحرك الحالي لا يدعم وضع اللغة التلقائي",
"字符串地址偏移": "سلسلة عنوان الإزاحة",
"无效": "باطل",
"清除OCR范围": "مسح نطاق التعرف الضوئي على الحروف",
"重命名": "إعادة تسمية"
}

View File

@ -804,5 +804,9 @@
"日志": "日誌",
"查看": "查看",
"标记": "標記",
"当前OCR引擎不支持设置语言为自动": "當前OCR引擎不支持設定語言為自動"
"当前OCR引擎不支持设置语言为自动": "當前OCR引擎不支持設定語言為自動",
"字符串地址偏移": "字串地址偏移",
"无效": "無效",
"清除OCR范围": "清除OCR範圍",
"重命名": "重命名"
}

View File

@ -804,5 +804,9 @@
"日志": "deník",
"查看": "viz",
"标记": "značka",
"当前OCR引擎不支持设置语言为自动": "Aktuální OCR engine nepodporuje nastavení jazyka na automatické"
"当前OCR引擎不支持设置语言为自动": "Aktuální OCR engine nepodporuje nastavení jazyka na automatické",
"字符串地址偏移": "Posun adresy řetězce",
"无效": "neplatné",
"清除OCR范围": "Vymazat rozsah OCR",
"重命名": "přejmenovat"
}

View File

@ -804,5 +804,9 @@
"日志": "Journal",
"查看": "siehe",
"标记": "Zeichen",
"当前OCR引擎不支持设置语言为自动": "Die aktuelle OCR-Engine unterstützt die Einstellung der Sprache auf automatisch nicht"
"当前OCR引擎不支持设置语言为自动": "Die aktuelle OCR-Engine unterstützt die Einstellung der Sprache auf automatisch nicht",
"字符串地址偏移": "String Adresse Offset",
"无效": "ungültig",
"清除OCR范围": "OCR-Bereich löschen",
"重命名": "umbenennen"
}

View File

@ -804,5 +804,9 @@
"日志": "journal",
"查看": "see",
"标记": "sign",
"当前OCR引擎不支持设置语言为自动": "The current OCR engine does not support setting the language to automatic"
"当前OCR引擎不支持设置语言为自动": "The current OCR engine does not support setting the language to automatic",
"字符串地址偏移": "String address offset",
"无效": "invalid",
"清除OCR范围": "Clear OCR range",
"重命名": "rename"
}

View File

@ -804,5 +804,9 @@
"日志": "Diario",
"查看": "Ver",
"标记": "Marcado",
"当前OCR引擎不支持设置语言为自动": "El motor OCR actual no admite configurar el lenguaje a automático"
"当前OCR引擎不支持设置语言为自动": "El motor OCR actual no admite configurar el lenguaje a automático",
"字符串地址偏移": "Desplazamiento de la dirección de la cadena",
"无效": "Inválido",
"清除OCR范围": "Eliminar el rango OCR",
"重命名": "Cambiar el nombre"
}

View File

@ -804,5 +804,9 @@
"日志": "Logs",
"查看": "Voir",
"标记": "Marquage",
"当前OCR引擎不支持设置语言为自动": "Le moteur OCR actuel ne prend pas en charge le réglage de la langue sur auto"
"当前OCR引擎不支持设置语言为自动": "Le moteur OCR actuel ne prend pas en charge le réglage de la langue sur auto",
"字符串地址偏移": "Décalage d'adresse de chaîne",
"无效": "Invalide",
"清除OCR范围": "Effacer la plage ocr",
"重命名": "Renommer"
}

View File

@ -804,5 +804,9 @@
"日志": "diario",
"查看": "vedi",
"标记": "segno",
"当前OCR引擎不支持设置语言为自动": "Il motore OCR corrente non supporta l'impostazione automatica della lingua"
"当前OCR引擎不支持设置语言为自动": "Il motore OCR corrente non supporta l'impostazione automatica della lingua",
"字符串地址偏移": "Spostamento indirizzo stringa",
"无效": "non valido",
"清除OCR范围": "Cancella intervallo OCR",
"重命名": "rinomina"
}

View File

@ -804,5 +804,9 @@
"日志": "ログ#ログ#",
"查看": "表示#ヒョウジ#",
"标记": "マークアップ",
"当前OCR引擎不支持设置语言为自动": "現在のOCRエンジンでは言語の自動設定はサポートされていません"
"当前OCR引擎不支持设置语言为自动": "現在のOCRエンジンでは言語の自動設定はサポートされていません",
"字符串地址偏移": "文字列アドレスオフセット",
"无效": "無効です",
"清除OCR范围": "OCR範囲のクリア",
"重命名": "名前を変更"
}

View File

@ -804,5 +804,9 @@
"日志": "로그",
"查看": "보기",
"标记": "태그",
"当前OCR引擎不支持设置语言为自动": "현재 OCR 엔진은 자동 언어 설정을 지원하지 않습니다."
"当前OCR引擎不支持设置语言为自动": "현재 OCR 엔진은 자동 언어 설정을 지원하지 않습니다.",
"字符串地址偏移": "문자열 주소 오프셋",
"无效": "유효하지 않음",
"清除OCR范围": "OCR 범위 지우기",
"重命名": "이름 바꾸기"
}

View File

@ -804,5 +804,9 @@
"日志": "dagboek",
"查看": "zie",
"标记": "teken",
"当前OCR引擎不支持设置语言为自动": "De huidige OCR-engine ondersteunt niet het instellen van de taal op automatisch"
"当前OCR引擎不支持设置语言为自动": "De huidige OCR-engine ondersteunt niet het instellen van de taal op automatisch",
"字符串地址偏移": "Tekenadres offset",
"无效": "ongeldig",
"清除OCR范围": "OCR-bereik wissen",
"重命名": "hernoemen"
}

View File

@ -804,5 +804,9 @@
"日志": "dziennik",
"查看": "zobacz",
"标记": "znak",
"当前OCR引擎不支持设置语言为自动": "Obecny silnik OCR nie obsługuje ustawienia języka na automatyczne"
"当前OCR引擎不支持设置语言为自动": "Obecny silnik OCR nie obsługuje ustawienia języka na automatyczne",
"字符串地址偏移": "Przesunięcie adresu ciągu",
"无效": "nieprawidłowe",
"清除OCR范围": "Wyczyść zakres OCR",
"重命名": "zmień nazwę"
}

View File

@ -804,5 +804,9 @@
"日志": "diário",
"查看": "ver",
"标记": "signo",
"当前OCR引擎不支持设置语言为自动": "O mecanismo OCR atual não suporta configurar o idioma para automático"
"当前OCR引擎不支持设置语言为自动": "O mecanismo OCR atual não suporta configurar o idioma para automático",
"字符串地址偏移": "Deslocamento do endereço do string",
"无效": "inválido",
"清除OCR范围": "Limpar o intervalo de OCR",
"重命名": "renomear"
}

View File

@ -804,5 +804,9 @@
"日志": "Журнал",
"查看": "Посмотреть",
"标记": "Маркировка",
"当前OCR引擎不支持设置语言为自动": "Текущий движок OCR не поддерживает настройку языка автоматически"
"当前OCR引擎不支持设置语言为自动": "Текущий движок OCR не поддерживает настройку языка автоматически",
"字符串地址偏移": "Смещение адреса строки",
"无效": "Неверный",
"清除OCR范围": "Очистить диапазон OCR",
"重命名": "Переименовать"
}

View File

@ -804,5 +804,9 @@
"日志": "journal",
"查看": "se",
"标记": "tecken",
"当前OCR引擎不支持设置语言为自动": "Den aktuella OCR-motorn stöder inte inställning av språket till automatiskt"
"当前OCR引擎不支持设置语言为自动": "Den aktuella OCR-motorn stöder inte inställning av språket till automatiskt",
"字符串地址偏移": "Strängadressförskjutning",
"无效": "ogiltig",
"清除OCR范围": "Rensa OCR-område",
"重命名": "Byt namn"
}

View File

@ -804,5 +804,9 @@
"日志": "บันทึกประจำวัน",
"查看": "ดู",
"标记": "เครื่องหมาย",
"当前OCR引擎不支持设置语言为自动": "เครื่องยนต์ OCR ปัจจุบันไม่รองรับการตั้งค่าภาษาเป็นอัตโนมัติ"
"当前OCR引擎不支持设置语言为自动": "เครื่องยนต์ OCR ปัจจุบันไม่รองรับการตั้งค่าภาษาเป็นอัตโนมัติ",
"字符串地址偏移": "การชดเชยที่อยู่สตริง",
"无效": "ไม่ถูกต้อง",
"清除OCR范围": "ล้างช่วง OCR",
"重命名": "เปลี่ยนชื่อ"
}

View File

@ -804,5 +804,9 @@
"日志": "Günlük",
"查看": "Gördün mü?",
"标记": "imza",
"当前OCR引擎不支持设置语言为自动": "Ağımdaki OCR motoru dili otomatik olarak ayarlamasını desteklemez"
"当前OCR引擎不支持设置语言为自动": "Ağımdaki OCR motoru dili otomatik olarak ayarlamasını desteklemez",
"字符串地址偏移": "Kelime adresi",
"无效": "Keçersiz",
"清除OCR范围": "OCR aralığını temizle",
"重命名": "Yeniden Adlandır"
}

View File

@ -804,5 +804,9 @@
"日志": "журнал",
"查看": "див.",
"标记": "знак",
"当前OCR引擎不支持设置语言为自动": "Поточний рушій OCR не підтримує встановлення мови як автоматичного"
"当前OCR引擎不支持设置语言为自动": "Поточний рушій OCR не підтримує встановлення мови як автоматичного",
"字符串地址偏移": "Вирівнювання адреси рядків",
"无效": "некоректний",
"清除OCR范围": "Очистити діапазон OCR",
"重命名": "перейменувати"
}

View File

@ -804,5 +804,9 @@
"日志": "Đăng nhập",
"查看": "Xem thêm",
"标记": "Đánh dấu",
"当前OCR引擎不支持设置语言为自动": "Công cụ OCR hiện tại không hỗ trợ thiết lập ngôn ngữ tự động"
"当前OCR引擎不支持设置语言为自动": "Công cụ OCR hiện tại không hỗ trợ thiết lập ngôn ngữ tự động",
"字符串地址偏移": "Thay đổi địa chỉ chuỗi",
"无效": "Không hợp lệ",
"清除OCR范围": "Xóa dải OCR",
"重命名": "Thay tên"
}

View File

@ -804,5 +804,9 @@
"日志": "",
"查看": "",
"标记": "",
"当前OCR引擎不支持设置语言为自动": ""
"当前OCR引擎不支持设置语言为自动": "",
"字符串地址偏移": "",
"无效": "",
"清除OCR范围": "",
"重命名": ""
}

View File

@ -28,8 +28,8 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/version)
include(generate_product_version)
set(VERSION_MAJOR 5)
set(VERSION_MINOR 52)
set(VERSION_PATCH 3)
set(VERSION_MINOR 53)
set(VERSION_PATCH 0)
add_library(pch pch.cpp)
target_precompile_headers(pch PUBLIC pch.h)

View File

@ -271,7 +271,7 @@ def MessageBox(msg, info = 'Message'):
ctypes.windll.user32.MessageBoxW(None, str(msg), str(info), 0)
return 0
os.MessageBox = MessageBox
sys.stdout=sys.stderr
#sys.stdout=sys.stderr
sys.path.insert(0, './LunaTranslator')
)"
#ifndef PYSTAND_CONSOLE
@ -365,6 +365,7 @@ int main()
}
#else
SetConsoleOutputCP(CP_UTF8);
/*
auto getCurrentTimestamp = []
{
auto now = std::chrono::system_clock::now();
@ -376,6 +377,7 @@ int main()
};
auto curr = getCurrentTimestamp();
freopen(curr.c_str(), "a", stderr);
*/
#endif
int hr = ps.RunString(init_script);
return hr;