当前位置: 首页 > news >正文

Java国际化处理

最近在做Kettle8.1的国际化工作,闲暇之余,就看了看Java的国际化处理,明白程序怎么样找到对应的国际化文件。

说到国际化,经常看到一个东西叫i18n,其实是internationalization的缩写(ps:以后起昵称什么的就可以仿照这个规则信手拈来,又专业又好记)。

Java中相关的有以下3个类:

  • ResourceBundle:国际化资源包。
  • Locale:表示了特定的地理、政治和文化地区。
  • MessageFormat:用以实现动态填充国际化文件的占位符。

问题一:基本使用

话不多说,直接上案例,java代码如下:

package com.szh;

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

public class TestI18n {
	public static void main(String[] args) throws Exception {
		Locale l1 = new Locale("zh", "CN");
		ResourceBundle rb1 = ResourceBundle.getBundle("test", l1);
		System.out.println(rb1.getString("str1"));

		ResourceBundle rb2 = ResourceBundle.getBundle("test", Locale.getDefault());
		System.out.println(rb2.getString("str1"));

		Locale l3 = new Locale("en", "US");
		ResourceBundle rb3 = ResourceBundle.getBundle("test", l3);
		System.out.println(rb3.getString("str1"));
	}
}

下面3个国际化文件目录如下:

test_zh_CN.properties

str1=\u4F60\u597D!!

test_en_US.properties

str1=Hello!!

test.properties(当在对应的语言环境的国际化文件中找不到key时,则去此文件中拿):

str1=\u4F60\u597D!

此时,可以看到test_zh_CN.properties和test.properties显示出来的是ASCII码,jdk提供了cmd命令native2ascii.exe,能够查看对应的ASCII码,如下所示:

C:\Users\szh>native2ascii
你好!
\u4f60\u597d!

运行结果1:

你好!!
你好!!
Hello!!

运行结果2(我的语言环境为中文,当test_zh_CN.properties中没有str1时,则会去打印test.properties中str1的值):

你好!
你好!
Hello!!

问题二:动态填充占位符

另外一个问题,经常见到需要动态填充国际化字符串文本的情况,即需要填充占位符。此时需要类MessageFormat登场了。

首先修改test_en_US.properties代码如下:

str1=Hello!!{0}, {2}, {1} and {3}

主程序如下(四个乱序的占位符,我们只传3个看看效果):

package com.szh;

import java.text.MessageFormat;
import java.util.Locale;
import java.util.ResourceBundle;

public class TestI18n {
	public static void main(String[] args) throws Exception {
		Locale l3 = new Locale("en", "US");
		ResourceBundle rb3 = ResourceBundle.getBundle("test", l3);
		String s1 = MessageFormat.format(rb3.getString("str1"), new Object[] { "aa", "bb", "cc" });
		String s2 = new MessageFormat(rb3.getString("str1")).format(new Object[] { "aa", "bb", "cc" });
		System.out.println(s1);
		System.out.println(s2);
	}
}

运行结果(依次按照占位符序号填充,第四个参数未传,则按照字符串原样打印):

Hello!!aa, cc, bb and {3}
Hello!!aa, cc, bb and {3}

问题三:如何找到任意位置的国际化文件

上面的例子均放在src根目录下,那么如何能够像Kettle中一样,拿到自定义位置的国际化文件呢?

首先,我们将test_zh_CN.properties复制一份到com.szh包下:

test_zh_CN.properties:

str1=\u665A\u5B89

主程序如下:

package com.szh;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;

public class TestI18n {

	@SuppressWarnings("rawtypes")
	public static void main(String[] args) throws Exception {
		Class cls = TestI18n.class;
		// 将message_zh_CN.properties放到TestI18n.java同级
		System.out.println("自定义位置:\n" + cls.getResource("message_zh_CN.properties"));
		InputStream is = null;
		try {
			is = cls.getResourceAsStream("message_zh_CN.properties");
			// PropertyResourceBundle继承于ResourceBundle
			ResourceBundle rb = new PropertyResourceBundle(new InputStreamReader(is, "UTF-8"));
			String str = rb.getString("str1");
			System.out.println(str);
		} catch (Exception e) {
			throw e;
		} finally {
			try {
				is.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

运行结果:

自定义位置:
file:/E:/J2SE_workspace/TestI18n/bin/com/szh/message_zh_CN.properties
晚安

通过查看Kettle国际化部分的源码,其思想同上,即通过传入不同的class参数,来对应找到不同位置的国际化文件。

另附,Kettle8.1,Spoon设计器界面公共部分(除转换、作业组件自身)需要汉化的整理文档:

https://download.csdn.net/download/songzehao/10800437

转载于:https://www.cnblogs.com/songzehao/p/10854270.html

相关文章:

  • 撩课大前端-面试宝典-第九篇
  • C# 后台获取前台交互判断
  • 《转》完美解决微信video视频隐藏控件和内联播放问题
  • 微信浏览器播放音频的问题:preload属性
  • Java并发编程之锁机制之(ReentrantLock)重入锁
  • Python:asyncio模块学习
  • Spring Security中异常上抛机制及对于转型处理的一些感悟
  • python学习记录-打印九九乘法表
  • Oracle数据库查看表空间是否为自增的
  • 将excel项目管理融入生活
  • Python正则表达式的7个使用典范
  • 线程组之间的JMeter传递变量
  • PIP总结
  • gulp压缩合并js与css
  • testng.xml 配置大全
  • 【399天】跃迁之路——程序员高效学习方法论探索系列(实验阶段156-2018.03.11)...
  • flutter的key在widget list的作用以及必要性
  • Javascript基础之Array数组API
  • linux学习笔记
  • Vue 动态创建 component
  • vue-cli在webpack的配置文件探究
  • 分享自己折腾多时的一套 vue 组件 --we-vue
  • 干货 | 以太坊Mist负责人教你建立无服务器应用
  • 汉诺塔算法
  • 你真的知道 == 和 equals 的区别吗?
  • 如何用Ubuntu和Xen来设置Kubernetes?
  • 使用 5W1H 写出高可读的 Git Commit Message
  • 微信小程序上拉加载:onReachBottom详解+设置触发距离
  • 移动端 h5开发相关内容总结(三)
  • 智能合约Solidity教程-事件和日志(一)
  • MiKTeX could not find the script engine ‘perl.exe‘ which is required to execute ‘latexmk‘.
  • JavaScript 新语法详解:Class 的私有属性与私有方法 ...
  • ​七周四次课(5月9日)iptables filter表案例、iptables nat表应用
  • # Pytorch 中可以直接调用的Loss Functions总结:
  • # Swust 12th acm 邀请赛# [ E ] 01 String [题解]
  • (二)windows配置JDK环境
  • (论文阅读32/100)Flowing convnets for human pose estimation in videos
  • (五) 一起学 Unix 环境高级编程 (APUE) 之 进程环境
  • (一)基于IDEA的JAVA基础1
  • (转) RFS+AutoItLibrary测试web对话框
  • (转)菜鸟学数据库(三)——存储过程
  • /bin/rm: 参数列表过长"的解决办法
  • /deep/和 >>>以及 ::v-deep 三者的区别
  • @angular/cli项目构建--Dynamic.Form
  • [CareerCup] 17.8 Contiguous Sequence with Largest Sum 连续子序列之和最大
  • [CUDA手搓]从零开始用C++ CUDA搭建一个卷积神经网络(LeNet),了解神经网络各个层背后算法原理
  • [English]英语积累本
  • [iOS开发]事件处理与响应者链
  • [LeetCode][138]【学习日记】深拷贝带有随机指针的链表
  • [Linux] CE知识随笔含Ansible、防火墙、VIM、其他服务
  • [one_demo_14]一个简单的easyui的demo
  • [Python进阶] 正则表达式介绍
  • [RoarCTF 2019]Easy Calc
  • [Ruby] 基础知识
  • [VulnHub靶机渗透] Nullbyte