[英]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:模块被编译成共享库(例如
coreSQLiteStudio
, guiSQLiteStudio
,然后有一个可执行模块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.我得到了解决方案。
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()
宏。
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.