Mar*_*ing 5 java locale resourcebundle internationalization
我们需要开始为我们的计划添加国际化。值得庆幸的是,还不是全部,只是一些部分,但我希望我们的方式能够扩大规模,以覆盖整个计划。问题是,我们的程序基于插件,因此并非所有字符串都属于同一个位置。
据我了解,Java的ResourceBundle工作原理是这样的。您创建一个扩展的类ResourceBundle,称为MyProgramStrings,以及特定于语言的类,称为MyProgramStrings_fr,MyProgramStrings_es等等。每个类都将键(字符串)映射到值(任何对象)。从哪里获取数据取决于每个类,但它们的共同位置是属性文件。
您可以分两个阶段查找值:首先获得正确的包,然后在其中查询所需的字符串。
Locale locale = Locale.getDefault(); // or = new Locale("en", "GB");
ResourceBundle rb = ResourceBundle.getBundle("MyProgramStrings", locale);
String wotsitName = rb.getString("wotsit.name");
Run Code Online (Sandbox Code Playgroud)
然而,我们需要的是将多个语言环境的结果组合到一个资源空间中。例如,插件需要能够覆盖已定义的字符串,并在代码查找该字符串时返回新值。
我对这一切有点迷失。有人可以帮忙吗?
更新:大卫·沃特斯问:
我已将我的答案放在底部,但我有兴趣听听您如何解决这个问题。
好吧,我们还没有走得太远 - 长期 WIBNI 总是成为最新危机的受害者 - 但我们将其基于插件实现的接口,并约定资源具有与接口相同的完全限定名称。
所以一个接口UsersAPI可能有各种不同的实现。默认情况下,该接口上的方法getBundle()返回相当于 ResourceBundle.get("...UsersAPI", locale). 该文件可以被替换,或者如果需要更复杂的东西,UsersAPI 的实现可以覆盖该方法。
到目前为止,这满足了我们的需要,但我们仍在寻找基于插件的更灵活的解决方案。
您不必将ResourceBundles 实现为一系列类,每个区域设置一个类(即名为MyProgramStrings, MyProgramStrings_fr,的类MyProgramStrings_de)。如果需要,ResourceBundle 类将回退到使用属性文件:
public static void main(String[] args) {
ResourceBundle bundle = ResourceBundle.getBundle("MyResources");
System.out.println("got bundle: " + bundle);
String valueInBundle = bundle.getString("someKey");
System.out.println("Value in bundle is: " + valueInBundle);
}
Run Code Online (Sandbox Code Playgroud)
如果我有一个在类路径上命名的文件MyResources.properties,那么此方法将导致:
got bundle: java.util.PropertyResourceBundle@42e816
Value in bundle is: someValue
Run Code Online (Sandbox Code Playgroud)
至于设置bundle的层次结构,或者将它们“合并”在一起,恐怕我帮不了什么忙,除了我知道Spring确实有一个分层MessageSources的概念(链接到API),它是在java.util.ResourceBundle的顶部,所以也许你可以使用Spring的功能来实现你想要的?
顺便说一句,这里是 javadoc 的相关部分ResourceBundle.getBundle(),解释了它的“搜索和实例化策略”:
- 首先,它尝试使用候选包名称加载一个类。如果可以使用指定的类加载器找到并加载这样的类,其赋值与 ResourceBundle 兼容,可以从 ResourceBundle 访问,并且可以实例化,则 getBundle 创建此类的新实例并将其用作结果资源包。
- 否则,getBundle 尝试查找属性资源文件。它通过替换所有“.”,从候选包名称生成路径名。带有“/”的字符并附加字符串“.properties”。它尝试使用 ClassLoader.getResource 查找具有此名称的“资源”。(请注意,getResource 意义上的“资源”与资源包的内容无关,它只是数据的容器,例如文件。)如果找到“资源”,它会尝试创建来自其内容的新 PropertyResourceBundle 实例。如果成功,该实例将成为结果资源包。
| 归档时间: |
|
| 查看次数: |
2840 次 |
| 最近记录: |