Qt translation handling

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Qt translation handling

Francis Giraldeau
Here is a small snipped I wanted to share about generation of qt translation
files.

The Qt translations are managed using two files: ts and qm. The ts files are
edited by translators and updated from source files. Therefore, they must be
added to the repository. To include the translations in the application, qm
binary file is generated. This file is generated in the build tree and must
not be added to the repository.

Qt5 suggests to use qt5_create_translation() macro. However, this macro
regenerate the ts file at build time. It is very inconvenient when working
on multiple branches, because it forces to either commit the modified
translation file or discard the update. Instead, we use a custom target
"make translations" that update ts files only when requested explicitely.

set(TS_FILES
    ${CMAKE_CURRENT_SOURCE_DIR}/translations/app_fr.ts
)
file(GLOB_RECURSE TS_SOURCES "*.cpp" "*.h" "*.ui")
add_custom_target(translations)
foreach(_ts_file ${TS_FILES})
    # generate a sensible name for this translation file
    get_filename_component(_ts_name ${_ts_file} NAME_WE)
    # call lupdate ourselves
    add_custom_command(
        OUTPUT "${_ts_file}"
        DEPENDS ${TS_SOURCES}
        COMMAND ${Qt5_LUPDATE_EXECUTABLE} -recursive ${CMAKE_CURRENT_SOURCE_DIR} -ts ${_ts_file}
    )
    # create a target that depends on the generated files
    add_custom_target(translate_${_ts_name} DEPENDS ${_ts_file})
    # attach the custom target for this ts file to the parent target
    add_dependencies(translations translate_${_ts_name})
endforeach()

# generate qm files
qt5_add_translation(QM_FILES ${TS_FILES})
configure_file(translations.qrc ${CMAKE_CURRENT_BINARY_DIR} COPYONLY)

add_executable(App
    ${QM_FILES}
    ${CMAKE_CURRENT_BINARY_DIR}/translations.qrc
)

Cheers,

Francis
--
Francis Giraldeau

--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
https://cmake.org/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Qt translation handling

angroyer
Bonjour Francis,

thank you for sharing this snippet.

I have read thoroughly your example and tried it but it seems to me that
this snippet is similar to the qt5_create_translation() function.

First of all, with cmake >= 3.0.0 and AUTORCC set to ON, adding
${CMAKE_CURRENT_BINARY_DIR}/translations.qrc in add_executable() make the
executable depends on the translations.qrc and make also translations.qrc
depends on the files listed in the translations.qrc. So everytime a .qm
listed in translations.qrc changes, the qrc_translations.cpp is created and
compiled. So, it is not necessary to add ${QM_FILES} in the add_executable()
statement.

So, with your piece of code:
 * ${CMAKE_CURRENT_BINARY_DIR}/translations.qrc in add_executable make App
depend on the qrc_translations.qrc and qrc_translations.qrc depend on files
listed in qrc_translations.qrc
 * each .qm file is dependent on a .ts file: statement qt5_add_translation()
 * each .ts file is dependent on ${TS_SOURCES}: statement
add_custom_command()

So everytime a file listed in ${TS_SOURCES} changes, the .ts is rebuilt, the
.qm is rebuilt and the qrc_translations.cpp is compiled. You could have
obtained the same thing with:

set(TS_FILES
    ${CMAKE_CURRENT_SOURCE_DIR}/translations/app_fr.ts
)
file(GLOB_RECURSE TS_SOURCES "*.cpp" "*.h" "*.ui")
qt5_create_translation(QM_FILES ${TS_FILES} ${TS_SOURCES})

configure_file(translations.qrc ${CMAKE_CURRENT_BINARY_DIR} COPYONLY)
add_executable(App
    ${CMAKE_CURRENT_BINARY_DIR}/translations.qrc
)

and translations.qrc containing:
<RCC>
    <qresource prefix="/">
        <file>gui_fr.qm</file>
    </qresource>
</RCC>

I have tested with cmake 3.16.1.

It is worth mentioning that the Qt documentation:
https://doc.qt.io/qt-5/qtlinguist-cmake-qt5-create-translation.html
indicates:
qt5_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} helloworld_en.ts
helloworld_de.ts)
without passing the list of source/headers files. So the .ts files are
reconstructed when the date of the source folder changes but not for the
date of the subdirectories. The date of the source folder changes when some
files are created/removed/modified in the directory but not for the files in
subdirectories.

This could leads to errors since the .ts files would not be rebuilt when a
file in a subdirectory change. So changing from branch to branch might
change the date of the source folder and regenerates the .ts files.

What do you think ?

In case you want to keep the .qm files in your source folder, you could
indicate to the cmake rule where to generate the .qm file with the
OUTPUT_LOCATION:
set_source_files_properties(${TS_FILES} PROPERTIES OUTPUT_LOCATION
${CMAKE_SOURCE_DIR}/translations)
See https://doc.qt.io/qt-5/qtlinguist-cmake-qt5-add-translation.html
It works also for qt5_create_translation() that calls in turn the
qt5_add_translation().

And so you do not need to copy the translations.qrc to the build folder. The
code becomes:

set(TS_FILES
    ${CMAKE_CURRENT_SOURCE_DIR}/translations/app_fr.ts
)
set_source_files_properties(${TS_FILES} PROPERTIES OUTPUT_LOCATION
${CMAKE_CURRENT_SOURCE_DIR}/translations)
file(GLOB_RECURSE TS_SOURCES "*.cpp" "*.h" "*.ui")
qt5_create_translation(QM_FILES ${TS_FILES} ${TS_SOURCES})

add_executable(App
    translations/translations.qrc
)

and translations/translations.qrc containing:
<RCC>
    <qresource prefix="/">
        <file>gui_fr.qm</file>
    </qresource>
</RCC>

Cordialement,
Anthony




--
Sent from: http://cmake.3232098.n2.nabble.com/
--

Powered by kitware.com/cmake

Kitware offers various services to support the CMake community. For more information on each offering, please visit https://cmake.org/services

Visit other Kitware open-source projects at https://www.kitware.com/platforms

Follow this link to subscribe/unsubscribe:
https://cmake.org/mailman/listinfo/cmake

This mailing list is deprecated in favor of https://discourse.cmake.org
Reply | Threaded
Open this post in threaded view
|

Re: Qt translation handling

angroyer
Another thing:

in case you don't want to re-generate the .ts files every time, you could
comment out:
file(GLOB_RECURSE TS_SOURCES "*.cpp" "*.h" "*.ui")
qt5_create_translation(QM_FILES ${TS_FILES} ${TS_SOURCES})

and use instead the following line with the .ts files already committed in
your project:
qt5_add_translation(QM_FILES ${TS_FILES})

Cordialement
Anthony




--
Sent from: http://cmake.3232098.n2.nabble.com/
--

Powered by kitware.com/cmake

Kitware offers various services to support the CMake community. For more information on each offering, please visit https://cmake.org/services

Visit other Kitware open-source projects at https://www.kitware.com/platforms

Follow this link to subscribe/unsubscribe:
https://cmake.org/mailman/listinfo/cmake

This mailing list is deprecated in favor of https://discourse.cmake.org