Warning, /frameworks/extra-cmake-modules/modules/ECMPoQmTools.cmake is written in an unsupported language. File is not indexed.
0001 # SPDX-FileCopyrightText: 2007-2009 Kitware, Inc. 0002 # SPDX-FileCopyrightText: 2007 Alexander Neundorf <neundorf@kde.org> 0003 # SPDX-FileCopyrightText: 2014 Aurélien Gâteau <agateau@kde.org> 0004 # 0005 # SPDX-License-Identifier: BSD-3-Clause 0006 0007 #[=======================================================================[.rst: 0008 ECMPoQmTools 0009 ------------ 0010 0011 This module provides the ``ecm_process_po_files_as_qm`` and 0012 ``ecm_install_po_files_as_qm`` functions for generating QTranslator (.qm) 0013 catalogs from Gettext (.po) catalogs, and the ``ecm_create_qm_loader`` 0014 function for generating the necessary code to load them in a Qt application 0015 or library. 0016 0017 :: 0018 0019 ecm_process_po_files_as_qm(<lang> [ALL] 0020 [INSTALL_DESTINATION <install_destination>] 0021 PO_FILES <pofile> [<pofile> [...]]) 0022 0023 Compile .po files into .qm files for the given language. 0024 0025 If ``INSTALL_DESTINATION`` is given, the .qm files are installed in 0026 ``<install_destination>/<lang>/LC_MESSAGES``. Typically, 0027 ``<install_destination>`` is set to ``share/locale``. 0028 0029 ``ecm_process_po_files_as_qm`` creates a "translations" target. This target 0030 builds all .po files into .qm files. If ``ALL`` is specified, these rules are 0031 added to the "all" target (and so the .qm files will be built by default). 0032 0033 :: 0034 0035 ecm_create_qm_loader(<sources_var_name(|target (since 5.83))> <catalog_name>) 0036 0037 Generates C++ code which ensures translations are automatically loaded at 0038 startup. The generated files are appended to the variable named 0039 ``<sources_var_name>`` or, if the first argument is a target (since 5.83), to 0040 the ``SOURCES`` property of ``<target>``. Any target must be created with 0041 ``add_executable()`` or ``add_library()`` and not be an alias. 0042 0043 It assumes that the .qm file for the language code ``<lang>`` is installed as 0044 ``<sharedir>/locale/<lang>/LC_MESSAGES/<catalog_name>.qm``, where 0045 ``<sharedir>`` is one of the directories given by the ``GenericDataLocation`` 0046 of ``QStandardPaths``. 0047 0048 Typical usage is like: 0049 0050 .. code-block:: cmake 0051 0052 set(mylib_SRCS foo.cpp bar.cpp) 0053 ecm_create_qm_loader(mylib_SRCS mycatalog) 0054 add_library(mylib ${mylib_SRCS}) 0055 0056 # Or, since 5.83: 0057 add_library(mylib foo.cpp bar.cpp) 0058 ecm_create_qm_loader(mylib mycatalog) 0059 0060 :: 0061 0062 ecm_install_po_files_as_qm(<podir>) 0063 0064 Searches for .po files and installs them to the standard location. 0065 0066 This is a convenience function which relies on all .po files being kept in 0067 ``<podir>/<lang>/``, where ``<lang>`` is the language the .po files are 0068 written in. 0069 0070 For example, given the following directory structure:: 0071 0072 po/ 0073 fr/ 0074 mylib.po 0075 0076 ``ecm_install_po_files_as_qm(po)`` compiles ``mylib.po`` into ``mylib.qm`` and 0077 installs it in ``<install_destination>/fr/LC_MESSAGES``. 0078 ``<install_destination>`` defaults to ``${LOCALE_INSTALL_DIR}`` if defined, 0079 otherwise it uses ``${CMAKE_INSTALL_LOCALEDIR}`` if that is defined, otherwise 0080 it uses ``share/locale``. 0081 0082 Since pre-1.0.0. 0083 #]=======================================================================] 0084 0085 include(${CMAKE_CURRENT_LIST_DIR}/QtVersionOption.cmake) 0086 0087 0088 # Copied from FindGettext.cmake 0089 function(_ecm_qm_get_unique_target_name _name _unique_name) 0090 set(propertyName "_ECM_QM_UNIQUE_COUNTER_${_name}") 0091 get_property(currentCounter GLOBAL PROPERTY "${propertyName}") 0092 if(NOT currentCounter) 0093 set(currentCounter 1) 0094 endif() 0095 set(${_unique_name} "${_name}_${currentCounter}" PARENT_SCOPE) 0096 math(EXPR currentCounter "${currentCounter} + 1") 0097 set_property(GLOBAL PROPERTY ${propertyName} ${currentCounter} ) 0098 endfunction() 0099 0100 0101 function(ecm_create_qm_loader sourcesvar_or_target catalog_name) 0102 if (TARGET ${sourcesvar_or_target}) 0103 get_target_property(target_type ${sourcesvar_or_target} TYPE) 0104 set(allowed_types "EXECUTABLE" "STATIC_LIBRARY" "MODULE_LIBRARY" "SHARED_LIBRARY" "OBJECT_LIBRARY" "INTERFACE_LIBRARY") 0105 if (NOT target_type IN_LIST allowed_types) 0106 message(FATAL_ERROR "Target argument passed to ecm_create_qm_loader is not an executable or a library: ${appsources_or_target}") 0107 endif() 0108 get_target_property(aliased_target ${sourcesvar_or_target} ALIASED_TARGET) 0109 if(aliased_target) 0110 message(FATAL_ERROR "Target argument passed to ecm_create_qm_loader must not be an alias: ${sourcesvar_or_target}") 0111 endif() 0112 endif() 0113 set(loader_base ${CMAKE_CURRENT_BINARY_DIR}/ECMQmLoader-${catalog_name}) 0114 0115 set(QM_LOADER_CATALOG_NAME "${catalog_name}") 0116 0117 set(QM_LOADER_CPP_FILE "${loader_base}.cpp") 0118 configure_file( 0119 ${ECM_MODULE_DIR}/ECMQmLoader.cpp.in 0120 ${QM_LOADER_CPP_FILE} 0121 @ONLY 0122 ) 0123 if (TARGET ${sourcesvar_or_target}) 0124 target_sources(${sourcesvar_or_target} PRIVATE ${QM_LOADER_CPP_FILE}) 0125 else() 0126 set(${sourcesvar_or_target} "${${sourcesvar_or_target}}" ${QM_LOADER_CPP_FILE} PARENT_SCOPE) 0127 endif() 0128 endfunction() 0129 0130 0131 function(ecm_process_po_files_as_qm lang) 0132 # Parse arguments 0133 set(options ALL) 0134 set(oneValueArgs INSTALL_DESTINATION) 0135 set(multiValueArgs PO_FILES) 0136 cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) 0137 0138 if(ARGS_UNPARSED_ARGUMENTS) 0139 message(FATAL_ERROR "Unknown keywords given to ecm_process_po_files_as_qm(): \"${ARGS_UNPARSED_ARGUMENTS}\"") 0140 endif() 0141 0142 if(NOT ARGS_PO_FILES) 0143 message(FATAL_ERROR "ecm_process_po_files_as_qm() must be called with PO_FILES argument") 0144 endif() 0145 0146 # Find lrelease and lconvert 0147 if (QT_MAJOR_VERSION EQUAL "5") 0148 find_package(Qt5LinguistTools CONFIG REQUIRED) 0149 else() 0150 find_package(Qt6 COMPONENTS LinguistTools CONFIG REQUIRED) 0151 endif() 0152 0153 if(TARGET Qt${QT_MAJOR_VERSION}::lconvert) 0154 set(lconvert_executable Qt${QT_MAJOR_VERSION}::lconvert) 0155 else() 0156 # Qt < 5.3.1 does not define Qt5::lconvert 0157 get_target_property(lrelease_location Qt5::lrelease LOCATION) 0158 get_filename_component(lrelease_path ${lrelease_location} PATH) 0159 find_program(lconvert_executable 0160 NAMES lconvert-qt5 lconvert 0161 PATHS ${lrelease_path} 0162 NO_DEFAULT_PATH 0163 ) 0164 endif() 0165 0166 # Create commands to turn po files into qm files 0167 set(qm_files) 0168 foreach (po_file ${ARGS_PO_FILES}) 0169 get_filename_component(po_file ${po_file} ABSOLUTE) 0170 get_filename_component(filename_base ${po_file} NAME_WE) 0171 0172 # Use own ECMPoQm/ subfolder for processing the files, to avoid cluttering 0173 # the default build dir as well as potential file/dir name clashes from 0174 # other build artifacts. 0175 # Include ${lang} in build dir because we might be called multiple times 0176 # with the same ${filename_base} 0177 set(build_dir ${CMAKE_CURRENT_BINARY_DIR}/ECMPoQm/${lang}) 0178 set(ts_file ${build_dir}/${filename_base}.ts) 0179 set(qm_file ${build_dir}/${filename_base}.qm) 0180 0181 file(MAKE_DIRECTORY ${build_dir}) 0182 0183 # lconvert from .po to .ts, then lrelease from .ts to .qm. 0184 add_custom_command(OUTPUT ${qm_file} 0185 COMMAND ${lconvert_executable} 0186 ARGS -i ${po_file} -o ${ts_file} -target-language ${lang} 0187 COMMAND Qt${QT_MAJOR_VERSION}::lrelease 0188 ARGS -removeidentical -nounfinished -silent ${ts_file} -qm ${qm_file} 0189 DEPENDS ${po_file} 0190 ) 0191 if (ARGS_INSTALL_DESTINATION) 0192 install( 0193 FILES ${qm_file} 0194 DESTINATION ${ARGS_INSTALL_DESTINATION}/${lang}/LC_MESSAGES 0195 ) 0196 endif() 0197 list(APPEND qm_files ${qm_file}) 0198 endforeach() 0199 0200 # Hook qm files to targets 0201 if(NOT TARGET translations) 0202 add_custom_target(translations) 0203 endif() 0204 0205 _ecm_qm_get_unique_target_name(translations target_name) 0206 0207 if (ARGS_ALL) 0208 add_custom_target(${target_name} ALL DEPENDS ${qm_files}) 0209 else() 0210 add_custom_target(${target_name} DEPENDS ${qm_files}) 0211 endif() 0212 0213 add_dependencies(translations ${target_name}) 0214 endfunction() 0215 0216 0217 function(ecm_install_po_files_as_qm podir) 0218 if (LOCALE_INSTALL_DIR) 0219 set(install_destination "${LOCALE_INSTALL_DIR}") 0220 elseif (CMAKE_INSTALL_LOCALEDIR) 0221 set(install_destination "${CMAKE_INSTALL_LOCALEDIR}") 0222 else() 0223 set(install_destination share/locale) 0224 endif() 0225 0226 get_filename_component(absolute_podir ${podir} ABSOLUTE) 0227 0228 # we try to find the po directory in the binary directory, in case it was downloaded 0229 # using ECM 0230 if (NOT (EXISTS "${absolute_podir}" AND IS_DIRECTORY "${absolute_podir}")) 0231 get_filename_component(absolute_podir ${CMAKE_BINARY_DIR}/${podir} ABSOLUTE) 0232 endif() 0233 0234 if (NOT (EXISTS "${absolute_podir}" AND IS_DIRECTORY "${absolute_podir}")) 0235 # Nothing to do if there's no podir and it would create an empty 0236 # LOCALE_INSTALL_DIR in that case. 0237 return() 0238 endif() 0239 0240 file(GLOB po_files "${absolute_podir}/*/*.po") 0241 foreach(po_file ${po_files}) 0242 get_filename_component(po_dir ${po_file} DIRECTORY) 0243 get_filename_component(lang ${po_dir} NAME) 0244 ecm_process_po_files_as_qm( 0245 ${lang} ALL 0246 PO_FILES ${po_file} 0247 INSTALL_DESTINATION ${install_destination} 0248 ) 0249 endforeach() 0250 endfunction()