From 0b75e045d8b523150fce098d4dd23797bdf96610 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Tue, 25 Apr 2023 10:14:54 +0200 Subject: CMake: Fix qt6_create_translation for same-named .ts files Consider a project where .ts files are structured by directory instead of by file name: translations/chinese/myapp.ts translations/czech/myapp.ts translations/french/myapp.ts translations/german/myapp.ts translations/italian/myapp.ts In that case, qt6_create_translation failed at configure time with the following error: Attempt to add a custom rule to output /build/myapp/.lupdate/myapp.ts.stamp.rule which already has a custom rule. Fix that by constructing a .ts.stamp file path that takes the relative path from CMAKE_CURRENT_SOURCE_DIR to the .ts file into account. Additionally, pass the paths of the timestamp files to qt6_add_translation with the __QT_INTERNAL_TIMESTAMP_FILES multi-value argument to avoid having to recalculate the paths of the timestamp files. Fixes: QTBUG-113152 Change-Id: Ifa08741cd621f2215eaf2f8fb848ecf6d5b9cf13 Reviewed-by: Alexey Edelev Reviewed-by: Qt CI Bot (cherry picked from commit d2eaccfe7f613faa2083277d2d43c10c85053126) Reviewed-by: Qt Cherry-pick Bot --- src/linguist/Qt6LinguistToolsMacros.cmake | 23 +++++++++++----- tests/auto/cmake/linguist/CMakeLists.txt | 1 + .../CMakeLists.txt | 22 +++++++++++++++ .../de/myobject.ts | 12 ++++++++ .../fr/myobject.ts | 12 ++++++++ .../myi18nobject.cpp | 32 ++++++++++++++++++++++ 6 files changed, 95 insertions(+), 7 deletions(-) create mode 100644 tests/auto/cmake/linguist/test_create_translation_same_base_names/CMakeLists.txt create mode 100644 tests/auto/cmake/linguist/test_create_translation_same_base_names/de/myobject.ts create mode 100644 tests/auto/cmake/linguist/test_create_translation_same_base_names/fr/myobject.ts create mode 100644 tests/auto/cmake/linguist/test_create_translation_same_base_names/myi18nobject.cpp diff --git a/src/linguist/Qt6LinguistToolsMacros.cmake b/src/linguist/Qt6LinguistToolsMacros.cmake index c992bfa41..123048139 100644 --- a/src/linguist/Qt6LinguistToolsMacros.cmake +++ b/src/linguist/Qt6LinguistToolsMacros.cmake @@ -39,6 +39,7 @@ function(qt6_create_translation _qm_files) if(NOT EXISTS "${stamp_file_dir}") file(MAKE_DIRECTORY "${stamp_file_dir}") endif() + set(stamp_files "") foreach(_ts_file ${_my_tsfiles}) get_filename_component(_ts_name ${_ts_file} NAME) if(_my_sources) @@ -66,7 +67,14 @@ function(qt6_create_translation _qm_files) file(WRITE ${_ts_lst_file} "${_lst_file_srcs}") endif() - set(stamp_file "${stamp_file_dir}/${_ts_name}.stamp") + file(RELATIVE_PATH _ts_relative_path ${CMAKE_CURRENT_SOURCE_DIR} ${_ts_file}) + string(REPLACE "../" "__/" _ts_relative_path "${_ts_relative_path}") + set(stamp_file "${stamp_file_dir}/${_ts_relative_path}.stamp") + list(APPEND stamp_files ${stamp_file}) + get_filename_component(full_stamp_file_dir "${stamp_file}" DIRECTORY) + if(NOT EXISTS "${full_stamp_file_dir}") + file(MAKE_DIRECTORY "${full_stamp_file_dir}") + endif() add_custom_command(OUTPUT ${stamp_file} COMMAND ${QT_CMAKE_EXPORT_NAMESPACE}::lupdate ARGS ${_lupdate_options} "@${_ts_lst_file}" -ts ${_ts_file} @@ -74,22 +82,22 @@ function(qt6_create_translation _qm_files) DEPENDS ${_dependencies} VERBATIM) endforeach() - qt6_add_translation(${_qm_files} __QT_INTERNAL_DEPEND_ON_TIMESTAMP_FILE ${_my_tsfiles}) + qt6_add_translation(${_qm_files} ${_my_tsfiles} __QT_INTERNAL_TIMESTAMP_FILES ${stamp_files}) set(${_qm_files} ${${_qm_files}} PARENT_SCOPE) endfunction() function(qt6_add_translation _qm_files) - set(options __QT_INTERNAL_DEPEND_ON_TIMESTAMP_FILE) + set(options) set(oneValueArgs) - set(multiValueArgs OPTIONS) + set(multiValueArgs OPTIONS __QT_INTERNAL_TIMESTAMP_FILES) cmake_parse_arguments(_LRELEASE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) set(_lrelease_files ${_LRELEASE_UNPARSED_ARGUMENTS}) + set(idx 0) foreach(_current_FILE ${_lrelease_files}) get_filename_component(_abs_FILE ${_current_FILE} ABSOLUTE) get_filename_component(qm ${_abs_FILE} NAME) - set(ts_stamp_file "${CMAKE_CURRENT_BINARY_DIR}/.lupdate/${qm}.stamp") # everything before the last dot has to be considered the file name (including other dots) string(REGEX REPLACE "\\.[^.]*$" "" FILE_NAME ${qm}) get_source_file_property(output_location ${_abs_FILE} OUTPUT_LOCATION) @@ -100,8 +108,9 @@ function(qt6_add_translation _qm_files) set(qm "${CMAKE_CURRENT_BINARY_DIR}/${FILE_NAME}.qm") endif() - if(_LRELEASE___QT_INTERNAL_DEPEND_ON_TIMESTAMP_FILE) - set(qm_dep "${ts_stamp_file}") + if(_LRELEASE___QT_INTERNAL_TIMESTAMP_FILES) + list(GET _LRELEASE___QT_INTERNAL_TIMESTAMP_FILES ${idx} qm_dep) + math(EXPR idx "${idx} + 1") else() set(qm_dep "${_abs_FILE}") endif() diff --git a/tests/auto/cmake/linguist/CMakeLists.txt b/tests/auto/cmake/linguist/CMakeLists.txt index ff8014f9c..add27b1f7 100644 --- a/tests/auto/cmake/linguist/CMakeLists.txt +++ b/tests/auto/cmake/linguist/CMakeLists.txt @@ -60,4 +60,5 @@ include("${_Qt6CTestMacros}") _qt_internal_test_expect_pass(test_add_translation_macro) if (TARGET Qt6::lupdate) _qt_internal_test_expect_pass(test_create_translation_macro) + _qt_internal_test_expect_pass(test_create_translation_same_base_names) endif() diff --git a/tests/auto/cmake/linguist/test_create_translation_same_base_names/CMakeLists.txt b/tests/auto/cmake/linguist/test_create_translation_same_base_names/CMakeLists.txt new file mode 100644 index 000000000..e395cd2b6 --- /dev/null +++ b/tests/auto/cmake/linguist/test_create_translation_same_base_names/CMakeLists.txt @@ -0,0 +1,22 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) + +project(test_create_translation_same_base_names) + +find_package(Qt6 COMPONENTS Core LinguistTools REQUIRED) + +set(my_srcs myi18nobject.cpp) + +set(ts_files "") +foreach(language de fr) + set(ts_file ${language}/myobject.ts) + set_property(SOURCE ${ts_file} + PROPERTY OUTPUT_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/${language}) + list(APPEND ts_files ${ts_file}) +endforeach() +qt_create_translation(qm_files ${my_srcs} ${ts_files}) + +add_executable(myobject ${my_srcs} ${qm_files}) +target_link_libraries(myobject Qt::Core) diff --git a/tests/auto/cmake/linguist/test_create_translation_same_base_names/de/myobject.ts b/tests/auto/cmake/linguist/test_create_translation_same_base_names/de/myobject.ts new file mode 100644 index 000000000..4d4292e5b --- /dev/null +++ b/tests/auto/cmake/linguist/test_create_translation_same_base_names/de/myobject.ts @@ -0,0 +1,12 @@ + + + + + main + + + Hello, world! + Hallo, Welt! + + + diff --git a/tests/auto/cmake/linguist/test_create_translation_same_base_names/fr/myobject.ts b/tests/auto/cmake/linguist/test_create_translation_same_base_names/fr/myobject.ts new file mode 100644 index 000000000..ab96d20e3 --- /dev/null +++ b/tests/auto/cmake/linguist/test_create_translation_same_base_names/fr/myobject.ts @@ -0,0 +1,12 @@ + + + + + main + + + Hello, world! + Bonjour le monde! + + + diff --git a/tests/auto/cmake/linguist/test_create_translation_same_base_names/myi18nobject.cpp b/tests/auto/cmake/linguist/test_create_translation_same_base_names/myi18nobject.cpp new file mode 100644 index 000000000..7ff200890 --- /dev/null +++ b/tests/auto/cmake/linguist/test_create_translation_same_base_names/myi18nobject.cpp @@ -0,0 +1,32 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include +#include +#include + +#include + +using namespace Qt::Literals::StringLiterals; + +int main(int argc, char **argv) +{ + QCoreApplication app(argc, argv); + QTranslator *translator = new QTranslator(); + QLocale frenchLocale = QLocale(QLocale::French); + QLocale::setDefault(frenchLocale); + if (!translator->load(QLocale(), "myobject.qm"_L1, {}, + qApp->applicationDirPath() + "/fr/"_L1)) { + qFatal("Could not load translation file!"); + } + + app.installTranslator(translator); + + QString text = QCoreApplication::translate("main", "Hello, world!"); + if (text != "Bonjour le monde!"_L1) + qFatal("Translation not found!"); + + std::fprintf(stdout, "%s\n", qPrintable(text)); + return 0; +} -- cgit v1.2.3