From 73992f139276b75aeddf78f476644a2d82f9e802 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20G=C3=A2teau?= Date: Sun, 4 May 2014 20:43:42 +0100 Subject: Add ECMPoQmTools module ecm_create_qm_from_po_files() was actually not very useful in practice. So that is deprecated, to be removed before ECM 1.0. Instead, the ECMPoQmTools provides several useful functions: ecm_create_qm_loader() (which already existed in ECMCreateQmFromPoFiles), ecm_process_po_files_as_qm() (which has the same signature as gettext_process_po_files() from the FindGettext module) and ecm_install_po_files_as_qm(), which is a convenience function mostly for the benefit of KDE Frameworks (although potentially useful for whatever other projects have the unusual requirement of a Gettext translation workflow but no Gettext usage in the code). NB: some clean-up to the documentation was done by Alex Merry as part of this commit. REVIEW: 117823 --- modules/ECMPoQmTools.cmake | 201 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 modules/ECMPoQmTools.cmake (limited to 'modules/ECMPoQmTools.cmake') diff --git a/modules/ECMPoQmTools.cmake b/modules/ECMPoQmTools.cmake new file mode 100644 index 00000000..e217dd3e --- /dev/null +++ b/modules/ECMPoQmTools.cmake @@ -0,0 +1,201 @@ +#.rst: +# ECMPoQmTools +# ------------ +# +# This module provides the ``ecm_process_po_files_as_qm`` and +# ``ecm_install_po_files_as_qm`` functions for generating QTranslator (.qm) +# catalogs from Gettext (.po) catalogs, and the ``ecm_create_qm_loader`` +# function for generating the necessary code to load them in a Qt application +# or library. +# +# :: +# +# ecm_process_po_files_as_qm( [ALL] +# [INSTALL_DESTINATION ] +# PO_FILES [ [...]]) +# +# Compile .po files into .qm files for the given language. +# +# If INSTALL_DESTINATION is given, the .qm files are installed in +# ``//LC_MESSAGES``. Typically, +# ```` is set to ``share/locale``. +# +# ``ecm_process_po_files_as_qm`` creates a "translations" target. This target +# builds all .po files into .qm files. If ALL is specified, these rules are +# added to the "all" target (and so the .qm files will be built by default). +# +# :: +# +# ecm_create_qm_loader( ) +# +# Generates a C++ file which ensures translations are automatically loaded at +# startup. The path of the .cpp file is appended to ````. +# +# It assumes that the .qm file for the language code ```` is installed as +# ``/locale//LC_MESSAGES/.qm``, where +# ```` is one of the directories given by the ``GenericDataLocation`` +# of ``QStandardPaths``. +# +# Typical usage is like: +# +# .. code-block:: cmake +# +# set(mylib_SRCS foo.cpp bar.cpp) +# ecm_create_qm_loader(mylib_SRCS mylib) +# add_library(mylib ${mylib_SRCS}) +# +# :: +# +# ecm_install_po_files_as_qm() +# +# Searches for .po files and installs them to the standard location. +# +# This is a convenience function which relies on all .po files being kept in +# ``//``, where ```` is the language the .po files are +# written in. +# +# For example, given the following directory structure:: +# +# po/ +# fr/ +# mylib.po +# +# ``ecm_install_po_files_as_qm(po)`` compiles ``mylib.po`` into ``mylib.mo`` and +# installs it in ``/fr/LC_MESSAGES``. +# ```` defaults to ``${LOCALE_INSTALL_DIR}`` if defined, +# otherwise it uses ``${CMAKE_INSTALL_LOCALEDIR}`` if that is defined, otherwise +# it uses ``share/locale``. + +#============================================================================= +# Copyright 2007-2009 Kitware, Inc. +# Copyright 2007 Alexander Neundorf +# Copyright 2014 Aurélien Gâteau +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file COPYING-CMAKE-SCRIPTS for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of extra-cmake-modules, substitute the full +# License text for the above reference.) + +include(CMakeParseArguments) + +# Copied from FindGettext.cmake +function(_ecm_qm_get_unique_target_name _name _unique_name) + set(propertyName "_ECM_QM_UNIQUE_COUNTER_${_name}") + get_property(currentCounter GLOBAL PROPERTY "${propertyName}") + if(NOT currentCounter) + set(currentCounter 1) + endif() + set(${_unique_name} "${_name}_${currentCounter}" PARENT_SCOPE) + math(EXPR currentCounter "${currentCounter} + 1") + set_property(GLOBAL PROPERTY ${propertyName} ${currentCounter} ) +endfunction() + + +function(ecm_create_qm_loader out_var catalog_name) + # catalog_name is used in ECMQmLoader.cpp.in + configure_file(${ECM_MODULE_DIR}/ECMQmLoader.cpp.in ECMQmLoader.cpp @ONLY) + set(${out_var} ${${out_var}} ${CMAKE_CURRENT_BINARY_DIR}/ECMQmLoader.cpp PARENT_SCOPE) +endfunction() + + +function(ecm_process_po_files_as_qm lang) + # Parse arguments + set(options ALL) + set(oneValueArgs INSTALL_DESTINATION) + set(multiValueArgs PO_FILES) + cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(ARGS_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "Unknown keywords given to ecm_process_po_files_as_qm(): \"${ARGS_UNPARSED_ARGUMENTS}\"") + endif() + + if(NOT ARGS_PO_FILES) + message(FATAL_ERROR "ecm_process_po_files_as_qm() must be called with PO_FILES argument") + endif() + + # Find lrelease and lconvert + + # This gives us Qt5::lrelease but unfortunately no Qt5::lconvert See + # https://bugreports.qt-project.org/browse/QTBUG-37937 + find_package(Qt5LinguistTools CONFIG REQUIRED) + + get_target_property(lrelease_location Qt5::lrelease LOCATION) + get_filename_component(lrelease_path ${lrelease_location} PATH) + find_program(lconvert_executable + NAMES lconvert-qt5 lconvert + PATHS ${lrelease_path} + ) + + # Create commands to turn po files into qm files + set(qm_files) + foreach (po_file ${ARGS_PO_FILES}) + get_filename_component(po_file ${po_file} ABSOLUTE) + get_filename_component(filename_base ${po_file} NAME_WE) + + # Include ${lang} in build dir because we might be called multiple times + # with the same ${filename_base} + set(build_dir ${CMAKE_CURRENT_BINARY_DIR}/${lang}) + set(ts_file ${build_dir}/${filename_base}.ts) + set(qm_file ${build_dir}/${filename_base}.qm) + + file(MAKE_DIRECTORY ${build_dir}) + + # lconvert from .po to .ts, then lrelease from .ts to .qm. + add_custom_command(OUTPUT ${qm_file} + COMMAND ${lconvert_executable} + ARGS -i ${po_file} -o ${ts_file} -target-language ${lang} + COMMAND Qt5::lrelease + ARGS -compress -removeidentical -silent ${ts_file} -qm ${qm_file} + DEPENDS ${po_file} + ) + if (ARGS_INSTALL_DESTINATION) + install( + FILES ${qm_file} + DESTINATION ${ARGS_INSTALL_DESTINATION}/${lang}/LC_MESSAGES + ) + endif() + list(APPEND qm_files ${qm_file}) + endforeach() + + # Hook qm files to targets + if(NOT TARGET translations) + add_custom_target(translations) + endif() + + _ecm_qm_get_unique_target_name(translations target_name) + + if (ARGS_ALL) + add_custom_target(${target_name} ALL DEPENDS ${qm_files}) + else() + add_custom_target(${target_name} DEPENDS ${qm_files}) + endif() + + add_dependencies(translations ${target_name}) +endfunction() + + +function(ecm_install_po_files_as_qm podir) + if (LOCALE_INSTALL_DIR) + set(install_destination "${LOCALE_INSTALL_DIR}") + elseif (CMAKE_INSTALL_LOCALEDIR) + set(install_destination "${CMAKE_INSTALL_LOCALEDIR}") + else() + set(install_destination share/locale) + endif() + + file(GLOB lang_dirs "${podir}/*") + foreach(lang_dir ${lang_dirs}) + file(GLOB po_files "${lang_dir}/*.po") + get_filename_component(lang ${lang_dir} NAME) + ecm_process_po_files_as_qm( + ${lang} ALL + PO_FILES ${po_files} + INSTALL_DESTINATION ${install_destination} + ) + endforeach() +endfunction() -- cgit v1.2.1