可选的 Qt 字符串翻译
Optional Qt string translation
我有这样的东西:
void FooWidget:showSomeDialog(bool is_translatable)
{
QMessageBox mbox(this);
if (is_translatable)
{
mbox.setWindowsTitle(tr("Title"));
mbox.setText(tr("Text"));
mbox.setInformativeText(tr("InformativeText"));
mbox.addButton(tr("Button1"), QMessageBox::YesRole);
mbox.addButton(tr("Button2"), QMessageBox::NoRole);
...
} else {
mbox.setWindowsTitle(QLatin1String("Title"));
mbox.setText(QLatin1String("Text"));
mbox.setInformativeText(QLatin1String("InformativeText"));
mbox.addButton(QLatin1String("Button1"), QMessageBox::YesRole);
mbox.addButton(QLatin1String("Button2"), QMessageBox::NoRole);
...
}
mbox.exec();
}
避免重复的更好方法是什么?
我试过像这样使用 lambda 函数:
auto func = is_translatable
? [](const char *str) -> QString { return tr(str); }
: [](const char *str) -> QString { return QLatin1String(str); };
但是没用。而且也不太好看
您可以这样使用 lambda:
void FooWidget:showSomeDialog(bool is_translatable)
{
auto makeLatin = [](auto const& str) {return QLatin1String(str);};
auto lambda = [this](auto& fun) {
this->mbox.setWindowsTitle(fun("Title"));
this->mbox.setText(fun("Text"));
this->mbox.setInformativeText(fun("InformativeText"));
this->mbox.addButton(fun("Button1"), QMessageBox::YesRole);
this->mbox.addButton(fun("Button2"), QMessageBox::NoRole);
...
};
if (is_translatable)
{
lambda(tr);
} else {
lambda(makeLatin);
}
mbox.exec();
}
您可以使用预处理器
#define TRANSLATE(cond, str) (cond) ? tr(str) : QLatin1String(str)
然后使用它,这样您就不再需要外部 if
。
mbox.setWindowsTitle(TRANSLATE(is_translatable, "Title"))
您可以添加翻译方法:
void FooWidget::translate(bool is_translatable, QString value)
{
if(is_translatable) return tr(value)
return QLatin1String(value);
}
void FooWidget:showSomeDialog(bool is_translatable)
{
QMessageBox mbox(this);
mbox.setWindowsTitle(translate(is_translatable, "Title");
mbox.setText(translate(is_translatable, "Text"));
mbox.setInformativeText(translate(is_translatable, "InformativeText"));
mbox.addButton(translate(is_translatable, "Button1"), QMessageBox::YesRole);
mbox.addButton(translate(is_translatable, "Button2"), QMessageBox::NoRole);
mbox.exec();
}
如果 is_translatable 可以成为 FooWidget 的成员,那么阅读起来会更整洁一些:
void FooWidget::translate(QString value)
{
if(this->is_translatable) return tr(value)
return QLatin1String(value);
}
void FooWidget:showSomeDialog()
{
QMessageBox mbox(this);
mbox.setWindowsTitle(translate("Title");
mbox.setText(translate("Text"));
mbox.setInformativeText(translate("InformativeText"));
mbox.addButton(translate("Button1"), QMessageBox::YesRole);
mbox.addButton(translate("Button2"), QMessageBox::NoRole);
mbox.exec();
}
我找到了我要找的东西:
void FooWidget:showSomeDialog(std::function<QString(const char*)> tr)
{
QMessageBox mbox(this);
mbox.setWindowsTitle(tr("Title"));
mbox.setText(tr("Text"));
mbox.setInformativeText(tr("InformativeText"));
mbox.addButton(tr("Button1"), QMessageBox::YesRole);
mbox.addButton(tr("Button2"), QMessageBox::NoRole);
...
mbox.exec();
}
用法:
showSomeDialog([](const char* s){ return QString::fromLatin1(s); });
showSomeDialog([](const char* s){ return FooWidget::tr(s); });
我有这样的东西:
void FooWidget:showSomeDialog(bool is_translatable)
{
QMessageBox mbox(this);
if (is_translatable)
{
mbox.setWindowsTitle(tr("Title"));
mbox.setText(tr("Text"));
mbox.setInformativeText(tr("InformativeText"));
mbox.addButton(tr("Button1"), QMessageBox::YesRole);
mbox.addButton(tr("Button2"), QMessageBox::NoRole);
...
} else {
mbox.setWindowsTitle(QLatin1String("Title"));
mbox.setText(QLatin1String("Text"));
mbox.setInformativeText(QLatin1String("InformativeText"));
mbox.addButton(QLatin1String("Button1"), QMessageBox::YesRole);
mbox.addButton(QLatin1String("Button2"), QMessageBox::NoRole);
...
}
mbox.exec();
}
避免重复的更好方法是什么?
我试过像这样使用 lambda 函数:
auto func = is_translatable
? [](const char *str) -> QString { return tr(str); }
: [](const char *str) -> QString { return QLatin1String(str); };
但是没用。而且也不太好看
您可以这样使用 lambda:
void FooWidget:showSomeDialog(bool is_translatable)
{
auto makeLatin = [](auto const& str) {return QLatin1String(str);};
auto lambda = [this](auto& fun) {
this->mbox.setWindowsTitle(fun("Title"));
this->mbox.setText(fun("Text"));
this->mbox.setInformativeText(fun("InformativeText"));
this->mbox.addButton(fun("Button1"), QMessageBox::YesRole);
this->mbox.addButton(fun("Button2"), QMessageBox::NoRole);
...
};
if (is_translatable)
{
lambda(tr);
} else {
lambda(makeLatin);
}
mbox.exec();
}
您可以使用预处理器
#define TRANSLATE(cond, str) (cond) ? tr(str) : QLatin1String(str)
然后使用它,这样您就不再需要外部 if
。
mbox.setWindowsTitle(TRANSLATE(is_translatable, "Title"))
您可以添加翻译方法:
void FooWidget::translate(bool is_translatable, QString value)
{
if(is_translatable) return tr(value)
return QLatin1String(value);
}
void FooWidget:showSomeDialog(bool is_translatable)
{
QMessageBox mbox(this);
mbox.setWindowsTitle(translate(is_translatable, "Title");
mbox.setText(translate(is_translatable, "Text"));
mbox.setInformativeText(translate(is_translatable, "InformativeText"));
mbox.addButton(translate(is_translatable, "Button1"), QMessageBox::YesRole);
mbox.addButton(translate(is_translatable, "Button2"), QMessageBox::NoRole);
mbox.exec();
}
如果 is_translatable 可以成为 FooWidget 的成员,那么阅读起来会更整洁一些:
void FooWidget::translate(QString value)
{
if(this->is_translatable) return tr(value)
return QLatin1String(value);
}
void FooWidget:showSomeDialog()
{
QMessageBox mbox(this);
mbox.setWindowsTitle(translate("Title");
mbox.setText(translate("Text"));
mbox.setInformativeText(translate("InformativeText"));
mbox.addButton(translate("Button1"), QMessageBox::YesRole);
mbox.addButton(translate("Button2"), QMessageBox::NoRole);
mbox.exec();
}
我找到了我要找的东西:
void FooWidget:showSomeDialog(std::function<QString(const char*)> tr)
{
QMessageBox mbox(this);
mbox.setWindowsTitle(tr("Title"));
mbox.setText(tr("Text"));
mbox.setInformativeText(tr("InformativeText"));
mbox.addButton(tr("Button1"), QMessageBox::YesRole);
mbox.addButton(tr("Button2"), QMessageBox::NoRole);
...
mbox.exec();
}
用法:
showSomeDialog([](const char* s){ return QString::fromLatin1(s); });
showSomeDialog([](const char* s){ return FooWidget::tr(s); });