zoukankan      html  css  js  c++  java
  • 关于操作系统中英文切换的.po和.mo介绍

    一、文件简介 

    .po文件,.mo文件,.pot文件是由gettext程序生成或者使用的源代码和编译结果。
     
    1、.pot文件 
    是一种模板文件,其实质与.po文件一样,其中包含了从源代码中提取所有的翻译字符串的列表,主要提供给翻译人员使用。
    从源码中扫描得到的翻译模版文件,原始语言取决于源码字符串中使用的自然语言,建议使用英文。纯文本格式;
     
    2、.po文件 
    根据 POT 文件建立的各种语言版本的待翻译文件,其中包含原始语言和被翻译的目标语言。纯文本格式;
    (1)用程序msginit来分析pot文件,生成各语言对应的po文件,比如中文就是zh_CN.po,法语就是fr.po文件。 
    (2)PO是Portable Object(可移植对象)的缩写形式,它是面向翻译人员的、提取于源代码的一种资源文件。 
    (3).po文件可以用任何编辑器如poEdit,vi,Emacs,editplus打开,交给翻译人员来将其中的文字翻译成本国语言。
     在我们系统中,直接新建.po文件修改即可。在诊断模式下:/usr/share/locale/zh_CN/LC_MESSAGES路劲下存放了对应的mo.po文件。目前仅支持中英文!
     
    3、.mo文件 
    供最终软件实际使用的文件,使用 PO 编译而成。二进制格式。
    (1)用msgfmt将.po文件编译成mo文件,这是一个二进制文件,不能直接编辑。 
    (2)MO是Machine Object(机器对象)的缩写形式,它是面向计算机的、由.po文件通过GNU gettext工具包编译而成的二进制文件,应用程序通过读取.mo文件使自身的界面转换成用户使用的语言,如简体中文。 
    (3)可以用工具如msgunfmt命令将.mo文件反编译为.po文件。 
     

    gettext是一套工具集的名称。这套工具集包含 xgettext/msginit/msgfmt 等一套建立模版(POT)、创建PO文件和编译MO文件的工具。

    gettext 包含的工具如下:

    • xgettext 从源码中生成POT模版或直接生成PO文件
    • msginit 基于POT文件生成待翻译的PO文件;
    • msgfmt 将PO文件编译成二进制的MO文件;
    • msgunfmt 顾名思义,将MO文件反编译成PO文件;
    • msgmerge 将POT模版文件与PO文件合并。用于在源码更新之后将新的待翻译内容更新到已经翻译的PO文件中;
    • msgcat 将多个PO文件合并在一起。
     
    维护:
           维护po的翻译人员在每次得到从新的程序源代码产生的po时,都用msgmerge来根据旧的已翻 译过的po来先处理一下新的未翻译的po。
    有的msgid前面一行有fuzzy的字样。这说明,第一这个po是被msgmerge处理过的;第二,已翻译的po里没有和这个msgid完全等同的 msgid,只有非常相似的。这种情况下,msgmerge仍然会用那个相似的msgid来翻译此msgid。不过会给这个msgid标记为fuzzy, 表示翻译人员仍然要翻译这 个msgid,并在翻译后去掉上面带fuzzy的这一行(翻译好后必须去掉,fuzyy。否则无法显示译文)。
    在我们系统中,原本/usr/share/locale/zh_CN/LC_MESSAGES路劲下仅存放了对应的mo文件。为了便于扩展,修改src/locale/zh_CN下的Makefile使得生成的po文件也保存在该路径下。翻译人员可以取得该po文件进行对应的翻译。然后将该翻译过后的po文件(例如中日,中韩)存放在/usr/share/locale/路径下即可。最后在程序代码中根据当前语言环境在该目录下寻找指定的语言包进行翻译即可。比如zhonghan.po。由于存在预加载,我们翻译好的.po文件需要重新编译版本下载安装。
    TIPS:假如想增加日文提示。需要在src/locale目录下仿照zh_CN再新建一个目录,Makefile的编写仿照zh_CN目录即可。然后在新建目录下添加翻译好的中日po文件。Makefile根据这个文件进行编译安装即可。同时也需要记得修改系统的查找mo文件函数。设备目前路径是usr/share/locale//zh_CN/LC_MESSAGES/msg.po,只需要仿照即可在locale目录下新增路径即可。
    如图所示:传入的lang需要和页面进行交互讨论,目前系统仅支持中文,需要新定义新的语言字段。然后下面的查找判断再根据传入的新语言类型增加一个判断即可。若bindtextdomain为空代表在当前路径下默认绑定最先找到的mo文件。testdomain则解读指定的mo文件,若为空则默认读取最新读到的mo文件。故存在多个mo文件需要指定绑定的mo. 详情参考man bindytextdomain 3.
     
    PO文件详解:
    po文件都是由一对对的msgid和msgstr组成的。msgid就是原文。msgstr就是译文。
    注:对于不可能出现的提示信息可以不写中文翻译。 
    1.可以看到setlocale(LC_ALL, " ");设置语言环境,第二个参数如果为空代表读取当前语言环境locale。设置失败返回NULL。“”之间不能加空格。
    2.接着就是bindtextdomain("msg", LANGUAGE_PATH),参考:man 3 bindtextdomain,功能是:设置包含 LC_MESSAGES 分类 (catalog) 的 locale 目录,程序的 .mo 文件就保存到其下的目录中。LC_MESSAGES 是 locale 的一个分类 (catalog),和其它的分类,如:LC_TIME、LC_CTYPE,是平级的概念。domainname、locale 目录、程序当前活动 locale,这三者会决定你需要将 .mo 放到 locale 目录的具体位置,因为当前locale可能是中文zh_CN,也可能是繁体中文zh_TW。最终存放路劲是: [locale 目录]/[活动 locale]/LC_MESSAGES/msg.mo。本设备存放路径则是usr/share/locale//zh_CN/LC_MESSAGES/msg.po
    3.textdomain("msg");参考:man 3 bindtextdomain,功能是:设置后来使用 gettext() 时的 domain。示例中设置:textdomain("msg")。一般与上一步的domainname相同。若存在多个mo文件,上述函数进行多次绑定后,则该函数就特别指定当前需要绑定的mo文件。
    4.gettext();参考:man 3 gettext, 功能是:根据环境读取mo文件中的 msgid还是msgstr,并返回适当的语言类型。
     
    总结步骤:
    一般的工作流程是这样的:
    1. 在源码中使用约定的语法来书写字符串,C语言默认是 gettext("hello, world")。在本文中,将使用 _("hello, world")
    2. 使用 xgettext 从源码中扫描出需要翻译的文本,建立 POT 文件;
    3. 使用 msginit 命令根据 POT 文件建立 PO 文件。或者直接在上一步也可以直接建立 PO 文件;
    4. 进行人工翻译(当然也可以进行机器翻译),翻译的结果保存在 PO 文件中;
    5. 使用 msgfmt 命令将 PO 文件编译成 MO 文件;
    6. 在程序中实现调用命令,本文中是 _ 函数,这个函数将读取并解析 MO 文件,根据调用的原始语言文本返回翻译之后的文本。
            
    C语言简单实例:
    1.新建1.c文件如下:
    2.xgettext -a 1.c -o 1.pot生成pot文件。会提取出所有的字符串,如下:
    3.根据.pot文件可以产生不同.po文件。
        export LANGUAGE=zh_CN设置当前语言环境为中文。
        msginit -l zh_CN.utf-8 -i 1.pot初始化1.pot文件,当前路径会生成zh_CN.po。
        进入zh_CN.po文件中增加对应字符串中文翻译即可。
    4.msgfmt zh_CN.po -o zh_CN.mo根据po文件生成mo文件。
    5.cp -f zh_CN.mo /usr/share/locale/zh_CN/LC_MESSAGES/test.mo。注意test.mo中的名称需要和代码中的domianname名称一致。
       复制mo文件到语言目录下。
     
    gcc 1.c,然后./a.out即可看到屏幕打印出来的是:“你好,世界”。
    若export LANGUAGE=en,即可看到屏幕打印出来的是:“hello, world”。
     
    若添加其他语言也很简单,只需要对待一个中文一样,生成一个mo文件,并安装到系统中对应的目录然后根据系统语言环境变量来读取即可。切换不同语言就相当于修改locale.
  • 相关阅读:
    spark dataframe 正则表达式匹配
    JVM申请的memory不够导致无法启动SparkContext
    <scope>provided</scope> 关于maven依赖中的scope的作用和用法
    web前端网站
    元素居中
    如何在Vue项目中使用vw实现移动端适配
    微任务、宏任务、同步、异步、Promise、Async、await
    前端自动化工作流环境
    Web前端学习笔记——构建前端自动化工作流环境
    JS判断值是否是数字
  • 原文地址:https://www.cnblogs.com/linux-wang/p/9001368.html
Copyright © 2011-2022 走看看