国际化程序实现

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

国际化问题简介

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


国际化

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

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

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}”的结构表示的都是占位符,该信息一定都需要格式化处理。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,366评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,521评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,689评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,925评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,942评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,727评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,447评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,349评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,820评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,990评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,127评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,812评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,471评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,017评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,142评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,388评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,066评论 2 355