Java程序国际化

编程入门 行业动态 更新时间:2024-10-26 06:34:59

Java<a href=https://www.elefans.com/category/jswz/34/1771429.html style=程序国际化"/>

Java程序国际化

准备工具:eclipse,Java14


Java程序化的原理很简单,就是配置语言文件,其中文件的内容以key-value形式保存。当调用主类文件时,直接在匹配key来返回value值进行输出。大概原理就是这样,接下来就是详细的解释。
先看一段Java代码,helloworld;
public class HelloWorld{public static void main(String[] arr){System.out.println("Hello world!");}
}

程序编译后执行,结果不出所料肯定是“hello world"。如果你在写一个软件,想要把软件跨地域进行应用,就必须适应各个地方的语言,例如中国,你就得输出:“你好,世界!”。日本,你就需要输出:“にいはお”。所以想要使软件具有跨地域性质,就必须为不同的人提供不同的语言习惯。


程序国际化思路

前面提到key-value形式的文件存储,其中的key是不可以改变的,但是value是可以改变的。 Java主要提供三个类来负责程序国际化:
  • javajava.util.Locale;用户封装特定的国家区域、语言环境。其实说白了就是标识你想要转换地区的语言格式。中国为zh_CN;新加坡=sg_SP。
  • java.util.ResourceBundle;用于加载国家、语言资源包。就是加载我刚才说的那个以key-value格式保存的那个文件。
  • java.text.MessageFormat;用于格式化带占位符的字符串。

上面三个类是负责程序国际化所用到的主要类,下面介绍怎么保存key-value形式的文件。
资源文件主要有三种形式:

  • baseName_language_country.properties
  • baseName_language.properties
  • baseName .properties

注:上述三种命名方式中,basename可以随便写,但是language和country是Java必须支持的语言格式。同时作者也查了一下这三种命名方式有什么区别,但是很高兴的告诉读者,我没有找到相关资料。但是我分别用这三种命名方式命名了一下资源文件,试了一下,感觉没啥大的区别。不过作者后来想了一下为啥存在第一种命名方式,因为要区分国界,地区啊!!!!


Java支持的国家和语言,读者可以直接复制下面这段代码进行测试查看:
public class Demo{public static void main(String[] args) {// TODO Auto-generated method stubvar languangeList = Locale.getAvailableLocales();for(var i:languangeList) {System.out.println(i.getDisplayCountry()+"="+i.getCountry()+" "+i.getDisplayLanguage()+"="+i.getLanguage());}}
}

下面是我在eclipse上的执行结果:


程序国际化

第一步:创建两个资源文件,第一个文件名为info_zh_CN.properties;内容如下:
#hello=你好!
hello=\u4F60\u597D\uFF01

第二个文件名为info_en_US.properties;该文件内容为:

hello=welcome read my works!thanks.

两个文件放在src任何一个位置,但是引用的时候,必须准确的给出位置,否则就会出现无法定位到资源异常。
我的文件放在eclipse的目录结构如下:
资源文件是放在resource资源包下的,上述的basename为Message,读者不必关心我的命名,只需要知道最终引用的就是这个资源文件就行了。
改写helloworld文件内容如下:

package learning;import java.util.Locale;
import java.util.ResourceBundle;public class Hello {public static void main(String[] args){// TODO Auto-generated method stub//取出系统默认的国家/语言环境var myLocale = Locale.getDefault(Locale.Category.FORMAT);System.out.println(myLocale);//根据指定的国家/语言环境加载资源文件var bundle = ResourceBundle.getBundle("resource.message",myLocale);//下面的这段代码没有myLocale参数,则默认调用本地区的语言格式//var bundle = ResourceBundle.getBundle("resource.message");//打印从资源文件中取得的消息System.out.println(bundle.getString("hello"));var locale = new Locale("en","US");//创建一个新的Locale对象,使其指向美国英语System.out.println(locale);var bundle2 = ResourceBundle.getBundle("resource.message",locale);System.out.println(bundle2.getString("hello"));}
}

上述的文件内容我已经提读者修正,不需要做过多的改变。
运行,其结果如下:

请读注释了解上述方法的含义。


动态程序国际化

如果一个软件,或者程序只能静态的处理一下字符串语言的转换,那么这个程序只能说太废,太次,太掉价。学习前面只是想让读者了解到其语言转换机制,接下来才是重药。 引入MessageFormat信息规范化类来处理包含缺省符(也叫占位符,不过我更喜欢交它缺省符!)的字符串。 新建一个语言包文件info2_zh_CN.properties,内容如下:
name=\u4F60\u597D{0}\uFF0C\u4ECA\u5929\u662F{1}\uFF0C\u8C22\u8C22\u60A8\u770B\u6211\u7684\u535A\u5BA2\uFF01

上面的ASCII码值翻译过来就是:你好{0},今天是{1},谢谢您看我的博客!
其中{x}是我们要动态传入值的位置,以便我们能够更好的体验程序。如果把上面的{1}改成{2},则只把MessageFormat.format(“str”,list)中的list[3]传给属性文件。读者可以自行实验,不必在乎错误。
写一个新的Java文件,测试上述语言包:

package learning;import java.text.MessageFormat;
import java.time.LocalDate;
import java.util.Locale;
import java.util.ResourceBundle;public class MessageFormatTest {public static void main(String[] args) {// TODO Auto-generated method stubvar L1 = Locale.getDefault(Locale.Category.FORMAT);//获取本机默认的语言格式,我的是中国,即zh_CNSystem.out.println(L1);//根据地区,即L1加载语言包,也就是咱们创建的info2XXX.properties文件var bun = ResourceBundle.getBundle("resource.info2",L1);//第一个参数是资源包,第二个参数是地域位置//取得资源包中对应的name信息var message = bun.getString("name");//使用MessageFormat类为带占位符的字符串传入参数//先设置要传入的参数var date = LocalDate.now();var str = new String[] {"reader", date.toString()};System.out.println(MessageFormat.format(message, str));}}

输出结果如下:
看看,是不是将参数动态的传入输出了。其实messageFormat不是唯一办法,但确实一个非常有效的办法,他们的输出形式无非就是字符串型而已。你可以利用正则表达式来改变其中的参数。当然,我就这么一提,写起来太麻烦,也没要,所以就不写了。


类文件可以代替属性文件

类文件代替属性文件,很简单,就是将key-value写入类中就行了。值得注意的是,很多人不支持用类文件来代替properties,因为类是需要编译才能用的,会加大程序运行的负重。但是我要告诉读我博客的人,类文件优势很大,如果你要加载一个过百万,千万的词条,属性文件岂不是写死人了?用类的化,你可以动态处理这些信息,同时,类只需要经过一次编译,就可重复使用,何乐而不为呢? 使用类文件来替代属性文件时应该满足以下条件:
  • 该类名必须遵守basename_language_country,命名规则。
  • 该类必须继承ListResourceBundle类,并且重写其getContents()方法,该方法返回的是一个Object二维数组,该数组的每一行只有两项,第一项是key值,第二项是value值。
    下面是我写的一个小demo:
public class demo_zh_CN extends ListResourceBundle{//定义资源private final static Object myList[][] = {{"name","你好啊!{0},今天是{1},谢谢你浏览我的博客,希望能给你带来帮助。"}}//重写getContents()方法public Object[][] getContents(){return mylist;}
}

注意引用此包的时候,一定要指定对的路径,不然会出错。
把上述测试MessageFormat类的程序进行修改,其运行结果如下:
不过注意的是,如果类文件资源和属性资源文件放在一个包下,且命名相同时(忽略后缀的情况下),程序先调用的是类文件,而不是属性文件。


个人支持类当资源文件,因为其中的getContents()方法,你可以随便写,类里面你可以创建任何的方法,然后用getContent()方法调用。你说多爽,多nice。

更多推荐

Java程序国际化

本文发布于:2023-07-27 22:08:43,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1225591.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:程序   Java

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!