Browse Source

FindGettext: Update documentation

- Updated module documentation.
- The Gettext_FOUND variable used (CMake 3.3). Uppercased GETTEXT_FOUND
  is also set to the same value by find_package_handle_standard_args().
- Updated all commands and arguments descriptions according to the
  current implementation.
- Moved the gettext_process_po_files() command to top as it seems to
  be a bit more convenient for usage than other two.
- Renamed "functions" to "commands" as some of these are macros and some
  are functions. From the user PoV, knowing whether some module command
  is a macro or a function is mostly irrelevant.
- Added extended examples section showing some basic usage of the module
  commands.

Fixes #16034
Peter Kokot 7 months ago
parent
commit
c13351533d
1 changed files with 338 additions and 37 deletions
  1. 338 37
      Modules/FindGettext.cmake

+ 338 - 37
Modules/FindGettext.cmake

@@ -5,84 +5,385 @@
 FindGettext
 -----------
 
-Find GNU gettext tools.
+Finds the GNU gettext tools and provides commands for producing multi-lingual
+messages:
 
-This module looks for the GNU gettext tools.
+.. code-block:: cmake
+
+  find_package(Gettext [<version>] ...)
+
+GNU gettext is a system for internationalization (i18n) and localization
+(l10n), consisting of command-line tools and a runtime library (``libintl``).
+This module finds the gettext tools (such as ``msgmerge`` and ``msgfmt``),
+while the runtime library can be found using the separate :module:`FindIntl`
+module, which abstracts ``libintl`` handling across various implementations.
+
+Common file types used with gettext:
+
+POT files
+  Portable Object Template (``.pot``) files used as the source template for
+  translations.
+
+PO files
+  Portable Object (``.po``) files containing human-readable translations.
+
+MO files
+  Machine Object (``.mo``) files compiled from ``.po`` files for runtime use.
 
 Result Variables
 ^^^^^^^^^^^^^^^^
 
 This module defines the following variables:
 
-``GETTEXT_FOUND``
-  True if gettext has been found.
+``Gettext_FOUND``
+  Boolean indicating whether (the requested version of) gettext is found.  For
+  backward compatibility, the ``GETTEXT_FOUND`` variable is also set to the same
+  value.
 
 ``GETTEXT_VERSION_STRING``
   The version of gettext found.
 
+Cache Variables
+^^^^^^^^^^^^^^^
+
+The following cache variables may also be set:
+
 ``GETTEXT_MSGMERGE_EXECUTABLE``
-  The full path to the msgmerge tool.
+  The full path to the ``msgmerge`` tool for merging message catalog and
+  template.
 
 ``GETTEXT_MSGFMT_EXECUTABLE``
-  The full path to the msgfmt tool.
+  The full path to the ``msgfmt`` tool for compiling message catalog to a binary
+  format.
 
-Functions
-^^^^^^^^^
+Commands
+^^^^^^^^
 
-This module provides several function.
+This module provides the following commands to work with gettext in CMake, if
+gettext is found:
 
-.. command:: gettext_create_translations
+.. command:: gettext_process_po_files
+
+  Creates a build rule that processes one or more ``.po`` translation files
+  into binary ``.mo`` files for a specified translatable language locale:
 
   .. code-block:: cmake
 
-    gettext_create_translations(<potfile> [ALL] <file>...)
+    gettext_process_po_files(
+      <language>
+      [ALL]
+      [INSTALL_DESTINATION <destdir>]
+      PO_FILES <po-files>...
+    )
 
-  This function creates a custom target "translations" which processes the
-  given .pot file to .mo files. The generated binary files will be installed
-  into ``share/locale/`` directory. Options:
+  This command defines a custom target that compiles the given ``<po-files>``
+  into ``.mo`` files for the specified ``<language>``.  On first invocation,
+  it also creates a global custom target named ``pofiles``, to which all
+  subsequent invocations contribute.  This target can be used to build all
+  translation files collectively or referenced in other CMake commands.
+
+  This command should be invoked separately for each language locale to
+  generate the appropriate ``.mo`` files per locale.
+
+  The arguments are:
+
+  ``<language>``
+    The target translatable language locale of the PO files.
+
+    This string is typically formatted as a locale identifier (e.g., ``de_DE``
+    for German as used in Germany, or ``de_AT`` for German as used in Austria,
+    etc.).  The part before the underscore specifies the language, and the
+    part after specifies the country or regional variant.  In some cases, a
+    shorter form using only the language code (e.g., ``de``) may also be used.
 
   ``ALL``
-    The translations will be created when building the default target.
+    This option adds the generated target to the default CMake build target so
+    that translations are built by default.
+
+  ``INSTALL_DESTINATION <destdir>``
+    Specifies the installation directory for the generated ``.mo`` files at
+    the install phase.  If specified, files are installed to:
+    ``<destdir>/<language>/LC_MESSAGES/*.mo``.  If not specified, files are
+    not installed.
+
+  ``PO_FILES <po-files>...``
+    A list of one or more ``.po`` translation files to be compiled into
+    ``.mo`` files at build phase for the specified ``<language>``.  Relative
+    paths will be interpreted relative to the current source directory
+    (:variable:`CMAKE_CURRENT_SOURCE_DIR`).
 
 .. command:: gettext_process_pot_file
 
+  Creates a build rule that processes a gettext Portable Object Template
+  (``.pot``) file and associated ``.po`` files into compiled gettext Machine
+  Object (``.mo``) files:
+
   .. code-block:: cmake
 
-      gettext_process_pot_file(<potfile> [ALL]
-                               [INSTALL_DESTINATION <destdir>]
-                               LANGUAGES <lang>...)
+    gettext_process_pot_file(
+      <pot-file>
+      [ALL]
+      [INSTALL_DESTINATION <destdir>]
+      LANGUAGES <languages>...
+    )
+
+  This command defines a custom target named ``potfiles`` that compiles the
+  given ``<pot-file>`` and language-specific ``.po`` files into binary ``.mo``
+  files for each specified language.  The corresponding ``<language>.po``
+  files must exist in the current binary directory
+  (:variable:`CMAKE_CURRENT_BINARY_DIR`) before this command is invoked.
 
-  This function creates a custom target "potfiles" which processes the given
-  .pot file to .mo files. Options:
+  The arguments are:
+
+  ``<pot-file>``
+    The path to the gettext Portable Object Template file (``.pot``) serving
+    as the source for translations.  If given as a relative path, it will be
+    interpreted relative to the current source directory
+    (:variable:`CMAKE_CURRENT_SOURCE_DIR`).
 
   ``ALL``
-    The .pot file will be processed when building the default target.
+    Adds the generated target to the default CMake build target so that the
+    files are built by default.
 
-  ``INSTALL_DESTINATION``
-    Install the results into the given directory (``share/locale/`` by
-    default). The language subdirectory will be taken into account.
+  ``INSTALL_DESTINATION <destdir>``
+    Specifies the installation directory for the generated ``.mo`` files at
+    the install phase.  If specified, files are installed to:
+    ``<destdir>/<language>/LC_MESSAGES/<pot-base-filename>.mo``.  If not
+    specified, files are not installed.
 
-.. command:: gettext_process_po_files
+  ``LANGUAGES <languages>...``
+    A list of one or more translatable language locales (e.g., ``en_US``,
+    ``fr``, ``de_DE``, ``zh_CN``, etc.).
+
+.. command:: gettext_create_translations
+
+  Creates a build rule that processes a given ``.pot`` template file and
+  associated ``.po`` translation files into compiled Machine Object (``.mo``)
+  files:
 
   .. code-block:: cmake
 
-    gettext_process_po_files(<lang> [ALL]
-                             [INSTALL_DESTINATION <dir>]
-                             PO_FILES <pofile>...)
+    gettext_create_translations(<pot-file> [ALL] <po-files>...)
 
-  This function creates a custom target "pofiles", which processes the given
-  .po files to .mo files for the given language. Options:
+  This command defines a custom target named ``translations`` that compiles
+  the specified ``<pot-file>`` and ``<po-files>`` into binary ``.mo`` files.
+  It also automatically adds an install rule for the generated ``.mo`` files,
+  installing them into the default
+  ``share/locale/<language>/LC_MESSAGES/<pot-base-filename>.mo`` path during
+  the install phase.
+
+  The arguments are:
+
+  ``<pot-file>``
+    The path to the gettext Portable Object Template file (``.pot``) serving
+    as the source for translations.  If given as a relative path, it will be
+    interpreted relative to the current source directory
+    (:variable:`CMAKE_CURRENT_SOURCE_DIR`).
 
   ``ALL``
-    The .po files will be processed when building the default target.
+    Adds the generated target to the default CMake build target so that
+    translations are created by default during the build.
+
+  ``<po-files>...``
+    A list of one or more translation source files in ``.po`` format, whose
+    filenames must follow the format ``<language>.po``.  Relative paths will
+    be interpreted relative to the current source directory
+    (:variable:`CMAKE_CURRENT_SOURCE_DIR`).
+
+  .. note::
+    For better control over build and installation behavior, use
+    :command:`gettext_process_po_files` instead.
+
+Examples
+^^^^^^^^
+
+Examples: Finding gettext
+"""""""""""""""""""""""""
+
+Finding the GNU gettext tools:
+
+.. code-block:: cmake
+
+  find_package(Gettext)
+
+Or, finding gettext and specifying a minimum required version:
+
+.. code-block:: cmake
+
+  find_package(Gettext 0.21)
+
+Or, finding gettext and making it required (if not found, processing stops
+with an error message):
+
+.. code-block:: cmake
+
+  find_package(Gettext REQUIRED)
+
+Example: Working With gettext in CMake
+""""""""""""""""""""""""""""""""""""""
+
+When starting with gettext, ``.pot`` file is considered to be created manually.
+For example, using a ``xgettext`` tool on the provided ``main.cxx`` source
+code file:
+
+.. code-block:: c++
+  :caption: ``main.cxx``
+  :emphasize-lines: 18
+
+  #include <iostream>
+  #include <libintl.h>
+  #include <locale.h>
+
+  int main()
+  {
+    // Set locale from environment
+    setlocale(LC_ALL, "");
+
+    // Bind the text domain
+    const char* dir = std::getenv("TEXTDOMAINDIR");
+    if (!dir) {
+      dir = "/usr/local/share/locale";
+    }
+    bindtextdomain("MyApp", dir);
+    textdomain("MyApp");
+
+    std::cout << gettext("Hello, World") << std::endl;
+
+    return 0;
+  }
+
+The ``xgettext`` tool extracts all strings from ``gettext()`` calls in provided
+source code and creates translatable strings:
+
+.. code-block:: console
+
+  $ xgettext -o MyApp.pot main.cxx
+
+Translatable files can be initialized by the project manually using
+``msginit`` tool:
+
+.. code-block:: console
+
+  $ mkdir -p locale/de_DE
+  $ msginit -l de_DE.UTF8 -o locale/de_DE/MyApp.po -i MyApp.pot --no-translator
+
+which creates a human-readable file that can be translated into a desired
+language (adjust as needed):
+
+.. code-block:: po
+  :caption: ``locale/de_DE/MyApp.po``
+  :emphasize-lines: 9
+
+  msgid ""
+  msgstr ""
+  "Language: de\n"
+  "Content-Type: text/plain; charset=UTF-8\n"
+  "Content-Transfer-Encoding: 8bit\n"
+  "Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+  msgid "Hello, World"
+  msgstr "Hallo, Welt"
+
+In CMake, the :command:`gettext_process_po_files` command provided by this
+module automatically creates the needed ``.mo`` files that application loads
+at runtime depending on the system environment variables such as ``LANG``.
+In the following example, also the :module:`GNUInstallDirs` module is used
+to provide the ``CMAKE_INSTALL_LOCALEDIR`` variable:
+
+.. code-block:: cmake
+  :caption: ``CMakeLists.txt``
+  :emphasize-lines: 9-14
+
+  cmake_minimum_required(VERSION 3.24)
+  project(GettextExample)
+  include(GNUInstallDirs)
+
+  find_package(Gettext)
+
+  if(Gettext_FOUND)
+    foreach(language IN ITEMS de_DE)
+      gettext_process_po_files(
+        ${language}
+        ALL
+        PO_FILES locale/${language}/MyApp.po
+        INSTALL_DESTINATION ${CMAKE_INSTALL_LOCALEDIR}
+      )
+    endforeach()
+  endif()
+
+  add_executable(example main.cxx)
+
+  # Find and link Intl library to use gettext() from libintl.h
+  find_package(Intl)
+  target_link_libraries(example PRIVATE Intl::Intl)
+
+  install(TARGETS example)
+
+.. code-block:: console
+
+  $ cmake -B build
+  $ cmake --build build
+  $ DESTDIR=$(pwd)/stage cmake --install build
+
+To utilize the translations, the ``de_DE`` locale needs to be enabled on the
+system (see ``locale -a``).  And then the localized output can be run:
+
+.. code-block:: console
+
+  $ LANG=de_DE.UTF-8 TEXTDOMAINDIR=./stage/usr/local/share/locale \
+    ./stage/usr/local/bin/example
+
+Example: Processing POT File
+""""""""""""""""""""""""""""
+
+The :command:`gettext_process_pot_file` command processes ``.po`` translation
+files located in the current binary directory into ``.mo`` files:
+
+.. code-block:: cmake
+  :caption: ``CMakeLists.txt``
+
+  find_package(Gettext)
+
+  if(Gettext_FOUND)
+    set(languages de_DE fr zh_CN)
+
+    foreach(language IN LISTS languages)
+      configure_file(locale/${language}.po ${language}.po COPYONLY)
+    endforeach()
+
+    gettext_process_pot_file(
+      MyApp.pot
+      ALL
+      INSTALL_DESTINATION ${CMAKE_INSTALL_LOCALEDIR}
+      LANGUAGES ${languages}
+    )
+  endif()
+
+Example: Creating Translations
+""""""""""""""""""""""""""""""
+
+Using a simplified :command:`gettext_create_translations` command to create
+``.mo`` files:
+
+.. code-block:: cmake
+  :caption: ``CMakeLists.txt``
+
+  find_package(Gettext)
+
+  if(Gettext_FOUND)
+    gettext_create_translations(
+      MyApp.pot
+      ALL
+      locale/de_DE.po
+      locale/fr.po
+      locale/zh_CN.po
+    )
+  endif()
 
-  ``INSTALL_DESTINATION``
-    Install the results into the given directory (``share/locale/`` by
-    default). The language subdirectory will be taken into account.
+See Also
+^^^^^^^^
 
-.. versionadded:: 3.2
-  If you wish to use the Gettext runtime library (libintl), use
-  :module:`FindIntl`.
+* The :module:`FindIntl` module to find the Gettext runtime library (libintl).
 #]=======================================================================]
 
 find_program(GETTEXT_MSGMERGE_EXECUTABLE msgmerge)