zoukankan      html  css  js  c++  java
  • 在Linux下开发多语言软件(gettext解决方案)

    最近的项目出现了一个bug。项目是基于一个已有的成熟开源软件之上做修改的,新写了加解密库,用于为该成熟开源软件增添加解密功能。功能增加完成后效果都很好,可是就是中文出不来了,也就是说没办法自适应多语言环境了(提示信息在中文操作系统下是中文,英文操作系统下是英文)。使用strace -o log [要调试的命令]定位出了其在执行期间调用的语言包情况,发现它并没有调用自有的语言包,反而调用了加解密库的语言包(但是这个加解密库就没有开发任何语言包),导致找不到该语言包而默认显示代码中的英文提示信息。经过寻找问题根源(下面的文章帮助了我),发现是加解密库中定义了PACKAGE宏,而该变量在gettext运行环境中担当着语言包名的作用,导致所有的翻译环境都成了加解密库的翻译环境了,自然由于找不到语言包而翻译失败。(在详细说一下加解密库中PACKAGE变量是怎么定义进去的:该变量是automake编译系统引进的。初衷是我想为configure添加--enable-debug选项,在该选项条件下configure,configure出来的config.h中就会包含DEBUG宏。我在该库的API头文件中include了config.h,便可以使用该宏判断是否要编译用于调试的代码。但是,于此同时,config.h中还包含了许多平台相关的宏,也包括上面提到的PACKAGE宏。也就是说,config.h文件不可以用到第三方库的对外头文件中,它是平台相关、环境相关的;而且包含的许多宏定义会覆盖掉使用该库的源码中的宏定义。那么问题来了,该如何为configure添加--enable-debug选项,并且影响源码中调试代码的编译呢?有待进一步查资料)

    之前的开发从来没有关注过多语言的问题,这次bug发生也是由于知识不足引起的。下面的文章详解了gettext多语言解决方案:

    转自http://blog.csdn.net/absurd/article/details/524767

    开发多语言软件是一件非常困难的事,各个国家的字符集的编码方式、货币符号、日期格式、数字格式、文字表现都各不相同,glibc提供了大量的函数处理这些事情,不再聱述了。这里要做的是,用一个简单的实例说明一下GetText的用法,GetText是一系列的工具和库函数,帮助程序员和翻译人员开发多语言软件的。

    GetText并不是一个神秘的东西,若非要在Win32下找一个东东与之对应的话,我想应该是资源文件(.res),它替你把字符串管理起来,在运行可以根据当前的语言,自动加载对应语言的字符串。

    这里假设要开发一个叫做foonly的软件包,它仅有一个源文件foonly.c,其功能是在屏幕上打印出”Hello, GetText!”。在没有支持多语言时,foonly.c的内容如下:

    #include <stdio.h>
    
    int main(int argc, char* argv[])
    
    {
    
        printf("Hello, GetText!/n");
    
       return 0;
    }

    好了,下面开启我们多语言软件的开发之旅:

    创建pot文件,pot是Portable Object Template的首字母缩写,与po对应的是mo,mo是Machine Object的首字母缩写。前者意指原始的字符串文件,一般用于给翻译人员去修改的,后者则是与机器相关的,一般是供程序读取。可以手工创建pot文件,也可以通过xgettext从代码中抽取字符串来产生。这里是用xgettext来产生的:

    xgettext -a foonly.c -o foonly.pot

    运行该命令后,我们发现,在当前目录下,产生了一个名foonly.pot的文件,打开该文件,可以看到:

    # SOME DESCRIPTIVE TITLE.
    
     # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
    
     # This file is distributed under the same license as the PACKAGE package.
    
     # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
    
     #
    
     #, fuzzy
    
     
    msgid ""
    
     msgstr ""
    
     "Project-Id-Version: PACKAGE VERSION/n"
    
     "POT-Creation-Date: 2005-11-07 20:06+0800/n"
    
     "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE/n"
    
     "Last-Translator: FULL NAME <EMAIL@ADDRESS>/n"
    
     "Language-Team: LANGUAGE <LL@li.org>/n"
    
     "MIME-Version: 1.0/n"
    
     "Content-Type: text/plain; charset=CHARSET/n"
    
     "Content-Transfer-Encoding: 8bit/n"
    
     #: foonly.c:5
    
     
    msgid "Hello, GetText!/n"
    
     msgstr ""

    根据pot产生不同语言的po文件,这里我们先产生一个简体中文的po文件:

    export LANG=zh_CN.gb2312

     msginit -l zh_CN.gb2312 -i foonly.pot 

    运行该命令后,我们发现,在当前目录下,产生了一个名zh_CN.po的文件,打开该文件,可以看到:

    # Chinese translations for PACKAGE package.
    
     # Copyright (C) 2005 THE PACKAGE'S COPYRIGHT HOLDER
    
     # This file is distributed under the same license as the PACKAGE package.
    
     # root <root@linux>, 2005.
    
     #
    
     msgid ""
    
     msgstr ""
    
     "Project-Id-Version: PACKAGE VERSION/n"
    
     "POT-Creation-Date: 2005-11-07 20:06+0800/n"
    
     "PO-Revision-Date: 2005-11-07 20:09+0800/n"
    
     "Last-Translator: root <root@linux>/n"
    
     "Language-Team: Chinese <zh-l10n@linux.org.tw>/n"
    
     "MIME-Version: 1.0/n"
    
     "Content-Type: text/plain; charset=GB2312/n"
    
     "Content-Transfer-Encoding: 8bit/n"
    
     #: foonly.c:5
    
     msgid "Hello, GetText!/n"
    
     msgstr ""

    翻译zh_CN.po里对应的字符串为中文:

    # Chinese translations for PACKAGE package.
    
     # Copyright (C) 2005 THE PACKAGE'S COPYRIGHT HOLDER
    
     # This file is distributed under the same license as the PACKAGE package.
    
     # root <root@linux>, 2005.
    
     #
    
     msgid ""
    
     msgstr ""
    
     "Project-Id-Version: PACKAGE VERSION/n"
    
     "POT-Creation-Date: 2005-11-07 20:06+0800/n"
    
     "PO-Revision-Date: 2005-11-07 20:09+0800/n"
    
     "Last-Translator: root <root@linux>/n"
    
     "Language-Team: Chinese <zh-l10n@linux.org.tw>/n"
    
     "MIME-Version: 1.0/n"
    
     "Content-Type: text/plain; charset=GB2312/n"
    
     "Content-Transfer-Encoding: 8bit/n"
    
     #: foonly.c:5
    
     
    msgid "Hello, GetText!/n"
    
     msgstr "你好,GetText!/n"

    根据po文件生成mo文件。

    msgfmt zh_CN.po -o zh_CN.mo

     运行该命令后,我们发现,在当前目录下,产生了一个名zh_CN.mo的文件。它是二进制的,不能用文本编辑器打开。

    安装mo文件到系统中:

    cp -f zh_CN.mo /usr/share/locale/zh_CN/LC_MESSAGES/foonly.mo

     修改程序。

    #include <stdio.h>
    
     #include <locale.h>
    
     #include <libintl.h>
    
     #define _(String) gettext (String)
    
     #define LOCALEDIR "/usr/share/locale/"
    
     #define PACKAGE "foonly"
    
     int main(int argc, char* argv[])
    
     {
    
         setlocale (LC_ALL, "");
    
         bindtextdomain (PACKAGE, LOCALEDIR);
    
         textdomain (PACKAGE);
    
         printf(_("Hello, GetText!/n"));
    
         return 0;
    
     }

    编译并运行:

    gcc -g foonly.c -o foonly

     ./foonly

     可以看到屏幕上打印出:

    你好, GetText!

     现在我们换成英文试一下:

    export LANG=es_US

    ./foonly

    可以看到屏幕上打印出:

    Hello, GetText!

    添加其它语言也很容易,不需要修改程序,只需要像对待中文一样,生成一个mo文件,并安装到系统中对应的目录即可。切换不同的语言仅仅是修改当前的locale就行了。

  • 相关阅读:
    微信二维码 场景二维码 用于推送事件,关注等 注册用户 ,经过测试
    简单的 Helper 封装 -- CookieHelper
    简单的 Helper 封装 -- SecurityHelper 安全助手:封装加密算法(MD5、SHA、HMAC、DES、RSA)
    Java反射机制
    Windows Azure Web Site (13) Azure Web Site备份
    Windows Azure Virtual Machine (1) IaaS用户手册
    Windows Azure Web Site (1) 用户手册
    Windows Azure Web Site (12) Azure Web Site配置文件
    Windows Azure Web Site (11) 使用源代码管理器管理Azure Web Site
    Windows Azure Web Site (10) Web Site测试环境
  • 原文地址:https://www.cnblogs.com/qxxnxxFight/p/4095007.html
Copyright © 2011-2022 走看看