Merge branch 'master' into devtools_papago_translate
This commit is contained in:
commit
918c877e04
@ -1,11 +1,12 @@
|
|||||||
include(QtUtils)
|
include(QtUtils)
|
||||||
msvc_registry_search()
|
msvc_registry_search()
|
||||||
find_qt5(Core Widgets)
|
find_qt5(Core Widgets WinExtras)
|
||||||
|
|
||||||
add_executable(Textractor WIN32
|
add_executable(Textractor WIN32
|
||||||
main.cpp
|
main.cpp
|
||||||
mainwindow.cpp
|
mainwindow.cpp
|
||||||
extenwindow.cpp
|
extenwindow.cpp
|
||||||
|
attachprocessdialog.cpp
|
||||||
host/exception.cpp
|
host/exception.cpp
|
||||||
host/host.cpp
|
host/host.cpp
|
||||||
host/textthread.cpp
|
host/textthread.cpp
|
||||||
@ -14,7 +15,7 @@ add_executable(Textractor WIN32
|
|||||||
Textractor.ico
|
Textractor.ico
|
||||||
)
|
)
|
||||||
target_precompile_headers(Textractor REUSE_FROM pch)
|
target_precompile_headers(Textractor REUSE_FROM pch)
|
||||||
target_link_libraries(Textractor Qt5::Widgets shell32 winhttp)
|
target_link_libraries(Textractor Qt5::Widgets Qt5::WinExtras shell32 winhttp)
|
||||||
|
|
||||||
if (NOT EXISTS ${CMAKE_FINAL_OUTPUT_DIRECTORY}/Qt5Core.dll AND NOT EXISTS ${CMAKE_FINAL_OUTPUT_DIRECTORY}/Qt5Cored.dll)
|
if (NOT EXISTS ${CMAKE_FINAL_OUTPUT_DIRECTORY}/Qt5Core.dll AND NOT EXISTS ${CMAKE_FINAL_OUTPUT_DIRECTORY}/Qt5Cored.dll)
|
||||||
add_custom_command(TARGET Textractor
|
add_custom_command(TARGET Textractor
|
||||||
|
48
GUI/attachprocessdialog.cpp
Normal file
48
GUI/attachprocessdialog.cpp
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#include "attachprocessdialog.h"
|
||||||
|
#include <QtWinExtras/QtWin>
|
||||||
|
|
||||||
|
extern const char* SELECT_PROCESS;
|
||||||
|
extern const char* ATTACH_INFO;
|
||||||
|
|
||||||
|
AttachProcessDialog::AttachProcessDialog(QWidget *parent, std::vector<std::pair<QString, HICON>> processIcons) :
|
||||||
|
QDialog(parent, Qt::WindowCloseButtonHint),
|
||||||
|
model(this)
|
||||||
|
{
|
||||||
|
ui.setupUi(this);
|
||||||
|
setWindowTitle(SELECT_PROCESS);
|
||||||
|
ui.label->setText(ATTACH_INFO);
|
||||||
|
ui.processIdEdit->setValidator(new QIntValidator(0, INT_MAX, this));
|
||||||
|
ui.processList->setModel(&model);
|
||||||
|
|
||||||
|
QPixmap transparent(100, 100);
|
||||||
|
transparent.fill(QColor::fromRgba(0));
|
||||||
|
for (const auto& [process, icon] : processIcons)
|
||||||
|
{
|
||||||
|
auto item = new QStandardItem(icon ? QIcon(QtWin::fromHICON(icon)) : transparent, process);
|
||||||
|
item->setEditable(false);
|
||||||
|
model.appendRow(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
connect(ui.buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||||
|
connect(ui.buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||||
|
connect(ui.processList, &QListView::clicked, [this](QModelIndex index)
|
||||||
|
{
|
||||||
|
selectedProcess = model.item(index.row())->text();
|
||||||
|
});
|
||||||
|
connect(ui.processList, &QListView::doubleClicked, [this](QModelIndex index)
|
||||||
|
{
|
||||||
|
selectedProcess = model.item(index.row())->text();
|
||||||
|
accept();
|
||||||
|
});
|
||||||
|
connect(ui.processIdEdit, &QLineEdit::returnPressed, [this]
|
||||||
|
{
|
||||||
|
selectedProcess = ui.processIdEdit->text();
|
||||||
|
accept();
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QString AttachProcessDialog::SelectedProcess()
|
||||||
|
{
|
||||||
|
return selectedProcess.isEmpty() ? ui.processIdEdit->text() : selectedProcess;
|
||||||
|
}
|
17
GUI/attachprocessdialog.h
Normal file
17
GUI/attachprocessdialog.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "qtcommon.h"
|
||||||
|
#include "ui_attachprocessdialog.h"
|
||||||
|
#include <QStandardItemModel>
|
||||||
|
|
||||||
|
class AttachProcessDialog : public QDialog
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit AttachProcessDialog(QWidget *parent, std::vector<std::pair<QString, HICON>> processIcons);
|
||||||
|
QString SelectedProcess();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::AttachProcessDialog ui;
|
||||||
|
QStandardItemModel model;
|
||||||
|
QString selectedProcess;
|
||||||
|
};
|
41
GUI/attachprocessdialog.ui
Normal file
41
GUI/attachprocessdialog.ui
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>AttachProcessDialog</class>
|
||||||
|
<widget class="QWidget" name="AttachProcessDialog">
|
||||||
|
<property name="windowModality">
|
||||||
|
<enum>Qt::WindowModal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>800</width>
|
||||||
|
<height>400</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="processIdEdit">
|
||||||
|
<property name="placeholderText">
|
||||||
|
<string>Process id</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QListView" name="processList"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
@ -2,11 +2,6 @@
|
|||||||
|
|
||||||
#include "qtcommon.h"
|
#include "qtcommon.h"
|
||||||
|
|
||||||
namespace Ui
|
|
||||||
{
|
|
||||||
class ExtenWindow;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct InfoForExtension
|
struct InfoForExtension
|
||||||
{
|
{
|
||||||
const char* name;
|
const char* name;
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include "extenwindow.h"
|
#include "extenwindow.h"
|
||||||
#include "host/host.h"
|
#include "host/host.h"
|
||||||
#include "host/hookcode.h"
|
#include "host/hookcode.h"
|
||||||
|
#include "attachprocessdialog.h"
|
||||||
#include <shellapi.h>
|
#include <shellapi.h>
|
||||||
#include <process.h>
|
#include <process.h>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
@ -14,6 +15,7 @@
|
|||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QFontDialog>
|
#include <QFontDialog>
|
||||||
|
#include <QHash>
|
||||||
|
|
||||||
extern const char* ATTACH;
|
extern const char* ATTACH;
|
||||||
extern const char* LAUNCH;
|
extern const char* LAUNCH;
|
||||||
@ -28,7 +30,6 @@ extern const char* SETTINGS;
|
|||||||
extern const char* EXTENSIONS;
|
extern const char* EXTENSIONS;
|
||||||
extern const char* FONT;
|
extern const char* FONT;
|
||||||
extern const char* SELECT_PROCESS;
|
extern const char* SELECT_PROCESS;
|
||||||
extern const char* ATTACH_INFO;
|
|
||||||
extern const char* SELECT_PROCESS_INFO;
|
extern const char* SELECT_PROCESS_INFO;
|
||||||
extern const char* FROM_COMPUTER;
|
extern const char* FROM_COMPUTER;
|
||||||
extern const char* PROCESSES;
|
extern const char* PROCESSES;
|
||||||
@ -153,16 +154,31 @@ namespace
|
|||||||
|
|
||||||
void AttachProcess()
|
void AttachProcess()
|
||||||
{
|
{
|
||||||
QMultiHash<QString, DWORD> allProcesses;
|
QMultiHash<QString, DWORD> processesMap;
|
||||||
|
std::vector<std::pair<QString, HICON>> processIcons;
|
||||||
for (auto [processId, processName] : GetAllProcesses())
|
for (auto [processId, processName] : GetAllProcesses())
|
||||||
|
{
|
||||||
if (processName && (showSystemProcesses || processName->find(L":\\Windows\\") == std::string::npos))
|
if (processName && (showSystemProcesses || processName->find(L":\\Windows\\") == std::string::npos))
|
||||||
allProcesses.insert(QFileInfo(S(processName.value())).fileName(), processId);
|
{
|
||||||
|
QString fileName = QFileInfo(S(processName.value())).fileName();
|
||||||
|
if (!processesMap.contains(fileName))
|
||||||
|
{
|
||||||
|
HICON bigIcon, smallIcon;
|
||||||
|
ExtractIconExW(processName->c_str(), 0, &bigIcon, &smallIcon, 1);
|
||||||
|
processIcons.push_back({ fileName, bigIcon ? bigIcon : smallIcon });
|
||||||
|
}
|
||||||
|
processesMap.insert(fileName, processId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::sort(processIcons.begin(), processIcons.end());
|
||||||
|
|
||||||
QStringList processList(allProcesses.uniqueKeys());
|
AttachProcessDialog attachProcessDialog(This, processIcons);
|
||||||
processList.sort(Qt::CaseInsensitive);
|
if (attachProcessDialog.exec())
|
||||||
if (QString process = QInputDialog::getItem(This, SELECT_PROCESS, ATTACH_INFO, processList, 0, true, &ok, Qt::WindowCloseButtonHint); ok)
|
{
|
||||||
if (process.toInt(nullptr, 0)) Host::InjectProcess(process.toInt(nullptr, 0));
|
QString process = attachProcessDialog.SelectedProcess();
|
||||||
else for (auto processId : allProcesses.values(process)) Host::InjectProcess(processId);
|
if (int processId = process.toInt(nullptr, 0)) Host::InjectProcess(processId);
|
||||||
|
else for (int processId : processesMap.values(process)) Host::InjectProcess(processId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LaunchProcess()
|
void LaunchProcess()
|
||||||
|
@ -10,9 +10,9 @@ Watch the [tutorial video](https://tinyurl.com/textractor-tutorial) for a quick
|
|||||||
## Download
|
## Download
|
||||||
|
|
||||||
Official stable releases of Textractor can be found [here](https://github.com/Artikash/Textractor/releases).<br>
|
Official stable releases of Textractor can be found [here](https://github.com/Artikash/Textractor/releases).<br>
|
||||||
Experimental builds of Textractor from the latest source can be found [here](https://ci.appveyor.com/project/Artikash/textractor/history) (in the 'Artifacts' section of a job).<br>
|
|
||||||
The last release of ITHVNR can be found [here](https://drive.google.com/open?id=13aHF4uIXWn-3YML_k2YCDWhtGgn5-tnO).<br>
|
The last release of ITHVNR can be found [here](https://drive.google.com/open?id=13aHF4uIXWn-3YML_k2YCDWhtGgn5-tnO).<br>
|
||||||
Try running vcredist if you get an error when starting Textractor.
|
Experimental builds of Textractor (with debug info) from the latest source can be found [here](https://ci.appveyor.com/project/Artikash/textractor/history) in the 'Artifacts' section of each job.<br>
|
||||||
|
Try running vcredist if you get an error when starting Textractor or if nothing happens when you try attaching to a game.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
|
@ -46,6 +46,7 @@ foreach ($language in @{
|
|||||||
"DeepL Translate",
|
"DeepL Translate",
|
||||||
"DevTools DeepL Translate",
|
"DevTools DeepL Translate",
|
||||||
"DevTools Papago Translate",
|
"DevTools Papago Translate",
|
||||||
|
"DevTools Systran Translate",
|
||||||
"Extra Newlines",
|
"Extra Newlines",
|
||||||
"Extra Window",
|
"Extra Window",
|
||||||
"Google Translate",
|
"Google Translate",
|
||||||
@ -66,7 +67,6 @@ foreach ($language in @{
|
|||||||
&"C:\Program Files (x86)\Windows Kits\10\App Certification Kit\signtool.exe" sign /a /v /t "http://timestamp.digicert.com" /fd SHA256 @(dir "$folder\**\*");
|
&"C:\Program Files (x86)\Windows Kits\10\App Certification Kit\signtool.exe" sign /a /v /t "http://timestamp.digicert.com" /fd SHA256 @(dir "$folder\**\*");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
rm -Force -Recurse -Verbose "Runtime";
|
rm -Force -Recurse -Verbose "Runtime";
|
||||||
mkdir -Force -Verbose "Runtime";
|
mkdir -Force -Verbose "Runtime";
|
||||||
foreach ($arch in @("x86", "x64"))
|
foreach ($arch in @("x86", "x64"))
|
||||||
@ -79,6 +79,7 @@ foreach ($arch in @("x86", "x64"))
|
|||||||
"Qt5Gui.dll",
|
"Qt5Gui.dll",
|
||||||
"Qt5Network.dll",
|
"Qt5Network.dll",
|
||||||
"Qt5WebSockets.dll",
|
"Qt5WebSockets.dll",
|
||||||
|
"Qt5WinExtras.dll"
|
||||||
"Qt5Widgets.dll",
|
"Qt5Widgets.dll",
|
||||||
"platforms",
|
"platforms",
|
||||||
"styles"
|
"styles"
|
||||||
|
@ -8,6 +8,7 @@ add_library(Copy\ to\ Clipboard MODULE copyclipboard.cpp extensionimpl.cpp)
|
|||||||
add_library(DeepL\ Translate MODULE deepltranslate.cpp translatewrapper.cpp network.cpp extensionimpl.cpp)
|
add_library(DeepL\ Translate MODULE deepltranslate.cpp translatewrapper.cpp network.cpp extensionimpl.cpp)
|
||||||
add_library(DevTools\ DeepL\ Translate MODULE devtoolsdeepltranslate.cpp devtools.cpp translatewrapper.cpp network.cpp extensionimpl.cpp)
|
add_library(DevTools\ DeepL\ Translate MODULE devtoolsdeepltranslate.cpp devtools.cpp translatewrapper.cpp network.cpp extensionimpl.cpp)
|
||||||
add_library(DevTools\ Papago\ Translate MODULE devtoolspapagotranslate.cpp devtools.cpp translatewrapper.cpp network.cpp extensionimpl.cpp)
|
add_library(DevTools\ Papago\ Translate MODULE devtoolspapagotranslate.cpp devtools.cpp translatewrapper.cpp network.cpp extensionimpl.cpp)
|
||||||
|
add_library(DevTools\ Systran\ Translate MODULE devtoolssystrantranslate.cpp devtools.cpp translatewrapper.cpp network.cpp extensionimpl.cpp)
|
||||||
add_library(Extra\ Newlines MODULE extranewlines.cpp extensionimpl.cpp)
|
add_library(Extra\ Newlines MODULE extranewlines.cpp extensionimpl.cpp)
|
||||||
add_library(Extra\ Window MODULE extrawindow.cpp extensionimpl.cpp)
|
add_library(Extra\ Window MODULE extrawindow.cpp extensionimpl.cpp)
|
||||||
add_library(Google\ Translate MODULE googletranslate.cpp translatewrapper.cpp network.cpp extensionimpl.cpp)
|
add_library(Google\ Translate MODULE googletranslate.cpp translatewrapper.cpp network.cpp extensionimpl.cpp)
|
||||||
@ -26,6 +27,7 @@ target_precompile_headers(Copy\ to\ Clipboard REUSE_FROM pch)
|
|||||||
target_precompile_headers(DeepL\ Translate REUSE_FROM pch)
|
target_precompile_headers(DeepL\ Translate REUSE_FROM pch)
|
||||||
target_precompile_headers(DevTools\ DeepL\ Translate REUSE_FROM pch)
|
target_precompile_headers(DevTools\ DeepL\ Translate REUSE_FROM pch)
|
||||||
target_precompile_headers(DevTools\ Papago\ Translate REUSE_FROM pch)
|
target_precompile_headers(DevTools\ Papago\ Translate REUSE_FROM pch)
|
||||||
|
target_precompile_headers(DevTools\ Systran\ Translate REUSE_FROM pch)
|
||||||
target_precompile_headers(Extra\ Newlines REUSE_FROM pch)
|
target_precompile_headers(Extra\ Newlines REUSE_FROM pch)
|
||||||
target_precompile_headers(Extra\ Window REUSE_FROM pch)
|
target_precompile_headers(Extra\ Window REUSE_FROM pch)
|
||||||
target_precompile_headers(Google\ Translate REUSE_FROM pch)
|
target_precompile_headers(Google\ Translate REUSE_FROM pch)
|
||||||
@ -43,6 +45,7 @@ target_link_libraries(Bing\ Translate winhttp Qt5::Widgets)
|
|||||||
target_link_libraries(DeepL\ Translate winhttp Qt5::Widgets)
|
target_link_libraries(DeepL\ Translate winhttp Qt5::Widgets)
|
||||||
target_link_libraries(DevTools\ DeepL\ Translate shell32 winhttp Qt5::Widgets Qt5::WebSockets)
|
target_link_libraries(DevTools\ DeepL\ Translate shell32 winhttp Qt5::Widgets Qt5::WebSockets)
|
||||||
target_link_libraries(DevTools\ Papago\ Translate shell32 winhttp Qt5::Widgets Qt5::WebSockets)
|
target_link_libraries(DevTools\ Papago\ Translate shell32 winhttp Qt5::Widgets Qt5::WebSockets)
|
||||||
|
target_link_libraries(DevTools\ Systran\ Translate shell32 winhttp Qt5::Widgets Qt5::WebSockets)
|
||||||
target_link_libraries(Extra\ Window Qt5::Widgets)
|
target_link_libraries(Extra\ Window Qt5::Widgets)
|
||||||
target_link_libraries(Google\ Translate winhttp Qt5::Widgets)
|
target_link_libraries(Google\ Translate winhttp Qt5::Widgets)
|
||||||
target_link_libraries(Lua lua53 Qt5::Widgets)
|
target_link_libraries(Lua lua53 Qt5::Widgets)
|
||||||
@ -59,10 +62,4 @@ if (NOT EXISTS ${CMAKE_FINAL_OUTPUT_DIRECTORY}/Qt5WebSockets.dll AND NOT EXISTS
|
|||||||
COMMAND set PATH=%PATH%$<SEMICOLON>${qt5_install_prefix}/bin
|
COMMAND set PATH=%PATH%$<SEMICOLON>${qt5_install_prefix}/bin
|
||||||
COMMAND Qt5::windeployqt --dir ${CMAKE_FINAL_OUTPUT_DIRECTORY} "${CMAKE_FINAL_OUTPUT_DIRECTORY}/DevTools\ DeepL\ Translate.dll"
|
COMMAND Qt5::windeployqt --dir ${CMAKE_FINAL_OUTPUT_DIRECTORY} "${CMAKE_FINAL_OUTPUT_DIRECTORY}/DevTools\ DeepL\ Translate.dll"
|
||||||
)
|
)
|
||||||
add_custom_command(TARGET DevTools\ Papago\ Translate
|
|
||||||
POST_BUILD
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E remove_directory "${CMAKE_CURRENT_BINARY_DIR}/windeployqt"
|
|
||||||
COMMAND set PATH=%PATH%$<SEMICOLON>${qt5_install_prefix}/bin
|
|
||||||
COMMAND Qt5::windeployqt --dir ${CMAKE_FINAL_OUTPUT_DIRECTORY} "${CMAKE_FINAL_OUTPUT_DIRECTORY}/DevTools\ Papago\ Translate.dll"
|
|
||||||
)
|
|
||||||
endif()
|
endif()
|
||||||
|
63
extensions/devtoolssystrantranslate.cpp
Normal file
63
extensions/devtoolssystrantranslate.cpp
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#include "qtcommon.h"
|
||||||
|
#include "devtools.h"
|
||||||
|
|
||||||
|
extern const wchar_t* ERROR_START_CHROME;
|
||||||
|
extern const wchar_t* TRANSLATION_ERROR;
|
||||||
|
|
||||||
|
extern Synchronized<std::wstring> translateTo, translateFrom;
|
||||||
|
extern QFormLayout* display;
|
||||||
|
extern Settings settings;
|
||||||
|
|
||||||
|
const char* TRANSLATION_PROVIDER = "DevTools Systran Translate";
|
||||||
|
const char* GET_API_KEY_FROM = nullptr;
|
||||||
|
bool translateSelectedOnly = true, rateLimitAll = false, rateLimitSelected = false, useCache = true, useFilter = true;
|
||||||
|
int tokenCount = 30, tokenRestoreDelay = 60000, maxSentenceSize = 2500;
|
||||||
|
|
||||||
|
QStringList languages
|
||||||
|
{
|
||||||
|
"Chinese: zh",
|
||||||
|
"Chinese (traditional): zt",
|
||||||
|
"English: en",
|
||||||
|
"French: fr",
|
||||||
|
"German: de",
|
||||||
|
"Italian: it",
|
||||||
|
"Japanese: ja",
|
||||||
|
"Korean: ko",
|
||||||
|
"Portuguese: pt",
|
||||||
|
"Spanish: es",
|
||||||
|
"Thai: th",
|
||||||
|
};
|
||||||
|
std::wstring autoDetectLanguage = L"auto";
|
||||||
|
|
||||||
|
BOOL WINAPI DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
|
||||||
|
{
|
||||||
|
switch (ul_reason_for_call)
|
||||||
|
{
|
||||||
|
case DLL_PROCESS_ATTACH:
|
||||||
|
{
|
||||||
|
DevTools::Start();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DLL_PROCESS_DETACH:
|
||||||
|
{
|
||||||
|
DevTools::Close();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<bool, std::wstring> Translate(const std::wstring& text)
|
||||||
|
{
|
||||||
|
if (!DevTools::Connected()) return { false, FormatString(L"%s: %s", TRANSLATION_ERROR, ERROR_START_CHROME) };
|
||||||
|
// DevTools can't handle concurrent translations yet
|
||||||
|
static std::mutex translationMutex;
|
||||||
|
std::scoped_lock lock(translationMutex);
|
||||||
|
|
||||||
|
DevTools::SendRequest("Page.navigate", FormatString(LR"({"url":"https://translate.systran.net/?&source=%s&target=%s&input=%s"})", translateFrom.Copy(), translateTo.Copy(), Escape(text)));
|
||||||
|
for (int retry = 0; ++retry < 100; Sleep(100))
|
||||||
|
if (auto translation = Copy(DevTools::SendRequest("Runtime.evaluate",
|
||||||
|
LR"({"expression":"document.querySelector('#outputEditor').textContent.trim() ","returnByValue":true})"
|
||||||
|
)[L"result"][L"value"].String())) if (!translation->empty()) return { true, translation.value() };
|
||||||
|
return { false, TRANSLATION_ERROR };
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user