Qt将翻译文本转换为英语
我的Qt应用程序支持动态翻译,即用户可以在应用程序运行时更改语言 现在我需要找到翻译字符串的英文对应词,但似乎找不到方法 比如说 给定QString s=tr(“你好”); 翻译完成后,我需要能够从s获得“你好” 以前有没有人这样做过,或者对如何实现有什么想法Qt将翻译文本转换为英语,qt,Qt,我的Qt应用程序支持动态翻译,即用户可以在应用程序运行时更改语言 现在我需要找到翻译字符串的英文对应词,但似乎找不到方法 比如说 给定QString s=tr(“你好”); 翻译完成后,我需要能够从s获得“你好” 以前有没有人这样做过,或者对如何实现有什么想法 谢谢在Qt中,无法从翻译后的字符串中获取原始字符串。最终,实际的转换是由QTranslator类完成的,该类不公开反向查找函数,甚至不公开为私有API 您需要更改代码以避免反向字符串查找。一种方法是始终将英文字符串或其他标识符存储在需要的
谢谢在Qt中,无法从翻译后的字符串中获取原始字符串。最终,实际的转换是由
QTranslator
类完成的,该类不公开反向查找函数,甚至不公开为私有API
您需要更改代码以避免反向字符串查找。一种方法是始终将英文字符串或其他标识符存储在需要的位置
这实际上是使用QAction时的常见情况,这就是为什么QAction提供在翻译字符串旁边存储任意数据的原因,在
QAction::setData()
中,在我的应用程序中,我需要将翻译消息写入UI,将原始消息写入程序日志文件
我的解决方案是创建一个包装类,该类可以转换数据和原始数据
class TS {
public:
TS(const char* str) {
init(str);
}
TS(const QString& str) {
init(str.toStdString().c_str());
}
TS& arg(const QString& arg1, const bool translate = true) {
this->orig = this->orig.arg(arg1);
if (translate) {
this->tran = this->tran.arg(qApp->translate("", arg1.toStdString().c_str()));
} else {
this->tran = this->tran.arg(arg1);
}
return *this;
}
TS& arg(const int arg1) {
this->orig = this->orig.arg(arg1);
this->tran = this->tran.arg(arg1);
return *this;
}
inline const QString& getOrig() const {
return this->orig;
}
inline const QString& getTran() const {
return this->tran;
}
private:
inline void init(const char* str) {
this->orig = str;
this->tran = qApp->translate("", str);
}
private:
QString orig;
QString tran;
};
用法:
void info(const TS& rsMsg);
...
m_rLog.info(QT_TRANSLATE_NOOP("", "Plain Text"));
m_rLog.info(TS(QT_TRANSLATE_NOOP("", "Text with argument : %1")).arg( 123 ));
根据Mykhailo Bryzhaks的回答,我稍微采用了这个类,这样我们就可以在.ts文件中包含上下文,这将使大型解决方案的实现变得更加简单:
#ifndef TrString_h__
#define TrString_h__
#include <QString>
#include <QRegularExpression>
#include <cassert>
class QObject;
namespace
{
static QRegularExpression s_findClassNameRegExp("(?<=\\bclass\\s)(\\w+)");
static QRegularExpression s_findQuotesRegExp("\"([^\"\\\\]|\\\\.)*\"");
}
#define TRStringVoid(QT_TRANSLATE_NOOP_STRING) TrString<void>(#QT_TRANSLATE_NOOP_STRING)
#define TRString(QT_TR_NOOP_STRING) TrString<decltype(this)>(this, #QT_TR_NOOP_STRING)
// Use //: MyComment
// one line before the call to add a comment for the translator
namespace
{
const QString kQT_TR_NOOP_Macro = "QT_TR_NOOP(";
const QString kQT_TRANSLATE_NOOP_Macro = "QT_TRANSLATE_NOOP(";
const QString kQT_TRANSLATE_NOOP_3_Macro = "QT_TRANSLATE_NOOP3(";
}
// Use TRString or TRStringVoid macro to get an instance of this class
template <class T> class TrString
{
enum class MacroType { Unknown, QT_TR_NOOP, QT_TRANSLATE_NOOP, QT_TRANSLATE_NOOP3 };
public:
// used for global functions where T is void
template <typename SfinaeT = void, typename SfinaeT2 = std::enable_if_t<std::is_void<T>::value, T>>
TrString(const char* lineString)
: m_native(lineString)
{
m_macroType = getLineStringType(lineString);
assert(("You must use TRStringVoid(QT_TRANSLATE_NOOP('Context','StringToTranslate')) here because you are not in a class context.",
(m_macroType == MacroType::QT_TRANSLATE_NOOP || m_macroType == MacroType::QT_TRANSLATE_NOOP3)));
initStrings();
}
// used for calls from within objects
template <typename SfinaeT = void, typename SfinaeT2 = std::enable_if_t<!std::is_void<T>::value, T>>
TrString(SfinaeT2 caller, const char* lineString)
: m_native(lineString)
{
m_macroType = getLineStringType(lineString);
checkIfTemplateHasCorrectType(caller);
initStrings();
}
TrString& operator=(const TrString& other)
{
m_scope = other.m_scope;
m_native = other.m_native;
m_translated = other.m_translated;
}
TrString& arg(const TrString& arg1)
{
this->m_native = this->m_native.arg(arg1.native());
this->m_translated = this->m_translated.arg(qApp->translate(m_scope.toLocal8Bit().data(), arg1.translated().toLocal8Bit().data()));
return *this;
}
TrString& arg(const QString arg1)
{
this->m_native = this->m_native.arg(arg1);
this->m_translated = this->m_translated.arg(arg1);
return *this;
}
TrString& arg(const double arg1)
{
this->m_native = this->m_native.arg(arg1);
this->m_translated = this->m_translated.arg(arg1);
return *this;
}
inline const QString& native() const
{
return this->m_native;
}
inline const QString& translated() const
{
return this->m_translated;
}
private:
template<class SfinaeT = T>
typename std::enable_if<!std::is_polymorphic< std::remove_pointer_t<SfinaeT>>::value, void>::type
checkIfTemplateHasCorrectType(SfinaeT caller)
{
assert(("You must use TRString(QT_TRANSLATE_NOOP('Context', 'StringToTranslate')) here because your class does not derive from QObject.",
(m_macroType == MacroType::QT_TRANSLATE_NOOP || m_macroType == MacroType::QT_TRANSLATE_NOOP3)));
}
template<class SfinaeT = T>
typename std::enable_if<std::is_polymorphic< std::remove_pointer_t<SfinaeT>>::value, void>::type
checkIfTemplateHasCorrectType(SfinaeT caller)
{
if (!dynamic_cast<QObject*>(caller))
assert(("You must use TRString(QT_TRANSLATE_NOOP('Context', 'StringToTranslate')) here because your class does not derive from QObject.",
(m_macroType == MacroType::QT_TRANSLATE_NOOP || m_macroType == MacroType::QT_TRANSLATE_NOOP3)));
else
m_isDerivedFromQObject = true;
}
MacroType getLineStringType(QString lineString) const
{
if (m_native.contains(kQT_TR_NOOP_Macro))
return MacroType::QT_TR_NOOP;
else if (m_native.contains(kQT_TRANSLATE_NOOP_3_Macro))
return MacroType::QT_TRANSLATE_NOOP3;
else if (m_native.contains(kQT_TRANSLATE_NOOP_Macro))
return MacroType::QT_TRANSLATE_NOOP;
else
{
assert(("You must you TRString(QT_TR_NOOP('StringToTranslate') or TRString(QT_TRANSLATE_NOOP('Context', 'StringToTranslate')) if you are not in a QObject derived class for this to work.", false));
return MacroType::Unknown;
}
}
inline void initStrings()
{
QRegularExpressionMatchIterator regExpIter = s_findQuotesRegExp.globalMatch(m_native);
QStringList macroArguments;
while (regExpIter.hasNext())
{
QRegularExpressionMatch match = regExpIter.next();
QString argumentString = match.captured(0);
argumentString.remove(0, 1);
argumentString.remove(argumentString.length() - 1, 1);
macroArguments.push_back(argumentString);
}
if (macroArguments.size() == 1 && m_macroType == MacroType::QT_TR_NOOP)
{
m_scope = QRegularExpressionMatch(s_findClassNameRegExp.match(typeid(T).name())).captured(0);
m_native = macroArguments[0];
}
else if ((macroArguments.size() == 2 && m_macroType == MacroType::QT_TRANSLATE_NOOP) || (macroArguments.size() == 3 && m_macroType == MacroType::QT_TRANSLATE_NOOP3))
{
m_scope = macroArguments[0];
m_native = macroArguments[1];
}
else
{
assert(("You must you TRString(QT_TR_NOOP('StringToTranslate') or TRString(QT_TRANSLATE_NOOP('Context', 'StringToTranslate')) if you are not in a QObject derived class for this to work.", false));
}
m_translated = qApp->translate(m_scope.toLocal8Bit().data(), m_native.toLocal8Bit().data());
}
MacroType m_macroType = MacroType::Unknown;
bool m_isDerivedFromQObject = false;
QString m_native;
QString m_translated;
QString m_scope;
};
#endif // TrString_h__
课堂外使用:
auto logString = TRStringVoid(QT_TRANSLATE_NOOP("Main", "Log message in main"));
如果您无意中使用了错误的Qt宏或错误的TRString宏,将创建一个断言,并显示一条关于如何修复调用的消息 因此,我遇到了同样的情况,我还希望避免在代码中重复一些字符串文本,并且仍然能够向我的应用程序的用户打印一些翻译后的错误消息,但随后将文本的原始英文版本记录到日志中 我开始使用jaba的代码,但在使用一些特殊字符(如“\n”和一些Unicode标记)时遇到了一些问题。事实证明,Qt解析由翻译宏标记的字符串文本的方法涉及替换这些特殊字符。transcode函数直接取自Qt的语言学家源代码,以便在运行时执行相同的过程。否则,translate函数将无法找到字符串,因为翻译文件中存储的内容与编译后的字符串不完全匹配。所以我能想到的是这样的:
#pragma once
#include <QApplication>
#include <QString>
#include <QRegularExpression>
#include <cassert>
class QObject;
//NOTE: enable_if_t is only available in C++14 so we need to define it here
template< bool Condition, typename T = void >
using enable_if_t = typename std::enable_if<Condition, T>::type;
namespace
{
constexpr char QT_TR_NOOP_MACRO [] = "QT_TR_NOOP(";
constexpr char QT_TRANSLATE_NOOP_MACRO [] = "QT_TRANSLATE_NOOP(";
constexpr char QT_TRANSLATE_NOOP_3_MACRO [] = "QT_TRANSLATE_NOOP3(";
//TODO: Add QT_TR_N_NOOP, QT_TRANSLATE_N_NOOP, QT_TRANSLATE_N_NOOP3
enum class MacroType { Unknown, QT_TR_NOOP, QT_TRANSLATE_NOOP, QT_TRANSLATE_NOOP3 };
MacroType getMacroTypeFromString(const QString& str)
{
if (str.contains(QT_TR_NOOP_MACRO))
return MacroType::QT_TR_NOOP;
else if (str.contains(QT_TRANSLATE_NOOP_3_MACRO))
return MacroType::QT_TRANSLATE_NOOP3;
else if (str.contains(QT_TRANSLATE_NOOP_MACRO))
return MacroType::QT_TRANSLATE_NOOP;
else
{
return MacroType::Unknown;
}
}
QStringList extractArguments(const QString& raw)
{
QStringList macroArguments;
const QRegularExpression findQuotesRegExp("\"([^\"\\\\]|\\\\.)*\"");
QRegularExpressionMatchIterator regExpIter = findQuotesRegExp.globalMatch(raw);
while (regExpIter.hasNext())
{
QRegularExpressionMatch match = regExpIter.next();
QString argumentString = match.captured(0);
argumentString.remove(0, 1); // Remove leading quote
argumentString.remove(argumentString.length() - 1, 1); // Remove trailing quote
macroArguments.push_back(argumentString);
}
return macroArguments;
}
QString transcode(const QString &str)
{
static const char tab[] = "abfnrtv";
static const char backTab[] = "\a\b\f\n\r\t\v";
// This function has to convert back to bytes, as C's \0* sequences work at that level.
const QByteArray ba = str.toUtf8();
std::vector<uchar> in(std::begin(ba), std::end(ba));
size_t inputLength = in.size();
QByteArray out;
out.reserve(static_cast<int>(inputLength));
for (size_t i = 0; i < inputLength;)
{
uchar c = in[i++];
if (c == '\\')
{
if (i >= inputLength)
break;
c = in[i++];
if (c == '\n')
continue;
if (c == 'x' || c == 'u' || c == 'U')
{
const bool unicode = (c != 'x');
QByteArray hex;
while (i < inputLength && isxdigit((c = in[i])))
{
hex += static_cast<char>(c);
i++;
}
if (unicode)
{
out += QString(QChar(hex.toUInt(nullptr, 16))).toUtf8();
}
else
{
out += static_cast<char>(hex.toUInt(nullptr, 16));
}
}
else if (c >= '0' && c < '8')
{
QByteArray oct;
int n = 0;
oct += static_cast<char>(c);
while (n < 2 && i < inputLength && (c = in[i]) >= '0' && c < '8')
{
i++;
n++;
oct += static_cast<char>(c);
}
out += static_cast<char>(oct.toUInt(nullptr, 8));
}
else
{
const char *p = strchr(tab, c);
out += !p ? static_cast<char>(c) : backTab[p - tab];
}
}
else
{
out += static_cast<char>(c);
}
}
return QString::fromUtf8(out.constData(), out.length());
}
}
#define TR_STRING_VOID(QT_TRANSLATE_NOOP_STRING) TranslatedString<void>(#QT_TRANSLATE_NOOP_STRING)
#define TR_STRING(QT_TR_NOOP_STRING) TranslatedString<decltype(this)>(#QT_TR_NOOP_STRING)
template <class T> class TranslatedString
{
public:
explicit TranslatedString(const char* raw)
{
init(raw);
}
inline const QString& native() const
{
return m_Native;
}
inline QString translated() const
{
return QCoreApplication::translate(qUtf8Printable(m_Scope), qUtf8Printable(m_Native));
}
private:
//TODO: The init method should be SFINAE'd such that only the
// respective macros for void vs QObject subclass are supported
//
inline void init(const QString& raw)
{
m_MacroType = getMacroTypeFromString(raw);
assert(("Unsupported Qt translation Macro Type", (m_MacroType != MacroType::Unknown)));
QStringList macroArguments = extractArguments(raw);
(macroArguments.size() == 2)));
if (macroArguments.size() == 1 && m_MacroType == MacroType::QT_TR_NOOP)
{
const QRegularExpression findClassNameRegExp("(?<=\\bclass\\s)(\\w+)");
m_Scope = QRegularExpressionMatch(findClassNameRegExp.match(typeid(T).name())).captured(0);
m_Native = transcode(macroArguments[0]);
}
else if ((macroArguments.size() == 2 && m_MacroType == MacroType::QT_TRANSLATE_NOOP) || (macroArguments.size() == 3 && m_MacroType == MacroType::QT_TRANSLATE_NOOP3))
{
m_Scope = macroArguments[0];
m_Native = transcode(macroArguments[1]);
}
else
{
//TODO: Figure out what to put here
}
}
MacroType m_MacroType = MacroType::Unknown;
QString m_Native;
QString m_Scope;
};
#pragma一次
#包括
#包括
#包括
#包括
类QObject;
//注意:如果仅在C++14中可用,则启用,因此我们需要在此处定义它
模板
使用enable_if_t=typename std::enable_if::type;
名称空间
{
constexpr char QT_TR_NOOP_MACRO[]=“QT_TR_NOOP(”;
constexpr char QT_TRANSLATE_NOOP_宏[]=“QT_TRANSLATE_NOOP(”;
constexpr char QT_TRANSLATE_NOOP_3_MACRO[]=“QT_TRANSLATE_NOOP3(”;
//TODO:添加QT_TR_N_NOOP、QT_TRANSLATE_N_NOOP、QT_TRANSLATE_N_NOOP3
枚举类宏类型{Unknown,QT_TR_NOOP,QT_TRANSLATE_NOOP,QT_TRANSLATE_NOOP3};
宏类型getMacroTypeFromString(常量QString&str)
{
if(str.contains(QT_TR_NOOP_宏))
返回宏类型::QT_TR_NOOP;
else if(str.contains(QT_TRANSLATE_NOOP_3_MACRO))
返回宏类型::QT_TRANSLATE_NOOP3;
else if(str.contains(QT_TRANSLATE_NOOP_MACRO))
返回宏类型::QT_TRANSLATE_NOOP;
其他的
{
返回宏类型::未知;
}
}
QStringList提取参数(常量QString&raw)
{
QStringList宏参数;
常量QRegularExpression findQuotesRegExp(“\”([^\\\\\\\]\\\\\)*”);
QRegularExpressionMatchIterator regExpIter=findQuotesRegExp.globalMatch(原始);
while(regExpIter.hasNext())
{
QRegularExpressionMatch=regExpIter.next();
QString argumentString=match.captured(0);
argumentString.remove(0,1);//删除前导引号
argumentString.remove(argumentString.length()-1,1);//删除尾随引号
宏参数。推回(argumentString);
}
返回宏参数;
}
QString转码(const QString&str)
{
静态常量字符选项卡[]=“abfnrtv”;
static const char backTab[]=“\a\b\f\n\r\t\v”;
//此函数必须转换回字节,因为C的\0*序列在该级别工作。
const QByteArray ba=str.toUtf8();
std::vector in(std::begin(ba),std::end(ba));
size_t inputLength=in.size();
QByteArray out;
输出保留(静态_转换(输入长度));
对于(大小i=0;i=输入长度)
打破
c=在[i++]中;
如果(c=='\n')
继续;
如果(c='x'| | c='u'| | c='u')
{
const bool unicode=(c!='x');
QByteArray十六进制;
而(i='0'&&c<'8')为else
{
QByteArray十月;
int n=0;
oct+=静态(c);
而(n<2&&i='0'&&c<'8')
{
i++;
n++;
auto logString = TRStringVoid(QT_TRANSLATE_NOOP("Main", "Log message in main"));
#pragma once
#include <QApplication>
#include <QString>
#include <QRegularExpression>
#include <cassert>
class QObject;
//NOTE: enable_if_t is only available in C++14 so we need to define it here
template< bool Condition, typename T = void >
using enable_if_t = typename std::enable_if<Condition, T>::type;
namespace
{
constexpr char QT_TR_NOOP_MACRO [] = "QT_TR_NOOP(";
constexpr char QT_TRANSLATE_NOOP_MACRO [] = "QT_TRANSLATE_NOOP(";
constexpr char QT_TRANSLATE_NOOP_3_MACRO [] = "QT_TRANSLATE_NOOP3(";
//TODO: Add QT_TR_N_NOOP, QT_TRANSLATE_N_NOOP, QT_TRANSLATE_N_NOOP3
enum class MacroType { Unknown, QT_TR_NOOP, QT_TRANSLATE_NOOP, QT_TRANSLATE_NOOP3 };
MacroType getMacroTypeFromString(const QString& str)
{
if (str.contains(QT_TR_NOOP_MACRO))
return MacroType::QT_TR_NOOP;
else if (str.contains(QT_TRANSLATE_NOOP_3_MACRO))
return MacroType::QT_TRANSLATE_NOOP3;
else if (str.contains(QT_TRANSLATE_NOOP_MACRO))
return MacroType::QT_TRANSLATE_NOOP;
else
{
return MacroType::Unknown;
}
}
QStringList extractArguments(const QString& raw)
{
QStringList macroArguments;
const QRegularExpression findQuotesRegExp("\"([^\"\\\\]|\\\\.)*\"");
QRegularExpressionMatchIterator regExpIter = findQuotesRegExp.globalMatch(raw);
while (regExpIter.hasNext())
{
QRegularExpressionMatch match = regExpIter.next();
QString argumentString = match.captured(0);
argumentString.remove(0, 1); // Remove leading quote
argumentString.remove(argumentString.length() - 1, 1); // Remove trailing quote
macroArguments.push_back(argumentString);
}
return macroArguments;
}
QString transcode(const QString &str)
{
static const char tab[] = "abfnrtv";
static const char backTab[] = "\a\b\f\n\r\t\v";
// This function has to convert back to bytes, as C's \0* sequences work at that level.
const QByteArray ba = str.toUtf8();
std::vector<uchar> in(std::begin(ba), std::end(ba));
size_t inputLength = in.size();
QByteArray out;
out.reserve(static_cast<int>(inputLength));
for (size_t i = 0; i < inputLength;)
{
uchar c = in[i++];
if (c == '\\')
{
if (i >= inputLength)
break;
c = in[i++];
if (c == '\n')
continue;
if (c == 'x' || c == 'u' || c == 'U')
{
const bool unicode = (c != 'x');
QByteArray hex;
while (i < inputLength && isxdigit((c = in[i])))
{
hex += static_cast<char>(c);
i++;
}
if (unicode)
{
out += QString(QChar(hex.toUInt(nullptr, 16))).toUtf8();
}
else
{
out += static_cast<char>(hex.toUInt(nullptr, 16));
}
}
else if (c >= '0' && c < '8')
{
QByteArray oct;
int n = 0;
oct += static_cast<char>(c);
while (n < 2 && i < inputLength && (c = in[i]) >= '0' && c < '8')
{
i++;
n++;
oct += static_cast<char>(c);
}
out += static_cast<char>(oct.toUInt(nullptr, 8));
}
else
{
const char *p = strchr(tab, c);
out += !p ? static_cast<char>(c) : backTab[p - tab];
}
}
else
{
out += static_cast<char>(c);
}
}
return QString::fromUtf8(out.constData(), out.length());
}
}
#define TR_STRING_VOID(QT_TRANSLATE_NOOP_STRING) TranslatedString<void>(#QT_TRANSLATE_NOOP_STRING)
#define TR_STRING(QT_TR_NOOP_STRING) TranslatedString<decltype(this)>(#QT_TR_NOOP_STRING)
template <class T> class TranslatedString
{
public:
explicit TranslatedString(const char* raw)
{
init(raw);
}
inline const QString& native() const
{
return m_Native;
}
inline QString translated() const
{
return QCoreApplication::translate(qUtf8Printable(m_Scope), qUtf8Printable(m_Native));
}
private:
//TODO: The init method should be SFINAE'd such that only the
// respective macros for void vs QObject subclass are supported
//
inline void init(const QString& raw)
{
m_MacroType = getMacroTypeFromString(raw);
assert(("Unsupported Qt translation Macro Type", (m_MacroType != MacroType::Unknown)));
QStringList macroArguments = extractArguments(raw);
(macroArguments.size() == 2)));
if (macroArguments.size() == 1 && m_MacroType == MacroType::QT_TR_NOOP)
{
const QRegularExpression findClassNameRegExp("(?<=\\bclass\\s)(\\w+)");
m_Scope = QRegularExpressionMatch(findClassNameRegExp.match(typeid(T).name())).captured(0);
m_Native = transcode(macroArguments[0]);
}
else if ((macroArguments.size() == 2 && m_MacroType == MacroType::QT_TRANSLATE_NOOP) || (macroArguments.size() == 3 && m_MacroType == MacroType::QT_TRANSLATE_NOOP3))
{
m_Scope = macroArguments[0];
m_Native = transcode(macroArguments[1]);
}
else
{
//TODO: Figure out what to put here
}
}
MacroType m_MacroType = MacroType::Unknown;
QString m_Native;
QString m_Scope;
};
std::enable_if_t<std::is_convertible<T, QObject>::value
namespace
{
enum class ERROR
{
COUNT,
ARGUMENT_SWAP,
};
static const std::map<ERROR, TranslatedString<void>> ERROR_STRINGS =
{
std::make_pair(ERROR::COUNT, TR_STRING_VOID(QT_TRANSLATE_NOOP("MainWindow", "%1"))),
// Translated text could be given as "Second Argument: %2, First Argument: %1"
std::make_pair(ERROR::ARGUMENT_SWAP, TR_STRING_VOID(QT_TRANSLATE_NOOP("MainWindow", "First Argument: %1, Second Argument: %2"))),
};
}
void MainWindow::retranslateUi()
{
static int count = 0;
count++;
// This has the copyright symbol unicode in it.
auto ts = TR_STRING(QT_TR_NOOP("Test translation. \xC2\xA9"));
// Both the translated string and the original text are available
ui->translatedLabel->setText(ts.translated());
ui->nativeLabel->setText(ts.native());
ui->translatedCountLabel->setText(ERROR_STRINGS.at(COUNT).translated().arg(count));
ui->nativeCountLabel->setText(ERROR_STRINGS.at(COUNT).native().arg(count));
// Note that the arguments need to be provided to each string
// so that they can be replaced according to the correct order
// of the translated text which is only available at runtime.
ui->translatedSwappedArgumentsLabel->setText(ERROR_STRINGS.at(ARGUMENT_SWAP).translated().arg(50.0).arg("String"));
ui->swappedArgumentsLabel->setText(ERROR_STRINGS.at(ARGUMENT_SWAP).native().arg(50.0).arg("String"));
}