Bootstrap

Qt 多语言

Qt 帮助文档
Qt5.9 c++ 开发指南

1. 多语言介绍

Qt 帮助文档介绍:
Qt 多语言

2. 多语言实现

2.1 将 .qm 文件拷贝到构建目录

QT 多语言无法切换问题 load失败 路径无效

.qm语言文件必须在构建目录中与.exe文件同一路径:

假如工程文件的路径为 D:\sample_code,工程的名字为 demo
则构建的目录为 D:\sample_code\build-demo-Desktop_Qt_5_14_2_MSVC2017_32bit-Debug

工程文件 .pro 中设置:

DESTDIR += bin
srcDir= $$system_path($$PWD)

TRANSLATIONS  = demo_ch.ts\
                               demo_en.ts

QMAKE_POST_LINK += xcopy   $$srcDir\*.qm $$DESTDIR /y/S &\

DESTDIR 设置可执行文件存放的位置,假如构建目录为H:\test\qt\build-QLabel Desktop_Qt_5_14_2_MSVC2017_32bit-Debug,在Debug模式,默认可执行文件在构建目录的子目录的debug文件夹中,如果做如下设置:

DESTDIR += bin

则可执行文件在构建目录中建立一个bin文件夹(和 debug 文件在同一目录),可执行文件在bin目录中

PWD 当前工程文件所在的路径
如:工程 QLabel.pro 所在的目录为 H:\test\qt\QLabel, 则该变量的值为:

message(PWD: $$PWD)

编译输出:

Project MESSAGE: PWD: H:/test/qt/QLabel

注意路径中的分隔符为 Qt 的分隔符,不是 windows 分隔符,如果要转换 Windows 系统的分隔符,如下:

#system_path(path) 将路径中的分隔符转换为系统的分隔符
makefilePath = $$system_path($$OUT_PWD)
message(OUT_PWD: $$OUT_PWD)
message(makefilePath: $$makefilePath)

编译输出:

Project MESSAGE: OUT_PWD: H:/test/qt/build-QLabel-Desktop_Qt_5_14_2_MSVC2017_32bit-Debug
Project MESSAGE: makefilePath: H:\test\qt\build-QLabel-Desktop_Qt_5_14_2_MSVC2017_32bit-Debug

DESTDIR 默认为构建目录,放置包括可执行文件的目录,上述代码会将目录设置为:

D:\sample_code\build-demo-Desktop_Qt_5_14_2_MSVC2017_32bit-Debug\bin

QMAKE_POST_LINK 语句中的 & 用于执行多条命令,如果后面还有命令,不管前面的命令是否执行成功都继续往后执行。(cmd-连续执行多条命令
xcopycmd 命令,/y用于取消提示以确认覆盖; /S 后缀用于复制目录和子目录,但不包括空目录,此处可不需要。

注意:路径中不能有空格,如果路径有空格,则不能复制成功,可从 编译输出 中查看命令执行结果,会提示 无效的参数数目

2.2 加载翻译文件

示例:Qt5.9 c++ 开发指南 书示例 samp16_1
代码见: Qt 电子书以及源码 ,提取码:0ufw


QTranslator *translator = NULL;//翻译器
//语言类型
enum LangType
{
    LANG_CH,
    LANG_EN
};

int main(int argc, char *argv[])
{
	QApplication a(argc, argv);
	//获取可执行文件所在的目录
	QString strAppPath = QCoreApplication::instance()->applicationDirPath();
	//根据配置文件或其他方式选择要用的语言版本 demo_cn 或 demo_en 
	LangType type = getLanguageType();
	QString strFileName("");
	if (type == LANG_EN)
		strFileName = "demo_en";
	else
		strFileName = "demo_ch";
  	
	//翻译语言的路径
	QString strFilePath = QString("%1/%2.qm").arg(strAppPath).arg(strFileName);
	//加载翻译语言
	translator->load(strFilePath);
	qApp->installTranslator(translator);
			
	a.exec();

	delete translator;
	
	return 0;
}

3. 翻译 Qt 自带右键菜单

参考:Qt 翻译原生 widgets(QTextEdit 右键菜单等)

Qt 自带 QTextEdit 和 QLineEdit 编辑时右键菜单语言翻译为 widget.ts 文件;使用Qt自带一些对话框,如 QColorDialog 也在该语言文件中翻译。

翻译文件 widget.ts 来源位置:Qt安装文件夹内:Qt\Qt5.14.2\5.14.2\Src\qtbase\src\widgets
如 Qt 安装在 D 盘根目录,则路径为:D:\Qt\Qt5.14.2\5.14.2\Src\qtbase\src\widgets (这里安装 Qt 版本为 5.14.2)
用Qt打开 widgets.pro 工程文件,在 widgets.pro 文件最后添加如下行:

TRANSLATIONS += widgets.ts

用 Qt Linguist 打开 widgets.ts 文件修改并发布 (不用 Qt中用 工具-外部-Qt语言家 来更新发布该文件翻译)
如果将 widget.ts 添加到应用程序的工程文件中,用Qt中的 工具-外部-Qt语言家 更新翻译,则之前用 Qt 语言家打开 widgets.ts 文件后发现之前翻译的部分变灰色了?应用程序中右键菜单还是英文的。

如果要几种语言切换,可以将原始未修改的英文版本的 .ts 生成 .qm 文件,分别命名为 widgets_en.ts,和 widgets_en.qm;然后将修改后的中文版本命名为 widgets_ch.ts 和 widgets_ch.qm,将这四个文件拷到应用程序的工程目录和其他翻译文件放一起。

最后在程序中加载翻译文件:


QTranslator *translator = NULL;//翻译器
QTranslator *translatorMenu = NULL; //Qt 自带右键菜单翻译

//语言类型
enum LangType
{
    LANG_CH,
    LANG_EN
};

int main(int argc, char *argv[])
{
	QApplication a(argc, argv);
	//获取可执行文件所在的目录 
	QString strAppPath = QCoreApplication::instance()->applicationDirPath();
	//根据配置文件或其他方式选择要用的语言版本 
	LangType type = getLanguageType();
	QString strAppLangFile(""), strWidgetsLangFile("");
	if (type == LANG_EN)
	{
		strAppLangFile= "demo_en";
		strWidgetsLangFile = "widgets_en";
	}
	else
	{
		strAppLangFile= "demo_ch";
		strWidgetsLangFile = "widgets_ch";
	}

	//加载右键菜单翻译文件
	translatorMenu->load(strAppPath + "/" + strWidgetsLangFile  + ".qm");
	qApp->installTranslator(translatorMenu);
	
	//翻译语言的路径
	QString strFilePath = QString("%1/%2.qm").arg(strAppPath).arg(strAppLangFile);
	//加载翻译语言
	translator->load(strFilePath);
	qApp->installTranslator(translator);
	
	a.exec();

	delete translator;
	delete translatorMenu;
	
	return 0;
}

4. 动态切换语言

参考:Qt实现动态切换语言


//移除原来的翻译文件
qApp->removeTranslator(translator);
//重新加载翻译文件,load 会丢弃原来的翻译文件
translator->load(strFile);
qApp->installTranslator(translator);

/*****************************************************
重新翻译当前页面  这个函数在 ui_filename.h 中,是有 ui 的话自动生成的,在 setupUi 函数中调用
如果有 ui 文件,则在 .cpp 文件中会有一条语句: ui->setupUi(this); 
函数 retranslateUi 其实就是将 ui 界面中语言翻译,如:

Widget->setWindowTitle(QCoreApplication::translate("Widget", "Widget", nullptr));
label->setText(QCoreApplication::translate("Widget", "label", nullptr));
pushButton->setText(QCoreApplication::translate("Widget", "button", nullptr));

因此,如果有些界面的翻译是在代码中设置的,如:
ui->label->setText(tr("label");
则 retranslateUi 不会更新该翻译,只会更新为界面设置的翻译
******************************************************/

ui->retranslateUi(this);
//如果有代码中翻译的部分,可以将这些翻译的部分放在一个函数中重新翻译一遍
updateCodeTrans();

//在更改语言的页面重新加载翻译文件,并更新该界面的翻译后,
//如果还有其他界面,则通过 changeEvent 识别修改翻译状态
void MainWindow::changeEvent(QEvent *e)
{
    QWidget::changeEvent(e);
    switch(e->type()) 
    {
        case QEvent::LanguageChange:
            ui->retranslateUi(this);
            updateCodeTrans(); //更新代码中的翻译
            break;
        default:
            break;
    }
}
;