This commit is contained in:
恍兮惚兮 2024-09-12 21:01:26 +08:00
parent a4fa41cabd
commit 01c1669cb9
58 changed files with 1138 additions and 261 deletions

View File

@ -67,7 +67,7 @@ def loadmainui():
def checklang():
from myutils.config import globalconfig, oldlanguage, loadlangviss
from myutils.config import globalconfig, oldlanguage, static_data
from qtsymbols import (
QDialog,
pyqtSignal,
@ -96,10 +96,12 @@ def checklang():
self.setFont(font)
self.current = "zh"
language_listcombox = QComboBox()
_, vis = loadlangviss()
inner, vis = [_[1] for _ in static_data["language_list_show"]], [
_[0] for _ in static_data["language_list_show"]
]
language_listcombox.addItems(vis)
language_listcombox.currentIndexChanged.connect(
lambda x: setattr(self, "current", _[x])
lambda x: setattr(self, "current", inner[x])
)
vb = QVBoxLayout(self)

View File

@ -268,7 +268,7 @@ def maybehavebutton(self, gameuid, post):
callback = functools.partial(
autoinitdialog,
self,
save_text_process_info["postprocessconfig"][post]['args'],
save_text_process_info["postprocessconfig"][post]["args"],
postprocessconfig[post]["name"],
600,
items,
@ -1032,19 +1032,19 @@ class dialog_setting_game_internal(QWidget):
formLayout2.addRow(
"源语言",
getsimplecombobox(
static_data["language_list_translator"],
[_["zh"] for _ in static_data["lang_list_all"]],
savehook_new_data[gameuid],
"private_srclang_2",
internal=static_data["language_list_translator_inner"],
internal=[_["code"] for _ in static_data["lang_list_all"]],
),
)
formLayout2.addRow(
"目标语言",
getsimplecombobox(
static_data["language_list_translator"],
[_["zh"] for _ in static_data["lang_list_all"]],
savehook_new_data[gameuid],
"private_tgtlang_2",
internal=static_data["language_list_translator_inner"],
internal=[_["code"] for _ in static_data["lang_list_all"]],
),
)

View File

@ -34,6 +34,7 @@ from gui.dynalang import LPushButton, LFormLayout
def __changeuibuttonstate(self, x):
gobject.baseobject.translation_ui.refreshtoolicon()
gobject.baseobject.translation_ui.translate_text.textbrowser.showhideorigin(x)
try:
self.fenyinsettings.setEnabled(x)
except:

View File

@ -1,5 +1,5 @@
import os
from myutils.config import globalconfig, static_data, getlanguse, loadlangviss
from myutils.config import globalconfig, static_data, getlanguse
from gui.usefulwidget import (
D_getsimplecombobox,
D_getIconButton,
@ -14,7 +14,9 @@ def changelang(_):
def setTablanglz(self):
inner, vis = loadlangviss()
inner, vis = [_[1] for _ in static_data["language_list_show"]], [
_[0] for _ in static_data["language_list_show"]
]
return [
[
(
@ -25,22 +27,22 @@ def setTablanglz(self):
[
"源语言",
D_getsimplecombobox(
static_data["language_list_translator"],
[_["zh"] for _ in static_data["lang_list_all"]],
globalconfig,
"srclang4",
internal=static_data[
"language_list_translator_inner"
internal=[
_["code"] for _ in static_data["lang_list_all"]
],
),
],
[
"目标语言",
D_getsimplecombobox(
static_data["language_list_translator"],
[_["zh"] for _ in static_data["lang_list_all"]],
globalconfig,
"tgtlang4",
internal=static_data[
"language_list_translator_inner"
internal=[
_["code"] for _ in static_data["lang_list_all"]
],
),
],

View File

@ -152,11 +152,11 @@ def selectllmcallback(self, countnum, btnplus, fanyi, name):
callback=functools.partial(
autoinitdialogx,
self,
translatorsetting[uid]['args'],
translatorsetting[uid]["args"],
(globalconfig["fanyi"][uid]["name"]),
800,
items,
"userconfig.copyed."+uid,
"userconfig.copyed." + uid,
uid,
),
icon="fa.gear",
@ -308,7 +308,7 @@ def initsome11(self, l, label=None, btnplus=False):
line = []
countnum = []
for fanyi in l:
which=translate_exits(fanyi,which=True)
which = translate_exits(fanyi, which=True)
if which is None:
continue
i += 1
@ -316,8 +316,8 @@ def initsome11(self, l, label=None, btnplus=False):
if fanyi in translatorsetting:
items = autoinitdialog_items(translatorsetting[fanyi])
if which==0:
if which == 0:
aclass = "translator." + fanyi
elif which == 1:
aclass = "userconfig.copyed." + fanyi
@ -325,7 +325,7 @@ def initsome11(self, l, label=None, btnplus=False):
callback=functools.partial(
autoinitdialogx,
self,
translatorsetting[fanyi]['args'],
translatorsetting[fanyi]["args"],
globalconfig["fanyi"][fanyi]["name"],
800,
items,

View File

@ -54,6 +54,7 @@ class Textbrowser(QFrame):
self.textbrowser.resize(size)
self.textbrowser.show()
self.textbrowser.setselectable(globalconfig["selectable"])
self.textbrowser.showhideorigin(globalconfig["isshowrawtext"])
def __init__(self, parent):
super().__init__(parent)
@ -64,16 +65,12 @@ class Textbrowser(QFrame):
self.loadinternal()
def iter_append(self, iter_context_class, origin, atcenter, text, color):
cleared = self.cleared
self.cleared = False
self.textbrowser.iter_append(
iter_context_class, origin, atcenter, text, color, cleared
)
self.textbrowser.iter_append(iter_context_class, origin, atcenter, text, color)
def append(self, origin, atcenter, text, tag, flags, color):
cleared = self.cleared
self.cleared = False
self.textbrowser.append(origin, atcenter, text, tag, flags, color, cleared)
self.textbrowser.append(origin, atcenter, text, tag, flags, color)
def clear(self):
self.cleared = True

View File

@ -328,10 +328,7 @@ class TranslatorWindow(resizableframeless):
color = kwargs.get("color")
clear = True
if globalconfig["isshowrawtext"]:
self.showline(clear=clear, text=text, isshowrawtext=True, color=color)
else:
self.showline(clear=clear)
self.showline(clear=clear, text=text, color=color)
def showstatus(self, res, color, clear, origin):
self.showline(clear=clear, text=res, color=color, origin=origin)
@ -351,7 +348,6 @@ class TranslatorWindow(resizableframeless):
origin = kwargs.get("origin", True)
text = kwargs.get("text", None)
color = kwargs.get("color", "black")
isshowrawtext = kwargs.get("isshowrawtext", False)
iter_context = kwargs.get("iter_context", None)
if clear:
@ -373,7 +369,7 @@ class TranslatorWindow(resizableframeless):
else:
hira = []
isshowhira = isshow_fenci = isfenciclick = False
if isshowrawtext:
if origin:
isshowhira = globalconfig["isshowhira"]
isshow_fenci = globalconfig["show_fenci"]
isfenciclick = (
@ -1074,6 +1070,9 @@ class TranslatorWindow(resizableframeless):
except:
globalconfig["isshowrawtext"] = not globalconfig["isshowrawtext"]
self.refreshtoolicon()
self.translate_text.textbrowser.showhideorigin(
globalconfig["isshowrawtext"]
)
def changeshowhidetrans(self):
try:

View File

@ -88,8 +88,8 @@ class commonbase:
def langmap_(self):
_ = dict(
zip(
static_data["language_list_translator_inner"],
static_data["language_list_translator_inner"],
[_["code"] for _ in static_data["lang_list_all"]],
[_["code"] for _ in static_data["lang_list_all"]],
)
)
_.update({"cht": "zh"})

View File

@ -528,18 +528,6 @@ def langfile(lang):
return "./files/lang/{}.json".format(lang)
def loadlangviss():
inners = []
vis = []
for i, l in enumerate(static_data["language_list_translator_inner"]):
if not os.path.exists(langfile(l)):
continue
inners.append(l)
vis.append(static_data["language_list_show"][i])
return inners, vis
def loadlanguage():
global language_last, languageshow
_language = getlanguse()
@ -657,8 +645,8 @@ def _TRL(kk):
def getlang_inner2show(langcode):
return dict(
zip(
static_data["language_list_translator_inner"],
static_data["language_list_translator"],
[_["code"] for _ in static_data["lang_list_all"]],
[_["zh"] for _ in static_data["lang_list_all"]],
)
).get(langcode, "??")

View File

@ -569,14 +569,21 @@ def parsemayberegexreplace(lst: list, line: str):
return line
def checklangisusing(langs):
if langs is None:
return True
elif isinstance(langs, list):
return getlanguse() in langs
elif isinstance(langs, str):
return getlanguse() == langs
raise Exception(langs)
def checkpostlangmatch(name):
for item in static_data["transoptimi"]:
if name == item["name"]:
try:
if isinstance(item["languageuse"], list):
return getlanguse() in item["languageuse"]
elif isinstance(item["languageuse"], str):
return getlanguse() == item["languageuse"]
return checklangisusing(item.get("languageuse", None))
except:
return True
@ -913,7 +920,7 @@ def createurl(url: str):
def createenglishlangmap():
return dict(
zip(
static_data["language_list_translator_inner"],
static_data["language_list_translator_inner_english"],
[_["code"] for _ in static_data["lang_list_all"]],
[_["en"] for _ in static_data["lang_list_all"]],
)
)

View File

@ -11,7 +11,7 @@ from gui.dynalang import LPushButton, LFormLayout, LLabel
def initsupports():
_allsupport = winrtutils.getlanguagelist()
supportmap = {}
for lang in static_data["language_list_translator_inner"] + [
for lang in [_["code"] for _ in static_data["lang_list_all"]] + [
"zh-Hans",
"zh-Hant",
]:
@ -38,7 +38,9 @@ def question(dialog: QDialog):
supportlang.setText("_,_".join([getlang_inner2show(f) for f in _allsupport]))
btndownload = LPushButton("添加语言包")
btndownload.clicked.connect(
lambda: gobject.baseobject.openlink(dynamiclink("{docs_server}/#/zh/windowsocr"))
lambda: gobject.baseobject.openlink(
dynamiclink("{docs_server}/#/zh/windowsocr")
)
)
formLayout.addRow(
"当前支持的语言", getboxlayout([supportlang, btndownload], makewidget=True)
@ -53,11 +55,11 @@ class OCR(baseocr):
if self.srclang not in self.supportmap:
_allsupport = initsupports()
idx = static_data["language_list_translator_inner"].index(self.srclang)
idx = [_["code"] for _ in static_data["lang_list_all"]].index(self.srclang)
raise Exception(
_TR("系统未安装")
+ ' "'
+ _TR(static_data["language_list_translator"][idx])
+ _TR([_["zh"] for _ in static_data["lang_list_all"]][idx])
+ '" '
+ _TR("的OCR模型")
+ "\n"
@ -66,7 +68,6 @@ class OCR(baseocr):
+ ", ".join([_TR(getlang_inner2show(f)) for f in _allsupport])
)
ret = winrtutils.OCR_f(imagebinary, self.supportmap[self.srclang], self.space)
boxs = [_[1:] for _ in ret]
texts = [_[0] for _ in ret]

View File

@ -131,6 +131,7 @@ class TextBrowser(QWidget, dataget):
self.iteryinyinglabelsave = {}
self.saveiterclasspointer = {}
self.extra_height = 0
self.trace = []
self.resets1()
def resets1(self):
@ -198,16 +199,19 @@ class TextBrowser(QWidget, dataget):
c.setCharFormat(f)
self.textbrowser.setTextCursor(c)
def iter_append(self, iter_context_class, origin, atcenter, text, color, cleared):
self._textbrowser_iter_append(
iter_context_class, origin, atcenter, text, color, cleared
)
def showhideorigin(self, show):
traces = self.trace.copy()
self.clear()
for t, trace in traces:
if t == 0:
self.append(*trace)
elif t == 1:
self.iter_append(*trace)
def _textbrowser_iter_append(
self, iter_context_class, origin, atcenter, text, color, cleared
):
def iter_append(self, iter_context_class, origin, atcenter, text, color):
self.trace.append((1, (iter_context_class, origin, atcenter, text, color)))
if iter_context_class not in self.saveiterclasspointer:
self._textbrowser_append(origin, atcenter, "", [], color, cleared)
self._textbrowser_append(origin, atcenter, "", [], color)
self.saveiterclasspointer[iter_context_class] = {
"currtext": "",
"curr": self._getcurrpointer(),
@ -247,16 +251,18 @@ class TextBrowser(QWidget, dataget):
self._createqfont(origin),
)
def append(self, origin, atcenter, text, tag, flags, color, cleared):
def append(self, origin, atcenter, text, tag, flags, color):
self.trace.append((0, (origin, atcenter, text, tag, flags, color)))
if origin and not globalconfig["isshowrawtext"]:
return
isshowhira, isshow_fenci, isfenciclick = flags
if len(tag):
font = self._createqfont(origin)
textlines, linetags = self._splitlinestags(font, tag, text)
text = "\n".join(textlines)
tag = self._join_tags(linetags, True)
self._textbrowser_append(
origin, atcenter, text, tag if isshowhira else [], color, cleared
origin, atcenter, text, tag if isshowhira else [], color
)
if isshow_fenci or isfenciclick:
self.addsearchwordmask(isshow_fenci, isfenciclick, tag)
@ -264,11 +270,10 @@ class TextBrowser(QWidget, dataget):
def _getqalignment(self, atcenter):
return Qt.AlignmentFlag.AlignCenter if atcenter else Qt.AlignmentFlag.AlignLeft
def _textbrowser_append(
self, origin, atcenter, text: str, tag: list, color, cleared
):
def _textbrowser_append(self, origin, atcenter, text: str, tag: list, color):
self.textbrowser.document().blockSignals(True)
font = self._createqfont(origin)
cleared = len(self.textbrowser.toPlainText()) == 0
self._setnextfont(font, cleared)
self.textbrowser.setAlignment(self._getqalignment(atcenter))
@ -722,3 +727,4 @@ class TextBrowser(QWidget, dataget):
self.saveiterclasspointer.clear()
self.textbrowser.move(0, 0)
self.atback_color.move(0, 0)
self.trace = []

View File

@ -12,6 +12,31 @@ class QGraphicsDropShadowEffect_multi(QGraphicsDropShadowEffect):
super().draw(painter)
class CachedQGraphicsDropShadowEffect_multi(QGraphicsDropShadowEffect):
def __init__(self, parent=None, x=1):
super().__init__(parent)
self.shadow_pixmap = QPixmap()
self.x = x
def draw(self, painter):
r = self.parent().devicePixelRatioF()
if self.shadow_pixmap.isNull():
size = QSize(painter.device().width(), painter.device().height()) * r
self.shadow_pixmap = QPixmap(size)
self.shadow_pixmap.setDevicePixelRatio(r)
self.shadow_pixmap.fill(Qt.GlobalColor.transparent)
shadow_painter = QPainter(self.shadow_pixmap)
shadow_painter.setRenderHint(QPainter.RenderHint.Antialiasing)
for _ in range(self.x):
super().draw(shadow_painter)
painter.setRenderHint(QPainter.RenderHint.Antialiasing)
painter.drawPixmap(
-int(self.parent().x()),
-int(self.parent().y()) - self.parent().parent().parent().parent().y(),
self.shadow_pixmap,
)
class TextLine(TextLabel_0):
def usingcolor(self):
@ -19,7 +44,7 @@ class TextLine(TextLabel_0):
def setShadow_internal(self, colorshadow, width=1, deepth=1):
shadow2 = QGraphicsDropShadowEffect_multi(deepth)
shadow2 = CachedQGraphicsDropShadowEffect_multi(self, deepth)
shadow2.setBlurRadius(width)
shadow2.setOffset(0)

View File

@ -215,10 +215,22 @@
return wrap
}
</script>
<style id="maybeshoworigin">
</style>
<script>
function _create_div_line_id(_id) {
function _showhideorigin(show) {
console.log(show)
let css = ['.lunatranslator_origin{ display: none; }', '.lunatranslator_origin{ display: block; }'][show]
document.getElementById('maybeshoworigin').innerHTML = css;
safe_calllunaheightchange(document.getElementById(rootdivid).offsetHeight)
}
function _create_div_line_id(_id, origin) {
let div = document.createElement("div");
div.id = _id;
if (1 == origin) {
div.classList.add('lunatranslator_origin')
}
document.getElementById(rootdivid).appendChild(div);
}
function _create_internal_text(style, styleargsjson, _id, textu, argsjson) {
@ -363,6 +375,7 @@
</script>
<script>
//api
showhideorigin = _showhideorigin
create_div_line_id = _create_div_line_id;
create_internal_text = _create_internal_text;
create_internal_rubytext = _create_internal_rubytext;

View File

@ -130,9 +130,11 @@ class TextBrowser(QWidget, dataget):
self.webivewwidget.eval(js)
# js api
def showhideorigin(self, show):
self.debugeval(f'showhideorigin("{int(show)}")')
def create_div_line_id(self, _id):
self.debugeval(f'create_div_line_id("{_id}");')
def create_div_line_id(self, _id, origin):
self.debugeval(f'create_div_line_id("{_id}","{int(origin)}")')
def clear_all(self):
self.debugeval(f"clear_all()")
@ -213,24 +215,24 @@ class TextBrowser(QWidget, dataget):
# native api end
def iter_append(self, iter_context_class, origin, atcenter, text, color, cleared):
def iter_append(self, iter_context_class, origin, atcenter, text, color):
if iter_context_class not in self.saveiterclasspointer:
_id = self.createtextlineid()
_id = self.createtextlineid(origin)
self.saveiterclasspointer[iter_context_class] = _id
_id = self.saveiterclasspointer[iter_context_class]
self._webview_append(_id, origin, atcenter, text, [], [], color)
def createtextlineid(self):
def createtextlineid(self, origin):
_id = f"luna_{uuid.uuid4()}"
self.create_div_line_id(_id)
self.create_div_line_id(_id, origin)
return _id
def append(self, origin, atcenter, text, tag, flags, color, cleared):
def append(self, origin, atcenter, text, tag, flags, color):
_id = self.createtextlineid()
_id = self.createtextlineid(origin)
self._webview_append(_id, origin, atcenter, text, tag, flags, color)
def measureH(self, font_family, font_size):

View File

@ -0,0 +1,61 @@
from myutils.subproc import subproc_w, autoproc
from translator.basetranslator import basetrans
import os, time
import windows
class TS(basetrans):
def inittranslator(self):
self.path = None
self.pair = None
self.checkpath()
def checkpath(self):
t = time.time()
t = str(t)
pipename = "\\\\.\\Pipe\\dreye_" + t
waitsignal = "dreyewaitload_" + t
self.engine = autoproc(
subproc_w(
'./files/plugins/shareddllproxy32.exe atlaswmain {} {} '.format(
pipename, waitsignal
),
name="atlaswmain",
)
)
windows.WaitForSingleObject(
windows.AutoHandle(windows.CreateEvent(False, False, waitsignal)),
windows.INFINITE,
)
windows.WaitNamedPipe(pipename, windows.NMPWAIT_WAIT_FOREVER)
self.hPipe = windows.AutoHandle(
windows.CreateFile(
pipename,
windows.GENERIC_READ | windows.GENERIC_WRITE,
0,
None,
windows.OPEN_EXISTING,
windows.FILE_ATTRIBUTE_NORMAL,
None,
)
)
return True
def x64(self, content):
if self.checkpath() == False:
return "error"
ress = []
for line in content.split("\n"):
if len(line) == 0:
continue
windows.WriteFile(self.hPipe, content.encode('utf-16-le'))
ress.append(
windows.ReadFile(self.hPipe, 4096).decode('utf-16-le')
)
return "\n".join(ress)
def translate(self, content):
return self.x64(content)

View File

@ -178,6 +178,8 @@ class TS(basetrans):
"vi": "vie",
"uk": "ukr",
"ar": "ara",
"sv": "swe",
"la": "lat",
}
def inittranslator(self):

View File

@ -37,6 +37,7 @@ class TS(basetrans):
"uk": "ukr",
"ar": "ara",
"sv": "swe",
"la": "lat",
}
def translate(self, query):

View File

@ -13,6 +13,9 @@ class TS(basetransdev):
"cht": "cht",
"vi": "vie",
"uk": "ukr",
"ar": "ara",
"sv": "swe",
"la": "lat",
}
def translate(self, content):

View File

@ -15,6 +15,8 @@ class TS(basetrans):
"vi": "vie",
"uk": "ukr",
"ar": "ara",
"sv": "swe",
"la": "lat",
}
def translate(self, query):

View File

@ -56,7 +56,7 @@ def initDeepLXData(sourceLang: str, targetLang: str):
class TS(basetrans):
def langmap(self):
x = {_: _.upper() for _ in static_data["language_list_translator_inner"]}
x = {_: _.upper() for _ in [_["code"] for _ in static_data["lang_list_all"]]}
x.pop("cht")
return x # {"zh":"ZH","ja":"JA","en":"EN","es":"ES","fr":"FR","ru":"RU"}

View File

@ -5,7 +5,7 @@ from translator.basetranslator import basetrans
class TS(basetrans):
def langmap(self):
x = {_: _.upper() for _ in static_data["language_list_translator_inner"]}
x = {_: _.upper() for _ in [_["code"] for _ in static_data["lang_list_all"]]}
x.pop("cht")
return x

View File

@ -22,15 +22,18 @@ class TS(basetrans):
"upgrade-insecure-requests": "1",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36",
}
host_html = self.proxysession.get("https://papago.naver.com/", headers=headers).text
url_path = re.compile("/home.(.*?).chunk.js").search(host_html).group()
host_html = self.proxysession.get(
"https://papago.naver.com/", headers=headers
).text
url_path = re.compile("/main.(.*?).chunk.js").search(host_html).group()
self.language_url = "".join(["https://papago.naver.com", url_path])
lang_html = self.proxysession.get(self.language_url, headers=headers).text
self.auth_key = self.get_auth_key(lang_html)
self.uuid = uuid.uuid4().__str__()
self.auth_key = re.search(r'"PPG "(.*)"(.*?)"\).toString', lang_html).groups()[
1
]
# Authorization: "PPG " + t + ":" + p.a.HmacMD5(t + "\n" + e.split("?")[0] + "\n" + n, "v1.8.4_bbf86e0446").toString(p.a.enc.Base64),
def get_auth_key(self, lang_html: str) -> str:
return re.compile('AUTH_KEY:"(.*?)"').findall(lang_html)[0]
self.uuid = uuid.uuid4().__str__()
def get_auth(self, url, auth_key, device_id, time_stamp):
auth = hmac.new(
@ -85,5 +88,7 @@ class TS(basetrans):
)
data = r.json()
return data["translatedText"]
try:
return data["translatedText"]
except:
raise Exception(data)

View File

@ -25,7 +25,7 @@
"rendertext_using": "textbrowser",
"rendertext_using_internal": {
"webview": "yinying",
"textbrowser": "yinying"
"textbrowser": "miaobian1"
},
"rendertext": {
"webview": {
@ -36,9 +36,9 @@
"name": "阴影字体",
"args": {
"fillcolor": "#eeeeee",
"shadowforce": 5,
"shadowR": 0.1,
"shadowR_ex": 3
"shadowforce": 10,
"shadowR": 0.25,
"shadowR_ex": 0
},
"argstype": {
"fillcolor": {
@ -92,8 +92,8 @@
"name": "描边字体",
"args": {
"fillcolor": "#eeeeee",
"width_rate": 0.1,
"width": 3,
"width_rate": 0.3,
"width": 0,
"trace": 0,
"reverse": true
},
@ -158,8 +158,8 @@
"name": "描边字体",
"args": {
"fillcolor": "#eeeeee",
"width_rate": 0.1,
"width": 3,
"width_rate": 0.25,
"width": 0,
"trace": 0,
"reverse": true
},
@ -199,9 +199,9 @@
"name": "阴影字体",
"args": {
"fillcolor": "#eeeeee",
"shadowforce": 5,
"shadowforce": 10,
"shadowR": 1,
"shadowR_ex": 3
"shadowR_ex": 0
},
"argstype": {
"fillcolor": {
@ -1786,6 +1786,12 @@
"color": "#1839f0",
"name": "快译通"
},
"atlas": {
"type": "offline",
"use": false,
"color": "#1839f0",
"name": "Atlas"
},
"sougou2": {
"use": false,
"color": "blue",

View File

@ -46,99 +46,203 @@
]
},
"language_list_show": [
"简体中文",
"日本語",
"繁體中文",
"English",
"Русский язык",
"Español",
"한국어",
"Français",
"Tiếng Việt",
"Türkçe",
"Polski",
"Українська Мова",
"Italiano",
"اللغة العربية",
"ภาษาไทย",
"བོད་སྐད།",
"Deutsch",
"Svenska",
"Nederlands",
"Čeština",
"Português"
[
"简体中文",
"zh"
],
[
"繁體中文",
"cht"
],
[
"English",
"en"
],
[
"Русский язык",
"ru"
],
[
"日本語",
"ja"
],
[
"Español",
"es"
],
[
"한국어",
"ko"
],
[
"Français",
"fr"
],
[
"Tiếng Việt",
"vi"
],
[
"Türkçe",
"tr"
],
[
"Polski",
"pl"
],
[
"Українська Мова",
"uk"
],
[
"Italiano",
"it"
],
[
"اللغة العربية",
"ar"
],
[
"ภาษาไทย",
"th"
],
[
"Deutsch",
"de"
],
[
"Svenska",
"sv"
],
[
"Nederlands",
"nl"
],
[
"Čeština",
"cs"
],
[
"Português",
"pt"
]
],
"language_list_translator": [
"简体中文",
"日语",
"繁体中文",
"英语",
"俄语",
"西班牙语",
"韩语",
"法语",
"越南语",
"土耳其语",
"波兰语",
"乌克兰语",
"意大利语",
"阿拉伯语",
"泰语",
"藏语",
"德语",
"瑞典语",
"荷兰语",
"捷克语",
"葡萄牙语",
"匈牙利语"
],
"language_list_translator_inner": [
"zh",
"ja",
"cht",
"en",
"ru",
"es",
"ko",
"fr",
"vi",
"tr",
"pl",
"uk",
"it",
"ar",
"th",
"bo",
"de",
"sv",
"nl",
"cs",
"pt",
"hu"
],
"language_list_translator_inner_english": [
"Simplified Chinese",
"Japanese",
"Traditional Chinese",
"English",
"Russian",
"Spanish",
"Korean",
"French",
"Vietnamese",
"Turkish",
"Polish",
"Ukrainian",
"Italian",
"Arabic",
"Thai",
"Tibetan",
"German",
"Swedish",
"Dutch",
"Czech",
"Portuguese",
"Hungarian"
"lang_list_all": [
{
"code": "zh",
"zh": "简体中文",
"en": "Simplified Chinese"
},
{
"code": "ja",
"zh": "日语",
"en": "Japanese"
},
{
"code": "cht",
"zh": "繁体中文",
"en": "Traditional Chinese"
},
{
"code": "en",
"zh": "英语",
"en": "English"
},
{
"code": "ru",
"zh": "俄语",
"en": "Russian"
},
{
"code": "es",
"zh": "西班牙语",
"en": "Spanish"
},
{
"code": "ko",
"zh": "韩语",
"en": "Korean"
},
{
"code": "fr",
"zh": "法语",
"en": "French"
},
{
"code": "vi",
"zh": "越南语",
"en": "Vietnamese"
},
{
"code": "tr",
"zh": "土耳其语",
"en": "Turkish"
},
{
"code": "pl",
"zh": "波兰语",
"en": "Polish"
},
{
"code": "uk",
"zh": "乌克兰语",
"en": "Ukrainian"
},
{
"code": "it",
"zh": "意大利语",
"en": "Italian"
},
{
"code": "ar",
"zh": "阿拉伯语",
"en": "Arabic"
},
{
"code": "th",
"zh": "泰语",
"en": "Thai"
},
{
"code": "bo",
"zh": "藏语",
"en": "Tibetan"
},
{
"code": "de",
"zh": "德语",
"en": "German"
},
{
"code": "sv",
"zh": "瑞典语",
"en": "Swedish"
},
{
"code": "nl",
"zh": "荷兰语",
"en": "Dutch"
},
{
"code": "cs",
"zh": "捷克语",
"en": "Czech"
},
{
"code": "pt",
"zh": "葡萄牙语",
"en": "Portuguese"
},
{
"code": "hu",
"zh": "匈牙利语",
"en": "Hungarian"
},
{
"code": "la",
"zh": "拉丁语",
"en": "Latin language"
}
],
"font_type_default": {
"default": [
@ -887,7 +991,7 @@
"link": "{main_server}/Resource/ocr_models/ja.zip"
},
{
"name": "英",
"name": "英",
"link": "{main_server}/Resource/ocr_models/en.zip"
},
{
@ -1141,7 +1245,7 @@
},
{
"name": "Locale_Remulator",
"link": "https://github.com/InWILL/Locale_Remulator/releases/download/v1.5.3-beta.1/Locale_Remulator.1.5.3-beta.1.zip"
"link": "https://github.com/InWILL/Locale_Remulator/releases/download/v1.5.4/Locale_Remulator.1.5.4.zip"
},
{
"name": "Ntleas",

View File

@ -284,7 +284,7 @@
"name": "附带上下文个数",
"type": "intspin",
"min": 0,
"max": 10,
"max": 99999,
"step": 1,
"rank": 4.9
},
@ -363,7 +363,7 @@
"附带上下文个数": {
"type": "intspin",
"min": 0,
"max": 10,
"max": 99999,
"step": 1,
"rank": 4.9
},
@ -457,7 +457,7 @@
"附带上下文个数": {
"type": "intspin",
"min": 0,
"max": 10,
"max": 99999,
"step": 1,
"rank": 4.9
},
@ -558,7 +558,7 @@
"name": "附带上下文个数",
"type": "intspin",
"min": 0,
"max": 10,
"max": 99999,
"step": 1,
"rank": 4.9
},
@ -627,7 +627,7 @@
"附带上下文个数": {
"type": "intspin",
"min": 0,
"max": 10,
"max": 99999,
"step": 1,
"rank": 4.9
},
@ -993,7 +993,7 @@
"context": {
"type": "intspin",
"min": 0,
"max": 10,
"max": 99999,
"step": 1,
"name": "附带上下文个数",
"rank": 4.9
@ -1136,7 +1136,7 @@
"append_context_num": {
"type": "intspin",
"min": 1,
"max": 32,
"max": 99999,
"step": 1,
"refswitch": "use_context",
"name": "利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)"
@ -1260,7 +1260,7 @@
"附带上下文个数": {
"type": "intspin",
"min": 0,
"max": 10,
"max": 99999,
"step": 1,
"rank": 4.9
},

View File

@ -854,5 +854,6 @@
"输出的内容": "المحتوى الناتج",
"选取OCR范围时不透明度": "التعتيم عند اختيار مجموعة التعرف الضوئي على الحروف",
"设为图标": "تعيين رمز",
"还原图标": "استعادة الرموز"
"还原图标": "استعادة الرموز",
"拉丁语": "اللاتينية"
}

View File

@ -854,5 +854,6 @@
"输出的内容": "輸出的內容",
"选取OCR范围时不透明度": "選取OCR範圍時不透明度",
"设为图标": "設為圖標",
"还原图标": "還原圖標"
"还原图标": "還原圖標",
"拉丁语": "拉丁語"
}

View File

@ -854,5 +854,6 @@
"输出的内容": "Výstupní obsah",
"选取OCR范围时不透明度": "Krytí při výběru rozsahu OCR",
"设为图标": "Nastavit jako ikona",
"还原图标": "obnovit ikony"
"还原图标": "obnovit ikony",
"拉丁语": "Latinský jazyk"
}

View File

@ -854,5 +854,6 @@
"输出的内容": "Ausgabeinhalt",
"选取OCR范围时不透明度": "Deckkraft bei Auswahl des OCR-Bereichs",
"设为图标": "Als Symbol festlegen",
"还原图标": "Symbole wiederherstellen"
"还原图标": "Symbole wiederherstellen",
"拉丁语": "Lateinische Sprache"
}

View File

@ -854,5 +854,6 @@
"输出的内容": "Output content",
"选取OCR范围时不透明度": "Opacity when selecting OCR range",
"设为图标": "Set as icon",
"还原图标": "restore icons"
"还原图标": "restore icons",
"拉丁语": "Latin language"
}

View File

@ -854,5 +854,6 @@
"输出的内容": "Contenido exportado",
"选取OCR范围时不透明度": "Opacidad al seleccionar el rango OCR",
"设为图标": "Establecer como icono",
"还原图标": "Restaurar iconos"
"还原图标": "Restaurar iconos",
"拉丁语": "Latín"
}

View File

@ -854,5 +854,6 @@
"输出的内容": "Contenu de la sortie",
"选取OCR范围时不透明度": "Opacité lorsque la plage OCR est sélectionnée",
"设为图标": "Faire une icône",
"还原图标": "Restaurer les icônes"
"还原图标": "Restaurer les icônes",
"拉丁语": "Latin"
}

View File

@ -854,5 +854,6 @@
"输出的内容": "Contenuto di output",
"选取OCR范围时不透明度": "Opacità durante la selezione dell'intervallo OCR",
"设为图标": "Imposta come icona",
"还原图标": "ripristina icone"
"还原图标": "ripristina icone",
"拉丁语": "Lingua latina"
}

View File

@ -854,5 +854,6 @@
"输出的内容": "出力の内容",
"选取OCR范围时不透明度": "OCR範囲選択時の不透明度",
"设为图标": "アイコンとして設定",
"还原图标": "リストアアイコン"
"还原图标": "リストアアイコン",
"拉丁语": "ラテン語"
}

View File

@ -854,5 +854,6 @@
"输出的内容": "내보낸 내용",
"选取OCR范围时不透明度": "OCR 범위 선택 시 불투명도",
"设为图标": "아이콘으로 설정",
"还原图标": "복원 아이콘"
"还原图标": "복원 아이콘",
"拉丁语": "라틴어"
}

View File

@ -854,5 +854,6 @@
"输出的内容": "Uitvoerinhoud",
"选取OCR范围时不透明度": "Opaciteit bij het selecteren van OCR-bereik",
"设为图标": "Als pictogram instellen",
"还原图标": "pictogrammen herstellen"
"还原图标": "pictogrammen herstellen",
"拉丁语": "Latijnse taal"
}

View File

@ -854,5 +854,6 @@
"输出的内容": "Zawartość wyjściowa",
"选取OCR范围时不透明度": "Przezroczystość przy wyborze zakresu OCR",
"设为图标": "Ustaw jako ikonę",
"还原图标": "przywróć ikony"
"还原图标": "przywróć ikony",
"拉丁语": "Język łaciński"
}

View File

@ -854,5 +854,6 @@
"输出的内容": "Conteúdo de saída",
"选取OCR范围时不透明度": "Opacidade ao seleccionar o intervalo OCR",
"设为图标": "Definir como ícone",
"还原图标": "restaurar ícones"
"还原图标": "restaurar ícones",
"拉丁语": "Língua latina"
}

View File

@ -854,5 +854,6 @@
"输出的内容": "Экспорт содержимого",
"选取OCR范围时不透明度": "Непрозрачность выбора диапазона OCR",
"设为图标": "Установить значок",
"还原图标": "Восстановить значок"
"还原图标": "Восстановить значок",
"拉丁语": "Латинский язык"
}

View File

@ -854,5 +854,6 @@
"输出的内容": "Utdatainnehåll",
"选取OCR范围时不透明度": "Opacitet vid val av OCR-område",
"设为图标": "Ange som ikon",
"还原图标": "återställ ikoner"
"还原图标": "återställ ikoner",
"拉丁语": "Latinska språk"
}

View File

@ -854,5 +854,6 @@
"输出的内容": "เนื้อหาที่ส่งออก",
"选取OCR范围时不透明度": "ความทึบเมื่อเลือกช่วง OCR",
"设为图标": "ตั้งค่าเป็นไอคอน",
"还原图标": "เรียกคืนไอคอน"
"还原图标": "เรียกคืนไอคอน",
"拉丁语": "ละติน"
}

View File

@ -854,5 +854,6 @@
"输出的内容": ıkış içeriği",
"选取OCR范围时不透明度": "OCR menzilini seçerken meşgullük",
"设为图标": "İşaretçi olarak ayarlayın",
"还原图标": "İşaretçikleri geri yükleyin"
"还原图标": "İşaretçikleri geri yükleyin",
"拉丁语": "Latin dili"
}

View File

@ -854,5 +854,6 @@
"输出的内容": "Вміст виводу",
"选取OCR范围时不透明度": "Непрозорість під час вибору діапазону OCR",
"设为图标": "Встановити як піктограму",
"还原图标": "відновити піктограми"
"还原图标": "відновити піктограми",
"拉丁语": "Латинська мова"
}

View File

@ -854,5 +854,6 @@
"输出的内容": "Nội dung xuất",
"选取OCR范围时不透明度": "Độ mờ đục khi chọn phạm vi OCR",
"设为图标": "Đặt làm biểu tượng",
"还原图标": "Khôi phục biểu tượng"
"还原图标": "Khôi phục biểu tượng",
"拉丁语": "Tiếng Việt"
}

View File

@ -855,7 +855,5 @@
"选取OCR范围时不透明度": "",
"设为图标": "",
"还原图标": "",
"俺たちに翼はない Prelude": "",
"俺たちに翼はない ―――under the innocent sky.": "",
"俺の名は~美少女と入れ替わったと思ったら巨根の男の娘になってしまった!?~": ""
"拉丁语": ""
}

View File

@ -90,6 +90,8 @@
* [@KirpichKrasniy](https://github.com/KirpichKrasniy)
* [uyjulian/AtlasTranslate](https://github.com/uyjulian/AtlasTranslate)
</details>

View File

@ -97,7 +97,7 @@ LunaHook_latest = dynalink(
"Github/LunaHook/releases/latest/download/Release_English.zip"
)
LocaleRe = "https://github.com/InWILL/Locale_Remulator/releases/download/v1.5.3-beta.1/Locale_Remulator.1.5.3-beta.1.zip"
LocaleRe = "https://github.com/InWILL/Locale_Remulator/releases/download/v1.5.4/Locale_Remulator.1.5.4.zip"
def createPluginDirs():

View File

@ -92,7 +92,8 @@
1. #### <i class="fa fa-volume-off"></i> <i class="btnstatus2 fa fa-volume-up"></i> 游戏静音
当绑定游戏窗口后不只是hook模式ocr或剪贴板模式都可以只要绑定了游戏窗口可以一键对游戏进行静音省去了在系统音量合成器进行游戏静音的麻烦。
1. #### <i class="fa fa-eye"></i> <i class="btnstatus2 fa fa-eye-slash"></i> 显示/隐藏原文
切换是否显示原文的状态,当下一次读取文本时,才真正生效。
切换是否显示原文,会立即生效。
1. #### <i class="fa fa-toggle-on"></i> <i class="btnstatus2 fa fa-toggle-off"></i> 使用/跳过翻译
切换是否使用翻译,系翻译的总开关,关闭后将不会进行任何翻译。
1. #### <i class="fa fa-music"></i> <i class="fa fa-icon fa-rotate-right"></i> 朗读

View File

@ -19,7 +19,7 @@
1. #### 显示/隐藏原文
切换是否显示原文的状态,当下一次读取文本时,才真正生效。
切换是否显示原文,会立即生效。
1. #### 使用/跳过翻译
切换是否使用翻译,系翻译的总开关,关闭后将不会进行任何翻译。

View File

@ -6,7 +6,7 @@
部署方法
1. [部署SakuraLLM到Kaggle/Google Colab](/zh/sakurallmkagglecolab.md)
1. [部署SakuraLLM到Google Colab](/zh/sakurallmcolab.md)
2. 其他部署方法可参考 https://github.com/SakuraLLM/SakuraLLM/wiki

View File

@ -1,4 +1,4 @@
## 部署SakuraLLM到Kaggle/Google Colab
## 部署SakuraLLM到Google Colab
### 1. 设置内网穿透以将请求转发给llama.cpp服务
@ -29,32 +29,10 @@
### 2. 部署到Kaggle/Google Colab
### 2. 部署到Google Colab
<!-- tabs:start -->
### **Kaggle**
1. 注册<a href="https://kaggle.com/" target="_blank">Kaggle</a>,导入<a href="https://kaggle.com/kernels/welcome?src=https://lunatranslator.org/nginxfile/kaggle_sakurallm.ipynb" target="_blank">ipynb脚本</a>
<details>
<summary>2. 选择GPU运行时打开网络连接。首次使用需要验证手机号</summary>
<img src="https://image.lunatranslator.org/zh/sakurallm/kaggle.2.png">
<img src="https://image.lunatranslator.org/zh/sakurallm/kaggle.3.png">
</details>
<details>
<summary>3. 设置ngrok密钥和域名以及使用的模型</summary>
将注册的ngrok的NGROK_TOKEN和NGROK_DOMAIN填入脚本中。<br>
REPO和MODEL是<code>https://huggingface.co/REPO</code>下的MODEL模型文件名
<img src="https://image.lunatranslator.org/zh/sakurallm/kaggle.png">
</details>
<details>
<summary>4. 运行脚本,稍微等待一分钟左右即可</summary>
llama.cpp是已经预先编译好的省去了编译的时间因此主要是下载模型需要花费一点时间。
<img src="https://image.lunatranslator.org/zh/sakurallm/kagglerun.png">
</details>
### **Google Colab**

View File

@ -21,7 +21,7 @@
- [翻译源设置](/zh/guochandamoxing.redirect)
- [如何使用大模型API翻译](/zh/guochandamoxing.md)
- [如何使用大模型离线翻译](/zh/offlinellm.md)
- [如何部署SakuraLLM到Kaggle/Google Colab](/zh/sakurallmkagglecolab.md)
- [如何部署SakuraLLM到Google Colab](/zh/sakurallmcolab.md)
- [如何使用调试浏览器翻译](/zh/tiaoshiliulanqi.md)
- [文本处理&翻译优化](/zh/textprocess.redirect)
- [各种文本处理方法的作用和用法](/zh/textprocess.md)

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 34)
set(VERSION_PATCH 8)
set(VERSION_MINOR 35)
set(VERSION_PATCH 0)
add_library(pch pch.cpp)
target_precompile_headers(pch PUBLIC pch.h)

View File

@ -0,0 +1,601 @@
#include "Atlas.h"
// https://github.com/uyjulian/AtlasTranslate
wchar_t AtlasPath[2 * MAX_PATH];
static int atlasVersion = 0;
int GetAtlasVersion()
{
return atlasVersion;
}
static int atlasTransDirection = 0;
int GetAtlasTransDirection()
{
return atlasTransDirection;
}
// dir is 1 for jap to eng, 2 for eng to jap.
typedef int __cdecl CreateEngineType(int x, int dir, int x3, char *x4);
static CreateEngineType *CreateEngine = 0;
typedef int __cdecl DestroyEngineType();
static DestroyEngineType *DestroyEngine = 0;
typedef int __cdecl TranslatePairType(char *in, char **out, void **dunno, unsigned int *maybeSize);
static TranslatePairType *TranslatePair = 0;
typedef int __cdecl AtlInitEngineDataType(int x1, int x2, int *x3, int x4, int *x5);
static AtlInitEngineDataType *AtlInitEngineData = 0;
// No clue what this does. Doesn't set direction.
typedef int __cdecl SetTransStateType(int dunno);
static SetTransStateType *SetTransState = 0;
static FreeAtlasDataType *FreeAtlasData = 0;
AwuWordDelType *AwuWordDel = 0;
// static TextRuleSet *ruleSet = 0;
// typedef int __cdecl AwuDlgAtlasPopupEnvDetailSetType(void *, char *type, void *x3, char *word);
// AwuDlgAtlasPopupEnvDetailSetType *AwuDlgAtlasPopupEnvDetailSet = 0;
HMODULE atlecont = 0;
HMODULE awdict = 0;
HMODULE awuenv = 0;
int atlasHappy = 0;
void UninitAtlas()
{
atlasTransDirection = 0;
atlasVersion = 0;
if (atlasHappy)
{
DestroyEngine();
atlasHappy = 0;
}
// if (ruleSet)
// {
// delete ruleSet;
// ruleSet = 0;
// }
if (atlecont)
{
FreeLibrary(atlecont);
atlecont = 0;
}
if (awdict)
{
FreeLibrary(awdict);
awdict = 0;
}
if (awuenv)
{
FreeLibrary(awuenv);
awuenv = 0;
}
}
// ATLAS_CAN_MODIFY lets me modify the original string, otherwise
// make and use a copy.
// ATLAS_NO_FREE means to return the atlas results directly
// rather than copy them over to a standard malloc-ed string.
char *AtlasTransSJIS(char *jis, int flags)
{
// Don't bother removing extra bytes, since it doesn't last long.
char *outjis = 0;
void *unsure = 0;
unsigned int maybeSize = 0;
char *temp = jis;
if (!(flags & ATLAS_CAN_MODIFY))
temp = (char *)malloc(1 + strlen(jis));
int p1 = 0;
int p2 = 0;
int lastJis = 1;
while (jis[p1])
{
if (jis[p1] == ' ' || jis[p1] == '\t' || jis[p1] == '\n' || jis[p1] == '\r' ||
(jis[p1] == -127 && jis[p1 + 1] == 64))
{
if (jis[p1] == -127)
p1++;
p1++;
if (!lastJis)
temp[p2++] = ' ';
}
else
{
lastJis = (jis[p1] < 0 && ((unsigned char)jis[p1] != 0x82 || (unsigned char)jis[p1 + 1] >= 0x9E || jis[p1 + 1] < 0x4F));
if (lastJis)
while (p2 > 0 && temp[p2 - 1] == ' ')
p2--;
unsigned char u = jis[p1];
// double-byte JIS.
if ((u >= 0x81 && u <= 0x9F) ||
(u >= 0xE0 && u <= 0xEF))
temp[p2++] = jis[p1++];
temp[p2++] = jis[p1++];
}
}
temp[p2] = 0;
// I completely ignore res. Not sure if it matters.
int res = TranslatePair(temp, &outjis, &unsure, &maybeSize);
if (!(flags & ATLAS_CAN_MODIFY))
free(temp);
if (unsure)
FreeAtlasData(unsure, 0, 0, 0);
if ((flags & ATLAS_NO_FREE))
return outjis;
if (outjis)
{
char *out = strdup(outjis);
FreeAtlasData(outjis, 0, 0, 0);
return out;
}
return 0;
}
wchar_t *AtlasTrans(const wchar_t *text, int len)
{
// return original string if no Japanese characters.
// if (atlasTransDirection == ATLAS_JAP_TO_ENG && !HasJap(text)) return 0;
// Don't bother removing extra bytes, since it doesn't last long.
if (len < 0)
len = (int)wcslen(text);
int len2 = 4 * len + 1;
char *jis = (char *)malloc(len2);
len2 = WideCharToMultiByte(932, 0, text, -1, jis, len2, 0, 0);
char *outjis;
if (!len2 || !(outjis = AtlasTransSJIS(jis, ATLAS_CAN_MODIFY | ATLAS_NO_FREE)))
{
free(jis);
return 0;
}
free(jis);
// Extra is so I can add on punctuation if I want.
len2 = (int)(3 + strlen(outjis));
wchar_t *out = (wchar_t *)malloc(sizeof(wchar_t) * len2);
len2 = (int)MultiByteToWideChar(932, 0, outjis, -1, out, len2);
FreeAtlasData(outjis, 0, 0, 0);
if (len2)
return out;
free(out);
return 0;
}
int LoadAtlasDlls()
{
if (atlecont && awdict && awuenv)
return 1;
wchar_t newPath[MAX_PATH * 2];
for (int i = 0; i < 2; i++)
{
for (int v = 14; v >= 13; v--)
{
if (i == 0)
{
wchar_t temp[MAX_PATH];
wsprintfW(temp, L"Software\\Fujitsu\\ATLAS\\V%i.0\\EJ", v);
HKEY hKey = 0;
if (ERROR_SUCCESS != RegOpenKey(HKEY_CURRENT_USER, temp, &hKey))
continue;
DWORD type;
DWORD size = sizeof(newPath) - 2;
wchar_t *name;
int res = RegQueryValueExW(hKey, L"TRENV EJ", 0, &type, (BYTE *)newPath, &size);
RegCloseKey(hKey);
if (ERROR_SUCCESS != res || type != REG_SZ || !(name = wcsrchr(newPath, '\\')))
continue;
name[1] = 0;
}
#ifndef NO_SHELL32
else
{
if (S_OK != SHGetFolderPathW(0, CSIDL_PROGRAM_FILES, 0, SHGFP_TYPE_CURRENT, newPath))
continue;
wsprintfW(wcschr(newPath, 0), L"\\ATLAS V%i\\", v);
}
#endif
wchar_t *w = wcschr(newPath, 0);
wcscpy(w, L"AtleCont.dll");
atlecont = LoadLibraryEx(newPath, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
wcscpy(w, L"awdict.dll");
awdict = LoadLibraryEx(newPath, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
wcscpy(w, L"awuenv.dll");
awuenv = LoadLibraryEx(newPath, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
if (atlecont && awdict && awuenv)
{
*w = 0;
wcscpy(AtlasPath, newPath);
atlasVersion = v;
return 1;
}
UninitAtlas();
}
}
return 0;
}
int AtlasIsLoaded()
{
return atlasHappy;
}
int InitAtlas(AtlasConfig &cfg, int transDirection)
{
if (atlasHappy)
{
if (transDirection == atlasTransDirection)
return 1;
UninitAtlas();
}
if (!LoadAtlasDlls())
return 0;
if (atlecont && awdict &&
(CreateEngine = (CreateEngineType *)GetProcAddress(atlecont, "CreateEngine")) &&
(DestroyEngine = (DestroyEngineType *)GetProcAddress(atlecont, "DestroyEngine")) &&
(TranslatePair = (TranslatePairType *)GetProcAddress(atlecont, "TranslatePair")) &&
(FreeAtlasData = (FreeAtlasDataType *)GetProcAddress(atlecont, "FreeAtlasData")) &&
(AtlInitEngineData = (AtlInitEngineDataType *)GetProcAddress(atlecont, "AtlInitEngineData")) &&
(SetTransState = (SetTransStateType *)GetProcAddress(atlecont, "SetTransState")) &&
//(AwuDlgAtlasPopupEnvDetailSet = (AwuDlgAtlasPopupEnvDetailSetType*)(awuenv, "AwuDlgAtlasPopupEnvDetailSet")) &&
(AwuWordDel = (AwuWordDelType *)GetProcAddress(awdict, "AwuWordDel")))
{
union
{
char temp[MAX_PATH * 4];
wchar_t path[MAX_PATH * 2];
};
wcscpy(path, cfg.trsPath);
wchar_t *name = wcsrchr(path, '\\');
if (name)
{
name[0] = 0;
name++;
}
else
{
name = cfg.trsPath;
wcscpy(path, L"Rule Sets\\");
}
if (1)
{
if (WideCharToMultiByte(932, 0, cfg.environment, -1, temp, 4 * MAX_PATH, 0, 0))
{
// SetTransState(1);
// Needed? No clue.
static int dunno[1000] = {0};
static int dunno2[1000] = {0};
if (0 == AtlInitEngineData(0, 2, dunno, 0, dunno2) && 1 == CreateEngine(1, transDirection, 0, temp))
{
atlasTransDirection = transDirection;
atlasHappy = 1;
return 1;
//}
}
}
}
}
UninitAtlas();
return 0;
}
// Basically just AtlasThreadProc, with some stuff removed.
wchar_t *TranslateFull(wchar_t *otext, int freeText, int NeedAbort(int line, int lines, void *data), void *data)
{
if (!otext) //|| !ruleSet)
return 0;
if (!otext)
return 0;
int len1 = wcslen(otext);
auto needFree = AtlasTrans(otext, len1);
return needFree;
int memLen = wcslen(otext);
int len = memLen;
int count = 1;
wchar_t *snipped = otext; // ruleSet->ParseText(otext, &len, &count);
wchar_t *text = otext;
if (!freeText)
text = (wchar_t *)malloc(sizeof(wchar_t) * memLen);
text[0] = 0;
len = 0;
int pos = 0;
// Doesn't work, sadly. Looks like atlas isn't threadsafe.
/*
wchar_t **strings = (wchar_t**) malloc(sizeof(wchar_t*) * count);
wchar_t *p = snipped;
for (int i=0; i<count; i++)
{
strings[i] = p;
while (*p) p++;
p++;
while (*p) p++;
p++;
}
int needExit = 0;
#pragma omp parallel for schedule(dynamic,1)
for (int i=0; i<count; i++)
{
if (needExit) continue;
if (NeedAbort && NeedAbort(i, count, data))
{
needExit = 1;
continue;
}
wchar_t *trans = wcschr(strings[i], 0) + 1;
wchar_t *needFree = AtlasTrans(trans, wcslen(trans));
if (needFree)
free(needFree);
}
free(strings);
//*/
for (int i = 0; i < count; i++)
{
if (NeedAbort && NeedAbort(i, count, data))
break;
wchar_t *trans, *prefix;
prefix = snipped + pos;
trans = wcschr(prefix, 0) + 1;
pos = (int)((wcschr(trans, 0) + 1) - snipped);
int oldLen = len;
wchar_t *needFree = 0;
if (trans[0])
{
int len1 = wcslen(trans);
needFree = AtlasTrans(trans, len1);
if (needFree)
{
trans = needFree;
// Copy over ending punctuation if it ATLAS got it wrong.
// Note: Commas currently handled elsewhere.
int len2 = wcslen(needFree);
if (len1 > 0 && len2 > 1)
{
wchar_t e1 = trans[len1 - 1];
wchar_t *e2 = &needFree[len2];
if (e2[-1] == ' ')
e2--;
if (e2[-1] == '.' || e2[-1] == ',' || e2[-1] == '?' || e2[-1] == '!')
e2--;
// desired punctuation.
wchar_t p = 0;
if (e1 == L'')
p = '!';
if (e1 == L'')
p = '!';
if (e1 == L'')
p = '.';
if (p)
{
if (*e2 == L'.' || *e2 == L'?' || *e2 == L'!')
{
// First part of handling for "!?" and shouted questions without '?'.
// second part further down.
if (*e2 == '?')
{
if (e1 == L'')
wcscpy(e2, L"!? ");
}
else if (*e2 == '.')
*e2 = p;
}
else
{
e2[0] = p;
e2[1] = ' ';
e2[2] = 0;
}
}
}
}
len += wcslen(trans);
}
len += wcslen(prefix);
if (len + 20 >= memLen)
{
memLen = len + len / 2 + 1000;
text = (wchar_t *)realloc(text, sizeof(wchar_t) * memLen);
}
if (prefix)
{
if (prefix[0] == ',')
{
if (oldLen && text[oldLen - 1] == ' ')
oldLen--;
if (oldLen && text[oldLen - 1] == '.' || text[oldLen - 1] == ',')
oldLen--;
}
else if (prefix[0] == '.')
{
if (oldLen && text[oldLen - 1] == ' ')
oldLen--;
if (oldLen > 1 && text[oldLen - 1] == '.' && (text[oldLen - 2] == '.' || prefix[0] == '.'))
oldLen--;
// Fix !..., ?..., and ?...?
if (oldLen && (text[oldLen - 1] == '?' || text[oldLen - 1] == '!'))
{
int s = oldLen - 1;
while (s && text[s - 1] == '!' || text[s - 1] == '?')
s--;
int count1 = oldLen - s;
int count2 = 1;
while (prefix[count2] == '.')
count2++;
memmove(text + oldLen + count2 - count1, text + s, (count1 + 1) * sizeof(wchar_t));
memcpy(text + s, prefix, sizeof(wchar_t) * count2);
prefix += count2;
oldLen += count2;
// handle the extra ? in ?...?
if (prefix[0] == text[oldLen - 1])
prefix++;
}
}
else if (prefix[0] == '?' || prefix[0] == '!')
{
if (oldLen && text[oldLen - 1] == ' ')
oldLen--;
if (oldLen > 1 && text[oldLen - 1] == '?')
if (oldLen > 2 && text[oldLen - 2] == '!')
oldLen--;
}
wcscpy(text + oldLen, prefix);
oldLen += wcslen(prefix);
}
if (trans)
{
if (oldLen && (text[oldLen - 1] == ',' || text[oldLen - 1] == '.' || text[oldLen - 1] == '!' || text[oldLen - 1] == '?'))
text[oldLen++] = ' ';
if (oldLen > 1 && (text[oldLen - 2] == '.' || text[oldLen - 2] == '!' || text[oldLen - 2] == '?'))
text[oldLen++] = ' ';
wcscpy(text + oldLen, trans);
oldLen += wcslen(trans);
}
len = oldLen;
if (needFree)
free(needFree);
}
free(snipped);
if (len && text[len - 1] == ' ')
text[len - 1] = 0;
return text;
}
char *TranslateFull(char *otext, int freeText, int NeedAbort(int line, int lines, void *data), void *data)
{
int len = -1;
auto ws = StringToWideString(otext, 932);
if (!ws.size())
return 0;
wchar_t *outw = TranslateFull(ws.data(), freeText, NeedAbort, data);
if (!outw)
return 0;
len = -1;
auto s = WideStringToString(outw, 932);
char *out = new char[s.size() + 1];
strcpy(out, s.c_str());
free(outw);
return out;
}
static wchar_t *logFile = 0;
void SetLogFile(wchar_t *file)
{
logFile = file;
}
wchar_t *TranslateFullLog(wchar_t *otext)
{
if (logFile && logFile[0])
{
HANDLE hMutex = CreateMutex(0, 0, L"TRAG Logging Super Mutext +10 from Outer Space");
DWORD res;
if (hMutex)
res = WaitForSingleObject(hMutex, 2000);
HANDLE hFile = CreateFile(logFile, GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_ALWAYS, 0, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
DWORD junk;
if (GetLastError() == ERROR_ALREADY_EXISTS)
SetFilePointer(hFile, 0, 0, FILE_END);
else
{
wchar_t bom = 0xFEFF;
WriteFile(hFile, &bom, sizeof(wchar_t), &junk, 0);
}
WriteFile(hFile, otext, sizeof(wchar_t) * wcslen(otext), &junk, 0);
WriteFile(hFile, L"\r\n", sizeof(wchar_t) * 2, &junk, 0);
CloseHandle(hFile);
}
if (hMutex)
{
// Prolly not needed.
if (WAIT_OBJECT_0 == res)
ReleaseMutex(hMutex);
CloseHandle(hMutex);
}
}
return TranslateFull(otext);
}
struct AtlasConfig atlcfg;
HANDLE mutex = NULL;
int atlaswmain(int argc, wchar_t *argv[])
{
HANDLE hPipe = CreateNamedPipe(argv[1], PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 65535, 65535, NMPWAIT_WAIT_FOREVER, 0);
SetEvent(CreateEvent(&allAccess, FALSE, FALSE, argv[2]));
if (ConnectNamedPipe(hPipe, NULL) != NULL)
{
DWORD len = 0;
}
while (true)
{
wchar_t src[4096] = {0};
DWORD _;
if (!ReadFile(hPipe, src, 4096 * 2, &_, NULL))
break;
if (!mutex)
{
mutex = CreateMutex(NULL, FALSE, NULL);
if (!mutex)
{
return false;
}
}
bool waitingForMutex = true;
while (waitingForMutex)
{
switch (WaitForSingleObject(mutex, INFINITE))
{
case WAIT_OBJECT_0:
{
waitingForMutex = false;
break;
}
case WAIT_ABANDONED:
{
return false;
}
default:
{
}
}
}
if (!AtlasIsLoaded())
{
// atlcfg.flags = ~BREAK_ON_SINGLE_LINE_BREAKS;
wcscpy(atlcfg.environment, L"Entertainment");
wcscpy(atlcfg.trsPath, L"");
InitAtlas(atlcfg, ATLAS_JAP_TO_ENG);
if (!AtlasIsLoaded())
{
ReleaseMutex(mutex);
auto text = L"Atlas Load Failed";
WriteFile(hPipe, text, wcslen(text) * 2, &_, NULL);
return false;
}
}
wchar_t *text = TranslateFull(src, 0, NULL, NULL);
WriteFile(hPipe, text, wcslen(text) * 2, &_, NULL);
free(text);
ReleaseMutex(mutex);
}
return 0;
}

View File

@ -0,0 +1,49 @@
#pragma once
#define ATLAS_JAP_TO_ENG 1
#define ATLAS_ENG_TO_JAP 2
// returns 0 if not initialized.
int GetAtlasTransDirection();
// Keep internal copy of flags and loaded rule set,
// which I cleanup on uninit.
struct AtlasConfig
{
unsigned int flags;
wchar_t environment[MAX_PATH];
wchar_t trsPath[MAX_PATH];
};
int InitAtlas(AtlasConfig &cfg, int transDirection);
void UninitAtlas();
int GetAtlasVersion();
typedef int __cdecl FreeAtlasDataType(void *mem, void *noSureHowManyArgs, void *, void *);
// extern FreeAtlasDataType *FreeAtlasData;
// Opens up dictionary type. Think word is what word to open it at, but the "Del" makes me wary.
typedef int __cdecl AwuWordDelType(int x1, char *type, int x3, char *word);
extern AwuWordDelType *AwuWordDel;
#define ATLAS_CAN_MODIFY 1
#define ATLAS_NO_FREE 2
// canModify means don't need to duplicate jis input string.
char *AtlasTransSJIS(char *jis, int flags = 0);
wchar_t *AtlasTrans(const wchar_t *jap, int len = -1);
extern wchar_t AtlasPath[2 * MAX_PATH];
int LoadAtlasDlls();
wchar_t *TranslateFull(wchar_t *otext, int freeText = 0, int NeedAbort(int line, int lines, void *data) = 0, void *data = 0);
char *TranslateFull(char *otext, int freeText = 0, int NeedAbort(int line, int lines, void *data) = 0, void *data = 0);
int AtlasIsLoaded();
// dirty hack
void SetLogFile(wchar_t *file);
wchar_t *TranslateFullLog(wchar_t *otext);
/*
wchar_t path[MAX_PATH];
GetCurrentDirectory(MAX_PATH, path);
delete LoadRuleSet(path, L"default.trs");
//*/

View File

@ -20,7 +20,7 @@ if(${CMAKE_SIZEOF_VOID_P} EQUAL 8)
set_target_properties(shareddllproxy PROPERTIES OUTPUT_NAME "shareddllproxy64")
else()
add_subdirectory(voiceroid2)
add_library(x86lib eztrans.cpp dreye.cpp jbj7.cpp kingsoft.cpp le.cpp neospeech.cpp ../implsapi.cpp LR.cpp)
add_library(x86lib Atlas.cpp eztrans.cpp dreye.cpp jbj7.cpp kingsoft.cpp le.cpp neospeech.cpp ../implsapi.cpp LR.cpp)
target_precompile_headers(voiceroid2 REUSE_FROM pch)
target_precompile_headers(x86lib REUSE_FROM pch)
target_link_libraries(shareddllproxy Mfplat mfuuid x86lib voiceroid2 ${Detours})

View File

@ -15,6 +15,7 @@ int lewmain(int argc, wchar_t *argv[]);
int neospeech(int argc, wchar_t *argv[]);
int neospeechlist(int argc, wchar_t *argv[]);
int eztrans(int argc, wchar_t *argv[]);
int atlaswmain(int argc, wchar_t *argv[]);
#else
#endif // !_WIN64
@ -75,6 +76,7 @@ int wmain(int argc, wchar_t *argv[])
{L"neospeech", neospeech},
{L"neospeechlist", neospeechlist},
{L"eztrans", eztrans},
{L"atlaswmain", atlaswmain},
#else
#endif // !_WIN64