JAVA使用GNU的Gettext后端国际化

时间:2022-08-28 13:37:35

JAVA使用GNU的Gettext后端国际化

Web前端一般使用jquery.i18n.properties.version.js进行国际化,而后端国际化一般采用的是基于resource.i18n.local.properties配置文件的国际化,先因工作需要,使用GNU Gettext进行国际化,该方式使用resource_local.po

步骤

  • 1 下载安装poedit.exe
  • 2 下载安装gettext
  • 3 创建示例工程
  • 4 引入gettext maven依赖
  • 5 编写翻译工具类
  • 6 编写测试类
  • 7 使用命令行或poedit提取待翻译内容创建pot模板文件
  • 8 按指定的local将模板文件编译为class文件
  • 9 运行测试类
  • 10 总结

1 下载安装poedit.exe

下载poedit.exe并安装到本地磁盘

2下载安装gettext

  • (1)下载gettext-static.zip(参考前面)
  • (2)将下载的zip文件解压,将bin目录添加到path环境变量,便于抽取待翻译内容以及编译class
    JAVA使用GNU的Gettext后端国际化

3 创建示例工程

我使用的是IDEA2016.03旗舰版,创建maven-webapp项目
JAVA使用GNU的Gettext后端国际化

4 引入gettext maven依赖

为了使用gettext的翻译功能,需要引入gettext的maven依赖:
JAVA使用GNU的Gettext后端国际化

5 编写翻译工具类

项目中要动态切换系统语言,因此每次创建示例时不使用构造方法,使用init方法初始化传入Locale得到Translation实例,代码如下:

package com.qingsb.gettext;

import gnu.gettext.GettextResource;

import java.util.Locale;
import java.util.ResourceBundle;

/** * Created by LONG on 2017/3/13. */
public class Translation {
    private ResourceBundle bundle;

    private Translation() {
    }

    public static Translation init(Locale locale) {
        ResourceBundle bundle = ResourceBundle.getBundle("Messages", locale);
        Translation t = new Translation();
        t.setBundle(bundle);
        return t;
    }

    public String __(String msgid) {
        return GettextResource.gettext(bundle, msgid);
    }

    public String _x(String msgid, String msgctxt) {
        return GettextResource.pgettext(bundle, msgctxt, msgid);
    }

    public String _n(String msgid, String msgid_plural, long n) {
        return GettextResource.ngettext(bundle, msgid, msgid_plural, n);
    }

    public String _nx(String msgid, String plural, long n, String context) {
        return GettextResource.npgettext(bundle, context, msgid, plural, n);
    }

    public ResourceBundle getBundle() {
        return bundle;
    }

    public void setBundle(ResourceBundle bundle) {
        this.bundle = bundle;
    }
}

6 编写测试类

为了验证翻译的正确性,我们编写几个测试的案例:

package com.qingsb.gettext;

import java.util.Locale;

/** * Created by LONG on 2017/3/13. */
public class Test {
    private static final void translate(Translation tool){
        //普通翻译
        System.out.println(tool.__("Hello"));

        //上下文翻译
        System.out.println(tool._x("post","a post"));
        System.out.println(tool._x("post","to post"));

        //单复数翻译
        System.out.printf(tool._n("%d comment\n", "%d comments\n", 1), 1);
        System.out.printf(tool._n("%d comment\n", "%d comments\n", 2), 2);

        //上下文相关的单复数翻译
        System.out.printf(tool._nx("%d comment\n", "%d comments\n", 1, "another context"), 1);
        System.out.printf(tool._nx("%d comment\n", "%d comments\n", 2, "another context"), 2);

    }
    public static void main(String[] args) {
        //中文环境
        Translation tool1=Translation.init(new Locale("zh","CN"));
        translate(tool1);
        System.out.println("------------------------------------------------");
        //英文环境
        Translation tool2=Translation.init(new Locale("en","US"));
        translate(tool2);
    }
}

7 使用命令行或poedit提取待翻译内容创建pot模板文件

由于使用简便以及项目中需要从众多文件中抽取即通过文件夹来扫描需要翻译的文件,因此这里使用poedit来抽取待翻译内容
首先,打开poedit新建文件,选择翻译语言为“简体中文”
JAVA使用GNU的Gettext后端国际化

然后,在标签“翻译属性”页选择“源代码字符集”为UTF-8(推荐),否则会抽取不正确
JAVA使用GNU的Gettext后端国际化

在“源路劲”标签点击加号,选择“添加文件夹”,选择到java这层(因人而异,因项目而异)
JAVA使用GNU的Gettext后端国际化
最后,在“源关键字”页增加关键字,这里增加了“__”、“_x”、“_n”、“_nx”四个关键字,即按照那种函数来抽取待翻译内容
JAVA使用GNU的Gettext后端国际化

8 按指定的local将模板文件编译为class文件

按照上一步操作可得到待翻译文件,命名为messages_zh_CN.po
并将简单的翻译填入msgstr处

# 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"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-03-13 21:24+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"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"

#: java/com/qingsb/gettext/Test.java:13
msgid "Hello"
msgstr "你好"

#: java/com/qingsb/gettext/Test.java:16
msgctxt "a post"
msgid "post"
msgstr "一篇文章"

#: java/com/qingsb/gettext/Test.java:17
msgctxt "to post"
msgid "post"
msgstr "发表文章"

#: java/com/qingsb/gettext/Test.java:20 java/com/qingsb/gettext/Test.java:21
msgid "%d comment\n"
msgid_plural "%d comments\n"
msgstr[0] ""
msgstr[1] ""

#: java/com/qingsb/gettext/Test.java:24 java/com/qingsb/gettext/Test.java:25
msgctxt "another context"
msgid "%d comment\n"
msgid_plural "%d comments\n"
msgstr[0] ""
msgstr[1] ""

最后将po文件17行CHARSET改为UTF-8,将使用如下命令其编译为class文件,并制定base name为Messages(在src/main目录下执行)
msgfmt –java2 -d resources -r Messages -l zh_CN resources/messages_zh_CN.po
同时一并生成英文环境的翻译文件
JAVA使用GNU的Gettext后端国际化

9 运行测试类

JAVA使用GNU的Gettext后端国际化


10 总结

  • 抽取后不用去修改工程中每一个硬编码的代码,只需要在硬编码方法内部使用翻译方法进行翻译

  • 命令行暂时还没发现可以按照文件夹来进行抽取待翻译内容,若有发现可以按照文件夹来的,还请指教

  • 特别感谢博客:Youth.霖的博客