多國語系選擇與切換


接續 翻譯應用程式 的內容,在tr()中基本上不使用變數,這會使得lupdate工具程式無法辨識要處理的翻譯字串,不過您可以使用QT_tr_NOOP()巨集函式,在將字串指定給變數之前,先經過巨集函式處理,例如:
QString FriendlyConversation::greeting(int type) {
     static const char *greeting_strings[] = {
         QT_TR_NOOP("Hello"),
         QT_TR_NOOP("Goodbye")
     };
     return tr(greeting_strings[type]);
}

若覺得麻煩而不想為每個字串加上tr()函式,或為了避免撰寫時的疏忽而忘了為字串加上tr()函式,則可以在.pro檔案中撰寫:
DEFINES += QT_NO_CAST_FROM_ASCII

這可以讓前置處理器為每個字串加上tr()函式,若前置處理器無法處理的字串,則會產生編譯錯誤,此時您必須親自為那些字串加上tr()函式。

若要應用程式依系統預設語系而自動選擇正確的.qm檔案,以顯示正確的語系文字,基本上可以使用QLocale::System()傳回代表預設語系的QLocale物件,例如:
QApplication app(argc, argv);
QTranslator translator;
translator.load("hello_" + QLocale::system().name()));
app.installTranslator(&translator);
...

以上例而言,若是在zh_TW之下,則會載入hello_zh_TW.qm檔案,您也可以搭配 Qt 資源系統,例如撰寫一個qrresource.qrc:
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>hello.qm</file>
</qresource>
<qresource lang="zh_TW">
<file alias="hello.qm">hello_zh_TW.qm</file>
</qresource>
</RCC>

再修改一下應用程式:
....
int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
   
    QTranslator translator;
    translator.load(":/hello");
    app.installTranslator(&translator);
    ....
    return app.exec();
}

此時若語系設定為zh_TW,則會自動去尋找hello_zh_TW.qm,若無符合的語系對應,則使用預設的hello.qm。

若要在應用程式中,可以讓使用者透過功能選單來自由選擇語系切換,則要讓QTranslator重新載入.qm檔案,然後將重跑一遍設定字串的程式,例如提供一個函式讓功能選單來呼叫:
void changeLanguage(const QString &locale) {
    translator.load("hello_" + locale);
    label1->setText(QObject::tr("caterpillar"));
    label2->setText(QObject::tr("Gossip"));
    ....
}