How tontegrate Qt4 qm files into binary using cmake and QRC

cmakeinternationalizationlocalizationqt4translation

I have a Qt4 CMake project and I'd like to integrate the QM files for i18n into the output binary. These are the rules I have so far for generating the TS and QM files:

set(myapp_TRANSLATIONS
    i18n/myapp_de.ts
)

set(FILES_TO_TRANSLATE
    ${myapp_SRCS}
    ${myapp_MOC_HDRS}
)

QT4_CREATE_TRANSLATION(QM_FILES ${FILES_TO_TRANSLATE} ${myapp_TRANSLATIONS})
QT4_ADD_TRANSLATION(QM ${myapp_TRANSLATIONS})

I tried the following to add the QM files to the executable:

add_executable(myapp ${myapp_SRCS} ${myapp_MOC_SRCS} ${myapp_RCC_SRCS} ${QM})

This is the initialization from main.cpp:

QTranslator qtTranslator;
qtTranslator.load("qt_" + QLocale::system().name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath));
app.installTranslator(&qtTranslator);

QTranslator appTranslator;
appTranslator.load("myapp_" + QLocale::system().name());
app.installTranslator(&appTranslator);

However, strings mypp shows that the translations are not going into the binary.

Update: I added each qm file to a i18n/translations.qrc:

<!DOCTYPE RCC><RCC version="1.0">
  <qresource prefix="/resources">
    <file>myapp_de.qm</file>
    <file>  ...   .qm</file>
  </qresource>
</RCC>

and using

QT4_ADD_RESOURCES(myapp_QM_RCC_SRCS i18n/translations.qrc)

and adding myapp_QM_RCC_SRCS to the executable dependencies.

But this fails during build time thanks to the fact that CMake does a shadow build (building outside the source dir) but parses the QRC files for dependencies expecting the referenced files relative to the QRC file (nice feature but there's no make rule how to build the QM file at that location). The QM files are in ${CMAKE_CURRENT_BINARY_DIR} (where they belong using shadow building) but expects it in ${CMAKE_CURRENT_SOURCE_DIR} (where non-generated files should be – so both locations would be correct, depending on situation).

Best Answer

I had the exact same problem. I came up with the following solution:

Create a QRC file that contains only the expected QM files, and give it a different prefix so it won't conflict with your other resources:

<RCC>
    <qresource prefix="/translators">
    <file>myapp_en.qm</file>
    </qresource>
</RCC>

Add a CMake rule to copy the QRC file to the output directory and then another rule to run the resource compiler:

# Change 'myapp_en' to be the base file name of the qrc file.
SET( trans_file myapp_en )
SET( trans_srcfile ${CMAKE_CURRENT_SOURCE_DIR}/${trans_file}.qrc)
SET( trans_infile ${CMAKE_CURRENT_BINARY_DIR}/${trans_file}.qrc)
SET( trans_outfile ${CMAKE_CURRENT_BINARY_DIR}/qrc_${trans_file}.cxx)

# Copy the QRC file to the output directory, because the files listed in the 
# qrc file are relative to that directory.
ADD_CUSTOM_COMMAND(
    OUTPUT ${trans_infile}
    COMMAND ${CMAKE_COMMAND} -E copy ${trans_srcfile} ${trans_infile}
    MAIN_DEPENDENCY ${trans_srcfile}
    )

# Run the resource compiler (rcc_options should already be set). We can't
# use QT4_ADD_RESOURCES because the qrc file may not exist yet.
ADD_CUSTOM_COMMAND(
    OUTPUT ${trans_outfile}
    COMMAND ${QT_RCC_EXECUTABLE}
    ARGS ${rcc_options} -name ${trans_file} -o ${trans_outfile} ${trans_infile}
    MAIN_DEPENDENCY ${trans_infile}
    DEPENDS ${qm_files}
    )

# Add compiled resources to executable dependency list
ADD_EXECUTABLE( ${APP_NAME} ... ${trans_outfile} )

Use ${Qt5Core_RCC_EXECUTABLE} instead of ${QT_RCC_EXECUTABLE} if you use Qt 5.

Related Topic