`
fehly
  • 浏览: 245401 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

应用程序国际化

    博客分类:
  • java
阅读更多

基本概念

国际化(Internationalization,I18N)
本地化(Localization,L10N)
应用程序国际化的目标

编写在任何受支持的区域设置中都同样能正常运行(且外观表现本地化)的代码
国际化中的Unicode编码

 

数字、日期和时间国际化

国际化/本地化工作的焦点

ƒ 语言
ƒ 数字格式
ƒ 时间/日期格式
ƒ 货币
ƒ 身份证、社保号码和护照
ƒ 电话号码、地址和邮政编码
ƒ 度量衡
ƒ 禁忌
ƒ 名字和称谓

 国际化程序中的数据显示

import java.util.*;
import java.text.DateFormat;
import java.text.NumberFormat;

public class TestDataFormat{
	public static void main(String args[]){
		Date now = new Date();
		Locale locale = Locale.getDefault();
		System.out.println("Locale: " + locale);
		DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, locale);		
		System.out.println(df.format(now));

		double d = 1234.56;	
		NumberFormat nf1 = NumberFormat.getInstance();
		System.out.println(nf1.format(d));
		
		NumberFormat nf2 = NumberFormat.getCurrencyInstance();
		System.out.println(nf2.format(d));		
	}
}

资源包

在国际化的应用程序中,通常以资源包(Resource Bundle)的形式来保存与运行环境相关的资源,如消息文本、菜单及按钮标签等,每一个资源包对应一种用户Locale。

<包名>-<语言代码>-<国家/地区代码>   例:myRes-zh-Cn
<包名>-<语言代码>                         例:MyLabels-en

资源包的两种表现形式: 

属性文件(Property File)
资源绑定类(Resource Bundle Class)

属性文件

属性文件可用于保存要进行国际化的字符串信息,属纯文本文件,文件名前缀与资源包同名、后缀为".properties"。
属性文件的格式与先前的系统属性导出文件的格式相同。
使用java.util .ResourceBundle类可以加载属性文件并读取其中的资源。

import javax.swing.*;
import java.util.Date;
import java.util.Locale;
import java.util.ResourceBundle;
import java.text.DateFormat;

public class TestI18N{
	private static ResourceBundle bundle;
	private static Locale currentLocale;
	static{
		currentLocale = Locale.getDefault();
		bundle = ResourceBundle.getBundle("MyLabels",currentLocale);	
	}
	
	public static void main(String args[]){
		JFrame jf = new JFrame(bundle.getString("title"));
		JMenuBar jmb = new JMenuBar();
		JMenu jm1 = new JMenu(bundle.getString("menu.file"));
		JMenu jm2 = new JMenu(bundle.getString("menu.edit"));
		JMenu jm3 = new JMenu(bundle.getString("menu.help"));		
		jmb.add(jm1);
		jmb.add(jm2);
		jmb.add(jm3);
		jf.setJMenuBar(jmb);
		
		JTextArea status = new JTextArea();
		status.setText(bundle.getString("currentEnv") + currentLocale.getDisplayName());		
		JLabel time = new JLabel();
		jf.add(status,"Center");
		jf.add(time,"South");
		jf.setSize(350,200);
		jf.setLocation(400,300);
		jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);			
		jf.setVisible(true);
		
		MyTimer mt = new MyTimer(time);
		mt.start();
	}
}

class MyTimer extends Thread{
	JLabel status;
	public MyTimer(JLabel status){
		this.status = status;	
	}
	public void run(){
		Locale locale = Locale.getDefault();
		while(true){
			Date now = new Date();
			DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL,locale);		
			status.setText(df.format(now));
			try{
				Thread.sleep(1000);
			}catch(InterruptedException e){
				e.printStackTrace();	
			}	
		}
	}
}

为避免因文本文件在不同平台上的编码方式不一而导致乱码问题,Java国际化程序的属性文件统一采用Unicode编码格式存储
JDK中提供了专门的工具native2ascii对属性文件进行Unicode编码转化。

命令格式

native2ascii [-<options>] <inputfile> [<outputfile>]
例:D:\>native2ascii D:\p1\a.properties D:\p2\a.properties

为避免文件混杂,也可将属性文件保存在单独的子目录中,访问时则使用"."分隔其路径层次。

资源绑定类

资源绑定类(Resource Bundle Class)是资源包的另一种表现形式,和属性文件相对应,每个资源绑定类对应一种不同的用户Locale。
资源绑定类应与资源包同名,其中保存的也是国际化的“键-值对”属性信息,但信息格式并不限于字符串类型。
继承抽象类java.util.ListResourceBundle是定义资源绑定类的最便捷方法,该类中采用二维对象数组(Object[][])的形式保存所有国际化资源、并提供了按照“键”查找“值”的功能。

资源绑定类的定义格式:

public class <bundle_name> extends ListResourceBundle{
      //实现抽象方法getContents()
      public Object[][] getContents(){
      return  contents;
}
//定义资源
private static final Object[][] contents = {
          {<key1>,<value1>},
          {<key2>,<value2>},
          …
     } 
}
import java.awt.*;
import javax.swing.*;
import java.util.Date;
import java.util.Locale;
import java.util.ResourceBundle;
import java.text.DateFormat;

public class TestResourceBundle{
	private static ResourceBundle bundle;
	private static Locale currentLocale;
	static{
		currentLocale = Locale.getDefault();
		bundle = ResourceBundle.getBundle("MyLabels",currentLocale);	
	}
	
	public static void main(String args[]){
		JFrame jf = new JFrame(bundle.getString("title"));
		JMenuBar jmb = new JMenuBar();
		JMenu jm1 = new JMenu(bundle.getString("menu.file"));
		JMenu jm2 = new JMenu(bundle.getString("menu.edit"));
		JMenu jm3 = new JMenu(bundle.getString("menu.help"));		
		jmb.add(jm1);
		jmb.add(jm2);
		jmb.add(jm3);
		jf.setJMenuBar(jmb);
		
		JTextArea status = new JTextArea();
		status.setText(bundle.getString("currentEnv") + currentLocale.getDisplayName());		
		Color bg = (Color)bundle.getObject("bgColor");
		status.setBackground(bg);
		
		JLabel time = new JLabel();
		jf.add(status,"Center");
		jf.add(time,"South");		
		jf.setSize(350,200);
		jf.setLocation(400,300);
		jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);			
		jf.setVisible(true);
		
		MyTimer mt = new MyTimer(time);
		mt.start();
	}
}

class MyTimer extends Thread{
	JLabel status;
	public MyTimer(JLabel status){
		this.status = status;	
	}
	public void run(){
		Locale locale = Locale.getDefault();
		while(true){
			Date now = new Date();
			DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL,locale);		
			status.setText(df.format(now));
			try{
				Thread.sleep(1000);
			}catch(InterruptedException e){
				e.printStackTrace();	
			}	
		}
	}
}

消息格式化

和使用NumberFormat、DateFormat等工具类格式化数字和日期/时间信息的情况类似, JDK 中还提供了一个java.text.MessageFormat类专门用来格式化包含有可变参数的文本消息。

import java.util.Date;
import java.util.Locale;
import java.text.MessageFormat;
import java.util.Scanner;

public class TestMessageFormat{
	private static int num = 10000;
	public static void main(String args[]){	
		TestMessageFormat tmf = new TestMessageFormat();
		System.out.print("请输入您的姓名:");
		String userName = new Scanner(System.in).next();
		System.out.println(tmf.formatMsg(userName));
	}
	public String formatMsg(String name){	
		String msg = "{0},欢迎您! 您是第{2}位访客,当前时间是{1}";
		Locale locale = Locale.getDefault();
		MessageFormat mf = new MessageFormat(msg,locale);
		Object[] msgArgs = {name,new Date(),++num};
		return mf.format(msgArgs);		
	}
}

相关术语:
消息模式(Message Pattern)
占位符(Placeholder)

 

占位符类型和样式

可以对消息模式串中的占位符进行可选的类型和样式设置,以获得更细致的格式化效果。

格式

{<index>,<type>,<style>}

设置占位符格式和样式

import java.util.Date;
import java.util.Locale;
import java.text.MessageFormat;
import java.util.Scanner;

public class TestPlaceholder{
	private static int num = 10000;
	public static void main(String args[]){	
		TestPlaceholder tmf = new TestPlaceholder();
		System.out.print("请输入您的姓名:");
		String userName = new Scanner(System.in).next();
		System.out.println(tmf.formatMsg(userName));
	}
	public String formatMsg(String name){	
		String msg = "{0},您好! 您是第{1}位访客,今天是{2,date,medium},当前时间{2,time,short}";
		Locale locale = Locale.getDefault();
		MessageFormat mf = new MessageFormat(msg,locale);
		Object[] msgArgs = {name,++num,new Date()};
		return mf.format(msgArgs);		
	}
}

国际化程序中的消息格式化

国际化应用程序中的消息模式字符串本身也需要进行本地化处理,此时可以将之保存到资源包中,以提供对应于不同Locale的版本,其实现方式与保存普通文本资源的方式相同。

使用资源包保存消息模式字符串

import java.awt.Color;
import java.util.ListResourceBundle;
public class MyMsgs extends ListResourceBundle {
	private final Object my_data[][] = {
		{"note","Please input your name: "},
		{"msg","Welcome,{0}! Your seriation no is {1},Date: {2,date,medium},  Time:{2,time,short}"}
	};
	public Object[][] getContents() {
		return my_data;
	}	
}
 
import java.awt.Color;
import java.util.ListResourceBundle;
public class MyMsgs_zh_CN extends ListResourceBundle {
	private final Object my_data[][] = {
		{"note","请输入您的姓名: "},
		{"msg","{0},您好! 您是第{1}位访客,今天是{2,date,medium},当前时间{2,time,short}"}
	};
	public Object[][] getContents() {
		return my_data;
	}	
}
 
import java.util.*;
import java.text.*;

public class Test{
	private static int num = 10000;
	public static void main(String args[]){
		Locale defaultLocale = Locale.getDefault();
		ResourceBundle bundle = ResourceBundle.getBundle("MyMsgs",defaultLocale);
		String note = bundle.getString("note");	
		String msg = bundle.getString("msg");	
		System.out.print(note);
		String userName = new Scanner(System.in).next();
		
		MessageFormat mf = new MessageFormat(msg,defaultLocale);
		Object[] msgArgs = {userName,++num,new Date()};
		System.out.println(mf.format(msgArgs));		
	}
}

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics