diff --git a/share/qt/translate.cmake b/share/qt/translate.cmake new file mode 100644 index 00000000000..a4eeef96038 --- /dev/null +++ b/share/qt/translate.cmake @@ -0,0 +1,82 @@ +# Copyright (c) 2025 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +set(input_variables + PROJECT_SOURCE_DIR + COPYRIGHT_HOLDERS + LCONVERT_EXECUTABLE + LUPDATE_EXECUTABLE + PYTHON_EXECUTABLE + XGETTEXT_EXECUTABLE +) + +foreach(var IN LISTS input_variables) + if(NOT DEFINED ${var}) + message(FATAL_ERROR "Variable '${var}' is not defined!") + endif() +endforeach() + +file(GLOB_RECURSE translatable_sources + "${PROJECT_SOURCE_DIR}/src/*.h" + "${PROJECT_SOURCE_DIR}/src/*.cpp" + "${PROJECT_SOURCE_DIR}/src/*.mm" +) + +file(GLOB_RECURSE qt_translatable_sources + "${PROJECT_SOURCE_DIR}/src/qt/*.h" + "${PROJECT_SOURCE_DIR}/src/qt/*.cpp" + "${PROJECT_SOURCE_DIR}/src/qt/*.mm" +) + +file(GLOB ui_files + "${PROJECT_SOURCE_DIR}/src/qt/forms/*.ui" +) + +set(subtrees crc32c crypto/ctaes leveldb minisketch secp256k1) +set(exclude_dirs bench compat crypto support test univalue) +foreach(directory IN LISTS subtrees exclude_dirs) + list(FILTER translatable_sources + EXCLUDE REGEX "${PROJECT_SOURCE_DIR}/src/${directory}/.*" + ) +endforeach() + +execute_process( + COMMAND ${CMAKE_COMMAND} -E env + XGETTEXT=${XGETTEXT_EXECUTABLE} + COPYRIGHT_HOLDERS=${COPYRIGHT_HOLDERS} + ${PYTHON_EXECUTABLE} + ${CMAKE_CURRENT_LIST_DIR}/extract_strings_qt.py + ${translatable_sources} + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/src + COMMAND_ERROR_IS_FATAL ANY +) + +execute_process( + COMMAND ${LUPDATE_EXECUTABLE} + -no-obsolete + -I ${PROJECT_SOURCE_DIR}/src + -locations relative + ${ui_files} + ${qt_translatable_sources} + ${PROJECT_SOURCE_DIR}/src/qt/bitcoinstrings.cpp + -ts ${PROJECT_SOURCE_DIR}/src/qt/locale/bitcoin_en.ts + COMMAND_ERROR_IS_FATAL ANY +) + +execute_process( + COMMAND ${LCONVERT_EXECUTABLE} + -drop-translations + -o ${PROJECT_SOURCE_DIR}/src/qt/locale/bitcoin_en.xlf + -i ${PROJECT_SOURCE_DIR}/src/qt/locale/bitcoin_en.ts + COMMAND_ERROR_IS_FATAL ANY +) + +file(READ "${PROJECT_SOURCE_DIR}/src/qt/locale/bitcoin_en.xlf" bitcoin_en) +string(REPLACE "source-language=\"en\" target-language=\"en\"" + "source-language=\"en\"" bitcoin_en "${bitcoin_en}" +) +string(REGEX REPLACE " *\n" + "" bitcoin_en "${bitcoin_en}" +) +file(WRITE "${PROJECT_SOURCE_DIR}/src/qt/locale/bitcoin_en.xlf" "${bitcoin_en}") diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index 73645283b4e..5a3f98738f6 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -289,69 +289,19 @@ if(BUILD_GUI_TESTS) add_subdirectory(test) endif() - -# Gets sources to be parsed to gather translatable strings. -function(get_translatable_sources var) - set(result) - set(targets) - foreach(dir IN ITEMS ${ARGN}) - get_directory_property(dir_targets DIRECTORY ${PROJECT_SOURCE_DIR}/${dir} BUILDSYSTEM_TARGETS) - list(APPEND targets ${dir_targets}) - endforeach() - foreach(target IN LISTS targets) - get_target_property(target_sources ${target} SOURCES) - if(target_sources) - foreach(source IN LISTS target_sources) - # Get an expression from the generator expression, if any. - if(source MATCHES ":([^>]+)>$") - set(source ${CMAKE_MATCH_1}) - endif() - cmake_path(GET source EXTENSION LAST_ONLY ext) - if(ext STREQUAL ".qrc") - continue() - endif() - if(NOT IS_ABSOLUTE source) - get_target_property(target_source_dir ${target} SOURCE_DIR) - cmake_path(APPEND target_source_dir ${source} OUTPUT_VARIABLE source) - endif() - get_property(is_generated - SOURCE ${source} TARGET_DIRECTORY ${target} - PROPERTY GENERATED - ) - if(NOT is_generated) - list(APPEND result ${source}) - endif() - endforeach() - endif() - endforeach() - set(${var} ${result} PARENT_SCOPE) -endfunction() - find_program(XGETTEXT_EXECUTABLE xgettext) -find_program(SED_EXECUTABLE sed) if(NOT XGETTEXT_EXECUTABLE) add_custom_target(translate COMMAND ${CMAKE_COMMAND} -E echo "Error: GNU gettext-tools not found" ) -elseif(NOT SED_EXECUTABLE) - add_custom_target(translate - COMMAND ${CMAKE_COMMAND} -E echo "Error: GNU sed not found" - ) else() - set(translatable_sources_directories src src/qt src/util) - if(ENABLE_WALLET) - list(APPEND translatable_sources_directories src/wallet) - endif() - get_translatable_sources(translatable_sources ${translatable_sources_directories}) - get_translatable_sources(qt_translatable_sources src/qt) - file(GLOB ui_files ${CMAKE_CURRENT_SOURCE_DIR}/forms/*.ui) - add_custom_target(translate - COMMAND ${CMAKE_COMMAND} -E env XGETTEXT=${XGETTEXT_EXECUTABLE} COPYRIGHT_HOLDERS=${COPYRIGHT_HOLDERS} $ ${PROJECT_SOURCE_DIR}/share/qt/extract_strings_qt.py ${translatable_sources} - COMMAND Qt6::lupdate -no-obsolete -I ${PROJECT_SOURCE_DIR}/src -locations relative ${CMAKE_CURRENT_SOURCE_DIR}/bitcoinstrings.cpp ${ui_files} ${qt_translatable_sources} -ts ${CMAKE_CURRENT_SOURCE_DIR}/locale/bitcoin_en.ts - COMMAND Qt6::lconvert -drop-translations -o ${CMAKE_CURRENT_SOURCE_DIR}/locale/bitcoin_en.xlf -i ${CMAKE_CURRENT_SOURCE_DIR}/locale/bitcoin_en.ts - COMMAND ${SED_EXECUTABLE} -i.old -e "s|source-language=\"en\" target-language=\"en\"|source-language=\"en\"|" -e "/<\\/target>/d" ${CMAKE_CURRENT_SOURCE_DIR}/locale/bitcoin_en.xlf - COMMAND ${CMAKE_COMMAND} -E rm ${CMAKE_CURRENT_SOURCE_DIR}/locale/bitcoin_en.xlf.old - WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/src - VERBATIM + add_custom_target(translate COMMAND ${CMAKE_COMMAND} + -D "PROJECT_SOURCE_DIR=${PROJECT_SOURCE_DIR}" + -D "COPYRIGHT_HOLDERS=${COPYRIGHT_HOLDERS}" + -D "LCONVERT_EXECUTABLE=$" + -D "LUPDATE_EXECUTABLE=$" + -D "PYTHON_EXECUTABLE=$" + -D "XGETTEXT_EXECUTABLE=${XGETTEXT_EXECUTABLE}" + -P ${PROJECT_SOURCE_DIR}/share/qt/translate.cmake ) endif()