Qt Translation 遇到的一些问题总结

2023-11-05

官方文档 Internationalization with Qt
贴一个比较好的总结 Qt中,软件多语言国际化翻译的方法与步骤


坑1:无法生成ts文件

实测在VS2013+QT 5.9上,点击Create New Translation File无法生成ts文件
在这里插入图片描述
提示ExitCode 1
在这里插入图片描述
注:在VS2015+Qt5.12上就没有问题

注:在新电脑上可以生成了(win11,应该跟系统没关?),但无法lupdate和lrelease

因此只能通过qt cmd的方式生成,首先在VS中生成.pro文件,然后在.pro最后添加ts文件

TRANSLATIONS += xxxxx_zh.ts\
	xxxxx_en.ts

运行qt cmd,输入 lupdate pro文件路径
在这里插入图片描述
此处会警报,解决办法见 Qt cmd警告 WARNING: Project ERROR: Cannot run compiler ‘cl‘ 解决办法

WARNING: Project ERROR: Cannot run compiler 'cl'. Output:
===================
===================
Maybe you forgot to setup the environment?

生成.ts文件,把ts文件拖进VS就会自动用Linguist打开

Info: creating stash file C:\Qt\Qt5.9.7\5.9.7\msvc2013_64\.qmake.stash
Updating 'xxxxxx/xxxxx_zh.ts'...
    Found 16 source text(s) (16 new and 0 already existing)
Updating 'xxxxxx/xxxxx_en.ts'...
    Found 16 source text(s) (16 new and 0 already existing)

VS里的lrelease也不能用了,把上面cmd指令里的lupdate 改为lrelease 运行即可
在这里插入图片描述
生成.qm文件

Info: creating stash file C:\Qt\Qt5.9.7\5.9.7\msvc2013_64\.qmake.stash
Updating 'xxxxxx/xxxxx_zh.qm'...
    Generated 2 translation(s) (0 finished and 2 unfinished)
    Ignored 14 untranslated source text(s)
Updating 'xxxxxx/xxxxx_en.qm'...
    Generated 0 translation(s) (0 finished and 0 unfinished)
    Ignored 16 untranslated source text(s)

上面显示unfinished是因为在Linguist中没有确认,此时ts文件中会显示<translation type="unfinished">,确认后会取消unfinished标记
在这里插入图片描述

上面的过程可以简化为三个批处理文件:run_qt_cmd.bat打开qt cmd窗口,cmd_lupdate.bat生成.ts文件,cmd_lrelease.bat生成.qm文件,以下给出批处理文件:
(以QT5.9+MSVC2013 X64为例)
run_qt_cmd.bat

C:\Windows\System32\cmd.exe /A /Q /K C:\Qt\Qt5.9.7\5.9.7\msvc2013_64\bin\qtenv2.bat

这一串命令可以通过cmd快捷方式获得
在这里插入图片描述
在这里插入图片描述

cmd_lupdate.bat

set path=C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin;C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\x86_amd64;%path%
lupdate pro文件路径

cmd_lrelease.bat

set path=C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin;C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\x86_amd64;%path%
lrelease  pro文件路径

使用方法:首先运行run_qt_cmd.bat打开cmd窗口,需要生成ts文件时将cmd_lupdate.bat拖进cmd;需要生成qm文件时将cmd_lrelease.bat拖进cmd


坑2:ts文件的中文乱码

用Linguist打开ts文件,里面的中文显示乱码。
在这里插入图片描述

ts文件本质就是一个xml,<?xml version="1.0" encoding="utf-8"?>,Qt Creator默认编码UTF8,VS则是GB2312,如果源代码里面存在中文的字面量字符串(Literal String),如tr("中文字符串"),lupdate会自动将中文字符串转为UTF8从而导致乱码
查看官方文档QObject::tr

[static] QString QObject::tr(const char *sourceText, const char *disambiguation = Q_NULLPTR, int n = -1)
Returns a translated version of sourceText, optionally based on a disambiguation string and value of n for strings containing plurals; otherwise returns QString::fromUtf8(sourceText) if no appropriate translated string is available.

QObject::tr会按照UTF8读取文本

所以,源代码中待翻译的文本(用tr包含的字符串),使用拉丁字母表示,可以是文本对应的英文的大概意思,甚至是中文拼音,只要方便翻译人员在Linguist中对照即可

注:.ui文件里的中文没问题,即qt designer里面的中文,因为它本身是按照UTF-8保存的


坑3:不能直接翻译全局变量、静态变量、符号常量字符串

因为全局变量、静态变量初始化发生在QTranslator::installTranslator之前,Qt无法替换(翻译)这些变量。而通过QT_TR_NOOP宏可以标识出静态生存期变量,让Qt可以晚一些再翻译这些变量,称为delayed translation,见官方文档QT_TR_NOOP的说明:

QT_TR_NOOP(sourceText)
Marks the UTF-8 encoded string literal sourceText for delayed translation in the current context (class).
The macro tells lupdate to collect the string, and expands to sourceText itself.

官方的示例:

QString FriendlyConversation::greeting(int type)
{
    static const char *greeting_strings[] = {
        QT_TR_NOOP("Hello"),
        QT_TR_NOOP("Goodbye")
    };
    return tr(greeting_strings[type]);
}

注意它明确提到 in the current context (class),例子中的静态字符串位于FriendlyConversation类作用域中,显然FriendlyConversation要不是QObject对象,要不是经过声明了Q_DECLARE_TR_FUNCTIONS宏,翻译动作始终需要由
QCoreApplication::translate来完成。Q_DECLARE_TR_FUNCTIONS的宏定义如下:

#define Q_DECLARE_TR_FUNCTIONS(context) \
public: \
    static inline QString tr(const char *sourceText, const char *disambiguation = Q_NULLPTR, int n = -1) \
        { return QCoreApplication::translate(#context, sourceText, disambiguation, n); } \
    QT_DECLARE_DEPRECATED_TR_FUNCTIONS(context) \
private:

对于常量字符串、符号常量字符串,它们甚至在编译时就被编译器替换好了,就更不可能经QCoreApplication::translate翻译了。像下面的做法都是徒劳:

#define DEFINE_MESSAGE_ QT_TR_NOOP("Failed to 1")
const char *kConstMessage = QT_TR_NOOP("Failed to 2");
static const char *kStaticConstMessage = QT_TR_NOOP("Failed to 3");
...
	QMessageBox::critical(nullptr, tr("Error"), tr(DEFINE_MESSAGE_);
	QMessageBox::critical(nullptr, tr("Error"), tr(kConstMessage);
	QMessageBox::critical(nullptr, tr("Error"), tr(kStaticConstMessage);
...

一种替代方案是通过一个类封装全局变量,并将类声明Q_DECLARE_TR_FUNCTIONS宏或者继承QObject

//GlobalMessageWarpper.h
class GlobalMessageWarpper
{
	Q_DECLARE_TR_FUNCTIONS(GlobalMessageWarpper)
public:
	static QString message() { return tr(kMessage); }
	static const char* kMessage;
};
//GlobalMessageWarpper.cpp
const char* GlobalMessageWarpper::kMessage = QT_TR_NOOP("Failed to ...");
//main.cpp
...
QMessageBox::critical(nullptr, tr("Error"), GlobalMessageWarpper::message());
...
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Qt Translation 遇到的一些问题总结 的相关文章

随机推荐

  • 限制服务器显示ip段,限制网段中的某段IP访问Samba服务器

    今天在百度知道看到这样一个问题 linux samba服务如何限制指定网段访问 例如 允许192 168 1 0网段访问 但不允许192 168 1 100 192 168 1 170访问 这个问题与我之前的一篇文章 Samba访问控制 貌
  • Android开发edittext输入监听

    在开发Android的过程中 对于edittext的使用频率还是挺高的 比如用户账号密码的输入 基本信息的填写 数据的填入等 一般都会通过button点击事件对其数据进行提取 不过在一些场景 需要实时监听或者当输入完毕之后要马上获取用户所输
  • 逻辑回归和SVM的区别

    1 LR采用log损失 SVM采用合页损失 2 LR对异常值敏感 SVM对异常值不敏感 3 在训练集较小时 SVM较适用 而LR需要较多的样本 4 LR模型找到的那个超平面 是尽量让所有点都远离他 而SVM寻找的那个超平面 是只让最靠近中间
  • FFmpeg从入门到入魔(2):保存流到本地MP4

    1 FFmpeg裁剪移植 之前我们简单地讲解了下如何在Linux系统中编译FFmpeg 但是编译出来的so体积太大 而且得到的多个so不便于使用 本节在此基础上 将详细讲解在编译FFmpeg时如何对相关模块作裁剪以精简so的体积 并且编译只
  • 文档权限服务器上,服务器上的权限

    服务器上的权限 内容精选 换一换 数据库安全服务与其他云服务的关系的依赖关系如图1所示 数据库安全服务实例创建在弹性云服务器上 用户可以通过该实例 为弹性云服务器上的自建数据库提供安全审计功能 数据库安全服务可以为关系型数据库服务中的RDS
  • Css:Conditional comments(条件注释)

    http msdn microsoft com en us library ms537512 VS 85 aspx http www quirksmode org css condcom html Item Example Comment
  • 23黑马QT笔记之猜数字游戏答案

    23黑马QT笔记之猜数字游戏答案 代码在自己写的day04的第一个项目 想要代码的直接评论 写上自己的邮箱 不要像以前发私信了 因为CSDN有时消息不同步 或者看了之后忘了
  • Flask基础: 增删改查

    app py 实现数据库的增删改查 from flask import make response request session abort jsonify from config settings import Config from
  • 隐藏导航条底部的黑线(shadowImage)四种办法

    方法一 当设置navigationBar的背景图片时移除黑线的方法 该方法会使translucent属性失效 objc view plain copy 方法一 当设置navigationBar的背景图片时移除黑线的方法 该方法会使trans
  • Python操作redis及redis的操作命令

    Python操作redis及redis的操作命令 Python操作redis https www cnblogs com melonjiang p 5342505 html https www cnblogs com xiaojing201
  • 实战Java高并发程序设计(第二版)-chp4锁

    多线程引用 需要维护并行数据结构间的一致性状态 需要为线程的切换和调度花费时间 参考 实战Java高并发程序设计 第二版 Unsafe类详解 java cas算法实现乐观锁 4 1 合理的锁性能 4 1 1 减少锁持有时间 原有的程序 对整
  • Linux搭建服务器

    文章目录 Linux搭建服务器 1 基础环境配置 1 1配置centos7 1 2安装xshall 1 3安装xftp7 2 配置jdk 1 8 第一步 卸载系统自带的OpenJDK以及相关的java文件 第二步 下载最新稳定JDK 第三步
  • Vue路由守卫(拦截)

    要解决的问题 最近做项目时 发现不登录账号和密码 在浏览器的地址栏直接输入路径也能跳转页面 就聊一下路由守卫吧 也叫路由拦截 话不多少 直接看操作 解决方案 在登录成功后 设置一个sessionStorage 通过这个sessionStor
  • vue可视化管理工具创建项目报错解决errno: -4058;连接超时

    vue可视化管理工具创建项目报错解决errno 4058 简介 vue创建项目时 errno 4058问题解决 使用vue ui指令时会报连接超时问题解决 总共两种解决方案 基础材料 使用的node js版本 18 12 1 vue版本 4
  • Pgsql:多表关联update更新字段和delete删除记录

    一 想用多表关联查询并且update更新指定字段 1 两表关联更新示例 UPDATE t user bank b SET is active 是 FROM t user arch u WHERE u arch id b arch id an
  • 浅拷贝和深拷贝的区别

    浅拷贝和深拷贝 总结 浅拷贝对象数据共享 深拷贝是一个完全独立的对象 因此对象数据不共享 浅拷贝 Shallow Copy 浅拷贝是指创建一个新的对象 但是该新对象只是原始对象的一个副本 具体而言 浅拷贝会创建一个新的对象 并将原始对象的引
  • matlab 载波调制,考虑载波和采样频率的2PSK调制 MATLAB仿真

    功能 生成psk调制信号 创建日期 2016 7 27 创建人 Alice 764499604 qq com clear all close all clc max 100 g zeros 1 max g randint 1 max 长度为
  • 5000月薪与50000月薪的Linux运维的区别

    做 运维 感觉像网管怎么办 新工作运维3个多月 天天就是维护重启服务器 更新代码 感觉这样下去几年后就没有什么竞争力了 这是知乎的一个热门运维问题 也是很多刚进入运维工作的同学面临的心境 确实 运维 可能是分水岭最明显的职位之一 有的人毕业
  • Docker修改容器内部文件的方法

    Docker修改容器内部文件的方法一共有三种 下面进行一一介绍 1 进入容器内部修改 使用下面的命令以命令行的形式可以进入容器的内部对文件进行修改 docker exec it 容器ID bin bash 不过里面没有vim 需要自行安装
  • Qt Translation 遇到的一些问题总结

    文章目录 坑1 无法生成ts文件 坑2 ts文件的中文乱码 坑3 不能直接翻译全局变量 静态变量 符号常量字符串 官方文档 Internationalization with Qt 贴一个比较好的总结 Qt中 软件多语言国际化翻译的方法与步