# translations.cmake - Translations using APT's translation system.
# Copyright (C) 2009, 2016 Julian Andres Klode <jak@debian.org>

function(apt_add_translation_domain)
    set(options)
    set(oneValueArgs DOMAIN)
    set(multiValueArgs TARGETS SCRIPTS EXCLUDE_LANGUAGES)
    cmake_parse_arguments(NLS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
    # Build the list of source files of the target
    set(files "")
    set(abs_files "")
    set(scripts "")
    set(abs_scripts "")
    set(targets ${NLS_TARGETS})
    set(domain ${NLS_DOMAIN})
    set(xgettext_params
        --add-comments
        --foreign
        --package-name=${PROJECT_NAME}
        --package-version=${PACKAGE_VERSION}
        --msgid-bugs-address=${PACKAGE_MAIL}
    )
    foreach(source ${NLS_SCRIPTS})
            string(SUBSTRING ${source} 0 1 init_char)
            string(COMPARE EQUAL ${init_char} "/" is_absolute)
            if (${is_absolute})
                set(file "${source}")
            else()
                set(file "${CMAKE_CURRENT_SOURCE_DIR}/${source}")
            endif()
            file(RELATIVE_PATH relfile ${PROJECT_SOURCE_DIR} ${file})
            list(APPEND scripts ${relfile})
            list(APPEND abs_scripts ${file})
        endforeach()
    foreach(target ${targets})
        get_target_property(source_dir ${target} SOURCE_DIR)
        get_target_property(sources ${target} SOURCES)
        foreach(source ${sources})
            string(SUBSTRING ${source} 0 1 init_char)
            string(COMPARE EQUAL ${init_char} "/" is_absolute)
            if (${is_absolute})
                set(file "${source}")
            else()
                set(file "${source_dir}/${source}")
            endif()
            file(RELATIVE_PATH relfile ${PROJECT_SOURCE_DIR} ${file})
            set(files ${files} ${relfile})
            set(abs_files ${abs_files} ${file})
        endforeach()

        target_compile_definitions(${target} PRIVATE -DAPT_DOMAIN="${domain}")
    endforeach()

    if("${scripts}" STREQUAL "")
        set(sh_pot "/dev/null")
    else()
        set(sh_pot ${PROJECT_BINARY_DIR}/${domain}.sh.pot)
        # Create the template for this specific sub-domain
        add_custom_command (OUTPUT ${sh_pot}
            COMMAND xgettext ${xgettext_params} -L Shell
                             -o ${sh_pot} ${scripts}
            DEPENDS ${abs_scripts}
            VERBATIM
            WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
        )
    endif()


    add_custom_command (OUTPUT ${PROJECT_BINARY_DIR}/${domain}.c.pot
        COMMAND xgettext ${xgettext_params} -k_ -kN_
                         --keyword=P_:1,2
                         -o ${PROJECT_BINARY_DIR}/${domain}.c.pot ${files}
        DEPENDS ${abs_files}
        VERBATIM
        WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
    )

    # We are building a ${domain}.pot with a header for launchpad, but we also
    # build a ${domain.pot}-tmp as a byproduct. The msgfmt command than depend
    # on the byproduct while their target depends on the output, so that msgfmt
    # does not have to be rerun if nothing in the template changed.
    add_custom_command (OUTPUT ${PROJECT_BINARY_DIR}/${domain}.pot
        BYPRODUCTS ${PROJECT_BINARY_DIR}/${domain}.pot-tmp
        COMMAND msgcomm --more-than=0 --sort-by-file
                         ${sh_pot}
                         ${PROJECT_BINARY_DIR}/${domain}.c.pot
                         --output=${PROJECT_BINARY_DIR}/${domain}.pot
        COMMAND msgcomm --more-than=0 --omit-header --sort-by-file
                         ${sh_pot}
                         ${PROJECT_BINARY_DIR}/${domain}.c.pot
                         --output=${PROJECT_BINARY_DIR}/${domain}.pot-tmp0
        COMMAND cmake -E copy_if_different
                         ${PROJECT_BINARY_DIR}/${domain}.pot-tmp0
                         ${PROJECT_BINARY_DIR}/${domain}.pot-tmp
        DEPENDS ${sh_pot}
                ${PROJECT_BINARY_DIR}/${domain}.c.pot
        WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
    )

    # We need a target to depend on otherwise, the msgmerge might not get called
    # with the make generator
    add_custom_target(nls-${domain}-template DEPENDS ${PROJECT_BINARY_DIR}/${domain}.pot)

    # Build .mo files
    file(GLOB translations "${PROJECT_SOURCE_DIR}/po/*.po")
    list(SORT translations)
    foreach(file ${translations})
        get_filename_component(langcode ${file} NAME_WE)
        if ("${langcode}" IN_LIST NLS_EXCLUDE_LANGUAGES)
            continue()
        endif()
        set(outdir ${PROJECT_BINARY_DIR}/locale/${langcode}/LC_MESSAGES)
        file(MAKE_DIRECTORY ${outdir})
        # Command to merge and compile the messages. As explained in the custom
        # command for msgcomm, this depends on byproduct to avoid reruns
        add_custom_command(OUTPUT ${outdir}/${domain}.po
            COMMAND msgmerge -qo ${outdir}/${domain}.po ${file} ${PROJECT_BINARY_DIR}/${domain}.pot-tmp
            DEPENDS ${file} ${PROJECT_BINARY_DIR}/${domain}.pot-tmp
        )
        add_custom_command(OUTPUT ${outdir}/${domain}.mo
            COMMAND msgfmt --statistics -o ${outdir}/${domain}.mo  ${outdir}/${domain}.po
            DEPENDS ${outdir}/${domain}.po
        )

        set(mofiles ${mofiles} ${outdir}/${domain}.mo)
        install(FILES ${outdir}/${domain}.mo
                DESTINATION "${CMAKE_INSTALL_LOCALEDIR}/${langcode}/LC_MESSAGES")
    endforeach(file ${translations})

    add_custom_target(nls-${domain} ALL DEPENDS ${mofiles} nls-${domain}-template)
endfunction()

# Usage: apt_add_update_po(output domain [domain ...])
function(apt_add_update_po)
    set(options)
    set(oneValueArgs TEMPLATE)
    set(multiValueArgs DOMAINS EXCLUDE_LANGUAGES)
    cmake_parse_arguments(NLS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
    set(output ${CMAKE_CURRENT_SOURCE_DIR}/${NLS_TEMPLATE}.pot)
    foreach(domain ${NLS_DOMAINS})
        list(APPEND potfiles ${PROJECT_BINARY_DIR}/${domain}.pot)
    endforeach()

    get_filename_component(master_name ${output} NAME_WE)
    add_custom_target(nls-${master_name}
                       COMMAND msgcomm --sort-by-file --add-location=file
                                        --more-than=0 --output=${output}
                                ${potfiles}
                       DEPENDS ${potfiles})

    file(GLOB translations "${PROJECT_SOURCE_DIR}/po/*.po")
    if (NOT TARGET update-po)
        add_custom_target(update-po)
    endif()
    foreach(translation ${translations})
            get_filename_component(langcode ${translation} NAME_WE)
            if ("${langcode}" IN_LIST NLS_EXCLUDE_LANGUAGES)
                continue()
            endif()
            add_custom_target(update-po-${langcode}
                COMMAND msgmerge -q --update --backup=none ${translation} ${output}
                DEPENDS nls-${master_name}
            )
            add_dependencies(update-po update-po-${langcode})
    endforeach()
    add_dependencies(update-po nls-${master_name})
endfunction()

function(apt_add_po_statistics excluded)
    add_custom_target(statistics)
    file(GLOB translations "${PROJECT_SOURCE_DIR}/po/*.po")
    foreach(translation ${translations})
            get_filename_component(langcode ${translation} NAME_WE)
            if ("${langcode}" IN_LIST excluded)
                add_custom_command(
                    TARGET statistics PRE_BUILD
                    COMMAND printf "%-6s " "${langcode}:"
                    COMMAND echo "ignored"
                    VERBATIM
                )
                continue()
            endif()
            add_custom_command(
                TARGET statistics PRE_BUILD
                COMMAND printf "%-6s " "${langcode}:"
                COMMAND msgfmt --statistics -o /dev/null ${translation}
                VERBATIM
            )
    endforeach()
endfunction()