Translations.cmake 7.5 KB

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