首页 > 其他分享 >QT实现多语言并动态切换

QT实现多语言并动态切换

时间:2022-09-08 08:11:41浏览次数:109  
标签:en zh 语言 CN language 切换 action 动态 QT

本文讲述在QT中动态切换多语言.
我会动态生成一个菜单,这个菜单会列出所有的语言,用户可以单选一种语言,选择语言后,界面就会切换到指定的语言

1.兜底的语言
当一个语言(字符串)没有被翻译时,他会用你代码中的语言(字符串)来显示, 这个语言(字符串)就是兜底的语言.
也就是说,如果你编码的菜单,字符串等用的是中文,我们就认为兜底的语言是中文
如果你编码的菜单,字符串用的是英文,那我们就认为兜底的是英文.
强烈建议,您用英文进行编码(兜底的语言是英文),我测试的情况是,如果用中文,生成的ts文件乱码!没测试QT5,不知道QT5是否会有同样的问题,乱码图片如下:

2.编码中的需要使用多语言的地方请用tr("")包围
比如: xxxCtrl->setText(tr("您好"));
用tr("")包围是告诉QT,这个字符串要当多语言来处理

3.菜单等QT设计器上输入的文本,已经被tr("")包围了,不用管

现在我们就来一步一步地实现多语言吧

a).编辑.pro文件,增加多个ts,在我们的实例中,我们要实现两个语言,一个是zh_CN,一个是en_US,如下:

TRANSLATIONS += res/language/zh_CN.ts \
                res/language/en_US.ts

注意:这里的res/language/是表示要生成ts的目录,你也可以不写res/language/那生成的ts文件就和pro在同一个目录下.
        如果你写了res/language/或者其他什么目录,你就需要手动创建这两个文件夹,res和.pro文件同一目录,language在res目录下
编辑好的样子如图:

b). 先用界面设计器设计两个菜单,一个是File,一个是Help,
然后拖两个控件上去,一个是lable,一个是LineEdit
lable用于静态显示一个文本,设置内容为"Static Text"
LineEdit用于编码显示文本,在代码中设置内容为"Dynamic Text 100"
差不多就是下面这个样子

void MainWindow::UpdateDynamicControls()
{
    QString strText = QString(tr("Dynamic Text %1")).arg(m_nValue);
    ui->lineEditDynamic->setText(strText);
}

c). 还记得我们的a)步骤吗,现在我们就要生成这两个ts文件了,方法如下:
工具->外部->QT语言专家->更新翻译

执行完后,就会生成en_US.ts和zh_CN.ts两个文件了,不妨可以打开看看,是个xml文件,记录了所有要翻译的文本和他们所在的位置.
此时两个文件是一模一样的,为啥呢? 因为虽然QT支持多语言,但翻译还是得我们自己来....

d). 翻译
找到Linguist,通常在QT的安装目录下的bin文件中,我是直接在开始中搜索到的(位于C:\Qt\4.8.6\bin\linguist.exe)

执行,后打开zh_CN.ts,开始翻译成英文的工作.
在弹出的对话框中,目标语言已经设置好了,就是Chinese

确定后就一个一个地翻译,如果某个你不想翻译,那也没有关系,就显示"兜底"显示的内容

翻译完了后,保存一下.退出.


d). 发布翻译,生成qm文件
工具->外部->QT语言专家->发布翻译

执行后,会生成两个文件,一个是zh_CN.qm一个是en_US.qm
生成的qm文件才是最终使用的文件.

e). 程序启动的时候,加载qm文件.
把zh_CN.qm和en_US.qm加到资源文件中去(您也可以不加入到资源文件,只要exe最终能找到qm文件就可以了)
加载后如图所示

程序启动的时候,需要加载.qm文件,加载的代码如下

void MyMultiLanguage::Switch(QString strNewLang)
{
    if (0 != m_strCurLanguage.compare(strNewLang))
    {
        QString strQM = QString(":/res/language/%1.qm").arg(strNewLang);

        if (QFile(strQM).exists())
        {
            QTranslator* translator = new QTranslator;
            if (translator->load(strQM))
            {
                m_strCurLanguage = strNewLang;

                if (NULL != m_translator)
                {
                    qApp->removeTranslator(m_translator);
                    delete m_translator;
                }

                m_translator = translator;
                qApp->installTranslator(m_translator);
            }
            else
            {
                delete translator;
                translator = NULL;
            }
        }

    }
}

这段代码并不复杂,代码几乎不言自明
比如传入的参数是zh_CN
那么就先判断":/res/language/zh_CN.qm"是否存在
如果文件存在,则new 一个QTranslator(QTranslator就什么呢?你这么理解好了,一个QTranslator就是一个qm)
如果QTranslator load成功,则把原来的QTranslator删除(removeTranslator,如果有的话),加载最新的QTranslator
最后,安装多语言依赖QApplication
qApp->installTranslator(m_translator);


加载翻译这段代码(g_MultiLanguage.Init("zh_CN");)在函数入口处(QApplication后)执行

int main(int argc, char *argv[])
{
    QTextCodec *codec = QTextCodec::codecForName("UTF-8");    //获取系统编码
    QTextCodec::setCodecForLocale(codec);
    QTextCodec::setCodecForCStrings(codec);
    QTextCodec::setCodecForTr(codec);


    QApplication a(argc, argv);

    //初始化多语言, 切换多语言依赖于QApplication
    g_MultiLanguage.Init("zh_CN");

    MainWindow w;
    w.show();

    int nRet = a.exec();

    //反初始化
    g_MultiLanguage.UnInit();

    return nRet;
}

运行,因为我们默认加载的是zh_CN.qm,所以运行界面显示为中文了,如下:

f). 加入顶层菜单language,供用户切换语言,代码如下:

    //在帮助之前,动态插入菜单language
    QMenu *languageMenu = new QMenu(tr("language"), menuBar());
    menuBar()->insertMenu(ui->menuHelp->menuAction(), languageMenu);

    //action_zh_CN = new QAction(QIcon(":/res/language/zh_CN.png"), "简体中文", this);
    //action_en_US = new QAction(QIcon(":/res/language/en_US.png"), "英文", this);

    //菜单项"简体中文",注意没有用tr包围
    QAction* action_zh_CN = new QAction("简体中文", this);
    action_zh_CN->setData("zh_CN");
    action_zh_CN->setCheckable(true);

    //菜单项"English",注意没有用tr包围
    QAction* action_en_US = new QAction("English", this);
    action_en_US->setData("en_US");
    action_en_US->setCheckable(true);

    //根据当前的语言设置选中菜单
    if (0 == g_MultiLanguage.GetCurLanguage().compare("zh_CN"))
    {
        action_zh_CN->setChecked(true);
    }
    else if (0 == g_MultiLanguage.GetCurLanguage().compare("en_US"))
    {
        action_en_US->setChecked(true);
    }

    //将简体中文和英文加入到language菜单中去,并设置好处理函数OnLanguageChanged
    QActionGroup* languageGroup = new QActionGroup(this);
    languageMenu->addAction(languageGroup->addAction(action_zh_CN));
    languageMenu->addAction(languageGroup->addAction(action_en_US));
    connect(languageGroup, SIGNAL(triggered(QAction *)), this, SLOT(OnLanguageChanged(QAction *)));

执行结果如下:

注意一下,我并没有把两个菜单项目"简体中文"和"English"用tr包围,因为这两个是不需要翻译的,他本身就代表用户要选择的语言.
处理语言切换的slot代码如下:

void MainWindow::OnLanguageChanged(QAction* action)
{
    if (NULL != action) {
        // load the language dependant on the action content
        //loadLanguage(action->data().toString());
        //setWindowIcon(action->icon());
        qDebug() << action->data().toString() << "\n";
        g_MultiLanguage.Switch(action->data().toString());
    }
}

g). 到此,我们离成功非常接近了.
我们切换语言时,会调用 qApp->installTranslator(m_translator); 这个函数会导致QEvent :: LanguageChange被发射出来
我们可以在这个事件的处理函数中,重新更新UI,完成多语言切换.
我们需要继承实现virtual void changeEvent(QEvent * event);

void MainWindow::changeEvent(QEvent * event)
{
    if (NULL != event) {
        switch (event->type()) {
            // this event is send if a translator is loaded
        case QEvent::LanguageChange:
            qDebug() << "case QEvent::LanguageChange" << endl;
            ui->retranslateUi(this);
            UpdateDynamicControls();
            break;
        default:
            break;
        }
    }
    QMainWindow::changeEvent(event);

}

最后这一步也是关键的一步,执行了两个函数:
ui->retranslateUi(this);这个函数是系统控件重新更新UI(语言)
UpdateDynamicControls();是我自己写的函数,也是动态去更新LineEdit的内容(语言),代码如下:

void MainWindow::UpdateDynamicControls()
{
    QString strText = QString(tr("Dynamic Text %1")).arg(m_nValue);
    ui->lineEditDynamic->setText(strText);
}

到此,切换语言工作完成!用户就可以在菜单里面选择自己想要的语言啦!

切换语言的调试输出:
"en_US"
case QEvent :: LanguageChange
说明每切换一次语言,就会收到QEvent :: LanguageChange一次

代码见:  http://q1024.com/files/qt_window-master.zip   000400目录
参考:https://wiki.qt.io/How_to_create_a_multi_language_application

[思考]
顶层菜单language没有翻译,不能切换语言,你知道怎么操作完成这个项目的翻译和语言切换吗?

标签:en,zh,语言,CN,language,切换,action,动态,QT
From: https://www.cnblogs.com/xingzaicpp/p/16667969.html

相关文章

  • 用qt designer"设计"出带圆点的单选菜单项
    先放张图,也许我们要的是右边的样子,而QT设计器设计出来是左边的样子,那怎么样稍做修改一下,实现右边的效果呢?另外,据说,在很久以前,QT实际上是可以设计出右边的样子的,但......
  • QT中修改窗口的标题和图标
    修改窗口标题QT的窗口默认名字是MainWindow,在这里介绍两种方法修改窗口的Title1.直接通过UI设计器修改:我修改成了"我的窗口"运行后,显示如下:好了,我们需要去找下,"......
  • SystemVerilog中动态数组调整大小
    题目:现有一个大小为100的动态数组如下,如何把它定义成大小为200,并且前100个元素仍然保留的数组,请写出具体代码integerdata;data=new[100]; 其实就一句代码:data=ne......
  • 【指北】动态规划从入门到入坟
    前言本【指北】适合正在学习DP的OIer。本【指北】中不仅有简单内容,还有较难内容,总体来讲适合不同水准的选手。本人才疏学浅,请大佬们在评论区中指出错误,我会加以改进......
  • Qt5.14.2使用虚拟键盘
    说明这是关于Qt5(Qt5.1.4.2),QWidget编程使用Qt虚拟键盘(qtvirtualkeyboard)Tag:QT5,Qt,软件盘、虚拟键盘,Widget程序,QML 作者:[email protected] 关键代码启用虚拟键盘......
  • 12.3窗口切换select框和iframe框
    fromseleniumimportwebdriverfromselenium.webdriver.common.byimportByimporttimedriver=webdriver.Chrome()driver.get('http://www.baidu.com')driver.maximiz......
  • Qt 信号槽连接不成功问题原因汇总
    1.拥有信号槽的类,必须继承QObject,声明Q_OBJECT宏。Qt帮助手册里搜索 “Signals&Slots”,可以看到以下说明:想要使用信号槽,必须继承QObject,必须加Q_OBJECT宏。2.信号......
  • QT之QCompleter的用法--- 最简单的使用方法
    本文讲解最简单的使用方法:QCompleter能实现自动填充功能,方便用户输入,提升用户的体验,一般和QLineEdit与QComboBox搭配起来使用.先来个最简单的示例:QStringListword_l......
  • Linux 静态库、动态库
    静态库静态库本质就是一个.o文件,命名为libxxx.a创建静态库:gcc-cadd.c#默认生成add.o文件gcc-c-olibadd.aadd.c#这就是标准的静态库文件arrcslibfu......
  • qt中json字符串的读写
    1、json字符串: 2、写json:  3读json:  ......