简体   繁体   English

QT - 嵌入翻译适用于 Windows,不适用于 Linux

[英]QT - embedding translations works on Windows, not on Linux

In the SQLiteStudio I started using CONFIG += lrelease embed_translations for automatically embedding all translations into the app's resources.在 SQLiteStudio 中,我开始使用CONFIG += lrelease embed_translations将所有翻译自动嵌入到应用程序的资源中。 I did so by declaring:我这样做是通过声明:

CONFIG  += lrelease embed_translations
QM_FILES_RESOURCE_PREFIX = /msg/translations
TRANSLATIONS += $$files(translations/*.ts)

This is done for all modules (in their pro files).这是为所有模块完成的(在他们的pro文件中)。 Modules are compiled into shared libraries (such as coreSQLiteStudio , guiSQLiteStudio and then there is a executable module sqlitestudio , which is the application to run and it's dynamically linked to others, so it looks like:模块被编译成共享库(例如coreSQLiteStudioguiSQLiteStudio ,然后有一个可执行模块sqlitestudio ,它是要运行的应用程序,它与其他应用程序动态链接,所以它看起来像:

sqlitestudio                    <- executable (contains *.qm files)
  `- guiSQLiteStudio.so                       (contains *.qm files)
       `- coreSQLiteStudio.so                 (contains *.qm files)

Then in runtime I'm using translation files with Qt's resources system (by call to QTranslator::load() with :/msg/translations/coreSQLiteStudio_pl_PL.qm , :/msg/translations/sqlitestudio_pl_PL.qm , etc).然后在运行时我使用带有 Qt 资源系统的翻译文件(通过调用QTranslator::load():/msg/translations/coreSQLiteStudio_pl_PL.qm:/msg/translations/sqlitestudio_pl_PL.qm等)。

This works well under Windows, but - for some reason - not under Linux.这在 Windows 下运行良好,但 - 由于某种原因 - 在 Linux 下运行良好。 The problem is that under Linux only files from sqlitestudio module (ie sqlitestudio_pl_PL.qm ) are visible under the :/msg/translations prefix, while under Windows also other module translations (ie coreSQLiteStudio_pl_PL.qm , guiSQLiteStudio_pl_PL.qm ) are visible under the same prefix.问题是在 Linux 下,只有来自sqlitestudio模块的文件(即sqlitestudio_pl_PL.qm )在:/msg/translations前缀下可见,而在 Windows 下其他模块翻译(即coreSQLiteStudio_pl_PL.qm下也是可见的)在相同的guiSQLiteStudio_pl_PL.qm下可见字首。

I've debugged TRANSLATIONS += $$files(translations/*.ts) and it is resolved properly for all modules (under Linux too).我已经调试了TRANSLATIONS += $$files(translations/*.ts)并且它已为所有模块正确解析(也在 Linux 下)。 Then I have debugged runtime contents of :/msg/translations and confirmed that only sqlitestudio qm files are visible under Linux, while under Windows all qm files (from all modules) are visible.然后我调试了:/msg/translations的运行时内容并确认只有sqlitestudio qm 文件在 Linux 下可见,而在 Windows 下所有 qm 文件(来自所有模块)都是可见的。

What could be causing this weird behavior?什么可能导致这种奇怪的行为?

(For wider code context you may refer to SQLiteStudio's code base - it's open source and available at GitHub) (对于更广泛的代码上下文,您可以参考SQLiteStudio 的代码库- 它是开源的,可在 GitHub 上获得)

EDIT - Further analysis:编辑 - 进一步分析:

A qrc file is generated properly by Qt, I can see it and it has expected contents. Qt 正确生成了一个 qrc 文件,我可以看到它并且它具有预期的内容。 I also see the rcc to compile it to the cpp file and make to compile it to the object file, then I see the object file linked into the final shared library.我还看到rcc将其编译为cpp文件并make将其编译为object文件,然后我看到object文件链接到最终共享库中。 I can see all these intermediate files in the build directory.我可以在构建目录中看到所有这些中间文件。

It seems that the problem is in runtime.似乎问题出在运行时。 I've listed all resources visible using function:我列出了使用 function 可见的所有资源:

void printResources(const QString& path, int indent)
{
    QDir d;
    d.setPath(path);
    for (QString& f : d.entryList(QStringList({"*"})))
    {
        qDebug() << QString(" ").repeated(indent) << f;
        if (!f.contains(".")) {
            printResources(path + "/" + f, indent + 4);
        }
    }
}

and then calling printResources(":/", 0);然后调用printResources(":/", 0); , which printed various resources, but it DID NOT contain QM files from the shared library resources, while it does contain QM files from the executable resources. ,它打印了各种资源,但它不包含来自共享库资源的 QM 文件,而它确实包含来自可执行资源的 QM 文件。 It also has all resources that were explicitly added to another resources file in the shared library (some static resources, not auto generated qm files).它还具有显式添加到共享库中另一个资源文件的所有资源(一些 static 资源,不是自动生成的 qm 文件)。

Why does Qt have problems accessing QM auto-generated resources from shared library and only under Linux?为什么 Qt 只能在 Linux 下从共享库访问 QM 自动生成的资源时出现问题?

I got the solution.我得到了解决方案。

Short answer简短的回答

Add QMAKE_RESOURCE_FLAGS += -name coreSQLiteStudio_qm_files to all pro files (and replace the coreSQLiteStudio_qm_files to unique name in each case).QMAKE_RESOURCE_FLAGS += -name coreSQLiteStudio_qm_files添加到所有pro文件(并在每种情况下将coreSQLiteStudio_qm_files替换为唯一名称)。

If you have other (explicit) resource files in the project, you will need to have dynamic, but predictible names, like: QMAKE_RESOURCE_FLAGS += -name ${QMAKE_TARGET}_${QMAKE_FILE_BASE} , so you can pass it to the Q_INIT_RESOURCE() macro.如果项目中有其他(显式)资源文件,则需要具有动态但可预测的名称,例如: QMAKE_RESOURCE_FLAGS += -name ${QMAKE_TARGET}_${QMAKE_FILE_BASE} ,因此您可以将其传递给Q_INIT_RESOURCE()宏。

Long answer长答案

The auto-generated (by qmake) resource file with qm files inside is compiled by the rcc into cpp file with a default initialization function qInitResources_qmake_qmake_qm_files() , which then is repeated over all other modules (shared libraries) and causes only one of those to be used in the runtime.内部带有 qm 文件的自动生成(由 qmake)资源文件由rcc编译为 cpp 文件,默认初始化 function qInitResources_qmake_qmake_qm_files() ,然后在所有其他模块(共享库)上重复,并导致其中一个在运行时使用。 Solution is to make initialization functions unique for each module, therefore you need to pass unique name of the resource initialization function to the rcc .解决方案是使每个模块的初始化函数唯一,因此您需要将资源初始化 function 的唯一名称传递给rcc By using statement like above (in the short answer) you will get initialization function qInitResources_coreSQLiteStudio_qm_files() .通过使用上面的语句(在简短的答案中),您将获得初始化 function qInitResources_coreSQLiteStudio_qm_files()

It seems like conflicting name of the function doesn't matter under Windows, but it does under Linux. function 的名称冲突似乎在 Windows 下无关紧要,但在 Linux 下确实如此。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM