1# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2# file Copyright.txt or https://cmake.org/licensing for details.
3
4#[=======================================================================[.rst:
5FindGettext
6-----------
7
8Find GNU gettext tools
9
10This module looks for the GNU gettext tools.  This module defines the
11following values:
12
13::
14
15  GETTEXT_MSGMERGE_EXECUTABLE: the full path to the msgmerge tool.
16  GETTEXT_MSGFMT_EXECUTABLE: the full path to the msgfmt tool.
17  GETTEXT_FOUND: True if gettext has been found.
18  GETTEXT_VERSION_STRING: the version of gettext found (since CMake 2.8.8)
19
20
21
22Additionally it provides the following macros:
23
24GETTEXT_CREATE_TRANSLATIONS ( outputFile [ALL] file1 ...  fileN )
25
26::
27
28    This will create a target "translations" which will convert the
29    given input po files into the binary output mo file. If the
30    ALL option is used, the translations will also be created when
31    building the default target.
32
33GETTEXT_PROCESS_POT_FILE( <potfile> [ALL] [INSTALL_DESTINATION <destdir>]
34LANGUAGES <lang1> <lang2> ...  )
35
36::
37
38     Process the given pot file to mo files.
39     If INSTALL_DESTINATION is given then automatically install rules will
40     be created, the language subdirectory will be taken into account
41     (by default use share/locale/).
42     If ALL is specified, the pot file is processed when building the all target.
43     It creates a custom target "potfile".
44
45GETTEXT_PROCESS_PO_FILES( <lang> [ALL] [INSTALL_DESTINATION <dir>]
46PO_FILES <po1> <po2> ...  )
47
48::
49
50     Process the given po files to mo files for the given language.
51     If INSTALL_DESTINATION is given then automatically install rules will
52     be created, the language subdirectory will be taken into account
53     (by default use share/locale/).
54     If ALL is specified, the po files are processed when building the all target.
55     It creates a custom target "pofiles".
56
57.. versionadded:: 3.2
58  If you wish to use the Gettext library (libintl), use :module:`FindIntl`.
59#]=======================================================================]
60
61find_program(GETTEXT_MSGMERGE_EXECUTABLE msgmerge)
62
63find_program(GETTEXT_MSGFMT_EXECUTABLE msgfmt)
64
65if(GETTEXT_MSGMERGE_EXECUTABLE)
66  execute_process(COMMAND ${GETTEXT_MSGMERGE_EXECUTABLE} --version
67                  OUTPUT_VARIABLE gettext_version
68                  ERROR_QUIET
69                  OUTPUT_STRIP_TRAILING_WHITESPACE)
70  get_filename_component(msgmerge_name ${GETTEXT_MSGMERGE_EXECUTABLE} NAME)
71  get_filename_component(msgmerge_namewe ${GETTEXT_MSGMERGE_EXECUTABLE} NAME_WE)
72  if (gettext_version MATCHES "^(${msgmerge_name}|${msgmerge_namewe}) \\([^\\)]*\\) ([0-9\\.]+[^ \n]*)")
73    set(GETTEXT_VERSION_STRING "${CMAKE_MATCH_2}")
74  endif()
75  unset(gettext_version)
76  unset(msgmerge_name)
77  unset(msgmerge_namewe)
78endif()
79
80include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
81FIND_PACKAGE_HANDLE_STANDARD_ARGS(Gettext
82                                  REQUIRED_VARS GETTEXT_MSGMERGE_EXECUTABLE GETTEXT_MSGFMT_EXECUTABLE
83                                  VERSION_VAR GETTEXT_VERSION_STRING)
84
85function(_GETTEXT_GET_UNIQUE_TARGET_NAME _name _unique_name)
86  set(propertyName "_GETTEXT_UNIQUE_COUNTER_${_name}")
87  get_property(currentCounter GLOBAL PROPERTY "${propertyName}")
88  if(NOT currentCounter)
89    set(currentCounter 1)
90  endif()
91  set(${_unique_name} "${_name}_${currentCounter}" PARENT_SCOPE)
92  math(EXPR currentCounter "${currentCounter} + 1")
93  set_property(GLOBAL PROPERTY ${propertyName} ${currentCounter} )
94endfunction()
95
96macro(GETTEXT_CREATE_TRANSLATIONS _potFile _firstPoFileArg)
97  # make it a real variable, so we can modify it here
98  set(_firstPoFile "${_firstPoFileArg}")
99
100  set(_gmoFiles)
101  get_filename_component(_potName ${_potFile} NAME)
102  string(REGEX REPLACE "^(.+)(\\.[^.]+)$" "\\1" _potBasename ${_potName})
103  get_filename_component(_absPotFile ${_potFile} ABSOLUTE)
104
105  set(_addToAll)
106  if(${_firstPoFile} STREQUAL "ALL")
107    set(_addToAll "ALL")
108    set(_firstPoFile)
109  endif()
110
111  foreach (_currentPoFile ${_firstPoFile} ${ARGN})
112    get_filename_component(_absFile ${_currentPoFile} ABSOLUTE)
113    get_filename_component(_abs_PATH ${_absFile} PATH)
114    get_filename_component(_lang ${_absFile} NAME_WE)
115    set(_gmoFile ${CMAKE_CURRENT_BINARY_DIR}/${_lang}.gmo)
116
117    add_custom_command(
118      OUTPUT ${_gmoFile}
119      COMMAND ${GETTEXT_MSGMERGE_EXECUTABLE} --quiet --update --backup=none -s ${_absFile} ${_absPotFile}
120      COMMAND ${GETTEXT_MSGFMT_EXECUTABLE} -o ${_gmoFile} ${_absFile}
121      DEPENDS ${_absPotFile} ${_absFile}
122    )
123
124    install(FILES ${_gmoFile} DESTINATION share/locale/${_lang}/LC_MESSAGES RENAME ${_potBasename}.mo)
125    set(_gmoFiles ${_gmoFiles} ${_gmoFile})
126
127  endforeach ()
128
129  if(NOT TARGET translations)
130    add_custom_target(translations)
131  endif()
132
133  _GETTEXT_GET_UNIQUE_TARGET_NAME(translations uniqueTargetName)
134
135  add_custom_target(${uniqueTargetName} ${_addToAll} DEPENDS ${_gmoFiles})
136
137  add_dependencies(translations ${uniqueTargetName})
138
139endmacro()
140
141
142function(GETTEXT_PROCESS_POT_FILE _potFile)
143  set(_gmoFiles)
144  set(_options ALL)
145  set(_oneValueArgs INSTALL_DESTINATION)
146  set(_multiValueArgs LANGUAGES)
147
148  CMAKE_PARSE_ARGUMENTS(_parsedArguments "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN})
149
150  get_filename_component(_potName ${_potFile} NAME)
151  string(REGEX REPLACE "^(.+)(\\.[^.]+)$" "\\1" _potBasename ${_potName})
152  get_filename_component(_absPotFile ${_potFile} ABSOLUTE)
153
154  foreach (_lang ${_parsedArguments_LANGUAGES})
155    set(_poFile  "${CMAKE_CURRENT_BINARY_DIR}/${_lang}.po")
156    set(_gmoFile "${CMAKE_CURRENT_BINARY_DIR}/${_lang}.gmo")
157
158    add_custom_command(
159      OUTPUT "${_poFile}"
160      COMMAND ${GETTEXT_MSGMERGE_EXECUTABLE} --quiet --update --backup=none -s ${_poFile} ${_absPotFile}
161      DEPENDS ${_absPotFile}
162    )
163
164    add_custom_command(
165      OUTPUT "${_gmoFile}"
166      COMMAND ${GETTEXT_MSGFMT_EXECUTABLE} -o ${_gmoFile} ${_poFile}
167      DEPENDS ${_absPotFile} ${_poFile}
168    )
169
170    if(_parsedArguments_INSTALL_DESTINATION)
171      install(FILES ${_gmoFile} DESTINATION ${_parsedArguments_INSTALL_DESTINATION}/${_lang}/LC_MESSAGES RENAME ${_potBasename}.mo)
172    endif()
173    list(APPEND _gmoFiles ${_gmoFile})
174  endforeach ()
175
176  if(NOT TARGET potfiles)
177    add_custom_target(potfiles)
178  endif()
179
180  _GETTEXT_GET_UNIQUE_TARGET_NAME( potfiles uniqueTargetName)
181
182  if(_parsedArguments_ALL)
183    add_custom_target(${uniqueTargetName} ALL DEPENDS ${_gmoFiles})
184  else()
185    add_custom_target(${uniqueTargetName} DEPENDS ${_gmoFiles})
186  endif()
187
188  add_dependencies(potfiles ${uniqueTargetName})
189
190endfunction()
191
192
193function(GETTEXT_PROCESS_PO_FILES _lang)
194  set(_options ALL)
195  set(_oneValueArgs INSTALL_DESTINATION)
196  set(_multiValueArgs PO_FILES)
197  set(_gmoFiles)
198
199  CMAKE_PARSE_ARGUMENTS(_parsedArguments "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN})
200
201  foreach(_current_PO_FILE ${_parsedArguments_PO_FILES})
202    get_filename_component(_name ${_current_PO_FILE} NAME)
203    string(REGEX REPLACE "^(.+)(\\.[^.]+)$" "\\1" _basename ${_name})
204    set(_gmoFile ${CMAKE_CURRENT_BINARY_DIR}/${_basename}.gmo)
205    add_custom_command(OUTPUT ${_gmoFile}
206      COMMAND ${GETTEXT_MSGFMT_EXECUTABLE} -o ${_gmoFile} ${_current_PO_FILE}
207      WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
208      DEPENDS ${_current_PO_FILE}
209    )
210
211    if(_parsedArguments_INSTALL_DESTINATION)
212      install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${_basename}.gmo DESTINATION ${_parsedArguments_INSTALL_DESTINATION}/${_lang}/LC_MESSAGES/ RENAME ${_basename}.mo)
213    endif()
214    list(APPEND _gmoFiles ${_gmoFile})
215  endforeach()
216
217
218  if(NOT TARGET pofiles)
219    add_custom_target(pofiles)
220  endif()
221
222  _GETTEXT_GET_UNIQUE_TARGET_NAME( pofiles uniqueTargetName)
223
224  if(_parsedArguments_ALL)
225    add_custom_target(${uniqueTargetName} ALL DEPENDS ${_gmoFiles})
226  else()
227    add_custom_target(${uniqueTargetName} DEPENDS ${_gmoFiles})
228  endif()
229
230  add_dependencies(pofiles ${uniqueTargetName})
231
232endfunction()
233