Translations.cmake 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  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. #
  65. # Make sure the .pot-tmp has no line numbers, to avoid useless rebuilding
  66. # of .mo files.
  67. add_custom_command (OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${domain}.pot
  68. BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/${domain}.pot-tmp
  69. COMMAND msgcomm --more-than=0 --omit-header --sort-by-file --add-location=file
  70. ${sh_pot}
  71. ${CMAKE_CURRENT_BINARY_DIR}/${domain}.c.pot
  72. --output=${CMAKE_CURRENT_BINARY_DIR}/${domain}.pot-tmp0
  73. COMMAND msgcomm --more-than=0 --sort-by-file
  74. ${sh_pot}
  75. ${CMAKE_CURRENT_BINARY_DIR}/${domain}.c.pot
  76. --output=${CMAKE_CURRENT_BINARY_DIR}/${domain}.pot
  77. COMMAND cmake -E copy_if_different
  78. ${CMAKE_CURRENT_BINARY_DIR}/${domain}.pot-tmp0
  79. ${CMAKE_CURRENT_BINARY_DIR}/${domain}.pot-tmp
  80. DEPENDS ${sh_pot}
  81. ${CMAKE_CURRENT_BINARY_DIR}/${domain}.c.pot
  82. WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
  83. )
  84. # We need a target to depend on otherwise, the msgmerge might not get called
  85. # with the make generator
  86. add_custom_target(nls-${domain}-template DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${domain}.pot)
  87. # Build .mo files
  88. file(GLOB translations "${PROJECT_SOURCE_DIR}/po/*.po")
  89. list(SORT translations)
  90. foreach(file ${translations})
  91. get_filename_component(langcode ${file} NAME_WE)
  92. if ("${langcode}" IN_LIST NLS_EXCLUDE_LANGUAGES)
  93. continue()
  94. endif()
  95. set(outdir ${CMAKE_CURRENT_BINARY_DIR}/locale/${langcode}/LC_MESSAGES)
  96. file(MAKE_DIRECTORY ${outdir})
  97. # Command to merge and compile the messages. As explained in the custom
  98. # command for msgcomm, this depends on byproduct to avoid reruns
  99. add_custom_command(OUTPUT ${outdir}/${domain}.po
  100. COMMAND msgmerge -qo ${outdir}/${domain}.po ${file} ${CMAKE_CURRENT_BINARY_DIR}/${domain}.pot-tmp
  101. DEPENDS ${file} ${CMAKE_CURRENT_BINARY_DIR}/${domain}.pot-tmp
  102. )
  103. add_custom_command(OUTPUT ${outdir}/${domain}.mo
  104. COMMAND msgfmt --statistics -o ${outdir}/${domain}.mo ${outdir}/${domain}.po
  105. DEPENDS ${outdir}/${domain}.po
  106. )
  107. set(mofiles ${mofiles} ${outdir}/${domain}.mo)
  108. install(FILES ${outdir}/${domain}.mo
  109. DESTINATION "${CMAKE_INSTALL_LOCALEDIR}/${langcode}/LC_MESSAGES")
  110. endforeach(file ${translations})
  111. add_custom_target(nls-${domain} ALL DEPENDS ${mofiles} nls-${domain}-template)
  112. endfunction()
  113. # Usage: apt_add_update_po(output domain [domain ...])
  114. function(apt_add_update_po)
  115. set(options)
  116. set(oneValueArgs TEMPLATE)
  117. set(multiValueArgs DOMAINS EXCLUDE_LANGUAGES)
  118. cmake_parse_arguments(NLS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  119. set(output ${CMAKE_CURRENT_SOURCE_DIR}/${NLS_TEMPLATE}.pot)
  120. foreach(domain ${NLS_DOMAINS})
  121. list(APPEND potfiles ${CMAKE_CURRENT_BINARY_DIR}/${domain}.pot)
  122. endforeach()
  123. get_filename_component(master_name ${output} NAME_WE)
  124. add_custom_target(nls-${master_name}
  125. COMMAND msgcomm --sort-by-file --add-location=file
  126. --more-than=0 --output=${output}
  127. ${potfiles}
  128. DEPENDS ${potfiles})
  129. file(GLOB translations "${PROJECT_SOURCE_DIR}/po/*.po")
  130. if (NOT TARGET update-po)
  131. add_custom_target(update-po)
  132. endif()
  133. foreach(translation ${translations})
  134. get_filename_component(langcode ${translation} NAME_WE)
  135. if ("${langcode}" IN_LIST NLS_EXCLUDE_LANGUAGES)
  136. continue()
  137. endif()
  138. add_custom_target(update-po-${langcode}
  139. COMMAND msgmerge -q --previous --update --backup=none ${translation} ${output}
  140. DEPENDS nls-${master_name}
  141. )
  142. add_dependencies(update-po update-po-${langcode})
  143. endforeach()
  144. add_dependencies(update-po nls-${master_name})
  145. endfunction()
  146. function(apt_add_po_statistics excluded)
  147. add_custom_target(statistics)
  148. file(GLOB translations "${PROJECT_SOURCE_DIR}/po/*.po")
  149. foreach(translation ${translations})
  150. get_filename_component(langcode ${translation} NAME_WE)
  151. if ("${langcode}" IN_LIST excluded)
  152. add_custom_command(
  153. TARGET statistics PRE_BUILD
  154. COMMAND printf "%-6s " "${langcode}:"
  155. COMMAND echo "ignored"
  156. VERBATIM
  157. )
  158. continue()
  159. endif()
  160. add_custom_command(
  161. TARGET statistics PRE_BUILD
  162. COMMAND printf "%-6s " "${langcode}:"
  163. COMMAND msgfmt --statistics -o /dev/null ${translation}
  164. VERBATIM
  165. )
  166. endforeach()
  167. endfunction()