FindGettext¶
查找 GNU gettext 工具并提供用于生成多语言消息的命令
find_package(Gettext [<version>] ...)
GNU gettext 是一个用于国际化 (i18n) 和本地化 (l10n) 的系统,由命令行工具和运行时库 (libintl
) 组成。此模块查找 gettext 工具(例如 msgmerge
和 msgfmt
),而运行时库可以使用单独的 FindIntl
模块查找,该模块抽象了各种实现中的 libintl
处理。
gettext 中常用的文件类型
- POT 文件
Portable Object Template (
.pot
) 文件用作翻译的源模板。- PO 文件
Portable Object (
.po
) 文件包含人类可读的翻译。- MO 文件
Machine Object (
.mo
) 文件由.po
文件编译而来,用于运行时使用。
结果变量¶
此模块定义了以下变量
Gettext_FOUND
布尔值,指示是否找到 gettext(以及请求的版本)。为了向后兼容,
GETTEXT_FOUND
变量也设置为相同的值。GETTEXT_VERSION_STRING
找到的 gettext 版本。
缓存变量¶
以下缓存变量也可以设置
GETTEXT_MSGMERGE_EXECUTABLE
msgmerge
工具的完整路径,用于合并消息目录和模板。GETTEXT_MSGFMT_EXECUTABLE
msgfmt
工具的完整路径,用于将消息目录编译为二进制格式。
命令¶
如果找到 gettext,此模块提供以下命令以在 CMake 中使用 gettext
- gettext_process_po_files¶
创建构建规则,将一个或多个
.po
翻译文件处理为指定可翻译语言区域的二进制.mo
文件gettext_process_po_files( <language> [ALL] [INSTALL_DESTINATION <destdir>] PO_FILES <po-files>... )
此命令定义了一个自定义目标,用于将给定的
<po-files>
编译成指定<language>
的.mo
文件。首次调用时,它还会创建一个名为pofiles
的全局自定义目标,所有后续调用都会向其贡献。此目标可用于集体构建所有翻译文件或在其他 CMake 命令中引用。应为每个语言区域单独调用此命令,以生成每个区域相应的
.mo
文件。参数为
<language>
PO 文件的目标可翻译语言区域。
此字符串通常格式为区域标识符(例如,用于德国德语的
de_DE
,或用于奥地利德语的de_AT
等)。下划线前的一部分指定语言,下划线后的一部分指定国家或地区变体。在某些情况下,也可以使用仅包含语言代码的较短形式(例如,de
)。ALL
此选项将生成的任务添加到默认的 CMake 构建任务,以便默认构建翻译。
INSTALL_DESTINATION <destdir>
指定在安装阶段生成
.mo
文件的安装目录。如果指定,文件将安装到:<destdir>/<language>/LC_MESSAGES/*.mo
。如果未指定,则不安装文件。PO_FILES <po-files>...
一个或多个
.po
翻译文件的列表,将在构建阶段为指定的<language>
编译成.mo
文件。相对路径将相对于当前源目录 (CMAKE_CURRENT_SOURCE_DIR
) 进行解释。
- gettext_process_pot_file¶
创建构建规则,处理 gettext 可移植对象模板 (
.pot
) 文件和相关的.po
文件,生成已编译的 gettext 机器对象 (.mo
) 文件gettext_process_pot_file( <pot-file> [ALL] [INSTALL_DESTINATION <destdir>] LANGUAGES <languages>... )
此命令定义了一个名为
potfiles
的自定义目标,它将给定的<pot-file>
和特定语言的.po
文件编译成每个指定语言的二进制.mo
文件。在调用此命令之前,相应的<language>.po
文件必须存在于当前二进制目录 (CMAKE_CURRENT_BINARY_DIR
) 中。参数为
<pot-file>
gettext 可移植对象模板文件 (
.pot
) 的路径,作为翻译的来源。如果给定相对路径,则将相对于当前源目录 (CMAKE_CURRENT_SOURCE_DIR
) 进行解释。ALL
将生成的任务添加到默认的 CMake 构建任务,以便默认构建文件。
INSTALL_DESTINATION <destdir>
指定在安装阶段生成
.mo
文件的安装目录。如果指定,文件将安装到:<destdir>/<language>/LC_MESSAGES/<pot-base-filename>.mo
。如果未指定,则不安装文件。LANGUAGES <languages>...
一个或多个可翻译语言区域的列表(例如,
en_US
、fr
、de_DE
、zh_CN
等)。
- gettext_create_translations¶
创建构建规则,处理给定的
.pot
模板文件和相关的.po
翻译文件,生成已编译的机器对象 (.mo
) 文件gettext_create_translations(<pot-file> [ALL] <po-files>...)
此命令定义了一个名为
translations
的自定义目标,它将指定的<pot-file>
和<po-files>
编译成二进制.mo
文件。它还会自动为生成的.mo
文件添加安装规则,在安装阶段将其安装到默认的share/locale/<language>/LC_MESSAGES/<pot-base-filename>.mo
路径。参数为
<pot-file>
gettext 可移植对象模板文件 (
.pot
) 的路径,作为翻译的来源。如果给定相对路径,则将相对于当前源目录 (CMAKE_CURRENT_SOURCE_DIR
) 进行解释。ALL
将生成的任务添加到默认的 CMake 构建任务,以便在构建过程中默认创建翻译。
<po-files>...
一个或多个
.po
格式的翻译源文件列表,其文件名必须遵循<language>.po
格式。相对路径将相对于当前源目录 (CMAKE_CURRENT_SOURCE_DIR
) 进行解释。
注意
为了更好地控制构建和安装行为,请改用
gettext_process_po_files()
。
示例¶
示例:查找 gettext¶
查找 GNU gettext 工具
find_package(Gettext)
或者,查找 gettext 并指定最小所需版本
find_package(Gettext 0.21)
或者,查找 gettext 并使其成为必需(如果未找到,则停止处理并显示错误消息)
find_package(Gettext REQUIRED)
示例:在 CMake 中使用 gettext¶
从 gettext 开始时,.pot
文件被认为是手动创建的。例如,在提供的 main.cxx
源代码文件上使用 xgettext
工具
main.cxx
¶#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;
}
xgettext
工具从提供的源代码中的 gettext()
调用中提取所有字符串并创建可翻译字符串
$ xgettext -o MyApp.pot main.cxx
项目可以使用 msginit
工具手动初始化可翻译文件
$ mkdir -p locale/de_DE
$ msginit -l de_DE.UTF8 -o locale/de_DE/MyApp.po -i MyApp.pot --no-translator
它会创建一个人类可读的文件,可以翻译成所需的语言(根据需要调整)
locale/de_DE/MyApp.po
¶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"
在 CMake 中,此模块提供的 gettext_process_po_files()
命令会自动创建所需的 .mo
文件,应用程序在运行时根据系统环境变量(例如 LANG
)加载这些文件。在以下示例中,还使用了 GNUInstallDirs
模块来提供 CMAKE_INSTALL_LOCALEDIR
变量
CMakeLists.txt
¶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)
$ cmake -B build
$ cmake --build build
$ DESTDIR=$(pwd)/stage cmake --install build
要利用翻译,需要在系统上启用 de_DE
区域设置(参见 locale -a
)。然后可以运行本地化输出
$ LANG=de_DE.UTF-8 TEXTDOMAINDIR=./stage/usr/local/share/locale \
./stage/usr/local/bin/example
示例:处理 POT 文件¶
gettext_process_pot_file()
命令将当前二进制目录中的 .po
翻译文件处理为 .mo
文件
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()
示例:创建翻译¶
使用简化的 gettext_create_translations()
命令创建 .mo
文件
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()
另请参阅¶
FindIntl
模块用于查找 Gettext 运行时库 (libintl)。