Qt 多语言程序设计的实现

目录
  • 简介
  • 1.tr()函数使用
  • 2.生成语言翻译文件
  • 3.使用 Qt Linguist 翻译 ts 文件
  • 4.调用翻译文件改变界面语言

简介

有些软件需要开发多语言界面版本,如中文版和英文版,并且在软件里可以方便地切换界面语言。Qt为多语言界面提供了很好的支持,使用Qt的一些规则和工具,可以很方便地为应用程序开发提供多界面支持。

使用Qt 开发多语言界面应用程序,主要包括以下几个步骤 。

(1)在程序设计阶段,程序代码中每 一 个用户可见的字符串都用 tr()函数封装,以便 Qt 提取界面字符串用千生成翻译资源文件。用 UI 设计器可视化设计窗体时统一用 一种语言,如汉语 。

(2)  在项目配置文件 (.pro 文件)中设置需要导出的翻译文件 (.ts 文件)名称,使用lupdate工具扫描项目文件中需要翻译的字符串,并生成翻译文件 。
   (3)  使用 Qt 的 Linguist 程序打开生成的翻译文件,将程序中的字符串翻译为需要的语 言 ,如将所有中文字符串翻译为英文 。
  ( 4)  使用 lrelease 工具编译翻译好的翻译文件, 生成更为紧凑的 ". qm" 文件 。
  ( 5)  在应用程序中用 QTranslator 调用不同的 " .qm" 文件,实现不同的语 言界面。

1.tr()函数使用

为了让 Qt 能自动提取程序中用户可见的字符串,对千每个字符串都需要使用 tr()函数封装 。tr()是 QObject 的 一个静态函数 ,在使用了 Q—OBJECT 宏定义的类或 QObject 的子类中,都可以直接使用 tr()函数,否则需要使用 QObject::tr()进行调用。或者在类定义中用 Q_DECLARE_TR_FUNCTIONS 宏把 tr()函数添加到类中之后 ,再直接调用 tr()函数 。

 tr()函数的定义 :

QString QObject::tr(const char *sourceText, const char *disambiguation=Q_NULLPTR,int  n = -1);

其中, sourceText 是源字符串 disambiguation 是为翻译者提供额外信息的字符串,用于对 些容易混淆的地方作说明,内容如下:

LabCellPos = new QLabel(tr( 当前单元格:"), this);
QMessageBox::information(this, tr("信息"), tr( "信息提示?"), QMessageBox::Yes) ;
QString strl= tr("左右", "大约的意思");
QString str2 = tr("左右", "掌握、控制的意思");

使用 tr()函数,需要注意以下事项。

① 尽量使用常量字符串 不要使用字符串变量。在 tr()函数中应直接传递字符串常量,而不是用变星传递字符串,如下面的代码使用了字符串变量,使用lupdate 工具提取项目中的 字符串时 将不能提取“不能删除 这个字符串。

char *errorStr="不能删除记录";
QString str2=tr(errorStr); 

②使用字符串变量时需要用 Qt_TR_NOOP() 宏进行标记 。若要 tr()函数中使用字符串变量 需要在定义字符串的地方用 Qt_TR_NOOP() 宏进行标记,这在使用字符串数组时比较有用。 例如:

canst char *cities[4]={Qt_TR_NOOP("Beijing"),
    Qt_TR_NOOP(" Shanghai"),
    Qt_TR_NOOP("Qingdao"),
    Qt_TR_NOOP("Wuhan")}; 

for (int i=O; i<4; i++)
{
    comboBox->additem(tr(cities[i])) ;
}

③tr()不能使用拼接的动态字符串。 tr()不能使用拼接的动态字符串,例如,下面的用法是错误的:

LabCellPos->setText(tr("第") + QString::number(current.row())+ tr("行");

正确的方式如下:

LabCellPos->setText(tr("第%1行").arg (current.row()));

翻译的字符串是“第%1行 ”, 然后再用 QString 的arg() 去替换占位符 "%1 "的内容。

④Qt_NO_CAST_FROM_ ASCII 的作用。在一个需要翻译为多语言的应用程序中,如果编写 程序时忘了对某个字符串使用 tr() 函数, lupdate 生成的翻译资源文件就会遗漏这个字符串。 为了避免这种疏忽错误,可以在项目配置文件(. pro 文件)中添加如下的定义:

DEFINES+= Qt_NO_CAST_FROM_ ASCII

这样在编译时,会禁止从 con char* 到QString 的隐式转换 ,强制每个字符串都必须使用 tr()或 QLatinlString()封装, 避免出现遗漏未翻译的字符串。

2.生成语言翻译文件

要生成多语言界面相关的翻译文件,除了之前所说的在对每个字符串 都使用 tr()函数封装之外,还需要在项目配置文件 (.pro 文件)中使用 TRANSLATIONS 定义语言翻译文件 (. ts 文件), 并使用 lupdate 工具生成语言翻译文件。

在项目的配置文件(*.pro)中增加如下的设置语句:

TRANSLATIONS += lang_Chs.ts     \

lang_Eng.ts

在项目设计期间,任何时候都可以使用lupdate 工具生成或更新翻译文件,方法是单击Qt Creator 主菜单的 “Tools”- "External" - "Qt 语言家”- "Update Translations(lupdate)" 菜单项, 若项目的源程序目录下没有lang_Chs.ts、lang_Eng.ts (具体名称可变)这两个文件,就会自动生成,如果 文件已经存在,则会更新这两个文件的内容。

3.使用 Qt Linguist 翻译 ts 文件

生成的 lang_Chs.ts、lang_Eng.ts 文件内包含了项目源程序和 UI 界面里的所有字符 串,使用 Qt Linguist 可以将这些字符串翻译为需要的语言版本。在 Qt 安装后的程序组里可以找到 Qt Linguist 软件。

lang_Chs.ts 是中文界面的翻译文件,由于源程序的界面就是用中文设计的,所以无需再 翻译 lang_Eng.ts 是英文翻译文件,需要将提取的所有中文字符串翻译为英文。

在Linguist 软件中打开文件lang_Eng.ts, 当第一次打开一个 ts 文件时, Linguist 会出现如下图所示的语言设置对话框,用千设置目标语言和所在国家和地区。这个对话框也可以通过 Linguist 主菜单的“编辑“一“翻译文件设置”菜单项调出。lang_Eng.ts 是用于英文界面的翻译文件,所以选择语言 “English", 国家/地区可选择 “UnitedStates”。

打开 lang_Eng.ts 文件后的 Linguist 软件界面如下图所示。左侧”上下文”列表里列出了项目中的所有窗口或类, 这个项目有4个窗口。”字符串”列表里列出了从项目的 UI 窗口和代码文件中提取的字符串,右侧“短语和表单”会显 示窗口界面的预览或字符串在源程序中出现的代码段。

在”字符串”列表中选择一个源文后,在下方会出现译 文编辑框,在此填写字符串对应的英文译文。 Linguist 可以 同时打开项目的多个 ts 文件,在选中一个源文后,在下方会 出现对应的多个语 言的译文编辑框 ,可以同时翻译为多个语言版本。

4.调用翻译文件改变界面语言

4.1. 生成 qm 文件

使用 Linguist 软件编辑翻译文件,将所有字符串都翻译后,在 Qt Creator 中单击主菜单项 "Tools" -- "External" -- "Qt 语言家”-- "Release Translations(lrelease) ",会在项目源程序目录 下生成与 ts 文件对应的 qm 文件,这是更为紧凑的翻译文件。 会生成  lang_Chs.qm和  lang_Eng.qm。

2. 项目启动时设置界面语言

使用 QTranslator 类设置界面的不同语言版本,需在应用程序启动时设置界面语言翻译文件, 即在 main()函数中进行处理 。项目 在main.cpp 的代码如下:

#include "mainwindow.h"
#include <QApplication>
#include <QTranslator>
#include <QSettings> 

QTranslator *trans=NULL ;
QString readSetting(); 

int main (int argc , char *argv[])
{
    QApplication app(argc, argv);
    trans = new QTranslator; 

    QString curLang=readSetting (); //读取语言设置

    if (curLang== "EN")
     {
        trans->load ("lang_Eng.qm");
     }
    else
    {
        trans->load("lang_Chs.qm");
    }

    app.installTranslator(trans); 

    MainWindow w;
    w.show();
    return app.exec();
}

QString readSetting()
{
    //注册表读取上 次设置的语言
    QString organization = "Language";
    QString appName= "test";
    QSettings settings(organization, appName) ;
    QStri n g Language=settings.value ("Language"," EN").toString();
    return Language ;
}

这里定义了 个全局变 trans, main.cpp 里定义了个函数 readSetting(), 用千从注册表里读取上次设置的界面语言版本。注册表里数据的读取和写入使用到 QSettings 类,在main()函数中,创建 QTranslator 类的对象 trans 后,调用 readSetting()函数从注册表里读取 上次的语言版本,若为 “EN" ,就用 load()函数载入编译后的英文翻译文件 lang_Eng.qm, 否则就载入中文翻译文件lang_Chs.qm ,再执行 app.installTranslator(trans) ,就可以给应用程序安装翻译器,实现需要的界面版本。

3. 动态切换语言

在软件运行时可以动态切换语 ,即 启软件就可以切换界面语言,测试程序的主窗 口上有“中文”和 “English" 两个工具栏按钮,用千实现中文和英文界面的切换。 下面是这两个 按钮的响应代码:

void MainWindow::on_actLang_CN_triggered()
{//中文界面

    qApp->removeTranslator(trans); 

    if (trans)
    {
        delete trans;
        trans = NULL;
    } 

    trans = new Qtranslator;
    trans->load("lang_Chs.qm");
    qApp->installTranslator(trans); 

    //这一步很关键
    ui->retranslateUi(this);  //刷新界面字符串

    QSettings settings("WWB-Qt", "test");
    settings.setValue ("Language ", "CN") ;
}

void Maindow::on_actLang_EN_triggered()
{//英文界面
    qApp->removeTranslator(trans) ;
    if (trans)
    {
        delete trans;
        trans = NULL;
    } 

    trans=new Qtranslator;
    trans->load( " sampl6_l_en.qm");
    qApp->installTranslator(trans) ; 

    //这一步很关键
    ui->retranslateUi(this) ; //刷新界面字符串
    QSettings settings( "WWB-Qt","test");
    settings.setValue ("Language", "EN");
}

一个应用程序只能加载一个翻译器 ,因为在 main()函数里已 经加载了一个翻译器 ,所以需 要先移除当前的翻译器,才能重新创建新的翻译器,加载翻译文件,并为应用程序重新加载新翻译器。

完成这些后还必须调用 UI的retranslateUi() 函数来刷新界面。

retranslateUi()函数是在窗口的 ui _" 头文件中自动生成的 ,如 mainwindow. ui 主窗口对应的 头文件 ui _mainwindow.h 里就有函数 retranslateUi(),这个函数使用 QApplication::translate() 函数将 所有界面字符串进行翻译 ,类似于 tr()函数的功能。

窗口在被创建时会自动调用此 retranslateUi() 函数,在程序运行中动态切换界面语言时,必须 手工调用此 retranslateUi() 函数,才可以立即更新界面语言。

若不是用 Designer 设计的窗口,而是完全由代码实现的窗口界面,需要专门设计一个 retranslateUi() 函数,将所有界面字符串用 tr() 函数进行翻译,并在动态切换语言时调用此函数。  很显然 这样做比较麻烦,特别是当软件比较大窗口非常多时。所以,大型的软件在重新设置语言版本后 一般要求重新启动软件才生效 ,在程序启动时根据上次的设置加载一次翻译器即可。

按钮响应代码的最后是将设置的语言版本写入本地配置文件 ,以便下次程序启动时自动加载相应的语言。

到此这篇关于Qt 多语言程序设计的实现的文章就介绍到这了,更多相关Qt 多语言程序设计内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 使用PyQt5设计GUI实现程序图形界面设计

    目录 一.熟悉designer--设计界面的神器 1.首先打开designer. 2.创建窗口 3.熟悉各部功能区域 二.设计自己的第一个GUI. 1.在designer中拖动控件来完善窗口程序. 2.保存为.ui文件 3.将.ui文件转换成.py文件 4.添加程序入口 一.熟悉designer--设计界面的神器 designer是一个强大的GUI设计工具,设计完之后还可以自动生成代码,然后我们将这些代码转换成python代码就可以了,是不是很方便!! 1.首先打开designer. 还记得我们

  • Qt 多语言程序设计的实现

    目录 简介 1.tr()函数使用 2.生成语言翻译文件 3.使用 Qt Linguist 翻译 ts 文件 4.调用翻译文件改变界面语言 简介 有些软件需要开发多语言界面版本,如中文版和英文版,并且在软件里可以方便地切换界面语言.Qt为多语言界面提供了很好的支持,使用Qt的一些规则和工具,可以很方便地为应用程序开发提供多界面支持. 使用Qt 开发多语言界面应用程序,主要包括以下几个步骤 . (1)在程序设计阶段,程序代码中每 一 个用户可见的字符串都用 tr()函数封装,以便 Qt 提取界面字符

  • C语言程序设计谭浩强第五版课后答案(第三章习题答案)

    1.假如我国国民生产总值的年增长率为7%, 计算10年后我国国民生产总值与现在相比增长多少百分比.计算公式为 p = ( 1 + r ) n p = (1+r)^n p=(1+r)n ,其中r为年增长率,n为年数,p为与现在相比的倍数. 题目解析: 此题的关键主要是利用数学库math中pow函数进行计算,若不熟悉可以查阅帮助文档,查看pow函数的用法. 代码示例: #include<stdio.h> #include <math.h> int main() { float p, r

  • C语言程序设计第五版谭浩强课后答案(第二章答案)

    1. 什么是算法?试从日常生活中找3个例子,描述它们的算法 算法:简而言之就是求解问题的步骤,对特定问题求解步骤的一种描述. 比如生活中的例子: 考大学 首先填报志愿表.交报名费.拿到准考证.按时参加考试.收到录取通知书.按照日期到指定学校报到. 去北京听演唱会 首先在网上购票.然后按时坐车到北京,坐车到演唱会会场. 把大象放进冰箱 先打开冰箱门,然后将大象放进冰箱,关冰箱. 2. 什么叫结构化的算法?为什么要提倡结构化的算法? 结构化算法:由一些顺序.选择.循环等基本结构按照顺序组成,流程的转

  • C语言程序设计50例(经典收藏)

    [程序1]题目:有1.2.3.4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?1.程序分析:可填在百位.十位.个位的数字都是1.2.3.4.组成所有的排列后再去 掉不满足条件的排列. 2.程序源代码: 复制代码 代码如下: #include "stdio.h"#include "conio.h"main(){  int i,j,k;  printf("\n");  for(i=1;i<5;i++) /*以下为三重循环*/   

  • 我放弃Python转Go语言的9大理由(附优秀书籍推荐)

    前言 Go大概2009年面世以来,已经8年了,也算是8年抗战.在这8年中,已经有很多公司开始使用Go语言开发自己的服务,甚至完全转向Go开发,也诞生了很多基于Go的服务和应用,比如Dokcer.k8s等,很多的大公司也在用,比如google(作为开发Go语言的公司,当仁不让).Facebook.腾讯.百度.阿里.京东.小米以及360,当然除了以上提到的,还有很多公司也都开始尝试Golang,这其中是什么原因呢?让我们来一起分析分析. 原因 1:性能 Go 极其地快.其性能与 Java 或 C++

  • Go语言正则表达式用法实例小结【查找、匹配、替换等】

    本文实例讲述了Go语言正则表达式用法.分享给大家供大家参考,具体如下: Go语言的正则表达式使用很简单,示例代码: 复制代码 代码如下: package test import (     "fmt"     "regexp" ) func RegixBase() {     //findTest()     //findIndexTest()     //findStringTest()     //findChinesString()     //findNum

  • Go语言使用sort包对任意类型元素的集合进行排序的方法

    本文实例讲述了Go语言使用sort包对任意类型元素的集合进行排序的方法.分享给大家供大家参考.具体如下: 使用sort包的函数进行排序时,集合需要实现sort.Inteface接口,该接口中有三个方法: 复制代码 代码如下: // Len is the number of elements in the collection.  Len() int  // Less reports whether the element with  // index i should sort before t

  • GO语言实现列出目录和遍历目录的方法

    本文实例讲述了GO语言实现列出目录和遍历目录的方法.分享给大家供大家参考.具体如下: GO语言获取目录列表用 ioutil.ReadDir(),遍历目录用 filepath.Walk(),使用方法课参考本文示例. 具体示例代码如下: 复制代码 代码如下: package main import (  "fmt"  "io/ioutil"  "os"  "path/filepath"  "strings" )

  • go语言if/else语句简单用法示例

    本文实例讲述了go语言if/else语句用法.分享给大家供大家参考,具体如下: if else分支在go语言里是简单明了的. 这里有个简单的例子. if语句可以没有else. 可以在条件语句前添加别的语句.这个语句中声明的变量的作用域在所有的分支中. 注意:在go语言中条件语句没必要带圆括号.但是分支中必须有大括号. 在go语言里面没有三元条件语句,所以即使是简单的条件语句你也必须使用全机构的if语句(就是说go里没有个?:表达式 ). 示例代码: 复制代码 代码如下: package main

  • go语言template用法实例

    本文实例讲述了go语言template用法.分享给大家供大家参考.具体分析如下: golang的template包很好用,做一些复杂的文本格式生成太有帮助了,生成网页也是很不错的,使用起来非常方便 复制代码 代码如下: package main import (     "fmt"     "os"     "text/template" ) type Latlng struct {     Lat float32     Lng float32

随机推荐