<术语>
国际化:internationalize,简称i18n,是指应用程序可以适应不同语言和地区的变化而变化的方案。
本地化:localization,检查l10n,是指应用程序适应某特定语言和地区的过程。
软件国际化是软件发展之必然,几乎所有的大众软件都支持多语言,最常见的就是英文软件的汉化版。
Java语言提供了基于unicode的国际化支持。通过Locale对象定义地区、语言、操作系统等信息,调用ResourceBundle的getBundle方法实现资源文件的数据绑定,轻松本地化不同的语言版本。
通过 ResourceBundle 和 Locale 2个类的定义可以看出 java 读取资源的流程为:language, country, variant -n-> language, country -n-> language -n-> Locale.getDefault()。
 ResourceBundle.getBundle(String baseName)
ResourceBundle.getBundle(String baseName)
 ResourceBundle.getBundle(String baseName, Locale locale)
ResourceBundle.getBundle(String baseName, Locale locale)

 Locale(String language)
Locale(String language)
 Locale(String language, String country)
Locale(String language, String country)
 Locale(String language, String country, String variant)
Locale(String language, String country, String variant)ResourceBundle 储存了键-值对形式的本地特殊化对象,如String,分为2种:ListResourceBundle和PropertyResourceBundle。
前者通过.class程序实现,后者通过.properties配置文件实现本地化,样例如下:
1、ListResourceBundle Example
1.1 默认(测试环境为中文)资源类

 /** *//**
/** *//**
 * $File: Rb.java             $
 * $File: Rb.java             $ 
 * $Revision: 1.0.0           $
 * $Revision: 1.0.0           $
 * $ $Date: 2006-8-18 2:12:11 $
 * $ $Date: 2006-8-18 2:12:11 $
 */
 */
 package org.anymobile.test;
package org.anymobile.test;

 import java.util.ListResourceBundle;
import java.util.ListResourceBundle;


 /** *//**
/** *//**
 *
 * 
 * @author Xu Jianxiang
 * @author Xu Jianxiang
 */
 */
 public class Rb extends ListResourceBundle
public class Rb extends ListResourceBundle


 {
{

 static final Object[][] contents =
    static final Object[][] contents =  {
{

 
             { "CHG", "修改" },
{ "CHG", "修改" }, 

 
             { "MSG", "消息" },
{ "MSG", "消息" }, 

 
             { "BYE", "再见" }
{ "BYE", "再见" }
 };
    };

 public Object[][] getContents()
    public Object[][] getContents()

 
     {
{
 return contents;
        return contents;
 }
    }
 }
}1.2 英文资源类

 /** *//**
/** *//**
 * $File: Rb_en.java        $
 * $File: Rb_en.java        $ 
 * $Revision: 1.0.0         $
 * $Revision: 1.0.0         $ 
 * $Date: 2006-8-18 2:14:37 $
 * $Date: 2006-8-18 2:14:37 $
 */
 */
 package org.anymobile.test;
package org.anymobile.test;

 import java.util.ListResourceBundle;
import java.util.ListResourceBundle;


 /** *//**
/** *//**
 *
 * 
 * @author Xu Jianxiang
 * @author Xu Jianxiang
 */
 */
 public class Rb_en extends ListResourceBundle
public class Rb_en extends ListResourceBundle


 {
{

 static final Object[][] contents =
    static final Object[][] contents =  {
{

 
             { "CHG", "change" },
{ "CHG", "change" },

 
             { "MSG", "message" },
{ "MSG", "message" },

 
             { "BYE", "bye" }
{ "BYE", "bye" }
 };
    };

 public Object[][] getContents()
    public Object[][] getContents()

 
     {
{
 return contents;
        return contents;
 }
    }
 }
}1.3 测试类

 /** *//**
/** *//**
 * $File: MyListResourceBundle.java $
 * $File: MyListResourceBundle.java $
 * $Revision: 1.0.0                 $
 * $Revision: 1.0.0                 $
 * $Date: 2006-8-18 2:24:30         $
 * $Date: 2006-8-18 2:24:30         $
 */
 */
 package org.anymobile.test;
package org.anymobile.test;

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


 /** *//**
/** *//**
 * Test java.util.ListResourceBundle
 * Test java.util.ListResourceBundle
 *
 * 
 * @author Xu Jianxiang
 * @author Xu Jianxiang
 */
 */
 public class MyListResourceBundle
public class MyListResourceBundle


 {
{
 public static void main( String[] args )
    public static void main( String[] args )

 
     {
{
 String baseName = "org.anymobile.test.Rb";
        String baseName = "org.anymobile.test.Rb";
 String key = "BYE";
        String key = "BYE";
 try
        try

 
         {
{
 ResourceBundle res = ResourceBundle.getBundle( baseName );
            ResourceBundle res = ResourceBundle.getBundle( baseName );
 System.out.println( res.getString( key ) );
            System.out.println( res.getString( key ) );
 
            
 res = ResourceBundle.getBundle( baseName, Locale.ENGLISH );
            res = ResourceBundle.getBundle( baseName, Locale.ENGLISH );
 System.out.println( res.getString( key ) );
            System.out.println( res.getString( key ) );
 }
        }
 catch ( MissingResourceException exp )
        catch ( MissingResourceException exp )

 
         {
{
 exp.printStackTrace();
            exp.printStackTrace();
 }
        }
 }
    }
 }
}运行结果:
再见
bye
2、PropertyResourceBundle Example
2.1 英文配置文件({project}/classes/resources/rb_en.properties)
 # rb_en.properties
# rb_en.properties

 CHG = change
CHG = change
 MSG = message
MSG = message
 BYE = bye
BYE = bye2.2 中文配置文件({project}/classes/resources/rb_zn_CN.properties)
 # rb_zn_CN.properties
# rb_zn_CN.properties

 CHG = 修改
CHG = 修改
 MSG = 消息
MSG = 消息
 BYE = 再见
BYE = 再见2.3 测试类

 /** *//**
/** *//**
 * $File: MyResourceBoundle.java $
 * $File: MyResourceBoundle.java $
 * $Revision: 1.0.0              $
 * $Revision: 1.0.0              $ 
 * $Date: 2006-8-18 1:19:06      $
 * $Date: 2006-8-18 1:19:06      $
 */
 */
 package org.anymobile.test;
package org.anymobile.test;

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


 /** *//**
/** *//**
 * Test java.util.PropertyResourceBundle
 * Test java.util.PropertyResourceBundle
 *
 * 
 * @author Xu Jianxiang
 * @author Xu Jianxiang
 */
 */
 public class MyPropResourceBundle
public class MyPropResourceBundle


 {
{
 public static void main( String[] args )
    public static void main( String[] args )

 
     {
{
 String baseName = "resources.rb";
        String baseName = "resources.rb";
 String key = "CHG";
        String key = "CHG";

 try
        try

 
         {
{
 //            ResourceBundle res = ResourceBundle.getBundle( baseName, Locale
//            ResourceBundle res = ResourceBundle.getBundle( baseName, Locale
 //                    .getDefault() );
//                    .getDefault() );
 ResourceBundle res = ResourceBundle.getBundle( baseName, new Locale("zh","CN","WINDOWS") );
            ResourceBundle res = ResourceBundle.getBundle( baseName, new Locale("zh","CN","WINDOWS") );
 System.out.println( key + ": " + res.getString( key ) );
            System.out.println( key + ": " + res.getString( key ) );

 res = ResourceBundle.getBundle( baseName, Locale.ENGLISH );
            res = ResourceBundle.getBundle( baseName, Locale.ENGLISH );
 System.out.println( key + ": " + res.getString( key ) );
            System.out.println( key + ": " + res.getString( key ) );
 }
        }
 catch ( MissingResourceException exp )
        catch ( MissingResourceException exp )

 
         {
{
 exp.printStackTrace();
            exp.printStackTrace();
 }
        }
 }
    }
 }
}运行结果:
CHG: 改变
CHG: change
另外,为了不致于在程序中产生乱码,可以通过jdk自带的native2ascii程序将.properties文件从本地编码转换成unicode编号格式的数据文件,为避免读取时因编码问题而出现乱码,可以先编写一个src.txt文件,然后执行指令:native2ascii src.txt dest.properties。转换后,如“中国”的unicode字符码为“\u4e2d\u56fd”。
如果需要将unicode恢复成原编码,可以执行指令:native2ascii -reverse dest.file src.file。
每次必须运行native2ascii方法比较繁琐,实际开发中,可以通过Apache Ant的native2Ascii任务进行批量转码。如:<native2ascii encoding="GBK" src="${src}" dest="${build}"/>
3、Spring 的消息国际化
org.springframework.context.ApplicationContext继承了org.springframework.context.MessgeResource接口,通过起getMessage()的各个版本读取文字消息的资源文件,从而实现消息国际化。
public interface MessageSource
{
String getMessage(String code, Object[] args, String defaultMessage, Locale locale);
}
参考资料:
Java 2 SDK Document
How to internationalize Java applications(Sun) 
http://java.sun.com/docs/books/tutorial/i18n/index.htmlISO Language Code    
http://www.ics.uci.edu/pub/ietf/http/related/iso639.txtISO Country Code      
http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html
	posted on 2006-08-18 03:42 
Xu Jianxiang 阅读(1094) 
评论(0)  编辑  收藏  所属分类: 
Java Tech