Translations.cmake 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. # translations.cmake - Translations using APT's translation system.
  2. # Copyright (C) 2009, 2016 Julian Andres Klode <jak@debian.org>
  3. function(apt_add_translation_domain)
  4. set(options)
  5. set(oneValueArgs DOMAIN)
  6. set(multiValueArgs TARGETS SCRIPTS EXCLUDE_LANGUAGES)
  7. cmake_parse_arguments(NLS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  8. # Build the list of source files of the target
  9. set(files "")
  10. set(abs_files "")
  11. set(scripts "")
  12. set(abs_scripts "")
  13. set(targets ${NLS_TARGETS})
  14. set(domain ${NLS_DOMAIN})
  15. set(xgettext_params
  16. --add-comments
  17. --foreign
  18. --package-name=${PROJECT_NAME}
  19. --package-version=${PACKAGE_VERSION}
  20. --msgid-bugs-address=${PACKAGE_MAIL}
  21. )
  22. foreach(source ${NLS_SCRIPTS})
  23. path_join(file "${CMAKE_CURRENT_SOURCE_DIR}" "${source}")
  24. file(RELATIVE_PATH relfile ${PROJECT_SOURCE_DIR} ${file})
  25. list(APPEND scripts ${relfile})
  26. list(APPEND abs_scripts ${file})
  27. endforeach()
  28. foreach(target ${targets})
  29. get_target_property(source_dir ${target} SOURCE_DIR)
  30. get_target_property(sources ${target} SOURCES)
  31. foreach(source ${sources})
  32. path_join(file "${source_dir}" "${source}")
  33. file(RELATIVE_PATH relfile ${PROJECT_SOURCE_DIR} ${file})
  34. set(files ${files} ${relfile})
  35. set(abs_files ${abs_files} ${file})
  36. endforeach()
  37. target_compile_definitions(${target} PRIVATE -DAPT_DOMAIN="${domain}")
  38. endforeach()
  39. if("${scripts}" STREQUAL "")
  40. set(sh_pot "/dev/null")
  41. else()
  42. set(sh_pot ${CMAKE_CURRENT_BINARY_DIR}/${domain}.sh.pot)
  43. # Create the template for this specific sub-domain
  44. add_custom_command (OUTPUT ${sh_pot}
  45. COMMAND xgettext ${xgettext_params} -L Shell
  46. -o ${sh_pot} ${scripts}
  47. DEPENDS ${abs_scripts}
  48. VERBATIM
  49. WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
  50. )
  51. endif()
  52. add_custom_command (OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${domain}.c.pot
  53. COMMAND xgettext ${xgettext_params} -k_ -kN_
  54. --keyword=P_:1,2
  55. -o ${CMAKE_CURRENT_BINARY_DIR}/${domain}.c.pot ${files}
  56. DEPENDS ${abs_files}
  57. VERBATIM
  58. WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
  59. )
  60. # We are building a ${domain}.pot with a header for launchpad, but we also
  61. # build a ${domain.pot}-tmp as a byproduct. The msgfmt command than depend
  62. # on the byproduct while their target depends on the output, so that msgfmt
  63. # does not have to be rerun if nothing in the template changed.
  64. add_custom_command (OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${domain}.pot
  65. BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/${domain}.pot-tmp
  66. COMMAND msgcomm --more-than=0 --sort-by-file
  67. ${sh_pot}
  68. ${CMAKE_CURRENT_BINARY_DIR}/${domain}.c.pot
  69. --output=${CMAKE_CURRENT_BINARY_DIR}/${domain}.pot
  70. COMMAND msgcomm --more-than=0 --omit-header --sort-by-file
  71. ${sh_pot}
  72. ${CMAKE_CURRENT_BINARY_DIR}/${domain}.c.pot
  73. --output=${CMAKE_CURRENT_BINARY_DIR}/${domain}.pot-tmp0
  74. COMMAND cmake -E copy_if_different
  75. ${CMAKE_CURRENT_BINARY_DIR}/${domain}.pot-tmp0
  76. ${CMAKE_CURRENT_BINARY_DIR}/${domain}.pot-tmp
  77. DEPENDS ${sh_pot}
  78. ${CMAKE_CURRENT_BINARY_DIR}/${domain}.c.pot
  79. WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
  80. )
  81. # We need a target to depend on otherwise, the msgmerge might not get called
  82. # with the make generator
  83. add_custom_target(nls-${domain}-template DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${domain}.pot)
  84. # Build .mo files
  85. file(GLOB translations "${PROJECT_SOURCE_DIR}/po/*.po")
  86. list(SORT translations)
  87. foreach(file ${translations})
  88. get_filename_component(langcode ${file} NAME_WE)
  89. if ("${langcode}" IN_LIST NLS_EXCLUDE_LANGUAGES)
  90. continue()
  91. endif()
  92. set(outdir ${CMAKE_CURRENT_BINARY_DIR}/locale/${langcode}/LC_MESSAGES)
  93. file(MAKE_DIRECTORY ${outdir})
  94. # Command to merge and compile the messages. As explained in the custom
  95. # command for msgcomm, this depends on byproduct to avoid reruns
  96. add_custom_command(OUTPUT ${outdir}/${domain}.po
  97. COMMAND msgmerge -qo ${outdir}/${domain}.po ${file} ${CMAKE_CURRENT_BINARY_DIR}/${domain}.pot-tmp
  98. DEPENDS ${file} ${CMAKE_CURRENT_BINARY_DIR}/${domain}.pot-tmp
  99. )
  100. add_custom_command(OUTPUT ${outdir}/${domain}.mo
  101. COMMAND msgfmt --statistics -o ${outdir}/${domain}.mo ${outdir}/${domain}.po
  102. DEPENDS ${outdir}/${domain}.po
  103. )
  104. set(mofiles ${mofiles} ${outdir}/${domain}.mo)
  105. install(FILES ${outdir}/${domain}.mo
  106. DESTINATION "${CMAKE_INSTALL_LOCALEDIR}/${langcode}/LC_MESSAGES")
  107. endforeach(file ${translations})
  108. add_custom_target(nls-${domain} ALL DEPENDS ${mofiles} nls-${domain}-template)
  109. endfunction()
  110. # Usage: apt_add_update_po(output domain [domain ...])
  111. function(apt_add_update_po)
  112. set(options)
  113. set(oneValueArgs TEMPLATE)
  114. set(multiValueArgs DOMAINS EXCLUDE_LANGUAGES)
  115. cmake_parse_arguments(NLS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  116. set(output ${CMAKE_CURRENT_SOURCE_DIR}/${NLS_TEMPLATE}.pot)
  117. foreach(domain ${NLS_DOMAINS})
  118. list(APPEND potfiles ${CMAKE_CURRENT_BINARY_DIR}/${domain}.pot)
  119. endforeach()
  120. get_filename_component(master_name ${output} NAME_WE)
  121. add_custom_target(nls-${master_name}
  122. COMMAND msgcomm --sort-by-file --add-location=file
  123. --more-than=0 --output=${output}
  124. ${potfiles}
  125. DEPENDS ${potfiles})
  126. file(GLOB translations "${PROJECT_SOURCE_DIR}/po/*.po")
  127. if (NOT TARGET update-po)
  128. add_custom_target(update-po)
  129. endif()
  130. foreach(translation ${translations})
  131. get_filename_component(langcode ${translation} NAME_WE)
  132. if ("${langcode}" IN_LIST NLS_EXCLUDE_LANGUAGES)
  133. continue()
  134. endif()
  135. add_custom_target(update-po-${langcode}
  136. COMMAND msgmerge -q --update --backup=none ${translation} ${output}
  137. DEPENDS nls-${master_name}
  138. )
  139. add_dependencies(update-po update-po-${langcode})
  140. endforeach()
  141. add_dependencies(update-po nls-${master_name})
  142. endfunction()
  143. function(apt_add_po_statistics excluded)
  144. add_custom_target(statistics)
  145. file(GLOB translations "${PROJECT_SOURCE_DIR}/po/*.po")
  146. foreach(translation ${translations})
  147. get_filename_component(langcode ${translation} NAME_WE)
  148. if ("${langcode}" IN_LIST excluded)
  149. add_custom_command(
  150. TARGET statistics PRE_BUILD
  151. COMMAND printf "%-6s " "${langcode}:"
  152. COMMAND echo "ignored"
  153. VERBATIM
  154. )
  155. continue()
  156. endif()
  157. add_custom_command(
  158. TARGET statistics PRE_BUILD
  159. COMMAND printf "%-6s " "${langcode}:"
  160. COMMAND msgfmt --statistics -o /dev/null ${translation}
  161. VERBATIM
  162. )
  163. endforeach()
  164. endfunction()