首页 > 编程语言 >转贴:使用GetText本地化编程

转贴:使用GetText本地化编程

时间:2022-12-18 20:02:36浏览次数:71  
标签:翻译 zh CN PACKAGE 本地化 gettext 转贴 GetText po


   

参考

  1. ​http://heavenporter.livejournal.com/5939.html​

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

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

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

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

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

一个简单的例子,

#include <stdio.h>
#include <locale.h>
#include <libintl.h>

/*使用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 <locale.h> #include <libintl.h>


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(LC_ALL,"") 的意思是使用环境变量(系统当前的值)

  • -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 目录):

# 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,以空格分隔 就可以了

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

GETTEXT_PACKAGE "foo-app"

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

#include <glib/gi18n.h>


这个 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), "<b>Normal mode Foo, translated:</b>");


变为:

gtk_label_set_markup(GTK_LABEL (label1), _("<b>Normal mode Foo, translated:</b>"));


这就是与此有关的全部内容,其中有两点例外之处。一个是不能在静态字符串中 使用 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 <gtk/gtk.h> #include <glib/gi18n.h> { 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 <gtk/gtk.h> #define GETTEXT_PACKAGE "test" #include <glib/gi18n-lib.h> { gtk_init (&argc, &argv); ... gtk_window_set_title(GTK_WINDOW(dialog), _("hi")); ... }


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

#include <libintl.h>


同时定义

#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 架构了,只需要生成 po 文件,设置 lang,翻译 po 就可以了。

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

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


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

echo zh_CN > po/LINGUAS


下面操作都在 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? [email protected] Please confirm by pressing Return, or enter your email address. [email protected] 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 http://www.iro.umontreal.ca/contrib/po/HTML/teams.html http://www.iro.umontreal.ca/contrib/po/HTML/leaders.html http://www.iro.umontreal.ca/contrib/po/HTML/index.html 已创建 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

标签:翻译,zh,CN,PACKAGE,本地化,gettext,转贴,GetText,po
From: https://blog.51cto.com/u_15082498/5951081

相关文章

  • 使用PoEdit翻译PO文件(转贴)
    使用wordpress及其众多的主题或插件时,如果需要汉化,我们就会用到PO文件和MO文件。其中PO文件是一个翻译列表,可以编辑,MO文件由PO文件按生成,供程序读取。这是Wordpress利用GNU......
  • 有效解决游戏出海难题,茄子科技为合作伙伴提供专业的本地化营销落地经验
    面对变幻莫测、内卷严重的海外市场,尽管相比国内游戏市场环境有着更多的增量红利,能够支撑行业高速发展,但随着入局者数量上涨,海外用户对出海产品的内容和质量要求越来越高。如......
  • 第五十五章 本地化和基于标签的开发
    第五十五章本地化和基于标签的开发介绍在基于标记的CSP页面开发过程中,可以配置某些标记,以便它们用消息字典条目替换文本。为此,在标记内部提供本地化属性language、doma......
  • 【Abp笔记】本地化
    本地化1.在自己模块添加本地化模块依赖在自己模块的DependsOn特性参数里,添加一个依赖typeof(AbpLocalizationModule),如果没有,就添加一个[DependsOn(typeof(AbpLoca......
  • 数据表的本地化
    本地化的目的是将某一个table或query当做一个数据表来进行处理,并且这个本地化的数据表可以用在sql语句中。需要用到控件:TFDLOCALSQL。例如,程序中有两个CONNECTION,分别是C......
  • 第四十四章 在CSP应用程序中本地化文本 - 显示本地化字符串的其他选项
    目录第四十四章在CSP应用程序中本地化文本-显示本地化字符串的其他选项显示本地化字符串的其他选项%response.GetTextMethodFormatTextMethod$$$FormatTextMacrosMat......
  • [转贴]英特尔Sapphire Rapids至强可扩展CPU完整型号爆料与路线图展望
     2022-10-1315:15· 稿源: cnbeta 腾讯云服务器促销:2核2G首年仅需40元历史新低 @结城安穗-YuuKi_AnS刚刚在社交媒体上,分享了与英特尔下一代SapphireRa......
  • .NET Core WebApi 多语言本地化,动态切换多语言
    .NETCoreWebApi多语言本地化,动态切换多语言原生的.netcorewebapi动态多语言本地话具体更多详细内容,可以参考官方文档首先看效果图整体项目结构图......
  • ctfshow web128(_()函数,php_gettext.dll)
     _()是一个函数_()==gettext()是gettext()的拓展函数,开启text扩展。需要php扩展目录下有php_gettext.dllget_defined_vars()函数get_defined_vars—返回由所有已定......
  • 【WPF】应用程序 本地化
    本地化就是根据不同地区语言显示不同的文字。本文环境:vs2022+.net6.0新的本地化方式使用资源字典,然后动态引用资源字典,以下以UI界面汉化为例:新建一个文件夹 Languag......