forked from Public-Mirror/Textractor
fix localization bug, add opption to select language translating from, and add error message to devtools deepl
This commit is contained in:
parent
084f26a72d
commit
e00b831e3d
@ -1,7 +1,6 @@
|
||||
#include "mainwindow.h"
|
||||
#include "module.h"
|
||||
#include <winhttp.h>
|
||||
#include <QApplication>
|
||||
|
||||
extern const wchar_t* UPDATE_AVAILABLE;
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
#include "network.h"
|
||||
#include <QStringList>
|
||||
#include "qtcommon.h"
|
||||
#include "network.h"
|
||||
|
||||
extern const wchar_t* TRANSLATION_ERROR;
|
||||
|
||||
extern Synchronized<std::wstring> translateTo, authKey;
|
||||
extern Synchronized<std::wstring> translateTo, translateFrom, authKey;
|
||||
|
||||
const char* TRANSLATION_PROVIDER = "Bing Translate";
|
||||
const char* GET_API_KEY_FROM = "https://www.microsoft.com/en-us/translator/business/trial/#get-started";
|
||||
@ -78,6 +78,7 @@ QStringList languages
|
||||
"Welsh: cy",
|
||||
"Yucatec Maya: yua"
|
||||
};
|
||||
std::wstring autoDetectLanguage = L"auto-detect";
|
||||
|
||||
bool translateSelectedOnly = false, rateLimitAll = true, rateLimitSelected = false, useCache = true;
|
||||
int tokenCount = 30, tokenRestoreDelay = 60000, maxSentenceSize = 1000;
|
||||
@ -85,23 +86,26 @@ int tokenCount = 30, tokenRestoreDelay = 60000, maxSentenceSize = 1000;
|
||||
std::pair<bool, std::wstring> Translate(const std::wstring& text)
|
||||
{
|
||||
if (!authKey->empty())
|
||||
{
|
||||
std::wstring translateFromComponent = translateFrom.Copy() == autoDetectLanguage ? L"" : L"&from=" + translateFrom.Copy();
|
||||
if (HttpRequest httpRequest{
|
||||
L"Mozilla/5.0 Textractor",
|
||||
L"api.cognitive.microsofttranslator.com",
|
||||
L"POST",
|
||||
FormatString(L"/translate?api-version=3.0&to=%s", translateTo.Copy()).c_str(),
|
||||
FormatString(L"/translate?api-version=3.0&to=%s%s", translateTo.Copy(), translateFromComponent).c_str(),
|
||||
FormatString(R"([{"text":"%s"}])", JSON::Escape(WideStringToString(text))),
|
||||
FormatString(L"Content-Type: application/json; charset=UTF-8\r\nOcp-Apim-Subscription-Key:%s", authKey.Copy()).c_str()
|
||||
})
|
||||
if (auto translation = Copy(JSON::Parse(httpRequest.response)[0][L"translations"][0][L"text"].String())) return { true, translation.value() };
|
||||
else return { false, FormatString(L"%s: %s", TRANSLATION_ERROR, httpRequest.response) };
|
||||
else return { false, FormatString(L"%s (code=%u)", TRANSLATION_ERROR, httpRequest.errorCode) };
|
||||
}
|
||||
|
||||
if (HttpRequest httpRequest{
|
||||
L"Mozilla/5.0 Textractor",
|
||||
L"www.bing.com",
|
||||
L"POST",
|
||||
FormatString(L"/ttranslatev3?fromLang=auto-detect&to=%s&text=%s", translateTo.Copy(), Escape(text)).c_str()
|
||||
FormatString(L"/ttranslatev3?fromLang=%s&to=%s&text=%s", translateFrom.Copy(), translateTo.Copy(), Escape(text)).c_str()
|
||||
})
|
||||
if (auto translation = Copy(JSON::Parse(httpRequest.response)[0][L"translations"][0][L"text"].String())) return { true, translation.value() };
|
||||
else return { false, FormatString(L"%s: %s", TRANSLATION_ERROR, httpRequest.response) };
|
||||
|
@ -5,7 +5,7 @@
|
||||
extern const wchar_t* TRANSLATION_ERROR;
|
||||
extern const char* USE_PREV_SENTENCE_CONTEXT;
|
||||
|
||||
extern Synchronized<std::wstring> translateTo, authKey;
|
||||
extern Synchronized<std::wstring> translateTo, translateFrom, authKey;
|
||||
|
||||
const char* TRANSLATION_PROVIDER = "DeepL Translate";
|
||||
const char* GET_API_KEY_FROM = "https://www.deepl.com/pro.html";
|
||||
@ -23,6 +23,7 @@ QStringList languages
|
||||
"Russian: RU",
|
||||
"Spanish: ES",
|
||||
};
|
||||
std::wstring autoDetectLanguage = L"auto";
|
||||
|
||||
bool translateSelectedOnly = true, rateLimitAll = true, rateLimitSelected = true, useCache = true;
|
||||
int tokenCount = 10, tokenRestoreDelay = 60000, maxSentenceSize = 1000;
|
||||
@ -33,25 +34,28 @@ int keyType = CAT;
|
||||
std::pair<bool, std::wstring> Translate(const std::wstring& text)
|
||||
{
|
||||
if (!authKey->empty())
|
||||
{
|
||||
std::string translateFromComponent = translateFrom.Copy() == autoDetectLanguage ? "" : "&source_lang=" + WideStringToString(translateFrom.Copy());
|
||||
if (HttpRequest httpRequest{
|
||||
L"Mozilla/5.0 Textractor",
|
||||
L"api.deepl.com",
|
||||
L"POST",
|
||||
keyType == CAT ? L"/v1/translate" : L"/v2/translate",
|
||||
FormatString("text=%S&auth_key=%S&target_lang=%S", Escape(text), authKey.Copy(), translateTo.Copy()),
|
||||
FormatString("text=%S&auth_key=%S&target_lang=%S", Escape(text), authKey.Copy(), translateTo.Copy()) + translateFromComponent,
|
||||
L"Content-Type: application/x-www-form-urlencoded"
|
||||
}; httpRequest && (!httpRequest.response.empty() || (httpRequest = HttpRequest{
|
||||
L"Mozilla/5.0 Textractor",
|
||||
L"api.deepl.com",
|
||||
L"POST",
|
||||
(keyType = !keyType) == CAT ? L"/v1/translate" : L"/v2/translate",
|
||||
FormatString("text=%S&auth_key=%S&target_lang=%S", Escape(text), authKey.Copy(), translateTo.Copy()),
|
||||
FormatString("text=%S&auth_key=%S&target_lang=%S", Escape(text), authKey.Copy(), translateTo.Copy()) + translateFromComponent,
|
||||
L"Content-Type: application/x-www-form-urlencoded"
|
||||
})))
|
||||
// Response formatted as JSON: translation starts with text":" and ends with "}]
|
||||
if (auto translation = Copy(JSON::Parse(httpRequest.response)[L"translations"][0][L"text"].String())) return { true, translation.value() };
|
||||
else return { false, FormatString(L"%s: %s", TRANSLATION_ERROR, httpRequest.response) };
|
||||
else return { false, FormatString(L"%s (code=%u)", TRANSLATION_ERROR, httpRequest.errorCode) };
|
||||
}
|
||||
|
||||
// the following code was reverse engineered from the DeepL website; it's as close as I could make it but I'm not sure what parts of this could be removed and still have it work
|
||||
int64_t r = _time64(nullptr), n = std::count(text.begin(), text.end(), L'i') + 1;
|
||||
@ -68,7 +72,7 @@ std::pair<bool, std::wstring> Translate(const std::wstring& text)
|
||||
"timestamp": %lld,
|
||||
"lang": {
|
||||
"target_lang": "%S",
|
||||
"source_lang_user_selected": "auto"
|
||||
"source_lang_user_selected": "%S"
|
||||
},
|
||||
"jobs": [{
|
||||
"raw_en_sentence": "%s",
|
||||
@ -80,7 +84,7 @@ std::pair<bool, std::wstring> Translate(const std::wstring& text)
|
||||
}]
|
||||
}
|
||||
}
|
||||
)", id, r + (n - r % n), translateTo.Copy(), JSON::Escape(WideStringToString(text)));
|
||||
)", id, r + (n - r % n), translateTo.Copy(), translateFrom.Copy(), JSON::Escape(WideStringToString(text)));
|
||||
// missing accept-encoding header since it fucks up HttpRequest
|
||||
if (HttpRequest httpRequest{
|
||||
L"Mozilla/5.0 Textractor",
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include <ShlObj.h>
|
||||
|
||||
extern const wchar_t* TRANSLATION_ERROR;
|
||||
extern Synchronized<std::wstring> translateTo;
|
||||
extern Synchronized<std::wstring> translateTo, translateFrom;
|
||||
extern QFormLayout* display;
|
||||
extern Settings settings;
|
||||
|
||||
@ -34,6 +34,7 @@ QStringList languages
|
||||
"Russian: ru",
|
||||
"Spanish: es",
|
||||
};
|
||||
std::wstring autoDetectLanguage = L"auto";
|
||||
|
||||
BOOL WINAPI DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
|
||||
{
|
||||
@ -115,10 +116,16 @@ std::pair<bool, std::wstring> Translate(const std::wstring& text)
|
||||
// DevTools can't handle concurrent translations yet
|
||||
static std::mutex translationMutex;
|
||||
std::scoped_lock lock(translationMutex);
|
||||
DevTools::SendRequest(L"Page.navigate", FormatString(LR"({"url":"https://www.deepl.com/translator#any/%s/%s"})", translateTo.Copy(), Escape(text)));
|
||||
DevTools::SendRequest(L"Page.navigate", FormatString(LR"({"url":"https://www.deepl.com/translator#%s/%s/%s"})", translateFrom.Copy(), translateTo.Copy(), Escape(text)));
|
||||
for (int retry = 0; ++retry < 100; Sleep(100))
|
||||
if (auto translation = Copy(DevTools::SendRequest(
|
||||
L"Runtime.evaluate", LR"({"expression":"document.querySelector('#target-dummydiv').innerHTML","returnByValue":true})")[L"result"][L"value"].String())
|
||||
) if (!translation->empty()) return { true, translation.value() };
|
||||
if (auto translation = Copy(
|
||||
DevTools::SendRequest(L"Runtime.evaluate", LR"({"expression":"document.querySelector('#target-dummydiv').innerHTML","returnByValue":true})")[L"result"][L"value"].String()
|
||||
)) if (!translation->empty()) return { true, translation.value() };
|
||||
if (auto errorMessage = Copy(
|
||||
DevTools::SendRequest(
|
||||
L"Runtime.evaluate",
|
||||
LR"({"expression":"document.querySelector('div.lmt__system_notification').innerHTML","returnByValue":true})"
|
||||
)[L"result"][L"value"].String()
|
||||
)) return { false, FormatString(L"%s: %s", TRANSLATION_ERROR, errorMessage.value()) };
|
||||
return { false, TRANSLATION_ERROR };
|
||||
}
|
||||
}
|
||||
|
@ -42,11 +42,10 @@ QColor colorPrompt(QWidget* parent, QColor default, const QString& title, bool c
|
||||
return color;
|
||||
}
|
||||
|
||||
struct PrettyWindow : QDialog
|
||||
struct PrettyWindow : QDialog, Localizer
|
||||
{
|
||||
PrettyWindow(const char* name)
|
||||
{
|
||||
Localize();
|
||||
ui.setupUi(this);
|
||||
ui.display->setGraphicsEffect(&outliner);
|
||||
setWindowFlags(Qt::FramelessWindowHint);
|
||||
@ -159,7 +158,7 @@ public:
|
||||
PrettyWindow("Extra Window")
|
||||
{
|
||||
ui.display->setTextFormat(Qt::PlainText);
|
||||
if (settings.contains(WINDOW) && QGuiApplication::screenAt(settings.value(WINDOW).toRect().bottomRight())) setGeometry(settings.value(WINDOW).toRect());
|
||||
if (settings.contains(WINDOW) && QApplication::screenAt(settings.value(WINDOW).toRect().bottomRight())) setGeometry(settings.value(WINDOW).toRect());
|
||||
maxSentenceSize = settings.value(MAX_SENTENCE_SIZE, maxSentenceSize).toInt();
|
||||
|
||||
for (auto [name, default, slot] : Array<const char*, bool, void(ExtraWindow::*)(bool)>{
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
extern const wchar_t* TRANSLATION_ERROR;
|
||||
|
||||
extern Synchronized<std::wstring> translateTo, authKey;
|
||||
extern Synchronized<std::wstring> translateTo, translateFrom, authKey;
|
||||
|
||||
const char* TRANSLATION_PROVIDER = "Google Translate";
|
||||
const char* GET_API_KEY_FROM = "https://codelabs.developers.google.com/codelabs/cloud-translation-intro";
|
||||
@ -120,6 +120,7 @@ QStringList languages
|
||||
"Yoruba: yo",
|
||||
"Zulu: zu"
|
||||
};
|
||||
std::wstring autoDetectLanguage = L"auto";
|
||||
|
||||
bool translateSelectedOnly = false, rateLimitAll = true, rateLimitSelected = false, useCache = true;
|
||||
int tokenCount = 30, tokenRestoreDelay = 60000, maxSentenceSize = 1000;
|
||||
@ -127,23 +128,28 @@ int tokenCount = 30, tokenRestoreDelay = 60000, maxSentenceSize = 1000;
|
||||
std::pair<bool, std::wstring> Translate(const std::wstring& text)
|
||||
{
|
||||
if (!authKey->empty())
|
||||
{
|
||||
std::wstring translateFromComponent = translateFrom.Copy() == autoDetectLanguage ? L"" : L"&source=" + translateFrom.Copy();
|
||||
if (HttpRequest httpRequest{
|
||||
L"Mozilla/5.0 Textractor",
|
||||
L"translation.googleapis.com",
|
||||
L"POST",
|
||||
FormatString(L"/language/translate/v2?format=text&target=%s&key=%s", translateTo.Copy(), authKey.Copy()).c_str(),
|
||||
FormatString(L"/language/translate/v2?format=text&target=%s&key=%s%s", translateTo.Copy(), authKey.Copy(), translateFromComponent).c_str(),
|
||||
FormatString(R"({"q":["%s"]})", JSON::Escape(WideStringToString(text)))
|
||||
})
|
||||
if (auto translation = Copy(JSON::Parse(httpRequest.response)[L"data"][L"translations"][0][L"translatedText"].String())) return { true, translation.value() };
|
||||
else return { false, FormatString(L"%s: %s", TRANSLATION_ERROR, httpRequest.response) };
|
||||
else return { false, FormatString(L"%s (code=%u)", TRANSLATION_ERROR, httpRequest.errorCode) };
|
||||
}
|
||||
|
||||
if (HttpRequest httpRequest{
|
||||
L"Mozilla/5.0 Textractor",
|
||||
L"translate.google.com",
|
||||
L"POST",
|
||||
L"/_/TranslateWebserverUi/data/batchexecute?rpcids=MkEWBc",
|
||||
"f.req=" + Escape(WideStringToString(FormatString(LR"([[["MkEWBc","[[\"%s\",\"auto\",\"%s\",true],[null]]",null,"generic"]]])", JSON::Escape((JSON::Escape(text))), translateTo.Copy()))),
|
||||
"f.req=" + Escape(WideStringToString(
|
||||
FormatString(LR"([[["MkEWBc","[[\"%s\",\"%s\",\"%s\",true],[null]]",null,"generic"]]])", JSON::Escape((JSON::Escape(text))), translateFrom.Copy(), translateTo.Copy())
|
||||
)),
|
||||
L"Content-Type: application/x-www-form-urlencoded"
|
||||
})
|
||||
{
|
||||
|
@ -41,13 +41,12 @@ bool logErrors = true;
|
||||
Synchronized<std::string> script;
|
||||
std::atomic<int> revCount = 0;
|
||||
|
||||
class Window : public QDialog
|
||||
class Window : public QDialog, Localizer
|
||||
{
|
||||
public:
|
||||
Window()
|
||||
: QDialog(nullptr, Qt::WindowMinMaxButtonsHint)
|
||||
{
|
||||
Localize();
|
||||
connect(&loadButton, &QPushButton::clicked, this, &Window::LoadScript);
|
||||
|
||||
if (scriptEditor.toPlainText().isEmpty()) scriptEditor.setPlainText(LUA_INTRO);
|
||||
|
@ -16,13 +16,12 @@ std::wstring replace;
|
||||
std::shared_mutex m;
|
||||
DWORD (*GetSelectedProcessId)() = nullptr;
|
||||
|
||||
class Window : public QDialog
|
||||
class Window : public QDialog, Localizer
|
||||
{
|
||||
public:
|
||||
Window()
|
||||
: QDialog(nullptr, Qt::WindowMinMaxButtonsHint)
|
||||
{
|
||||
Localize();
|
||||
ui.setupUi(this);
|
||||
|
||||
connect(ui.regexEdit, &QLineEdit::textEdited, this, &Window::SetRegex);
|
||||
|
@ -1,20 +1,18 @@
|
||||
#include "qtcommon.h"
|
||||
#include "extension.h"
|
||||
#include <fstream>
|
||||
#include <QApplication>
|
||||
#include <QPlainTextEdit>
|
||||
|
||||
extern const char* LOAD_SCRIPT;
|
||||
|
||||
constexpr auto STYLE_SAVE_FILE = u8"Textractor.css";
|
||||
|
||||
class Window : public QDialog
|
||||
class Window : public QDialog, Localizer
|
||||
{
|
||||
public:
|
||||
Window()
|
||||
: QDialog(nullptr, Qt::WindowMinMaxButtonsHint)
|
||||
{
|
||||
Localize();
|
||||
connect(&loadButton, &QPushButton::clicked, this, &Window::LoadScript);
|
||||
|
||||
if (scriptEditor.toPlainText().isEmpty()) scriptEditor.setPlainText("/*https://doc.qt.io/qt-5/stylesheet-syntax.html*/");
|
||||
|
@ -11,13 +11,12 @@ extern const char* HEXADECIMAL;
|
||||
std::unordered_map<int64_t, std::unordered_multiset<int64_t>> linkedTextHandles;
|
||||
std::shared_mutex m;
|
||||
|
||||
class Window : public QDialog
|
||||
class Window : public QDialog, Localizer
|
||||
{
|
||||
public:
|
||||
Window()
|
||||
: QDialog(nullptr, Qt::WindowMinMaxButtonsHint)
|
||||
{
|
||||
Localize();
|
||||
connect(&linkButton, &QPushButton::clicked, this, &Window::Link);
|
||||
|
||||
layout.addWidget(&linkList);
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
extern const char* NATIVE_LANGUAGE;
|
||||
extern const char* TRANSLATE_TO;
|
||||
extern const char* TRANSLATE_FROM;
|
||||
extern const char* TRANSLATE_SELECTED_THREAD_ONLY;
|
||||
extern const char* RATE_LIMIT_ALL_THREADS;
|
||||
extern const char* RATE_LIMIT_SELECTED_THREAD;
|
||||
@ -21,16 +22,18 @@ extern const wchar_t* TOO_MANY_TRANS_REQUESTS;
|
||||
extern const char* TRANSLATION_PROVIDER;
|
||||
extern const char* GET_API_KEY_FROM;
|
||||
extern QStringList languages;
|
||||
extern std::wstring autoDetectLanguage;
|
||||
extern bool translateSelectedOnly, rateLimitAll, rateLimitSelected, useCache;
|
||||
extern int tokenCount, tokenRestoreDelay, maxSentenceSize;
|
||||
std::pair<bool, std::wstring> Translate(const std::wstring& text);
|
||||
|
||||
// backwards compatibility
|
||||
const char* LANGUAGE = u8"Language";
|
||||
const std::string TRANSLATION_CACHE_FILE = FormatString("%s Translation Cache.txt", TRANSLATION_PROVIDER);
|
||||
|
||||
QFormLayout* display;
|
||||
Settings settings;
|
||||
Synchronized<std::wstring> translateTo = L"en", authKey;
|
||||
Synchronized<std::wstring> translateTo = L"en", translateFrom = L"auto", authKey;
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -46,27 +49,38 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
class Window : public QDialog
|
||||
class Window : public QDialog, Localizer
|
||||
{
|
||||
public:
|
||||
Window() :
|
||||
QDialog(nullptr, Qt::WindowMinMaxButtonsHint)
|
||||
{
|
||||
Localize();
|
||||
display = new QFormLayout(this);
|
||||
|
||||
settings.beginGroup(TRANSLATION_PROVIDER);
|
||||
|
||||
auto languageCombo = new QComboBox(this);
|
||||
languageCombo->addItems(languages);
|
||||
auto translateToCombo = new QComboBox(this);
|
||||
translateToCombo->addItems(languages);
|
||||
int language = -1;
|
||||
if (settings.contains(LANGUAGE)) language = languageCombo->findText(settings.value(LANGUAGE).toString(), Qt::MatchEndsWith);
|
||||
if (language < 0) language = languageCombo->findText(NATIVE_LANGUAGE, Qt::MatchStartsWith);
|
||||
if (language < 0) language = languageCombo->findText("English", Qt::MatchStartsWith);
|
||||
languageCombo->setCurrentIndex(language);
|
||||
saveLanguage(languageCombo->currentText());
|
||||
display->addRow(TRANSLATE_TO, languageCombo);
|
||||
connect(languageCombo, &QComboBox::currentTextChanged, this, &Window::saveLanguage);
|
||||
if (settings.contains(LANGUAGE)) language = translateToCombo->findText(settings.value(LANGUAGE).toString(), Qt::MatchEndsWith);
|
||||
if (settings.contains(TRANSLATE_TO)) language = translateToCombo->findText(settings.value(TRANSLATE_TO).toString(), Qt::MatchEndsWith);
|
||||
if (language < 0) language = translateToCombo->findText(NATIVE_LANGUAGE, Qt::MatchStartsWith);
|
||||
if (language < 0) language = translateToCombo->findText("English", Qt::MatchStartsWith);
|
||||
translateToCombo->setCurrentIndex(language);
|
||||
SaveTranslateTo(translateToCombo->currentText());
|
||||
display->addRow(TRANSLATE_TO, translateToCombo);
|
||||
connect(translateToCombo, &QComboBox::currentTextChanged, this, &Window::SaveTranslateTo);
|
||||
languages.push_front("?: " + S(autoDetectLanguage));
|
||||
auto translateFromCombo = new QComboBox(this);
|
||||
translateFromCombo->addItems(languages);
|
||||
language = -1;
|
||||
if (settings.contains(TRANSLATE_FROM)) language = translateFromCombo->findText(settings.value(TRANSLATE_FROM).toString(), Qt::MatchEndsWith);
|
||||
if (language < 0) language = translateFromCombo->findText(NATIVE_LANGUAGE, Qt::MatchStartsWith);
|
||||
if (language < 0) language = translateFromCombo->findText("?", Qt::MatchStartsWith);
|
||||
translateFromCombo->setCurrentIndex(language);
|
||||
SaveTranslateFrom(translateFromCombo->currentText());
|
||||
display->addRow(TRANSLATE_FROM, translateFromCombo);
|
||||
connect(translateFromCombo, &QComboBox::currentTextChanged, this, &Window::SaveTranslateFrom);
|
||||
for (auto [value, label] : Array<bool&, const char*>{
|
||||
{ translateSelectedOnly, TRANSLATE_SELECTED_THREAD_ONLY },
|
||||
{ rateLimitAll, RATE_LIMIT_ALL_THREADS },
|
||||
@ -123,9 +137,13 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
void saveLanguage(QString language)
|
||||
void SaveTranslateTo(QString language)
|
||||
{
|
||||
settings.setValue(LANGUAGE, S(translateTo->assign(S(language.split(": ")[1]))));
|
||||
settings.setValue(TRANSLATE_TO, S(translateTo->assign(S(language.split(": ")[1]))));
|
||||
}
|
||||
void SaveTranslateFrom(QString language)
|
||||
{
|
||||
settings.setValue(TRANSLATE_FROM, S(translateFrom->assign(S(language.split(": ")[1]))));
|
||||
}
|
||||
} window;
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <QSettings>
|
||||
#include <QMainWindow>
|
||||
#include <QDialog>
|
||||
#include <QApplication>
|
||||
#include <QLayout>
|
||||
#include <QFormLayout>
|
||||
#include <QLabel>
|
||||
@ -26,6 +27,7 @@ constexpr auto WINDOW = u8"Window";
|
||||
|
||||
struct Settings : QSettings { Settings(QObject* parent = nullptr) : QSettings(CONFIG_FILE, QSettings::IniFormat, parent) {} };
|
||||
struct QTextFile : QFile { QTextFile(QString name, QIODevice::OpenMode mode) : QFile(name) { open(mode | QIODevice::Text); } };
|
||||
struct Localizer { Localizer() { Localize(); } };
|
||||
inline std::wstring S(const QString& s) { return { s.toStdWString() }; }
|
||||
inline QString S(const std::string& s) { return QString::fromStdString(s); }
|
||||
inline QString S(const std::wstring& s) { return QString::fromStdWString(s); }
|
||||
|
1
text.cpp
1
text.cpp
@ -134,6 +134,7 @@ const char* READ_ERROR = u8"Textractor: Reader ERROR (likely an incorrect R-code
|
||||
const char* HIJACK_ERROR = u8"Textractor: Hijack ERROR";
|
||||
const char* COULD_NOT_FIND = u8"Textractor: could not find text";
|
||||
const char* TRANSLATE_TO = u8"Translate to";
|
||||
const char* TRANSLATE_FROM = u8"Translate from";
|
||||
const char* TRANSLATE_SELECTED_THREAD_ONLY = u8"Translate selected text thread only";
|
||||
const char* RATE_LIMIT_ALL_THREADS = u8"Rate limit all text threads";
|
||||
const char* RATE_LIMIT_SELECTED_THREAD = u8"Rate limit selected text thread";
|
||||
|
Loading…
x
Reference in New Issue
Block a user