Chinaunix首页 | 论坛 | 博客
  • 博客访问: 9413422
  • 博文数量: 1748
  • 博客积分: 12961
  • 博客等级: 上将
  • 技术积分: 20070
  • 用 户 组: 普通用户
  • 注册时间: 2009-01-09 11:25
个人简介

偷得浮生半桶水(半日闲), 好记性不如抄下来(烂笔头). 信息爆炸的时代, 学习是一项持续的工作.

文章分类

全部博文(1748)

文章存档

2024年(24)

2023年(26)

2022年(112)

2021年(217)

2020年(157)

2019年(192)

2018年(81)

2017年(78)

2016年(70)

2015年(52)

2014年(40)

2013年(51)

2012年(85)

2011年(45)

2010年(231)

2009年(287)

分类: 其他平台

2018-02-01 16:09:03

C语言本地化-例程.zip

先看 Linux下C语言的本地化/国际化实现

http://blog.csdn.net/taiyang1987912/article/details/48974823

####################################################

在linux系统下,以c语言程序为例来实现程序的国际化,即让程序根据Linux系统不同的语言环境的不同来显示出对应该语言的文字,即先让c程序支持国际化然后再进行本地化翻译。

Linux上实现这个过程需要用到xgettext和msgfmt这两个工具。

Xgettext 是国际化的工具,用来提取程序中的字符串,生成*.po或是*.pot的文件,

msgfmt是本地化的工具,用来编译翻译后的.po文件为.mo文件,这样系统在启动时候会扫描系统环境提取对应名字的.mo文件中的字符串替代原来的英文,实现本地化。

如我们来做一个简单的rpm包,包文件的目录树如下:

hello.c /*我们用来测试的c语言程序*/

po /zh_CN.po /*放在该包根目录下的po目录。对应于该程序进行的中文翻译*/

第一步、支持国际化的C程序(hello.c)如下:


[html] view plain copy
  1. #include <stdio.h>  
  2. #include <libintl.h> // gettext 库支持  
  3. #include <locale.h> // 本地化locale的翻译支持  
  4.   
  5. #define _(STRING) gettext(STRING) //为了减少代码量和输入量,用别名_(STRING)替换gettext(STRONG)  
  6. #define PACKAGE "hello" // 定义软件包的名字为hello  
  7. #define LOCALEDIR “/usr/share/locale/” //定义系统语言环境的目录,该目录下存放各种国际化的语言,不同系统可能有差异。  
  8.   
  9.   
  10. int main (int argv, char *argc[] )  
  11. {  
  12.   setlocale (LC_ALL, ""); //设置locale为系统默认语言环境,gtk程序不需要,因为gtk_init()已经帮我们做了  
  13.   bindtextdomain (PACKAGE, LOCALEDIR); //关联包名称及其对应的国际化翻译语言所在路径  
  14.   textdomain (PACKAGE); //定义.mo文件的名字,省略“.mo”后缀,(可以多个路径下的不同mo文件)  
  15.   
  16.   printf(_("Hello, World\n")); //国际化字符串支持,结合上面的替换,实际应是:printf(gettext("Hello, World\n"));  
  17.   printf(_("This is a example of locale&rpm @ Neoshine Desktop 5\n"));  
  18.   
  19.   return 0;  
  20. }   
第二步、提取待翻译po并进行本地化


先用下面的命令提取出c程序中需要进行本地化的语言文件。

[Lee@leedd.com hello]$  xgettext  -k––keyword=_  hello.c  -o  hello.pot

再用poedit或是vim翻译hello.pot中对应英文为中文并另存为zh_CN.po,作为中文本地化的翻译文件。

如下面翻译后的zh_CN.po文件的内容:

1 msgid “”2 msgstr “”

3 “Project-Id-Version: n”

4 “Report-Msgid-Bugs-To: n”

5 “POT-Creation-Date: 2010-03-11 11:52+0800n”

6 “PO-Revision-Date: n”

7 “Last-Translator: Leedd n”

8 “Language-Team: n”

9 “MIME-Version: 1.0n”

10 “Content-Type: text/plain; charset=UTF-8n”

11 “Content-Transfer-Encoding: 8bitn”

12

13 #: hello.c:15

14 #, c-format

15 msgid “Hello, World!n”

16 msgstr “你好,世界!n”

17

18 #: hello.c:16

19 #, c-format

20 msgid “This is a example of locale&rpm @ Leedd.com !n”

21 msgstr “这是在沉思小屋下的关于”本地化”和”rpm打包”的测试!n”

第三步、把翻译后的文件打包

制作rpm包相当于给源程序添加一个外衣,让用户很容易的安装、使用,而不用理会源程序的编译过程等细节。如果要进行rpmbuild我们需要先写个SPEC文件,如下:

Neoshine-hello-wrold.spec文件内容

[html] view plain copy
  1. Name: neoshine-hello-world  
  2. Version: 5.0  
  3. Release: 1  
  4. License: GPL+  
  5. Group: Applications/System  
  6. URL: 
  7.   
  8. Source0: %{name}-%{version}.tar.bz2  
  9. BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root  
  10. Summary: A applet for Neoshine Desktop (or the other similar Linux system).  
  11. BuildRequires: gettext  
  12. BuildRequires: gcc  
  13.   
  14. %description  
  15. A hello world examples for the locale&rpm  
  16.   
  17. %prep  
  18. %setup -q  
  19.   
  20.   
  21. ##,%build  
  22.   
  23.   
  24. %install  
  25. mkdir -p ${RPM_BUILD_ROOT}/usr/share/locale/zh_CN/LC_MESSAGES  
  26. mkdir -p ${RPM_BUILD_ROOT}/var/tmp/hello  
  27. xgettext -k –keyword=_ hello.c -o po/hello.pot  
  28. pushd ./po  
  29. msgmerge zh_CN.po hello.pot  
  30. msgfmt zh_CN.po -o hello.mo  
  31. cp hello.mo ${RPM_BUILD_ROOT}/usr/share/locale/zh_CN/LC_MESSAGES  
  32. popd  
  33.   
  34. gcc hello.c -o ${RPM_BUILD_ROOT}/var/tmp/hello/hello.out  
  35.   
  36. %clean  
  37. rm -rf $RPM_BUILD_ROOT  
  38.   
  39. %files  
  40. %defattr(-,root,root)  
  41. /var/tmp/hello/*  
  42. /usr/share/locale/zh_CN/LC_MESSAGES  
  43.   
  44. %changelog  
  45. * Thu Mar 11 2010 Leedd <iam@leedd.com> 5.0-1-Inital  
已经有了源文件和SPEC文件后,需要把他们分别放在rpmbuild目录下对应的SOURCESSPECS目录中,然后打包:


[Lee@leedd.com SPECS]$ rpmbuild -bs neoshine-hello-world.specWrote: /home/Lee/rpmbuild/SRPMS/neoshine-hello-world-5.0-1.src.rpm

[Lee@leedd.com SPECS]$ mock -r neoshine-5-i686––rebuild  /home/Lee/rpmbuild/SRPMS/neoshine-hello-world-5.0-1.src.rpm

本文用到的源程序:     SOURCES源文件:neoshine-hello-world-5.0.tar.bz2  SPEC文件:  neoshine-hello-world.spec  编译后的源码包:neoshine-hello-world-5.0-1.src.rpm

参考文章:

[1] Hello World

[2] Linux 国际化编程 http://riuliyu.blog126.fc2.com/blog-entry-20.html

[3] 认识下linux下程序的国际化(C语言实例)

http://swinging-breeze.blogspot.com/2009/05/linuxc.html(已经被墙)

Google的缓存:http://203.208.39.132/search?q=cache:E-Os3g0yHjsJ:swinging-breeze.blogspot.com/2009/05/linuxc.html+hello+world+%E5%9B%BD%E9%99%85%E5%8C%96+c%E8%AF%AD%E8%A8%80&cd=1&hl=zh-CN&ct=clnk&gl=cn&st_usg=ALhdy2_j1VcwccRlk394Xz6n81ZnDCvbuQ


附加:如何把“Hello world!”打印显示为“你好,世界!”?

1)编辑test_helloworld.c

$vim test_helloworld.c
[html] view plain copy
  1. #include <stdio.h>    
  2. #include <locale.h>    
  3. #include <libintl.h>    
  4.   
  5. #define PACKAGE_NAME "test_helloworld"    
  6. #define PACKAGE_LOCALEDIR "po"    
  7. #define _(x) gettext(x)    
  8.    
  9. int main (int argc, char *argv[])    
  10. {    
  11.   setlocale(LC_ALL, "");    
  12.   // Comment: printf "1 Hello world!"    
  13.   printf(_("1 Hello world!\n"));    
  14.   setlocale(LC_MESSAGES, "zh_CN.UTF-8");    
  15.   bindtextdomain(PACKAGE_NAME, PACKAGE_LOCALEDIR);    
  16.   textdomain(PACKAGE_NAME);     
  17.   // Comment: printf "2 Hello world!"    
  18.   printf(_("2 Hello world!\n"));       
  19.   return 0;    
  20. }    

2)从.c源文件中提取需要进行国际化/翻译的字串,生成.po(portable object file)

xgettext --add-comments --keyword=_ test_helloworld.c -o test_helloworld.pot --from-code=UTF-8
$ cp test_helloworld.pot test_helloworld.po

3)修改并翻译字串文件.po

用xgettext命令提取出来的.pot文件,修改和翻译后的.po文件内容如下:

[html] view plain copy
  1. # SOME DESCRIPTIVE TITLE.    
  2. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER    
  3. # This file is distributed under the same license as the PACKAGE package.    
  4. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.    
  5. #    
  6. #, fuzzy    
  7. msgid ""    
  8. msgstr ""    
  9. "Project-Id-Version: PACKAGE VERSION\n"    
  10. "Report-Msgid-Bugs-To: \n"    
  11. "POT-Creation-Date: 2013-01-14 16:42+0800\n"    
  12. "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"    
  13. "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"    
  14. "Language-Team: LANGUAGE <LL@li.org>\n"    
  15. "Language: \n"    
  16. "MIME-Version: 1.0\n"    
  17. "Content-Type: text/plain; charset=UTF-8\n"    
  18. "Content-Transfer-Encoding: 8bit\n"    
  19.     
  20. #. Comment: printf "1 Hello world!"    
  21. #: test_helloworld.c:14    
  22. #, c-format    
  23. msgid "1 Hello world!\n"    
  24. msgstr "1 你好,世界!\n"    
  25.     
  26. #. Comment: printf "2 Hello world!"    
  27. #: test_helloworld.c:22    
  28. #, c-format    
  29. msgid "2 Hello world!\n"    
  30. msgstr "2 你好,世界!\n"  

4)把翻译好的.po文件转化为程序运行时可读取的二进制文件.mo(machine object file)

msgfmt test_helloworld.po -o test_helloworld.mo
(为了查看,也可将mo文件反向转换成po文件,$msgunfmt test_helloworld.mo -o test_helloworld.po)

5)把转化好的.mo文件放置到相应的LOCALEDIR路径下供程序执行时使用

$ mkdir -p po/zh_CN.UTF-8/LC_MESSAGES/
$ cp test_helloworld.mo po/zh_CN.UTF-8/LC_MESSAGES/

6)最后就可以编译并运行

$ gcc -Wall test_helloworld.c -o test_helloworld
$ ./test_helloworld 
1 Hello world!
2 你好,世界!


GNU locale 

locale被设计用来设定当前系统区域环境相关的信息来满足不同用户对国际化和本地化的需要,相关环境变量信息如下:

[html] view plain copy
  1. $ locale    
  2. LANG=en_US.UTF-8    
  3. LANGUAGE=    
  4. LC_CTYPE="en_US.UTF-8"    
  5. LC_NUMERIC="en_US.UTF-8"    
  6. LC_TIME="en_US.UTF-8"    
  7. LC_COLLATE="en_US.UTF-8"    
  8. LC_MONETARY="en_US.UTF-8"    
  9. LC_MESSAGES=en_US.UTF-8    
  10. LC_PAPER="en_US.UTF-8"    
  11. LC_NAME="en_US.UTF-8"    
  12. LC_ADDRESS="en_US.UTF-8"    
  13. LC_TELEPHONE="en_US.UTF-8"    
  14. LC_MEASUREMENT="en_US.UTF-8"    
  15. LC_IDENTIFICATION="en_US.UTF-8"    
  16. LC_ALL=    


GNU gettext 

gettext被设计用来实现国际化和本地化,通过gettext可以索引到字串的多国语言翻译,从而为国际化和本地化的字串显示提供基础。

Self-check

要理解test_helloworld.c里面相关locale和国际化相关API最好的方法就是亲自读一读glibc中的locale和intl相关目录下的src code,如setlocale.c、textdomain.c、bindtextdom.c、gettext.c等。多用man命令查一下这些命令或API,配合google和wikipedia


####################################################


然后在看play.c 源码中有部分代码如下.
设置区域 


  1. C 库函数 - setlocale()
  2. C 标准库 - <locale.h> C 标准库 - <locale.h>

  3. 描述
  4. C 库函数 char *setlocale(int category, const char *locale) 设置或读取地域化信息。

  5. 声明
  6. 下面是 setlocale() 函数的声明。

  7. char *setlocale(int category, const char *locale)
  8. 参数
  9. category -- 这是一个已命名的常量,指定了受区域设置影响的函数类别。
  10. LC_ALL 包括下面的所有选项。
  11. LC_COLLATE 字符串比较。参见 strcoll()
  12. LC_CTYPE 字符分类和转换。例如 strtoupper()
  13. LC_MONETARY 货币格式,针对 localeconv()
  14. LC_NUMERIC 小数点分隔符,针对 localeconv()
  15. LC_TIME 日期和时间格式,针对 strftime()
  16. LC_MESSAGES 系统响应。
  17. locale -- 如果 locale 是 NULL 或空字符串 "",则区域名称将根据环境变量值来设置,其名称与上述的类别名称相同。
  18. 返回值
  19. 如果成功调用 setlocale(),则返回一个对应于区域设置的不透明的字符串。如果请求无效,则返回值是 NULL。

  20. 实例
  21. 下面的实例演示了 setlocale() 函数的用法。

  22. #include <locale.h>
  23. #include <stdio.h>
  24. #include <time.h>

  25. int main ()
  26. {
  27.    time_t currtime;
  28.    struct tm *timer;
  29.    char buffer[80];

  30.    time( &currtime );
  31.    timer = localtime( &currtime );

  32.    printf("Locale is: %s\n", setlocale(LC_ALL, "en_GB"));
  33.    strftime(buffer,80,"%c", timer );
  34.    printf("Date is: %s\n", buffer);

  35.   
  36.    printf("Locale is: %s\n", setlocale(LC_ALL, "de_DE"));
  37.    strftime(buffer,80,"%c", timer );
  38.    printf("Date is: %s\n", buffer);

  39.    return(0);
  40. }
  41. 让我们编译并运行上面的程序,这将产生以下结果:

  42. Locale is: en_GB
  43. Date is: Thu 23 Aug 2012 06:39:32 MST
  44. Locale is: de_DE
  45. Date is: Do 23 Aug 2012 06:39:32 MST  
textdomain函数用于设置默认域。此功能设置 调用的gettext()  的domain.
textdomain - set domain for future gettext() calls
#include
char * textdomain (const char * domainname);
domainname一般指的是程序本身的名字,
而 gettext是把指定的字符串改变成本地话的字符串, 翻译时需要 本地的domain.  本地demain的设置通过 textdomain 设置.
char * gettext (const char * msgid); //msgid为要转化的字符串, 输出为转化为本地后的字符串.

如果使用如下, 则不需要调用 textdomain. 
char * dgettext (const char * domainname, const char * msgid);
char * dcgettext (const char * domainname, const char * msgid, int category);
category 为 LC_ALL 等内容.

本地化一般用于 多语言 本地化编程
http://blog.csdn.net/blaider/article/details/8011069

参考

介绍

GetText是GNU的一个项目, 有最丰富的信息。下面大致翻译一下GetText主页的介绍 :

“通常,程序及其文档信息都是用英语语言写的,程序运行时同用户交互的信息也是英语。这是一个事实,不仅仅GNU的软件是这样,其他大部分私有软件或自由软件也是这样。一方面,对于来自所有国家的开发者、维护者和用户来说,相互沟通中使用一种通用的语言非常的方便。另一方面,相对于母语来说大多数人并不适应使用英语,而且他们的日常工作都是尽可能的使用他们自己的母语。多数人都会喜欢他们的计算机屏幕显示的英语更少,显示的母语更多。"

GNU 的 'gettext' 是 GNU翻译项目的一个重要步骤,我们依赖于它来作很多其他的步骤。这个软件包给程序员、翻译者,或者用户提供了一套集成工具和文档。详细地说,GNU gettext 提供了一套工具,能让其他 GNU 软件创建多语言信息。..."

翻译真累!直接说汉语吧!

gettext的工作流程是这样的:比如我们写一个C程序,通常printf等输出信息都是English的。如果我们在程序中加入gettext支持,在需要交互的字符串上用gettext函数,程序运行是就可以先调用gettext函数处理字符串,替换当前的字符串了。注意是运行时替换。

简单使用的例子

一个简单的例子,

#include  #include  #include  /*使用gettext通常使用类似下面的一个带函数的宏定义
  *你完全可以不用,直接使用 gettext(字符串) */ #define _(S) gettext(S) /*PACKAGE是本程序最终的名字(运行时输入的命令)*/ #define PACKAGE "jian_gettext" int main(int argc, char **argv)
{ /* 下面三个参数都是使用gettext时候需要使用的
  * setlocale
  * bindtextdomain
  * textdomain */ setlocale(LC_ALL,"");
  bindtextdomain(PACKAGE, "locale");
  textdomain(PACKAGE);

  printf(_("Hello,GetText!\n")); return 0;
}

使用gettext的流程

1 头文件包含:

#include 
#include 

2 定义宏定义(完全是为了方便,而且几乎所有程序都这样)

#define _(S) gettext(S)

3 设置locale和mo文件将要存放的路径,关联程序

  setlocale(LC_ALL,"");
  bindtextdomain(PACKAGE, "locale");
  textdomain(PACKAGE);

4 制作po文件(示例程序是:jian_gettext.c)

xgettext -a jian_gettext.c -o jian_gettext.po  --from-code=utf-8

5 修改生成的 jian_gettext.po 文件,将下面行中的 CHARSET 换成 UTF-8

"Content-Type: text/plain; charset=CHARSET\n"

再翻译其中的string(其他的string不要改):

#: jian_gettext.c:14
#, c-format
msgid "Hello,GetText!\n"
msgstr "你好,GetText!\n"

6 生成mo文件,

msgfmt jian_gettext.po -o jian_gettext.mo

7 创建存放mo文件的目录,(例子使用./locale)

mkdir -pv locale/zh_CN/LC_MESSAGES/
cp -v jian_gettext.mo locale/zh_CN/LC_MESSAGES/

8 运行程序,你的程序应该是这样编译好的:

gcc -Wall -o jian_gettext jian_gettext.c

没有错误,上面的程序运行结果如下:

# ./jian_gettext
你好,GetText!

细节

setlocale()

setlocale(LC_ALL,"") 的意思是使用环境变量(系统当前的值)

xgettext

  • -k 参数 可以只搜索某些字符串,没有用的信息省略。
xgettext jian_gettext.c -k_ -o jian_gettext.po
  • -l 参数 可以针对某一语言生成po文件,中文为例:
msginit -l zh_CN -i jian_gettext.po

上面命令会生成 zh_CN.po 文件,可由此修改生成mo文件

多文件的 PO

一个开源项目中,通常有很多源文件,我们都需要翻译其中的字符串。通常步骤如下:

  • 进入 PO 目录执行(一定要是 PO 目录):
# intltool-update -m

得到一个文件列表告诉我应该把它们加入 POTFILES.in 文件.

  • 跳到 PO 目录的父目录,使用新的 POTFILES.in 生成 POT 文件::
xgettext -a -f po/POTFILES.in -o po/xxx.pot

我使用的一个示例:

# xgettext -k_ -f po/POTFILES.in -o po/mutter-moblin.pot --from-code="utf-8"

intltool-update —pot 生成 pot 文件intltool-update —maintain

示例:

创建po文件

创建并进入/po目录,创建POTFILES.in,内容为你需要提取源码中有需要翻译的字符串的源文件列表,每行一个文件,然后执行intltool-update —pot产生pot文件,如果将来你在维护代码中代码有变化或者在POTFILES.in中新增了源文件,可用intltool-update —maintain更新。

有了pot文件,现在需要产生各种语言的po文件,如msginit —locale=zh_CN产生中文po文件,如将来源文件有变化可以intltool-update zh_CN更新zh_CN.po,接下来翻译的工作就是你自己来做了。

要生成特定语言的mo文件,需要维护configure.ac中的ALL_LINGUAS,以空格分隔就可以了

GTK 程序中使用 gettext

首先,您必须声明一些允许 gettext 库为您的应用程序找到正确消息的名称。请注意,在现实的场景中,构建系统将为您处理这些名称,但是出于我们的需要,可以使用下面的名称:

GETTEXT_PACKAGE "foo-app"LOCALEDIR "mo"

在此之后,您必须正确地包含 gettext Header。完成该任务的最简单的方法是使用 GLib 提供的可用 Header(在 Versions 2.4 及更高版本中可用):

#include 

这个 Header 为您提供了 () 和 N() 宏,用来标记可翻译的字符串,稍后您将看到。

现在,您必须以一种 gettext 可以识别并在运行时进行翻译的方式来标记用户可见的字符串。出于这两个目的,您可以使用 _() 宏,它是 gettext() 函数完整调用的简短别名。

gettext() 函数查找消息目录中提供的字符串,以判断对于当前语言,是否存在一个经过翻译的合适的版本。如果存在,它会返回翻译结果;否则,它会返回原始字符串。当您为源代码进行翻译准备工作时,在扫描过程中将单词 gettext 作为标记,以便提取要翻译的消息并将其放置到单独的文件中。

认识到了这一点,您就可以开始以不同的语言进行表达了。在程序开始执行之前,您必须初始化 gettext:

bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);

现在,您可以使用 gettext() 调用来替换所出现的每个可以翻译的字符串。因此,下面的代码行形式:

gtk_label_set_markup(GTK_LABEL (label1), "Normal mode Foo, translated:");

变为:

gtk_label_set_markup(GTK_LABEL (label1), _("Normal mode Foo, translated:"));

这就是与此有关的全部内容,其中有两点例外之处。一个是不能在静态字符串中使用 gettext(),因为它是一个函数。在这种情况下,可以使用 N_() 宏,它不进行任何扩展,但会被作为对翻译内容进行标记的关键词。稍后在需要使用的地方,可以和前面一样使用 () 。

const char *msg = N_("Important message");

do_important_stuff(_(msg));

另一个例外是包含某个数值变量的情况,如检索的文件的数目。在这种情况下,可以使用 ngettext() 函数,它能够理解复数。GNU gettext 库手册中包含了该函数的细节信息,以及关于 gettext() 函数的使用和操作的细节信息。

最后,请正确地选择哪些内容应该翻译,哪些内容不应该翻译。通常,所有用户可见的字符串都是翻译工作的候选对象。然而,对于调试信息和其他面向开发人员的信息,可以保留其中的部分或所有内容不进行翻译,以使得您自己和其他开发人员能够理解并在源代码中对其进行查找。FooWidget 便是这种方式的一个示例(请参见下面的“自定义小部件”),它包含了一个模拟的调试模式,在该模式中 RTL 或者 LTR 标记都没有进行翻译。

与此类似,避免翻译那些不是真正的单词的内容。例如,不要翻译 TCP/IP 状态标记,即使它们最初来自于英语单词。这类错误几乎随处可见,例如,在Microsoft Windows 的网络工具中,类似 SYN_ACK 的内容被翻译 为毫无意义的波兰语 ZGODN_POTW。其结果是所有的人,包括说本族语的人,都被弄糊涂了,感到无法理解,甚至在 Internet 上查阅这样的信息。

使用

#include 
#include 

{
    gtk_set_locale();
    //bindtextdomain (PACKAGE, LOCALEDIR);
    //textdomain (PACKAGE);
    bindtextdomain ("test", "/usr/share/locale");
      textdomain ("test");
       gtk_init (&argc, &argv);
...
gtk_window_set_title(GTK_WINDOW(dialog), _("hi"));
...
}

使用

#include 
#define GETTEXT_PACKAGE "test"
#include 

{
 gtk_init (&argc, &argv);
...
gtk_window_set_title(GTK_WINDOW(dialog), _("hi"));
...
}

上述两种方法是一样的。第一种中 gi18n.h将为我们引用

#include 

同时定义

#define _(String) gettext (String)

而第二中方法中gi18n-lib.h必须在我们定义了 GETTEXT_PACKAGE 宏之后才为我们定义

#define _(String) dgettext (GETTEXT_PACKAGE, String)

由于

gtk_init(); -->gtk_init_check() -->gtk_parse_args() -->gettext_initialization ()

gettext_initialization的代码实现:

static void
gettext_initialization (void)
{
#ifdef ENABLE_NLS
 bindtextdomain (GETTEXT_PACKAGE, GTK_LOCALEDIR);
 bindtextdomain (GETTEXT_PACKAGE "-properties", GTK_LOCALEDIR);
#    ifdef HAVE_BIND_TEXTDOMAIN_CODESET
 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
 bind_textdomain_codeset (GETTEXT_PACKAGE "-properties", "UTF-8");
#    endif
#endif
}

mutter-moblin 项目 i18n 实现

mutter-moblin 已经有 i18n 架构了,只需要生成 po 文件,设置 lang,翻译po 就可以了。

设置 LINGUAS 环境变量

直接修改 configure 也可以,但是不推荐。

# Substitute ALL_LINGUAS so we can use it in po/Makefile
ALL_LINGUAS="zh_CN"

通常在 po/ 目录下创建一个文件 LINGUAS

echo zh_CN > po/LINGUAS

创建 zh_CN.po 文件

下面操作都在 po 目录下:

首先,更新 POTFILES.in 文件

[root@localhost po]# intltool-update --pot  # 生成 mutter-moblin-netbook-plugin.pot
[root@localhost po]# ll
总计 28
-rw-r--r-- 1 root root    6 06-18 01:03 LINGUAS
-rw-r--r-- 1 1000 1000 6899 06-05 21:54 Makefile.in.in
-rw-r--r-- 1 root root 8998 06-18 01:04 mutter-moblin-netbook-plugin.pot
-rw-r--r-- 1 1000 1000  978 06-05 20:46 POTFILES.in

生成 zh_CN.po

[root@localhost po]# msginit --locale=zh_CN
新的翻译库应该包含您的电子邮件地址,这样用户就可以对您的翻译提出意见,
同时软件维护者也可以在出现技术问题时联络您。

Is the following your email address?
  root@localhost.localdomain
Please confirm by pressing Return, or enter your email address.
jian.li@turbolinux.com.cn
A translation team for your language (zh) does not exist yet.
If you want to create a new translation team for zh or zh_CN, please visit
  
  
  

已创建 zh_CN.po。

注意,上面创建的 zh_CN.po 文件是 gbk 编码,现在多用 UTF-8 编码。所以需要用下面命令创建(其实就是把 locale 参数的值 zh_CN 换成 zh_CN.utf8):

# msginit -l zh_CN.utf8

接下来翻译 po 文件。

检查翻译正误

翻译过程中通常有一些粗心的错误。需要检查:

msgfmt -c mutter-moblin-0.27.6/po/zh_CN.po



阅读(1571) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~