今天看啥  ›  专栏  ›  江湖非良人

国际化程序实现

江湖非良人  · 简书  ·  · 2019-07-25 01:10

  所谓的国际化的程序指的是同一个程序代码可以根据不同的国家实现不同的语言描述,但是程序处理的核心业务是相同的。

国际化问题简介

  现在假设有一款企业管理平台,决定推广到其他国家,首先要考虑的问题是什么?


国际化

  通过上图可以发现,如果想要实现国际化的程序开发,那么要解决的问题就在于以下两点:

  • 如何可以定义保存文字的文件信息;
  • 如何可以根据不同区域语言的编码,读取指定的资源信息;

Locale

  如果想要实现国际化,那么首先需要解决的就是不同国家用户的区域和语言编码问题,而在java.util包中提供有专门描述区域和语言编码的类:Locale,而后主要可以使用Locale类中的两个构造方法进行实例化:

  • 构造方法:public Locale​(String language);
  • 构造方法:public Locale​(String language, String country);
import java.util.Locale;
public class JavaApiDemo {
    public static void main(String[] args) throws Exception {
        Locale loc=new Locale("zh","CN");//中文环境
        System.out.println(loc);
    }
}

  如果说现在想要自动获得当前的运行环境,那么现在就可以利用Locale类本身默认的方式进行实例化:

  • 读取本地默认环境:public static Locale getDefault​();
import java.util.Locale;
public class JavaApiDemo {
    public static void main(String[] args) throws Exception {
        Locale loc = Locale.getDefault();//获得默认环境
        System.out.println(loc);
    }
}

  在实际的开发过程中,很多人并不关心国家和语言的编码,所以为了简化开发,Locale也将世界上一些常用的国家编码设置为常量。

import java.util.Locale;
public class JavaApiDemo {
    public static void main(String[] args) throws Exception {
        Locale loc = Locale.CHINA;//中文环境
        System.out.println(loc);
    }
}

  使用常量可以避免一些区域编码信息的繁琐。

读取资源文件:ResourceBundle

  创建一个资源文件: Messages.properties,添加一行“info=来了老弟”:

#资源文件名称:Messages.properties
info=来了老弟

  现在已经准备好了资源文件,那么随后就需要进行资源文件的读取操作了,而读取资源文件主要依靠的是java.util.ResourceBundle类完成,此类定义如下:

public abstract class ResourceBundle extends Object

  ResourceBundle是一个抽象类,如果说想要进行此类对象的实例化可以直接利用该类中提供的一个静态方法完成:

  • 获取ResourceBundle类对象:
      public static final ResourceBundle getBundle​(String baseName);
       -- baseName:描述的是资源文件的名称,但是没有后缀;
  • 根据key读取资源内容: public final String getString​(String key);
    范例:使用ResourceBundle类读取内容
import java.util.Locale;
import java.util.ResourceBundle;
public class JavaApiDemo {
    public static void main(String[] args) throws Exception {
        ResourceBundle resource = ResourceBundle.getBundle("com.mldn.demo.Messages");
//        String val = resource.getString("info");//直接读取会产生乱码
        String val = new String(resource.getString("info").getBytes("ISO-8859-1"), "utf-8");
        System.out.println(val);//来了老弟
    }
}

  资源文件的包路径一定要填写正确,读取数据的key也必须要存在,否则会抛出MissingResourceException异常;

实现国际化程序

  现在国际化程序的实现前期准备已经全部完成了,也就是说依靠资源文件、Locale、ResourceBundle类就可以实现国际化的处理操作,那么下面来进行国际化的程序实现(核心关键:读取资源信息)。
1、在classpath下建立:com.mldn.demo.Messages_zh_CN.properties;

#资源文件名称:Messages_zh_CN.properties
info=欢迎您的访问!

2、在classpath下建立:com.mldn.demo.Messages_en_US.properties;

#资源文件名称:Messages_en_US.properties
info=Welcome!

  现在加上没有默认区域的资源文件,一共定义了三个资源:



3、通过程序进行指定区域的资源信息加载

import java.util.ResourceBundle;
public class JavaApiDemo {
    public static void main(String[] args) throws Exception {
        ResourceBundle resource = ResourceBundle.getBundle("com.mldn.demo.Messages");
//        String val = resource.getString("info");//直接读取会产生乱码
        String val = new String(resource.getString("info").getBytes("ISO-8859-1"), "utf-8");
        System.out.println(val);//欢迎您的访问!
    }
}

  此时在利用ResourceBundle类读取资源时并没有设置一个明确的Locale对象,但是发现“Messages_zh_CN”文件生效了,因为这个方法中默认加载的就是当前本地的Locale的资源:

public static final ResourceBundle getBundle(String baseName) {
    return getBundleImpl(baseName, Locale.getDefault(), getLoader(Reflection.getCallerClass()), getDefaultControl(baseName));
}

4、如果现在有需要也可以修改当前的Locale环境,则可以使用ResourceBundle类中如下方法:

  • 获取ResourceBundle:
      public static final ResourceBundle getBundle​(String baseName, Locale locale);
import java.util.Locale;
import java.util.ResourceBundle;
public class JavaApiDemo {
    public static void main(String[] args) throws Exception {
        ResourceBundle resource = ResourceBundle.getBundle("com.mldn.demo.Messages",Locale.US);
//        String val = resource.getString("info");//直接读取会产生乱码
        String val = new String(resource.getString("info").getBytes("ISO-8859-1"), "utf-8");
        System.out.println(val);
    }
}

  如果现在有指定区域的组员文件存在时,那么没有设置区域的资源文件的信息将不会被读取。
  资源读取顺序:读取指定区域的资源文件>默认的本地资源>公共的资源(没有区域设置的)

消息格式化 MessageFormat

  当用户登录成功后,一般都会显示这样的信息“XXX,欢迎您的光临!”,也就是这时会显示用户名,那么如果这些内容保存在资源文件里面,则需要通过占位符进行描述,同时对于读取出来的数据也需要进行消息格式化的处理。
范例:修改资源文件

  • 中文资源文件:com.mldn.demo.Messages_zh_CN.properties;
#资源文件名称:Messages_zh_CN.properties
info=欢迎{0}的访问!当前日期是{1}
  • 英文资源文件:com.mldn.demo.Messages_en_US.properties;
info=Welcome {0} date:{1}!

  如果有需要可以继续添加“{2}”、“{3}”之类的占位符;
  此时如果就进行资源文件读取则会将占位符的信息一起读取出来所以此时就需要利用MessageFormat类进行格式化处理。

MessageFormat

  在MessageFormat类中提供了一个格式化文本的方法:
    public static String format​(String pattern, Object... arguments);
范例:格式化文本实现国际化

import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.ResourceBundle;
public class JavaApiDemo {
    public static void main(String[] args) throws Exception {
        ResourceBundle resource = ResourceBundle.getBundle("com.mldn.demo.Messages",Locale.US);
//        String val = resource.getString("info");//直接读取会产生乱码
        String val = new String(resource.getString("info").getBytes("ISO-8859-1"), "utf-8");
        System.out.println(MessageFormat.format(val,"张三",new SimpleDateFormat("yyyy-MM-dd").format(new Date())));
    }
}

  如果再日后开发中见到资源文件中出现“{0}”、“{1}”的结构表示的都是占位符,该信息一定都需要格式化处理。




原文地址:访问原文地址
快照地址: 访问文章快照