习惯Qt存储可本地化字符串的方式?

时间:2017-05-08 19:35:39

标签: c++ qt localization

Qt网站建议在代码中间存储可本地化的字符串,如下所示:

fileMenu = menuBar()->addMenu(tr("&File"));

但是,我应该如何多次存储项目中出现的字符串?将它们放在单例中有效但tr()调用意味着我必须单独初始化它们:

struct MyLocalizableStrings
{
    QString mErrorMessageFileNotFound;
    QString mErrorMessageNoCanDoThis;

    MyLocalizableStrings() :
        mErrorMessageFileNotFound(QObject::tr("File not found.")),
        mErrorMessageNoCanDoThis(QObject::tr("Operation is not possible at the moment."))
        {}
};        

笨拙而容易搞砸;我更喜欢将声明和初始化保持在一起。当然可以将一系列const char*保留在专用命名空间中,但是在调用站点存在忘记tr()的风险 - 整个方法严重不合标准。

有更好的想法吗?

1 个答案:

答案 0 :(得分:1)

多次出现并且意图相同的字符串需要在一个或多个专用类中 - 所以你几乎把它弄好了。该类需要其翻译上下文,以便翻译人员更容易理解这些是常见消息。您还应该利用C ++ 11中的成员初始化来干燥:

首先,让我们建立一个基类和必要的帮助者:

#include <QCoreApplication>

template <typename Derived>
class LocalizableStringBase {
   Q_DISABLE_COPY(LocalizableStringBase)
protected:
   using S = QString;
   static LocalizableStringBase * m_instance;
   LocalizableStringBase() {
      Q_ASSERT(!m_instance);
      m_instance = this;
   }
   ~LocalizableStringBase() {
      m_instance = nullptr;
   }
public:
   static const Derived * instance() {
      return static_cast<const Derived*>(m_instance);
   }
   void reset() {
     auto self = static_cast<const Derived*>(this);
     self->~Derived();
     new (self) Derived();
   }
};

#define DEFINE_LOCALIZABLE_STRINGS(Derived) \
   template <> \
   LocalizableStringBase<Derived> * LocalizableStringBase<Derived>::m_instance = {}; \
   const Derived & Derived##$() { return *(Derived::instance()); }

然后,对于您需要的每组可本地化字符串:

// Interface

class MyLocalizableStrings : public LocalizableStringBase<MyLocalizableStrings> {
   Q_DECLARE_TR_FUNCTIONS(MyLocalizableStrings)
public:
   S errorMessageFileNotFound = tr("File not found.");
   S errorMessageNoCanDoThis = tr("Operation is not possible at the moment.");
};

// Implementation

DEFINE_LOCALIZABLE_STRINGS(MyLocalizableStrings)

用法:

#include <QDebug>

void test() {
   qDebug() << MyLocalizableStrings$().errorMessageFileNotFound;
}

int main(int argc, char ** argv)
{
   QCoreApplication app{argc, argv};
   MyLocalizableStrings str1;
   test();
   // Change language here
   str1.reset();
   test();
}

这是相当可读的,并且没有重复的标识符。它还避免了静态初始化命令惨败。