首页 > 代码库 > (转)QT中文乱码与国际化支持

(转)QT中文乱码与国际化支持

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

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

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

3、  对话框实现多语言

一、       中文乱码

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

#include <QTextCodec>

int main(int argc, char **argv)
{
           QApplication app(argc, argv);
           QTextCodec *codec = QTextCodec::codecForName("GB2312");

           QTextCodec::setCodecForLocale(codec);
           QTextCodec::setCodecForCStrings(codec);
           QTextCodec::setCodecForTr(codec);

           …… ……
            return app.exec();
}

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

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

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

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

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

QFile file("xxxx.txt");
QTextStream stream(file,QIODevice::ReadOnly);
stream.setCodeC( QTextCodec::codecForName("GB2312") );
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菜单进行更新。)
      • 使用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

    • #include "stdafx.h"
      #include <QtGui/QApplication>
      #include <QtGui/QtGui>
      #include "DialogLogin.h"
      
      int main(int argc, char *argv[])
      {
          QApplication app(argc, argv);
          QTextCodec::setCodecForLocale(QTextCodec::codecForLocale());
      
          // 安装QT运行库翻译器
          QTranslator translatorQT;
          {
              QStringList environment = QProcess::systemEnvironment();
              QString str;
              bool bFinded = false;
      
              foreach(str, environment)
              {
                  if(str.startsWith("QTDIR="))
                  {
                      bFinded = true;
                      break;
                  }
              }
      
              if(bFinded)
              {
                  str = str.mid(6);
                  bFinded = translatorQT.load("qt_" + QLocale::system().name(),str.append("/translations/"));
      
                  if(bFinded)
                      app.installTranslator(&translatorQT);
                  else
                      qDebug() <<QObject::tr("Can‘t find the translation file for Chinese!");
              }
              else
              {
                  qDebug() << QObject::tr("Please set the environment variable QTDIR");
              }
          }
      
          // 安装程序自身翻译器
          QTranslator translatorApp;
          {
              QString strLanguageDir = QCoreApplication::applicationDirPath();
              strLanguageDir.append("/Language/");
      
              QString strFilePath = QApplication::applicationFilePath();
              QString strFileName = strFilePath.right(strFilePath.size() - strFilePath.lastIndexOf(/) - 1);
      
              strFileName = strFileName.left(strFileName.indexOf(.));
              strFileName.append(_);
              strFileName.append(QLocale::system().name());
              bool bFinded = translatorApp.load(strFileName,strLanguageDir);
      
              if(bFinded)
                  app.installTranslator(&translatorApp);
              else
              {
                  qDebug() << QObject::tr("Can‘t Find The Translation‘s File For Chinese!");
              }
          }
      
          CDialogLogin dlg;
      
          return dlg.exec();
      }

      DialogLogin.h

    • #pragma once
      #include <QtGui/QDialog>
      
      class QLineEdit;
      class CDialogLogin : public QDialog
      {
          Q_OBJECT
      
      public:
          CDialogLogin(QWidget* parent = 0);
          ~CDialogLogin(void);
      
      
      public slots:
          virtual        void    accept();
      
      private:
          QLineEdit*    m_pUsrLineEdit;
          QLineEdit*    m_pPwdLineEdit;
      };

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

    • #include "stdafx.h"
      #include "DialogLogin.h"
      #include <QtGui/QtGui>
      
      CDialogLogin::CDialogLogin(QWidget* parent/* = 0 */)
          : QDialog(parent)
      {
          QLabel* pUsrLabel = new QLabel(tr("User Name:"));
          QLabel* pPwdLabel = new QLabel(tr("Password:"));
      
          m_pUsrLineEdit = new QLineEdit();
          m_pPwdLineEdit = new QLineEdit();
          m_pPwdLineEdit->setEchoMode(QLineEdit::Password);
      
          QGridLayout* pGridLayout = new QGridLayout();
      
          pGridLayout->addWidget(pUsrLabel,0,0,1,1);
          pGridLayout->addWidget(m_pUsrLineEdit,0,1,1,3);
          pGridLayout->addWidget(pPwdLabel,1,0,1,1);
          pGridLayout->addWidget(m_pPwdLineEdit,1,1,1,3);
          pGridLayout->setSpacing(25);
      
          QPushButton* pBtnOK = new QPushButton(tr("Login"));
          QPushButton* pBtnCancel = new QPushButton(tr("Cancel"));
      
          QHBoxLayout* pBtnLayout = new QHBoxLayout();
          pBtnLayout->setSpacing(60);
          pBtnLayout->addWidget(pBtnOK);
          pBtnLayout->addWidget(pBtnCancel);
      
          QVBoxLayout* pDlgLayout = new QVBoxLayout();
          pDlgLayout->setMargin(30);
          pDlgLayout->addLayout(pGridLayout);
          pDlgLayout->addStretch(40);
          pDlgLayout->addLayout(pBtnLayout);
          pDlgLayout->setSpacing(40);
          setLayout(pDlgLayout);
      
          connect(pBtnOK,SIGNAL(clicked()),this,SLOT(accept()));
          connect(pBtnCancel,SIGNAL(clicked()),this,SLOT(reject()));
      
          setWindowTitle(tr("Login"));
          resize(300,200);
      }
      
      CDialogLogin::~CDialogLogin(void)
      {
      }
      
      void CDialogLogin::accept()
      {
          if(m_pUsrLineEdit->text().trimmed() == tr("lcf") && m_pPwdLineEdit->text().trimmed() == tr("lcf"))
          {
              QDialog::accept();
          }
          else
          {
              QMessageBox::warning(this,tr("Warning"),tr("User Name or Password is wrong!"),QMessageBox::Yes);
      
              m_pUsrLineEdit->setFocus();
          }
      }

      其中英文界面如图:

      图1.2 英文界面

    • 中文界面如图:

      图1.3 中文界面

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