使用 CMake 一键构建多语言程序:从 gettext 到自动生成 .mo 文件的完整实践
摘要(147字): 本文提供一套完整的C程序国际化解决方案,通过CMake自动化实现GNU gettext多语言支持。文章包含最小可运行示例程序,演示如何通过_()宏标记翻译文本,并详细讲解CMake脚本如何自动完成.pot文件提取、.po翻译文件生成及.mo二进制编译全流程。项目支持中/英/日/俄多语言切换,构建时只需执行make i18n-translations-zh_CN即可生成中文版本,
🌍 使用 CMake 一键构建多语言程序:从 gettext 到自动生成 .mo 文件的完整实践
摘要:
本文详细介绍如何使用 GNU gettext 与 CMake 实现 C 项目的多语言国际化(i18n)自动化构建流程。通过一个简洁可运行的示例,你将学会如何自动提取源码中的可翻译字符串、生成 .po 翻译文件、编译 .mo 语言包,并在程序中动态切换语言。本文提供完整的 CMake 脚本 与 示例 C 代码,一键构建即可体验中、英、日、俄多语言输出。
💡 一、什么是 gettext?
gettext 是 Linux 和类 UNIX 系统中最主流的国际化解决方案。
它的核心思想是:
把程序中的人类可读文本与实际显示的语言解耦,通过
.po翻译文件动态加载。
当程序运行时,会根据系统语言(LANG=zh_CN.UTF-8 等)自动选择相应语言的翻译文件。
⚙️ 二、项目结构
这是我们最终的示例项目结构,CMake 会自动生成 i18n 文件夹及翻译内容:
gettext_example/
├── src/
│ └── main.c
├── CMakeLists.txt
└── build/
└── i18n/
├── lang.pot
├── po/
│ ├── zh_CN.po
│ ├── ru.po
│ └── ja.po
└── locale/
└── zh_CN/LC_MESSAGES/lang.mo
🧠 三、C 源码示例:最小可运行多语言程序
src/main.c
#include <stdio.h>
#include <locale.h>
#include <libintl.h>
#define _(s) gettext(s)
int main(void) {
// 设置系统语言(自动检测环境变量 LANG)
setlocale(LC_ALL, "");
// 指定翻译域与目录
bindtextdomain("lang", "i18n/locale");
textdomain("lang");
printf(_("Hello!\n"));
printf(_("Welcome to the gettext demo.\n"));
printf(_("This program shows how to switch languages.\n"));
const char *name = "cheungxiongwei";
printf(_("Nice to meet you, %s!\n"), name);
return 0;
}
✅ 输出示例:
英文环境
LANG=en_US.UTF-8 ./main
Hello!
Welcome to the gettext demo.
This program shows how to switch languages.
Nice to meet you, Anya!
中文环境
LANG=zh_CN.UTF-8 ./main
你好!
欢迎使用 gettext 示例。
这个程序展示了如何切换语言。
很高兴认识你,cheungxiongwei!
🏗️ 四、CMake 自动化脚本
以下脚本会自动完成以下任务:
- 提取源文件中的
_()翻译字符串; - 自动初始化
.po翻译文件; - 自动合并
.pot更新; - 自动编译
.mo二进制语言包; - 支持多语言(中文、俄语、日语)并行处理。
CMakeLists.txt
注意:仅限 Linux 运行,CMakeLists.txt 脚本没做跨平台处理。
cmake_minimum_required(VERSION 3.10)
project(gettext_example C)
# 主程序
add_executable(main src/main.c)
# 查找 gettext 工具
find_program(XGETTEXT xgettext REQUIRED)
find_program(MSGINIT msginit REQUIRED)
find_program(MSGMERGE msgmerge REQUIRED)
find_program(MSGFMT msgfmt REQUIRED)
# 语言配置
set(LINGUAS "zh_CN.UTF-8" "ru" "ja" CACHE STRING "List of languages to support")
set(TEXT_DOMAIN "lang")
# 源码文件
file(GLOB_RECURSE SRC_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.c")
if(NOT SRC_FILES)
message(FATAL_ERROR "No source files found under src/")
endif()
foreach(f ${SRC_FILES})
list(APPEND SRC_FILES_ABSOLUTE "${CMAKE_CURRENT_SOURCE_DIR}/${f}")
endforeach()
# 输出目录配置
set(GEN_DIR "${CMAKE_BINARY_DIR}/i18n")
set(POT_FILE "${GEN_DIR}/${TEXT_DOMAIN}.pot")
set(PO_DIR "${GEN_DIR}/po")
set(LOCALE_DIR "${GEN_DIR}/locale")
# 提取翻译字符串
add_custom_target(i18n-extract-pot
COMMENT "Extracting translatable strings -> ${POT_FILE}"
COMMAND ${CMAKE_COMMAND} -E make_directory ${GEN_DIR}
COMMAND ${XGETTEXT} --from-code=UTF-8 --output=${POT_FILE} --no-location -k_ ${SRC_FILES_ABSOLUTE}
COMMAND sed -i "s/charset=CHARSET/charset=UTF-8/" ${POT_FILE}
DEPENDS ${SRC_FILES_ABSOLUTE}
)
# 生成多语言任务
foreach(lang ${LINGUAS})
set(PO_FILE "${PO_DIR}/${lang}.po")
set(MO_PATH "${LOCALE_DIR}/${lang}/LC_MESSAGES")
set(MO_FILE "${MO_PATH}/${TEXT_DOMAIN}.mo")
add_custom_target(i18n-translations-${lang}
COMMAND ${CMAKE_COMMAND} -E make_directory ${PO_DIR}
COMMAND sh -c "if [ ! -f \"${PO_FILE}\" ]; then echo \"Initializing ${PO_FILE}\"; ${MSGINIT} --input=${POT_FILE} --output-file=${PO_FILE} --locale=${lang} --no-translator; fi"
COMMAND sh -c "if [ -f \"${PO_FILE}\" ]; then echo \"Merging ${POT_FILE} -> ${PO_FILE}\"; ${MSGMERGE} --update --backup=none ${PO_FILE} ${POT_FILE} || true; fi"
COMMAND ${CMAKE_COMMAND} -E make_directory ${MO_PATH}
COMMAND sh -c "echo \"Compiling ${PO_FILE} -> ${MO_FILE}\"; ${MSGFMT} --output-file=${MO_FILE} ${PO_FILE}"
VERBATIM
)
add_dependencies(i18n-translations-${lang} i18n-extract-pot)
endforeach()
🚀 五、构建与测试
mkdir build && cd build
cmake ..
make
make i18n-translations-zh_CN
LANG=zh_CN.UTF-8 ./main
✅ 效果:
项目将自动生成 .po 与 .mo 文件,你只需编辑 .po 即可实现新语言翻译。
#, c-format
msgid "Hello!\n"
msgstr "你好!\n"
#, c-format
msgid "Welcome to the gettext demo.\n"
msgstr "欢迎使用 gettext 示例。\n"
#, c-format
msgid "This program shows how to switch languages.\n"
msgstr "这个程序展示了如何切换语言。\n"
#, c-format
msgid "Nice to meet you, %s!\n"
msgstr "很高兴认识你,cheungxiongwei!\n"
🏁 六、总结
通过本文你学会了:
- 如何用 CMake 自动化 gettext 国际化流程;
- 如何生成
.po、.mo文件; - 如何通过环境变量切换程序语言;
- 如何构建一个真正可运行的多语言 C 项目。
✨ 只需执行 make i18n-translations-zh_CN,你的程序即可支持中文输出。
这套方案轻量、可移植,非常适合 嵌入式系统、CLI 工具、或 跨平台 C 应用 使用。
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐
所有评论(0)