# 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.

cmake_minimum_required(VERSION 3.22)

set(input_variables
  PROJECT_SOURCE_DIR
  COPYRIGHT_HOLDERS
  LCONVERT_EXECUTABLE
  LUPDATE_EXECUTABLE
  XGETTEXT_EXECUTABLE
)

foreach(var IN LISTS input_variables)
  if(NOT DEFINED ${var})
    message(FATAL_ERROR "Variable '${var}' is not defined!")
  endif()
endforeach()

# Extract _("...") strings for translation and convert to Qt stringdefs so that
# they can be picked up by Qt linguist.
function(extract_strings output)
  execute_process(
    COMMAND ${XGETTEXT_EXECUTABLE}
      --output=bitcoinstrings.po
      --no-location
      --from-code=utf-8
      --keyword=_
      ${ARGN}
    COMMAND_ERROR_IS_FATAL ANY
  )

  file(STRINGS "bitcoinstrings.po" text ENCODING "UTF-8")

  set(messages "${COPYRIGHT_HOLDERS}")
  foreach(line IN LISTS text)
    if(line MATCHES "^msgid \"(.*)\"$")
      set(msgid "${CMAKE_MATCH_1}")
    elseif(line MATCHES "^\"(.*)\"$")
      string(APPEND msgid "${CMAKE_MATCH_1}")
    elseif(line MATCHES "^msgstr .*$" AND NOT msgid STREQUAL "")
      # CMake uses ';' as a list separator.
      # We need to temporarily replace that in order to keep strings intact.
      string(REPLACE ";" "<cmake-semicolon>" msgid "${msgid}")
      list(APPEND messages "${msgid}")
    endif()
  endforeach()

  set(content [[// Automatically generated by translate.cmake

#include <QtGlobal>

#ifdef __GNUC__
#define UNUSED __attribute__((unused))
#else
#define UNUSED
#endif

static const char UNUSED *bitcoin_strings[] = {
]])

  set(prefix "QT_TRANSLATE_NOOP(\"bitcoin-core\", \"")
  set(suffix "\"),\n")

  list(SORT messages)
  list(JOIN messages "${suffix}${prefix}" messages_str)
  string(APPEND content "${prefix}${messages_str}${suffix}")
  string(APPEND content "};\n")
  string(REPLACE "<cmake-semicolon>" ";" content "${content}")

  file(WRITE "${output}" "${content}")
endfunction()

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()

extract_strings("${PROJECT_SOURCE_DIR}/src/qt/bitcoinstrings.cpp"
  ${translatable_sources}
)

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 " *<target xml:space=\"preserve\"></target>\n"
  "" bitcoin_en "${bitcoin_en}"
)
file(WRITE "${PROJECT_SOURCE_DIR}/src/qt/locale/bitcoin_en.xlf" "${bitcoin_en}")
