• QT中文乱码与国际化支持


    转自:http://blog.csdn.net/alicehyxx/article/details/4960571

    QT国际化支持

        Qt内部采用的全Unicode编码,这从根本上保证了多国语界面实现的正确性和便捷性。Qt本身提供的linguist工具,用来实现翻译过程十分方便。MFC中利用资源DLL切换资源,或使用多个RC文件进行不同语言版本编译等方法都十分麻烦,如果你曾经使用过MFC,QT解决多语言问题的便捷性绝对会让你感觉是一种享受。本文讨论以下几个方面内容:

    1、  QT中解决中文乱码的方法;

    2、  QT中实现国家化支持。

    3、  对话框实现多语言

    一、       中文乱码

    1、  在程序中直接使用中文,需要在程序中加入以下代码:

    1. #include <QTextCodec>  
    2.   
    3. int main(int argc, char **argv)  
    4. {  
    5.            QApplication app(argc, argv);  
    6.            QTextCodec *codec = QTextCodec::codecForName("GB2312");  
    7.   
    8.            QTextCodec::setCodecForLocale(codec);  
    9.            QTextCodec::setCodecForCStrings(codec);  
    10.            QTextCodec::setCodecForTr(codec);  
    11.   
    12.            …… ……  
    13.             return app.exec();  
    14. }  

    这样在程序中使用tr(“中文”)或者直接使用“中文”了;

    2、  解决读取ini文件中中文乱码

    QSettings settings("xxxx.ini",QSettings::IniFormat);

    settings.setIniCodec(QTextCodec::codecForName("GB2312")); settings.beginGroup("company");

    3、  解决读取中文文件中文的乱码

    1. QFile file("xxxx.txt");  
    2. QTextStream stream(file,QIODevice::ReadOnly);  
    3. stream.setCodeC( QTextCodec::codecForName("GB2312") );  
    4. stream.readAll();  

     

     

    二、       国际化支持

     

    QT中实现多国语言,建议在程序中直接英文,而后通过不同的翻译文件实现多语言的支持。实现多国语的步骤有如下几步(提及的工具均为QT自带):

    Ø  在需要被翻译的字符串前面加标识tr,如QString str = tr(“hello,world!”); 这很重要,因为翻译工具会把源码中tr标识的字符串提取出来,翻译成其他语言,如果没有用tr标识的,不会被工具提取。在界面中输入的文字,默认已经是加上tr的了,所以在翻译时也能看见。

    Ø  在QT工程文件*.pro中增加一项:TRANSLATIONS += *.ts,扩展名为.ts是翻译的源文件。一般会在命名中把区域加进去,更好的注释这些文件是用于什么语言的,可以根据“语言_国家”的形式形成文件名。比如中命名为myapp_zh_CN.ts, zh表示简体中文,而CN表示的就是中华人名共和国。可以参照ISO语言与国家代码标准:http://blog.csdn.net/alicehyxx/archive/2009/12/06/4952318.aspx

    Ø  使用lupdate工具提取翻译源文件,【运行】中输入CMD,打开命令行窗口,利用CD命令切换到QT安装目录的BIN目录中,而后输入:

    lupdate *.pro

    *.pro包含pro文件的全路径。lupdate会解析*.pro文件,生成TRANSLATIONS中的 *.ts 文件,这些文件可以被linguist工具打开,按照提示一个一个的翻译成需要的文件并保存。

    Ø  重复以上两步!
    (针对以上两步,VS2005中可以直接使用菜单【QT】à 【Create new translations File】创建,如果文件已经存在,可以通过图1.1菜单进行更新。)

        

    图1.1 VS2005_lupdate

    Ø  使用lrelease工具发布翻译文件的二进制文件,这样在程序运行时载入会大大的加快速度。在命令行窗口中继续输入:

    lrelease *.ts

    *.ts包含ts文件的全路径。这个工具会提示你多少语句被翻译,多少被忽略了等。生成的文件是*.qm,与同名的*.ts只是换了一个扩展名。这个就是我们程序需要使用到的文件。

    (VS2005中可以使用图1.1中的菜单lrelease来实现该步骤)

    Ø  使用*.qm文件。程序可以通过两种方式加载翻译文件,一种硬编码方式,直接指定加载的语言,代码如下:

    int main(int argc,char* argv[])

    {

             QApplication app(arcg,argv);

             QTranslator translator;

             translator.load(“basicdraw_zh_CN”);

             app.installTranslator(&translator);

    }

    另外一种是自动判断翻译当前的locale,再装入相应的翻译文件,如下所示:

    int main(int argc,char* argv[])

    {

             QApplication app(arcg,argv);

             QString locale = QLocale::system().name();

             QTranslator translator;

             translator.load(QString(“basicdraw_”) + locale);

             app.installTranslator(&translator);

    }

    其中QLocale::system().name()返回以“语言_国家”形式形成的字符串,比如zh_CN。

    至于通过控件,比如ComboBox选择语言,并实现动态切换,以后再讨论。

    三、       对话框实现多语言

    在实际程序中实现多语言切换,需要生成的qm文件应该包含两个:

    Ø  QT运行库相关的qm文件:在QT安装目录的translations目录下,存在需要*.ts文件,利用lrelease命令生成对应的qm文件。

    Ø  利用“二”中的步骤生成程序本身需要的*.ts文件,并生成qm文件。

    QApplication支持多个翻译文件,并根据后加入先使用的搜索顺序进行搜索。

    具体代码如下:
    main.cpp

     

    1. #include "stdafx.h"  
    2. #include <QtGui/QApplication>  
    3. #include <QtGui/QtGui>  
    4. #include "DialogLogin.h"  
    5.   
    6. int main(int argc, char *argv[])  
    7. {  
    8.     QApplication app(argc, argv);  
    9.     QTextCodec::setCodecForLocale(QTextCodec::codecForLocale());  
    10.   
    11.     // 安装QT运行库翻译器  
    12.     QTranslator translatorQT;  
    13.     {  
    14.         QStringList environment = QProcess::systemEnvironment();  
    15.         QString str;  
    16.         bool bFinded = false;  
    17.   
    18.         foreach(str, environment)  
    19.         {  
    20.             if(str.startsWith("QTDIR="))  
    21.             {  
    22.                 bFinded = true;  
    23.                 break;  
    24.             }  
    25.         }  
    26.   
    27.         if(bFinded)  
    28.         {  
    29.             str = str.mid(6);  
    30.             bFinded = translatorQT.load("qt_" + QLocale::system().name(),str.append("/translations/"));  
    31.   
    32.             if(bFinded)  
    33.                 app.installTranslator(&translatorQT);  
    34.             else  
    35.                 qDebug() <<QObject::tr("Can't find the translation file for Chinese!");  
    36.         }  
    37.         else  
    38.         {  
    39.             qDebug() << QObject::tr("Please set the environment variable QTDIR");  
    40.         }  
    41.     }  
    42.   
    43.     // 安装程序自身翻译器  
    44.     QTranslator translatorApp;  
    45.     {  
    46.         QString strLanguageDir = QCoreApplication::applicationDirPath();  
    47.         strLanguageDir.append("/Language/");  
    48.   
    49.         QString strFilePath = QApplication::applicationFilePath();  
    50.         QString strFileName = strFilePath.right(strFilePath.size() - strFilePath.lastIndexOf('/') - 1);  
    51.   
    52.         strFileName = strFileName.left(strFileName.indexOf('.'));  
    53.         strFileName.append('_');  
    54.         strFileName.append(QLocale::system().name());  
    55.         bool bFinded = translatorApp.load(strFileName,strLanguageDir);  
    56.   
    57.         if(bFinded)  
    58.             app.installTranslator(&translatorApp);  
    59.         else  
    60.         {  
    61.             qDebug() << QObject::tr("Can't Find The Translation's File For Chinese!");  
    62.         }  
    63.     }  
    64.   
    65.     CDialogLogin dlg;  
    66.   
    67.     return dlg.exec();  
    68. }  

    DialogLogin.h

    1. #pragma once  
    2. #include <QtGui/QDialog>  
    3.   
    4. class QLineEdit;  
    5. class CDialogLogin : public QDialog  
    6. {  
    7.     Q_OBJECT  
    8.   
    9. public:  
    10.     CDialogLogin(QWidget* parent = 0);  
    11.     ~CDialogLogin(void);  
    12.   
    13. public slots:  
    14.     virtual     void    accept();  
    15.   
    16. private:  
    17.     QLineEdit*  m_pUsrLineEdit;  
    18.     QLineEdit*  m_pPwdLineEdit;  
    19. };  

    程序中使用了两个QTranslator对象,在app利用函数installTranslator()进行翻译器安装时,并没有拷贝qm文件,而是在需要的时候在qm文件中进行查找。也即是说:QTranslator在load以后,并没有把qm文件中的数据拷贝一份。如果qm在这期间被删除或修改,对程序都是有影响的。扩展开来,QTranslator必须保证要一直有效,如果在函数中定义的局部变量,函数结束后就自动释放掉了,那么翻译工作就不能正常进行。
    DialogLogin.cpp

    1. #include "stdafx.h"  
    2. #include "DialogLogin.h"  
    3. #include <QtGui/QtGui>  
    4.   
    5. CDialogLogin::CDialogLogin(QWidget* parent/* = 0 */)  
    6.     : QDialog(parent)  
    7. {  
    8.     QLabel* pUsrLabel = new QLabel(tr("User Name:"));  
    9.     QLabel* pPwdLabel = new QLabel(tr("Password:"));  
    10.   
    11.     m_pUsrLineEdit = new QLineEdit();  
    12.     m_pPwdLineEdit = new QLineEdit();  
    13.     m_pPwdLineEdit->setEchoMode(QLineEdit::Password);  
    14.   
    15.     QGridLayout* pGridLayout = new QGridLayout();  
    16.   
    17.     pGridLayout->addWidget(pUsrLabel,0,0,1,1);  
    18.     pGridLayout->addWidget(m_pUsrLineEdit,0,1,1,3);  
    19.     pGridLayout->addWidget(pPwdLabel,1,0,1,1);  
    20.     pGridLayout->addWidget(m_pPwdLineEdit,1,1,1,3);  
    21.     pGridLayout->setSpacing(25);  
    22.   
    23.     QPushButton* pBtnOK = new QPushButton(tr("Login"));  
    24.     QPushButton* pBtnCancel = new QPushButton(tr("Cancel"));  
    25.   
    26.     QHBoxLayout* pBtnLayout = new QHBoxLayout();  
    27.     pBtnLayout->setSpacing(60);  
    28.     pBtnLayout->addWidget(pBtnOK);  
    29.     pBtnLayout->addWidget(pBtnCancel);  
    30.   
    31.     QVBoxLayout* pDlgLayout = new QVBoxLayout();  
    32.     pDlgLayout->setMargin(30);  
    33.     pDlgLayout->addLayout(pGridLayout);  
    34.     pDlgLayout->addStretch(40);  
    35.     pDlgLayout->addLayout(pBtnLayout);  
    36.     pDlgLayout->setSpacing(40);  
    37.     setLayout(pDlgLayout);  
    38.   
    39.     connect(pBtnOK,SIGNAL(clicked()),this,SLOT(accept()));  
    40.     connect(pBtnCancel,SIGNAL(clicked()),this,SLOT(reject()));  
    41.   
    42.     setWindowTitle(tr("Login"));  
    43.     resize(300,200);  
    44. }  
    45.   
    46. CDialogLogin::~CDialogLogin(void)  
    47. {  
    48. }  
    49.   
    50. void CDialogLogin::accept()  
    51. {  
    52.     if(m_pUsrLineEdit->text().trimmed() == tr("lcf") && m_pPwdLineEdit->text().trimmed() == tr("lcf"))  
    53.     {  
    54.         QDialog::accept();  
    55.     }  
    56.     else  
    57.     {  
    58.         QMessageBox::warning(this,tr("Warning"),tr("User Name or Password is wrong!"),QMessageBox::Yes);  
    59.   
    60.         m_pUsrLineEdit->setFocus();  
    61.     }  
    62. }  


    其中英文界面如图:

    图1.2 英文界面

     


    中文界面如图:

    图1.3 中文界面

     


  • 相关阅读:
    Vsftp的PASV mode(被动模式传送)和Port模式及 Linux下VsFTP配置全方案
    vsftpd:500 OOPS: vsftpd: refusing to run with writable root inside chroot ()错误的解决方法
    CentOS7.2部署FTP
    Apache与Nginx的优缺点比较
    MySQL存储引擎--MyISAM与InnoDB区别
    CentOS 7下搭建配置SVN服务器
    Remi 安装源
    tmpx75 I2C 温度传感器驱动程序添加
    QT 5.7.0 交叉编译记录
    am335x SGX 移植
  • 原文地址:https://www.cnblogs.com/pamxy/p/2991428.html
Copyright © 2020-2023  润新知