java.util.ResourceBundle用法详解

java.util.ResourceBundle用法详解java.util.ResourceBundle用法详解

大家好,又见面了,我是你们的朋友全栈君。

初识国际化和ResourceBundle

这个类主要用来解决国际化和本地化问题。国际化和本地化可不是两个概念,两者都是一起出现的。可以说,国际化的目的就是为了实现本地化,详细的介绍可以看本文的最后。比如对于“取消”,中文中我们使用“取消”来表示,而英文中我们使用“cancel”。若我们的程序是面向国际的(这也是软件发展的一个趋势),那么使用的人群必然是多语言环境的,实现国际化就非常有必要。而ResourceBundle可以帮助我们轻松完成这个任务:当程序需要一个特定于语言环境的资源时(如 String),程序可以从适合当前用户语言环境的资源包(大多数情况下也就是.properties文件)中加载它。这样可以编写很大程度上独立于用户语言环境的程序代码,它将资源包中大部分(即便不是全部)特定于语言环境的信息隔离开来。

这使编写的程序可以:

  • 轻松地本地化或翻译成不同的语言
  • 一次处理多个语言环境
  • 以后可以轻松进行修改,以便支持更多的语言环境 

测试及验证

下面我们来模拟一个多语言的环境

定义四个资源文件:res_en_US.properties、res_zh_CN.properties、res_zh.properties、res.properties

res_en_US.properties:cancelKey=cancel
res_zh_CN.properties:cancelKey=\u53D6\u6D88(取消)

res_zh.properties:cancelKey=\u53D6\u6D88zh(取消zh)

res.properties:cancelKey=\u53D6\u6D88default(取消default)


命名规则按照:资源名+_语言_国别.properties,每个资源文件中定义了本地化的信息,那么系统如何取到对应的资源文件呢?
ResourceBundle bundle = ResourceBundle.getBundle("res", new Locale("zh", "CN"));

其中new Locale(“zh”, “CN”);这个对象就告诉了程序你的本地化信息,就拿这个来说吧:程序首先会去classpath下寻找res_zh_CN.properties

若不存在,那么会去找res_zh.properties,若还是不存在,则会去寻找res.properties,要还是找不到的话,那么就该抛异常了:MissingResourceException
我们可以来写个测试程序验证一下:

package bundle.test;

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

public class BundleTest {

	public static void main(String args[]) {
		ResourceBundle bundle = ResourceBundle.getBundle("res", new Locale("zh", "CN"));
		String cancel = bundle.getString("cancelKey");
		System.out.println(cancel);
		
		bundle = ResourceBundle.getBundle("res", Locale.US);
		cancel = bundle.getString("cancelKey");
		System.out.println(cancel);
		
		bundle = ResourceBundle.getBundle("res", Locale.getDefault());
		cancel = bundle.getString("cancelKey");
		System.out.println(cancel);

		bundle = ResourceBundle.getBundle("res", Locale.GERMAN);
		cancel = bundle.getString("cancelKey");
		System.out.println(cancel);
	}
}

输出:
取消
cancel
取消
取消

这里前三个都在我们的预期范围之内,但是最后一个GERMAN,应该会去使用res.properties这个资源包吧?怎么使用了res_zh_CH.properties?
原来ResourceBundle为我们提供了一个fallback(也就是一个备用方案),这个备用方案就是根据当前系统的语言环境来得到的本地化信息。
所以若是找不到GERMAN的,之后就会去找CHINA了,所以找到了res_zh_CH.properties这个资源包
这点我也是看了源代码才明白的,下面就贴上一些关键的源代码:
	ResourceBundle baseBundle = null;
	for (Locale targetLocale = locale;
	     targetLocale != null;
	     targetLocale = control.getFallbackLocale(baseName, targetLocale)) {// 这里就是去拿备用方案的
	    // do something 我们暂时不关心
	}

跟踪control.getFallbackLocale(baseName, targetLocale)看看备用方案到底是什么?
	public Locale getFallbackLocale(String baseName, Locale locale) {
	    if (baseName == null) {
		throw new NullPointerException();
	    }
	    Locale defaultLocale = Locale.getDefault();
	    return locale.equals(defaultLocale) ? null : defaultLocale;
	}
当显式定义的本地化信息并不是当前系统的本地化信息时,若未能通过显式定义的找到资源包,那么就去转而通过当前系统的本地化信息去找了~
最后放一点小知识吧~

国际化和本地化

国际化(Internationalization)是设计一个适用于多种语言和地区的应用程序的过程。适用于多种语言和地区的含义是当使用不同语言及处于不同的地区的用户在使用这个应用程序时,应用程序必须使用他们能看懂的语言和符合他们文化习惯来显示信息。国际化有时候被简称为i18n,因为有18个字母在国际化的英文单词的字母i和n之间。

一个国际化的程序通常具有以下特征:

  • 有一个附加的本地化数据(localized  data)及拥有在全世界各个地区执行的能力。
  • 文本的元素,比如状态信息或GUI截面的lables,不是直接写(hardcoded)在程序中,而是被存储在本地化的数据中,并且能被程序正确的动态的使用。
  • 支持新的语言时,不需要修改程序,不需要重新编译。
  • 文化差异的数据,比如日期和货币,必须根据拥护的语言和习惯显示不同的格式。
  • 可以被迅速的本地化。
        本地化(Localization)是指通过增加本地描述的构件(locale-specific components )和文字翻译工作来使应用程序适应于不同的语言和地区的过程。本地化有时候被简称为l10n,应为有10个字母在本地化的英文单词的字母l和n之间。通常本地化最耗时的工作应该是文字翻译。本地化工作者们要根据地区的具体需求来为日期、数字和通货等数据建立新的格式。其他类型的数据,象声音,图象等,也需要根据具体需要来决定是否本地化。



版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/158687.html原文链接:https://javaforall.net

(0)
上一篇 2022年7月13日 下午9:00
下一篇 2022年7月13日 下午9:00


相关推荐

  • Cocos2d-X在SwitchControl使用

    Cocos2d-X在SwitchControl使用

    2022年1月1日
    46
  • 移远EC20串口使用阻塞问题

    移远EC20串口使用阻塞问题今天我们郭工使用我写的 EC20 程序发现了一个严重的问题 就是运行一段时间后会出现丢数据的情况 使用供应商的程序却能很好的运行我很奇怪 仔细看了供应商的历程发现他们用的是 select 机制 我突然有个灵感是不是我的读取串口导致了串口阻塞 一查果然是 Linux 下直接用 read 读串口可能会造成堵塞 或数据读出错误 然而用 select 先查询 com 口是否可读则可以

    2026年3月18日
    1
  • 如何用Cursor+Claude两个神器,两步完成APP开发?

    如何用Cursor+Claude两个神器,两步完成APP开发?

    2026年3月16日
    2
  • sleep() 和 wait() 的区别

    sleep() 和 wait() 的区别sleep 方法是线程类 Thread 的静态方法 让调用线程进入睡眠状态 让出执行机会给其他线程 等到休眠时间结束后 线程进入就绪状态和其他线程一起竞争 cpu 的执行时间 因为 sleep 是 static 静态的方法 他不能改变对象的机锁 当一个 synchronized 块中调用了 sleep 方法 线程虽然进入休眠 但是对象的机锁没有被释放

    2026年3月17日
    2
  • vue 获取当前路由的子路由

    vue 获取当前路由的子路由获取当前路由的子路由 routes varroutes children this router options routes varroute this route matched for vari 0 i route length 1 i routes routes children find e e name route length 1 i routes routes children find e

    2026年3月16日
    3
  • 图解一致性哈希算法的基本原理

    图解一致性哈希算法的基本原理一致性哈希的基本原理一致性哈希算法是将每个Node节点映射到同一个圆上。将各Node的key采用hash计算,可得到一个整数数组。将该数组排序后,首尾相连即是一个圆。如下图所示简单来说,一致性Hash算法将整个哈希值空间组织成一个虚拟的圆环,如假设某哈希函数H的值空间为0-2^32-1(即哈希值是一个32位无符号整形),整个哈希环如下:整个空间按顺时针方向组织,圆环的正上方的点代表0,0点右侧的第一个点代表1,以此类推,2、3、4、5、6……直到2^32-1,也就是说0点左侧..

    2022年7月27日
    7

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号