2017-05-08 67 views
1

Qt的网站推荐将本地化字符串就在这样的代码中间:存储可本地化字符串的习惯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

只要使用tr(“foo”),只要你需要它。尽管它看起来像代码重复,但它是最好的方法。在字符串中存储本地化并不是一个好主意。您的MyLocalizableStrings可防止例如动态语言的变化,除非你添加一个重新翻译功能...而这里又变得越来越复杂。所以,只要使用tr(“foo”)就可以了。拼写错误很容易通过语言学家发现。 – Lorenz

+1

http://doc.qt.io/qt-5/i18n-source-translation.html#using-qt-tr-noop-and-qt-translate-noop-in-c – Evgeny

+0

@洛伦兹它比代码重复更糟糕,这是数据重复。我会在另一个函数中写一个函数“Operation not possible”,在另一个函数中写作“此刻不可能的操作”,并且在一年之内,我将无法记住这里是否存在任何语义差异。更糟糕的是,它可能不是我,而是一个完全不同的人,没有能力/时间来检查代码,将代码翻译成语言这样的语言。最佳实践存在的原因是:不会复制硬编码的用户可读消息。 – sigil

回答

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(); 
} 

这是相当可读没有重复的标识符。它也避免了静态初始化顺序失败。

+0

谢谢你的传统能力和全面的答案!也许我会用它来取代我昨天解决的劣势'std :: map'方法,这主要是因为它的简单性。 – sigil

+0

至少对我而言,仍然存在这样的问题:这种方法不支持动态语言更改。一个简单的静态类函数是不够的? 'class TrStrings:public QObject {Q_OBJECT public:static QString errorMessage(){return tr(“error”);}};' – Lorenz

+0

@Lorenz它确实支持动态语言更改。您必须在语言更改时重新创建“MyLocalizableStrings”对象,并在顶级窗口上调用QWidget :: update(),并假定所有小部件都配置为直接从字符串类获取文本。 –