在 translations.qrc 文件中读取翻译器文件 .ts/.qm

Posted

技术标签:

【中文标题】在 translations.qrc 文件中读取翻译器文件 .ts/.qm【英文标题】:Read translator file .ts/.qm on translations.qrc file 【发布时间】:2017-04-10 15:10:01 【问题描述】:

我正在尝试在我的 Qt 项目中导入翻译文件(Linux 系统上的 Qt 5.6),但我无法上传翻译文件,因为 QTranslator::load 方法总是返回 false

我有以下“testTrl”项目结构:

在项目根目录我有“resources”文件夹,其中包括“qml.qrc”、“translations.qrc”和“translations”文件夹:

/resources/qml.qrc
/resources/translations.qrc
/resources/translations/testTrl_it.ts
/resources/translations/testTrl_it.qm
/resources/translations/testTrl_en.ts
/resources/translations/testTrl_en.qm
...

我已经通过“lrelease”和“lupdate”命令获得了“.ts”和“.qm”文件。

项目文件:

testTrl.pro 文件:

TEMPLATE = app

QT += qml quick core widgets
CONFIG += c++11

SOURCES += main.cpp

RESOURCES += $$PWD/resources/qml.qrc \
             $$PWD/resources/translations.qrc

TRANSLATIONS += $$PWD/resources/translations/testTrl_it.ts \
                $$PWD/resources/translations/testTrl_en.ts

# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =

# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =

# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

# Default rules for deployment.
qnx: target.path = /tmp/$$TARGET/bin
else: unix:!android: target.path = /opt/$$TARGET/bin
!isEmpty(target.path): INSTALLS += target

translations.qrc 文件:

<RCC>
    <qresource prefix="/translations" lang="it">
        <file alias="testTrl.qm">translations/testTrl_it.qm</file>
    </qresource>
    <qresource prefix="/translations" lang="en">
        <file alias="testTrl.qm">translations/testTrl_en.qm</file>
    </qresource>
</RCC>

main.cpp 文件:

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QTranslator>
#include <QDebug>

int main(int argc, char *argv[])

    QGuiApplication app(argc, argv);

    QTranslator translator;

    const QString lang = "en";
    QLocale::setDefault(lang);

    bool isTrlsFileLoaded = translator.load(":/translations/testTrl.qm");

    if(!isTrlsFileLoaded) 
        qDebug() << "FILE NOT LOADED";
    
    else 
        qDebug() << "FILE LOADED";
        qApp->installTranslator(&translator);
    

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();

“isFileTranslatorLoaded”始终为“假”。我该如何解决这个问题?

【问题讨论】:

你确定资源文件被编译成二进制文件吗? 试试我的解决方案:P 【参考方案1】:

首先,您的 .qrc 文件写入错误:第二个标签 &lt;qresource&gt; 应该是 &lt;/qresource&gt;,最后一个 &lt;RCC&gt; 应该是 &lt;/RCC&gt;

虽然你的源代码是部分的,但我猜你正在寻找的行是

bool isFileTranslatorLoaded = translator->load(":/translations/translations/app_it.qm");

QTranslator::load 只能加载已编译的 (.qm) 文件。从资源中删除 .ts 文件(此外,这是一种安全措施,因为它们通常会暴露您的项目结构、源代码行等的一部分)。

另一种方法

作为建议,您可以通过在资源文件中设置语言来减少加载翻译时的关联代码。

<RCC>
  <qresource prefix="/translations">
    <file alias="app.qm">translations/app_en.qm</file>
  </qresource>
  <qresource prefix="/translations" lang="it">
    <file alias="app.qm">translations/app_it.qm</file>
  </qresource>
</RCC>

然后,您只需加载一个通用翻译器:

bool isFileTranslatorLoaded = translator->load(":/translations/app.qm");

Qt 会为当前语言环境使用适当的文件。它对于在设计时指定的其他资源(例如图像)特别有用,或者只是为了减少代码混乱。

注意:请注意,alias 允许您根据需要删除双重 translations/translations

设置区域设置

如前所述,上面的代码使用当前语言环境从资源中选择正确的文件。翻译加载器可能看起来像

bool loadTranslationsForLanguage(const QString& lang) 
  QLocale::setDefault(lang);

  std::unique_ptr<QTranslator> translator(new QTranslator());
  if (!translator->load(":/translations/app.qm")) return false;

  qApp->installTranslator(translator.release()); // possible memory-leak, see below

  return true;

有关在this answer 中设置语言环境的更多信息。

更换译员

如果您已经加载了翻译器,那么您将面临新的挑战,因为 Qt 将允许您安装新的翻译器,但会继续使用旧文件(搜索翻译时,它会在第一次匹配时停止)。

要实现语言更改,您必须跟踪已安装的所有翻译器,并在切换时将其删除。

std::unique_ptr<QTranslator> m_currentTranslator; // use one for each .qm

bool loadTranslationsForLanguage(const QString& lang) 
  QLocale::setDefault(lang);

  std::unique_ptr<QTranslator> translator(new QTranslator());
  if (!translator->load(":/translations/app.qm")) return false;

  qApp->removeTranslator(m_currentTranslator.get());
  qApp->installTranslator(translator.get());
  m_currentTranslator.swap(translator);

  return true;

【讨论】:

我遵循了您的建议,但 isFileTranslatorLoaded 始终返回 false。我修改了我的源代码: bool isFileTranslatorLoaded = translate->load(":/translations/navisit.qm");资源文件是:translations/navis_it.qmtranslations/navis_en.qm 我不知道... 好的,两点:去掉别名中的it和en后缀,两个别名应该一样:navis.qm。另一方面,您是否在加载自定义翻译之前设置了当前语言环境? QLocale::setDefault("it"); 之类的东西? 不,我没有设置 QLocale。在调用加载函数之前,如何在 main.cpp 文件中配置 QLocale?感谢您的建议 没什么,我已经听从了你的建议,但是 .qm 文件没有加载,可能是 qt 5.6 套件有问题。如doc.qt.io/qt-5/qtlinguist-hellotr-example.html 所述,我还在 Windows 上创建了一个项目,但加载 .qm 文件失败。我不知道如何使用 qtranslator。这似乎很容易,但行不通。 这并不难,在某些时候可能会很棘手,但并不难。我已经使用它们好几年了,非常棒。可能还有很多其他的失败点,所以我建议你编辑你的问题并发布一个minimal reproducible example,这是一个简单的项目,它有一个派生自QObject 的类,并在构造函数中使用类似qDebug() &lt;&lt; tr("Hello world!"); 的东西。在您的main() 函数中,只需创建QApplication,加载翻译,创建类并退出(字符串将在构造函数中打印出来)。然后,运行lupdatelrelease 工具来创建翻译。

以上是关于在 translations.qrc 文件中读取翻译器文件 .ts/.qm的主要内容,如果未能解决你的问题,请参考以下文章

深入理解计算机系统 1.4 处理器读取和解释存储在内存中的指令

Linux命令之查看日志等实时文件命令(less tail)使用

中文文件如何翻译为英文

JSX 文件中的“ ”在某些浏览器中被翻译为“”

Linux之文件内容查看

文件查看命令