【鸿蒙PC命令行适配】鸿蒙 PC 实战:交叉编译gettext三方库,实现中英文转换
gettext的主要作用是为软件提供国际化(i18n)和本地化(l10n)支持,使程序能够以用户选择的语言显示界面文本、提示信息等。文本翻译:程序中的固定文本(如按钮标签、错误提示、菜单项)被标记为可翻译的字符串。在运行时,gettext会根据系统语言设置,从对应的“消息目录”(.mo 文件)中查找并返回翻译后的文本。基于消息目录:它不提供自动翻译服务,而是依赖开发者提供翻译文件(.po
gettext是一个用于软件国际化(i18n)和本地化(l10n)的工具集,其核心作用是帮助程序根据用户的语言环境,动态地将界面文本翻译成多种语言,从而支持多语言用户。
文章目录
-
- 一、什么是gettext?
- 二、gettext 的主要功能和用途:
- 三、如何在鸿蒙PC命令行工具中移植三方库gettext?
- 四、错误处理:
-
- 4.1 错误1:Relocations in generic ELF (EM:183) error adding symbols:file in wrong format
- 4.2 错误2:checking host system type... Invalid configuration `aarch64-linux-ohos': OS `ohos' not recognized:
- 4.3 错误3:Error loading shared library libintl.so.8: No such file or directory(needed by ./hello_getttext_other)
- 五、总结:
一、什么是gettext?
gettext的主要作用是为软件提供国际化(i18n)和本地化(l10n)支持,使程序能够以用户选择的语言显示界面文本、提示信息等。具体来说,它的核心功能包括:
- 文本翻译:程序中的固定文本(如按钮标签、错误提示、菜单项)被标记为可翻译的字符串。在运行时,
gettext会根据系统语言设置,从对应的“消息目录”(.mo 文件)中查找并返回翻译后的文本。 - 基于消息目录:它不提供自动翻译服务,而是依赖开发者提供翻译文件(.po 文件,经编译为 .mo 文件)。这些文件包含原始文本(msgid)与对应语言的翻译(msgstr)的映射关系。
- 支持多种语言环境:通过读取环境变量(如
LANG、LC_ALL)和系统 locale 设置,gettext能自动适配用户的语言偏好。 - 广泛应用于开源软件:它是 GNU 项目和许多 Linux 应用程序的标准本地化方案,被用于翻译命令行工具、桌面应用等。
二、gettext 的主要功能和用途:
2.1 消息翻译与编目管理:
gettext 提供了一套与 GNU gettext 兼容的纯 Python 实现,用于从源代码中提取需要翻译的字符串,并构建翻译消息目录(.po/.mo 文件),从而在运行时根据用户的语言环境动态加载对应的翻译。
2.2 支持多语种界面:
通过 gettext,开发者可以为应用程序创建不同语言版本的消息编目,使程序能够以适合用户的语言显示消息,实现国际化界面。
2.3 简化代码中的翻译处理:
在代码中,通常使用 _() 函数(单下划线)包装需要翻译的字符串,而不是直接使用硬编码的文本。这样,gettext 可以在运行时替换为对应语言的翻译内容。
2.4 分离代码与文本内容:
gettext 并不自动翻译文本,而是帮助开发者提取、组织和访问程序中使用的文本消息,将翻译工作与代码逻辑分离,便于维护和协作。
2.5 兼容性与灵活性:
gettext 模块提供两套 API:
- 高层 API:类似于 GNU gettext,适用于单语言场景,依赖用户的语言环境设置。
- 基于类的 API:允许在模块级别进行本地化,支持运行时动态切换语言。
2.5 典型工作流程(以软件开发为例):
- 标记源代码:在代码中用 _(“文本”) 标记需翻译的字符串。
- 提取字符串:使用 xgettext 工具生成 POT(模板)文件。
- 翻译字符串:将 POT 转换为 PO 文件,由翻译人员填写译文。
- 编译翻译:使用 msgfmt 将 PO 文件编译为二进制 MO 文件。 - 部署翻译:将 MO 文件放在指定位置,供程序加载。
三、如何在鸿蒙PC命令行工具中移植三方库gettext?
3.1 编译环境准备:
在鸿蒙PC命令行工具中移植使用的是交叉编译的方式,交叉编译是指在A架构(如x86_64 Linux)编译出能在B架构(如鸿蒙PC)运行的程序,这样可以达到命令跨平台运行的目的。
本人使用的是vagrant ubuntu 22.04的镜像包进行的测试,在x86_64的Linux主机(Ubuntu 24.04)上编译出能在aarch64架构HarmonyOS系统的鸿蒙PC上运行的程序。

学习教程可以看看Ubuntu如何搭建OpenHarmony_6.1.0.28的lycium_plusplus及鸿蒙 PC 环境设计的 C/C++ 编译框架 这个文章,讲的还是比较详细的。
3.2 下载并配置ohos-sdk(版本:OpenHarmony_6.1.0.28):
直接使用wget将这个包下载下来,我们可以看到这个包的大小有2.33G:
wget https://cidownload.openharmony.cn/version/Daily_Version/OpenHarmony_6.1.0.28/20260120_120146/version-Daily_Version-OpenHarmony_6.1.0.28-20260120_120146-ohos-sdk-full.tar.gz

使用tar来解压这个gz压缩包:
tar xf version-Daily_Version-OpenHarmony_6.1.0.28-20260120_120146-ohos-sdk-full.tar.gz

接下来,我们进入linux目录中,我们解压native模块:
unzip -q native-linux-x64-6.1.0.28-Beta1.zip

同时,再次解压toolchains模块:
unzip -q toolchains-linux-x64-6.0.0.46-Beta1.zip

3.3 配置环境变量:
SDK解压完成之后,这里我们设置一下全局的环境变量,配置交叉编译必备的环境变量(可以根据自己的):
export OHOS_SDK=~/harmonypc/linux
echo $OHOS_SDK
# 下面的都是根据上面的环境变量来动态配置的,不需要改动
export PATH=${OHOS_SDK}/native/llvm/bin:${OHOS_SDK}/native/build-tools/cmake/bin:$PATH
export AS=${OHOS_SDK}/native/llvm/bin/llvm-as
export CC="${OHOS_SDK}/native/llvm/bin/clang --target=aarch64-linux-ohos"
export CXX="${OHOS_SDK}/native/llvm/bin/clang++ --target=aarch64-linux-ohos"
export LD=${OHOS_SDK}/native/llvm/bin/ld.lld
export STRIP=${OHOS_SDK}/native/llvm/bin/llvm-strip
export RANLIB=${OHOS_SDK}/native/llvm/bin/llvm-ranlib
export OBJDUMP=${OHOS_SDK}/native/llvm/bin/llvm-objdump
export OBJCOPY=${OHOS_SDK}/native/llvm/bin/llvm-objcopy
export NM=${OHOS_SDK}/native/llvm/bin/llvm-nm
export AR=${OHOS_SDK}/native/llvm/bin/llvm-ar
export CFLAGS="-fPIC -D__MUSL__=1"
export CXXFLAGS="-fPIC -D__MUSL__=1"

上面在设置完全局环境变量后,我们再执行$CC -v命令可以查询到clang的版本号,就说明设置成功了,到此为止,编译环境就全部准备就绪,接下来就可以进行编译移植了。
3.4 编译三方库gettext命令集:
提供的链接
https://ftp.gnu.org/gnu/gettext/gettext-0.26.tar.gz是gettext工具包 0.26 版本的源代码压缩包。下载并编译此包,即可获得gettext命令行工具(如xgettext、msgfmt、msgmerge),这些工具用于从源代码中提取可翻译字符串、管理翻译文件并生成最终的 .mo 文件,是实现软件多语言支持的基础设施。
源码的原始仓库维护在github上,我们直接使用git clone下载下来:
wget https://ftp.gnu.org/gnu/gettext/gettext-0.26.tar.gz
tar xf gettext-0.26.tar.gz
cd gettext-0.26

配置编译规则,通过configure脚本指定目标架构、安装路径、依赖等,核心参数说明,完整配置命令:
CC="$CC $CFLAGS" ./configure --host=aarch64-unknown-linux-musl --prefix=`pwd`/geettext_target
- aarch64-unknown-linux-musl:目标架构(对应鸿蒙PC的aarch64-linux-ohos)
- –prefix:指定安装路径(建议设为源码目录下的target,方便后续引用)

使用make命令进行编译(多线程编译,可根据CPU核心数调整-j后的数字,加快编译速度):
make

使用make install命令安装到指定路径(–prefix指定的target目录,这里是当前源码目录下的geettext_target目录):
make install

- 1.configure是GNU Autotools生成的配置脚本,核心作用是检测环境、适配平台、生成Makefile,新手只需掌握“配置→编译→安装”核心三步;
- 2.鸿蒙PC交叉编译的核心是通过–host=aarch64-linux-ohos指定目标架构,并提前配置鸿蒙PC SDK的交叉编译器环境变量;
- 3.鸿蒙PC编译需确保编译器、依赖库均为适配鸿蒙PC的aarch64版本,避免混用x86架构的工具或依赖。
3.5 确认编译产物:
安装完成后,进入target目录,会看到以下核心产物(适配aarch64-linux-ohos架构):
lib/:库文件目录,包含libintl.so.8,核心文件。
bin/:工具目录,包含鸿蒙PC版可执行文件(用于验证库可用性),如xgettext、msgfmt、msgmerge等,这里我们可以看到gettext相关的工具。

那么,我们可以手写一个C的程序来验证一下库是否可用:
#include <stdio.h>
#include <locale.h>
#include <libintl.h>
int main() {
setlocale(LC_ALL, "");
bindtextdomain("hello", "./locales");
textdomain("hello");
printf(gettext("Hello, world!\n"));
return 0;
}

以上代码的作用是,这段 C 程序使用 GNU gettext 的国际化框架(libintl)为字符串“Hello, world!\n”提供按系统语言自动切换的翻译,并输出到标准输出。
- etlocale(LC_ALL, “”):按当前环境变量(LANG、LC_ALL、LANGUAGE 等)设置程序的区域与编码。空字符串表示“从环境继承”,如 zh_CN.UTF-8、en_US.UTF-8。
- bindtextdomain(“hello”, “./locales”):为消息域 hello 指定翻译文件的根目录。运行时会在 ./locales/
- textdomain(“hello”):设置当前默认消息域为 hello,后续 gettext(…) 就在这个域下查找。
- gettext(“Hello, world!\n”):以“Hello, world!\n”为消息 ID,在 hello 域对应的 .mo 文件中查翻译;找不到时返回原文。
- printf(…):将翻译结果打印到标准输出,最后 return 0 正常退出。
接下来我们使用鸿蒙PC的clang进行编译,将上面写的C程序编译成可执行文件:

生成中文翻译文件 locales/zh_CN/LC_MESSAGES:
mkdir -p locales/zh_CN/LC_MESSAGES
生成中文翻译文件 locales/zh_CN/LC_MESSAGES/hello.po:
msgid ""
msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Language: zh_CN\n"
msgid "Hello, world!\n"
msgstr "你好,世界!\n"
编译 .mo 并准备目录结构:
msgfmt -o locales/zh_CN/LC_MESSAGES/hello.mo locales/zh_CN/LC_MESSAGES/hello.po
接下来,我们使用clang进行编译,将上面写的C程序编译成可执行文件:
/root/harmonypc/linux/native/llvm/bin/clang --target=aarch64-linux-ohos\
-I /root/test/gettext-0.26/geettext_target/include \
/root/test/main.c \
-L /root/test/gettext-0.26/geettext_target/lib \
-lintl -o /root/test/hello_getttext
这里最后打包的文件为hello_getttext,将hello_getttext拷贝到鸿蒙PC的/root目录下。

注意:在lib目录下面有一个libintl.so.8文件,这个文件是gettext库的动态链接库,我们需要将这个文件拷贝到鸿蒙PC的/root目录下。
3.6 鸿蒙PC端验证:
所有文件拷贝到鸿蒙PC之后,启动终端,执行binary-sign-tool命令分别对hello_getttext进行自签名。
先需要进行签名部署,在鸿蒙 PC 上部署的程序和库文件完成后,需要进行 签名 操作,保证安全性与系统兼容性:
binary-sign-tool sign -inFile \xxxx\hello_getttext -outFile \xxxx\hello_getttext -selfSign "1"

如果出现 “Permission denied” 等错误,需要检查当前用户是否有足够的权限执行这些操作,或者尝试使用sudo来提升权限,我这里使用chmod 755 命令来修改文件权限。
接下来执行hello_getttext程序:

至此,鸿蒙PC版的hello_getttext编译移植完成。
四、错误处理:
4.1 错误1:Relocations in generic ELF (EM:183) error adding symbols:file in wrong format
在编译鸿蒙PC版的geettext时,configure已经顺利通过,但是执行make命令编译时,最后链接阶段遇到如下报错:

从日志看,编译器使用的ohos sdk的clang,但是最终链接so时,链接器没有使用ohos sdk的lld,而是用了系统的ld,即使我们定义了LD环境变量也不起作用,就导致了最终的链接失败。在CFLAGS里指定了–target=aarch64-linux-ohos架构,但是libtool并没有去使用它,导致平台架构判断失败,使用了错误的链接器。要解决这个问题,需要在执行configure命令时,给CC环境变量强制追加一个–target=aarch64-linux-ohos,参考命令如下所示,我们将预先定义好的CFLAGS环境变量追加给CC环境变量即可:
CC="$CC $CFLAGS" ./configure --host=aarch64-unknown-linux-musl --prefix=`pwd`/geettext_target
重新执行./configure之后,重新运行make命令,就可以顺利编译通过了。
4.2 错误2:checking host system type… Invalid configuration aarch64-linux-ohos': OS ohos’ not recognized:
ds -c and -o together... yes
checking for stdio.h... yes
checking for stdlib.h... yes
checking for string.h... yes
checking for inttypes.h... yes
checking for stdint.h... yes
checking for strings.h... yes
checking for sys/stat.h... yes
checking for sys/types.h... yes
checking for unistd.h... yes
checking for wchar.h... yes
checking for minix/config.h... no
checking for vfork.h... no
checking whether it is safe to define __EXTENSIONS__... yes
checking whether _XOPEN_SOURCE should be defined... no
checking build system type... x86_64-pc-linux-gnu
checking host system type... Invalid configuration `aarch64-linux-ohos': OS `ohos' not recognized
configure: error: /bin/bash ././config.sub aarch64-linux-ohos failed
基于OHOS SDK环境,对某些C/C++应用进行交叉编译时需要指定–host=aarch64-linux-ohos参数,以便configure能正常识别目标平台架构和编译器等信息,在编译命令时遇到了一个报错:

在执行configure过程中,调用了/bin/bash ./build-aux/config.sub aarch64-linux-ohos,但是脚本不识别ohos这个配置,导致configure失败,更换host为aarch64-unknown-linux-musl,更换–host参数,重新执行configure命令:
CC="$CC $CFLAGS" ./configure --host=aarch64-unknown-linux-musl --prefix=`pwd`/geettext_target
4.3 错误3:Error loading shared library libintl.so.8: No such file or directory(needed by ./hello_getttext_other)
接下来尝试运行hello_getttext_other命令,发现报错了,找不到几个共享库,原因是因为这几个共享库文件并不在系统查找动态库的标准路径中。
解决办法是设置环境变量:LD_LIBRARYA_PATH,将共享库所在路径追加到环境变量LD_LIBRARYA_PATH中,如下所示,假设这几个共享库位于hello_getttext_other命令同一层级下,那么我们可以这样设置:export LD_LIBRARYA_PATH=…/:$LD_LIBRARYA_PATH,如下图所示:
export LD_LIBRARYA_PATH=../:$LD_LIBRARYA_PATH

五、总结:
鉴于鸿蒙操作系统(HarmonyOS)是一种与Windows、Linux及macOS等传统操作系统不同的新型平台,其软件架构和EABI(Embedded Application Binary Interface)等特性均采用了全新的设计,统一配置鸿蒙SDK的工具链环境变量,能从根源上避免编译工具冲突,保证交叉编译的一致性和可复现性,本次移植的gettext库版本为0.26,该版本基于musl libc构建,与鸿蒙PC的底层libc完全兼容,编译产物无任何依赖问题,可直接在鸿蒙PC上稳定运行,无崩溃、无内存泄漏。
更多推荐



所有评论(0)