嵌入式攻城狮_RayJie

嵌入式攻城狮_RayJie

一、多语言界面设计

1.多语言界面设计概述

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

Qt 开发多语言界面应用程序的步骤

  • 在程序设计阶段,程序代码中每一种用户可见的字符串都,以便 Qt 提取界面字符串用于生成翻译资源文件。用 Ul 设计器可视化设计窗体时统一用一种语言,如汉语。
  • 在项目配置文件(.pro文件),,
  • 使用工具扫描项目文件中需要翻译的字符串,并生成翻译文件。
  • 使用 打开生成的翻译文件,将程序中的字符串翻译为需要的语言,如将所有中文字符串翻译为英文
  • ==使用 lrelease 工具编译翻译好的翻译文件,生成更为紧凑的 “.qm” 文件
  • 在应用程序中用 QTranslator 类调用不同的 “.qm” 文件,实现不同的语言界面。

2.tr函数的使用

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

  tr() 函数的定义是:

[static] QString QObject::tr(const char *sourceText, const char *disambiguation = nullptr, int n = -1)
  • 函数说明:

    如果存在 sourceText 的翻译版本,则返回翻译后的文本;如果没有则返回 sourceText 的 UTF-8 编码字符串。

  • 参数说明:

    • 参数 sourceText:表示源字符串

    • 参数disambiguation:是为翻译者提供额外信息的字符串,用于对一些容易混淆的地方作说明

    • 参数n:可选参数,用于处理含有复数形式的文本

  • 示例:

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

    • 尽量使用常量字符串,不要使用字符串变量。在 tr() 函数中应该直接传递字符串常量,而不是用变量传递字符串

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

      const char *cities[4] = {Qt_TR_NOOP("Beijing"),
                          Qt_TR_NOOP("Shanghai"),
                          Qt_TR_NOOP("Qingdao"),
                          Qt_TR_NOOP("Wuhan")  };
      
      for (int i = 0; i < 4; i++)
      	comboBox->addItem(tr(cities[i]));
      
    • tr() 函数不能使用拼接的动态字符串

      错误的方式:

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

      正确的方式:

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

      用 QString 的 arg() 去替换占位符 “%1” 的内容。

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

      DEFINES += Qt_NO_CAST_FROM_ASCII
      

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

3. 生成语言翻译文件

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

  首先,在项目的配置文件中增加如下的设置语句:

TRANSLATIONS = trans_cn.ts \
            trans_en.ts

这里设置生成两个语言翻译文件 “trans_cn.ts” 和 “trans_en.ts” 分别是中文和英文翻译文件。文件名称可以任意设计,只要有所区分即可。

  然后,为了使用lupdate工具来扫描源代码中的tr()函数调用,并生成.ts格式的翻译文件。需要对项目中的字符串全部采用 tr() 函数封装,对于不符合 tr() 函数使用规则的地方进行修改。例如:

LabCellPos->setText(tr("当前单元格:%1 行,%2 列").arg(current.row()).arg(current.column()));

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

Qt基础 | 多语言界面设计-LMLPHP

Qt基础 | 多语言界面设计-LMLPHP

4.使用 Qt Linguist 翻译 ts 文件

  生成的 trans_cn.ts 和 trans_en.ts 文件内包含了项目源程序和 UI 界面里的所有字符串,使用 Qt Linguist 软件可以将这些字符串翻译为需要的语言版本。trans_cn.ts是中文界面的翻译文件,由于源程序的界面就是用中文设计的,所以无需再翻译。trans_en.ts是英文翻译文件,需要将提取的所有中文字符串翻译为英文。

  使用 Qt Linguist 软件打开文件 trans_en.ts,当第一次打开一个 ts 文件时,Linguist 会出现如下所示的语言设置对话框,用于设置目标语言和所在国家和地区。这个对话框也可以通过 Linguist 主菜单 “编辑“ --> “翻译文件设置” 菜单项调出。

Qt基础 | 多语言界面设计-LMLPHP

  打开 trans_en.ts 文件后的 Qt Linguist 软件界面如下:

Qt基础 | 多语言界面设计-LMLPHP

  • 左侧 “上下文” 列表里列出项目中的所有窗口或类
  • “字符串” 列表列出了从项目的 UI 窗口和代码文件中提取的字符串
  • 右侧 “短语和表单” 会显示窗口界面的预览或字符串在源程序中出现的代码段

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

Qt基础 | 多语言界面设计-LMLPHP

5.生成 qm 文件

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

Qt基础 | 多语言界面设计-LMLPHP

Qt基础 | 多语言界面设计-LMLPHP

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

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

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("D:/Project/QtProject/trans/trans_en.qm");
    else
        trans->load("D:/Project/QtProject/trans/trans_cn.qm");
    app.installTranslator(trans);

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

QString readSetting()
{
    QString organization="WWB-Qt";//用于注册表,
    QString appName="trans"; //HKEY_CURRENT_USER/WWB-Qt/trans
    QSettings  settings(organization,appName);//创建
    settings.setValue("Language","EN");	 //调整这个值可分别创建英文与中文界面
    QString Language=settings.value("Language","CN").toString();//读取Language键的值
    return  Language;
}
  • readSetting() 函数,用于从注册表里读取设置的界面语言版本,注册表里数据的读取和写入使用到 QSettings 类。
  • main() 函数中,调用 readSetting() 函数从注册表中读取界面语言版本,然后用 load() 函数载入对应的翻译文件,最后,调用 installTranslator() 函数为应用程序安装翻译器,实现需要的界面版本。

动态切换语言

  在软件运行时可以动态切换语言,即无需重启软件就可以切换界面语言。一个应用程序只能加载一个翻译器,因为在 main() 函数里已经加载了一个翻译器,所以需要先移除当前的翻译器,才能重新创建新的翻译器,加载翻译文件,并为应用程序重新加载新翻译器。完成这些后还必须调用 UI 的 retranslateUi() 函数来刷新界面。

void MainWindow::on_actLang_CN_triggered()
{//中文界面
    qApp->removeTranslator(trans);
    delete trans;

    trans=new QTranslator;
    trans->load("C:/Users/85733/Desktop/QT5.12Samp2019/chap16Aux/samp16_1MultiLanguage/samp16_1_cn.qm");
    qApp->installTranslator(trans);
    ui->retranslateUi(this);

    QSettings   settings("WWB-Qt","trans"); //注册表键组
    settings.setValue("Language","CN"); //界面语言,汉语
}

void MainWindow::on_actLang_EN_triggered()
{//英文界面
    qApp->removeTranslator(trans);
    delete trans;

    trans=new QTranslator;
    trans->load("C:/Users/85733/Desktop/QT5.12Samp2019/chap16Aux/samp16_1MultiLanguage/samp16_1_en.qm");
    qApp->installTranslator(trans);
    ui->retranslateUi(this);

    QSettings   settings("WWB-Qt","trans"); //注册表键组
    settings.setValue("Language","EN"); //界面语言,英语
}

大型软件的多语言设计

  大型的软件在重新设置语言版本后,一般要求重新启动软件才生效 ,在程序启动时根据上次的设置加载一次翻译器即可。代码如下:

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("D:/Project/QtProject/trans/trans_en.qm");
    else
        trans->load("D:/Project/QtProject/trans/trans_cn.qm");
    app.installTranslator(trans);

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

QString readSetting()
{
    QString organization="WWB-Qt";//用于注册表,
    QString appName="trans"; //HKEY_CURRENT_USER/WWB-Qt/trans
    QSettings  settings(organization,appName);//创建
    QString Language=settings.value("Language","CN").toString();//读取Language键的值
    return  Language;
}

当点击工具栏按钮进行中文和英文的界面切换时,只修改注册表的值,不删除当前的翻译器。

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

    QSettings   settings("WWB-Qt","trans"); //注册表键组
    settings.setValue("Language","CN"); //界面语言,汉语
}

void MainWindow::on_actLang_EN_triggered()
{//英文界面

    QSettings   settings("WWB-Qt","trans"); //注册表键组
    settings.setValue("Language","EN"); //界面语言,英语
}
07-31 20:31