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_FOUND3.3 版本中新增。
布尔值,指示是否找到了(请求版本)的 gettext。
Gettext_VERSION版本 4.2 中添加。
找到的 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>...要在构建阶段为指定的
<language>编译成.mo文件的一个或多个.po翻译文件的列表。相对路径将相对于当前源目录(CMAKE_CURRENT_SOURCE_DIR)进行解释。
- gettext_process_pot_file¶
创建一个构建规则,该规则将 gettext Portable Object Template(
.pot)文件和相关的.po文件处理为编译后的 gettext Machine Object(.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 Portable Object Template 文件(
.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翻译文件处理为编译后的 Machine Object(.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 Portable Object Template 文件(
.pot)的路径,作为翻译的来源。如果给出的是相对路径,则将相对于当前源目录(CMAKE_CURRENT_SOURCE_DIR)进行解释。ALL将生成的目录添加到默认 CMake 构建目录中,以便在构建时默认创建翻译。
<po-files>...一个或多个
.po格式的翻译源文件列表,其文件名必须遵循<language>.po的格式。相对路径将相对于当前源目录(CMAKE_CURRENT_SOURCE_DIR)进行解释。
注意
为了更好地控制构建和安装行为,请改用
gettext_process_po_files()。
已弃用变量¶
以下变量提供用于向后兼容性
GETTEXT_FOUND自 4.2 版本起已弃用: 使用
Gettext_FOUND,其值相同。布尔值,指示是否找到了(请求版本)的 gettext。
GETTEXT_VERSION_STRING自 4.2 版本起已弃用: 被
Gettext_VERSION替代。找到的 gettext 的版本。
示例¶
示例:查找 gettext¶
查找 GNU gettext 工具
find_package(Gettext)
或者,查找 gettext 并指定最低必需版本
find_package(Gettext 0.21)
或者,查找 gettext 并将其设为必需(如果未找到,则处理将停止并显示错误消息)
find_package(Gettext REQUIRED)
示例:在 CMake 中使用 gettext¶
开始使用 gettext 时,.pot 文件被认为是手动创建的。例如,使用 xgettext 工具处理提供的 main.cxx 源文件
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() 命令会自动创建应用程序在运行时根据系统环境变量(如 LANG)加载所需的 .mo 文件。在以下示例中,还使用了 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)。