北岛夜话
原创工业智能控制领域(PLC、单片机/嵌入式、机器人、通信、机器视觉)的技术及经验分享。
文章570 浏览9851046

再谈gettext的工作原理

今天这篇文章继续讨论gettext。

一、gettext如何判断加载哪种语言?

gettext根据环境变量来决定加载哪个便携对象的二进制数据文件(.mo),按以下顺序进行查找(优先级由高到低):

  1. LANGUAGE(最高优先级):

    其键值可以是单个语言(比如:zh_CN.UTF-8),也可以是多种语言,以冒号分割(比如:zh_CN.UTF-8:en_US.UTF-8)。这种情况下,gettext 会从左到右依次尝试每种语言,直到找到可用的翻译(即存在对应的 .mo文件)。如果某种语言的 .mo文件不存在或未加载,则继续尝试下一个。如果所有列出的语言选项都失效,则回退到源代码中的原始字符串;

  2. LC_ALL:这是一个全局变量,包括所有的LC_*。可以读取,尽量不要直接写;

  3. LC_MESSAGES:专门控制消息翻译区的变量;

  4. LANG(最低优先级)

二、gettext加载语言数据的时机

    函数:bindtextdomain(domain, dir)、bind_textdomain_codeset(domain, codeset)、textdomain(domain)

    均不会触发便携对象二进制数据文件(.mo)的加载。

    1、bindtextdomain(domain, dir)

            告诉 gettext:域domain的 .mo文件存放在 dir目录下。只是记录路径,不读取任何文件。      

    2、bind_textdomain_codeset(domain, codeset)

            指定域的输出编码(例如 UTF-8)。只设置编码转换规则,不触发加载。

    3、textdomain(domain)

            设置当前活动的域。只是切换当前域的名称,不加载 .mo。

    真正触发加载(.mo)文件的是第一次调用gettext(msg)函数。

    为了提高性能,gettext会缓存加载的便携对象二进制数据文件(.mo),默认不会自动检测其文件的变化。换句话说,当更新了翻译文件后,正在运行的程序不会自动加载最新的翻译。可以通过重新启动的方式设置环境变量,从而切换语言。另外在Linux(glibc)下,可以通过改变外部变量_nl_msg_cat_cntr的值,使gettext刷新缓存,这种情况下不用重启软件。

    #ifdef __GLIBC__

        extern int _nl_msg_cat_cntr; // 这是 GLIBC 内部的翻译缓存计数器

        _nl_msg_cat_cntr++;          // 通过增加计数器来强制刷新 gettext 缓存

    #endif

三、获取及设置环境变量的函数

3.1、Windows平台(包含头文件<windows.h>

    3.1.1、用getenv()或getenv_s()函数获取环境变量

    函数声明:

    char *getenv(const char *varname);

    参数:环境变量的名称

    返回值:指向环境变量的指针,失败返回NULL

    例如:getenv("LANGUAGE")

    errno_t getenv_s(size_t *pReturnValue,char* buffer,size_t numberOfElements,const char *varname);

    名称中的s表示security(安全),参数:

  • pReturnValue:所需的缓冲区大小,如果找不到该变量,则为 0。

  • buffer:用于存储环境变量值的缓冲区。

  • numberOfElements:缓存区的大小。

  • varname:环境变量名称。

     返回值:如果成功,则为零;如果失败,则返回错误代码。

    3.1.2、可以用_putenv_s()函数设置环境变量,声明如下:

    errno_t _putenv_s(const char *varname,const char *value_string);

    参数:

  • varname:环境变量名称。

  • value_string:要将环境变量设置为的值。

    返回值:如果成功,则返回 0;否则,返回错误代码。

    例如:_putenv_s("LANGUAGE", "zh_CN.UTF-8");

3.2、POSIX平台(Linux),包含头文件<stdlib.h>

     3.2.1、用getenv()函数获取环境变量,函数声明:

        char * getenv(const char *name);

        参数:name -- 包含被请求变量名称的 C 字符串。

        返回值:一个以 null 结尾的字符串,该字符串为被请求环境变量的值。如果该环境变量不存在,则返回 NULL。

      3.2.2、用setenv()函数设置环境变量,函数声明:
        
int setenv(const char *name, const char *value, int overwrite);

        参数:

    • name:环境变量的名称;

    • value:环境变量的值;

    • overwrie:是否覆盖。0=不覆盖,非0值=覆盖

        返回值:0=成功,非0值表示失败,会设置errno

    3.2.3、用unsetenv()函数删除环境变量

        int unsetenv(const char *name);

        参数:name->要删除的环境变量

        返回值:同setenv()函数


取消

感谢您的支持,欢迎常来看看!

扫码支持
一点动力,多少随意

打开支付宝扫一扫,即可进行扫码打赏哦

最后编辑于:2026/06/15作者: 北岛李工

发表评论

恭祝各位朋友在丙午马年新春快乐,工作顺利,阖家安康!

×