• Qt翻译(本地化)坑总结


    官方文档 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
    
    • 1
    • 2

    运行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?
    
    • 1
    • 2
    • 3
    • 4

    生成.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)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    上面显示unfinished是因为在Linguist中没有确认,此时ts文件中会显示,确认后会取消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
    
    • 1

    这一串命令可以通过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文件路径
    
    • 1
    • 2

    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文件路径
    
    • 1
    • 2

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


    坑2:ts文件的中文乱码

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

    ts文件本质就是一个xml,,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]);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    注意它明确提到 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:
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    对于常量字符串、符号常量字符串,它们甚至在编译时就被编译器替换好了,就更不可能经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);
    ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    一种替代方案是通过一个类封装全局变量,并将类声明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());
    ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
  • 相关阅读:
    Cmake常用命令(二)
    多智能体强化学习设计20231108
    Kubernetes(K8s):未来云原生应用的引擎
    Github每日精选(第67期):go语言必须跳过的坑100-go-mistakes
    JS逆向——建筑市场监管公共服务平台
    redis7.0源码阅读:redis的基本存储结构
    99%的亚马逊运营都不知道爆单小技巧——社媒促销代码
    flutte: 可滚动列表
    Elastic Stack 8.0 安装 - 保护你的 Elastic Stack 现在比以往任何时候都简单
    26 | 信任始于握手:TLS1.2连接过程解析
  • 原文地址:https://blog.csdn.net/Kelvin_Yan/article/details/127935306