Ber*_*own 3 java resourcebundle internationalization java-ee
在Java EE环境中,我们通常用于在属性/资源文件中存储文本.并且该属性文件与某些视图HTML标记文件相关联.例如,如果您的标签"名字"在HTML页面上更改为"全名",则可以使用该属性进行更新.
firstName=First Name
someOtherData=This is the data to display on screen, from property file
Run Code Online (Sandbox Code Playgroud)
如果您所处的环境很难定期更新这些属性文件,那么开发人员使用哪种架构来更改通常位于属性文件中的文本/标签内容?或者假设您需要在重新部署属性文件更改之前更改该内容.一个糟糕的解决方案是将其存储在数据库中?开发人员使用memcache吗?这通常用于缓存解决方案吗?
编辑-1数据库实际上不是为这类任务设计的(拉动文本显示在屏幕上),但数据库有用例.我可以添加区域设置列或状态字段,也可以按组添加列过滤器.如果我不使用数据库或属性文件,那么分布式键/值解决方案将允许我添加自定义过滤器?
编辑-2你会在java框架之外使用解决方案吗?像键/值数据存储一样?memcachedb?
Paw*_*yda 11
我想向您保证,如果您需要对本地化文本进行不断更改,例如它们往往因部署而异,那么数据库就是您的选择.好吧,不仅仅是数据库,你需要以某种方式缓存你的字符串.当然,我想你不想完全重建你的资源访问层.
为此我可以建议扩展ResourceBundle类以自动从数据库加载字符串并将其存储WeakHashMap.我WeakHashMap之所以选择它的功能 - 它不再需要从地图中删除一个键来减少内存占用.无论如何,您需要创建一个访问者类.既然你提到了J2EE,这是非常古老的技术,我将为你提供Java SE 1.4兼容的例子(它可以很容易地为新的Java重新工作,只需在需要时添加@Override并在Enumeration中添加一些String泛化):
public class WeakResourceBundle extends ResourceBundle {
private Map cache = new WeakHashMap();
protected Locale locale = Locale.US; // default fall-back locale
// required - Base is abstract
// @Override
protected Object handleGetObject(String key) {
if (cache.containsKey(key))
return cache.get(key);
String value = loadFromDatabase(key, locale);
cache.put(key, value);
return value;
}
// required - Base is abstract
// @Override
public Enumeration getKeys() {
return loadKeysFromDatabase();
}
// optional but I believe needed
// @Override
public Locale getLocale() {
return locale;
}
// dummy testing method, you need to provide your own
// should throw MissingResourceException if key does not exist
private String loadFromDatabase(String key, Locale aLocale) {
System.out.println("Loading key: " + key
+ " from database for locale:"
+ aLocale );
return "dummy_" + aLocale.getDisplayLanguage(aLocale);
}
// dummy testing method, you need to provide your own
private Enumeration loadKeysFromDatabase() {
return Collections.enumeration(new ArrayList());
}
}
Run Code Online (Sandbox Code Playgroud)
由于一些奇怪的ResourceBundle加载规则,您实际上需要扩展WeakResourceBundle类以为受支持的语言创建一个类:
// Empty Base class for Invariant Language (usually English-US) resources
// Do not need to modify anything here since I already set fall-back language
package com.example.i18n;
public class MyBundle extends WeakResourceBundle {
}
Run Code Online (Sandbox Code Playgroud)
每个支持一种语言(我知道它很糟糕):
// Example class for Polish ResourceBundles
package com.example.i18n;
import java.util.Locale;
public class MyBundle_pl extends WeakResourceBundle {
public MyBundle_pl() {
super();
locale = new Locale("pl");
}
}
Run Code Online (Sandbox Code Playgroud)
现在,如果你需要实例化你的ResourceBundle,你只需要打电话:
// You probably need to get Locale from web browser
Locale polishLocale = new Locale("pl", "PL");
ResourceBundle myBundle = ResourceBundle.getBundle(
"com.example.i18n.MyBundle", polishLocale);
Run Code Online (Sandbox Code Playgroud)
并访问密钥:
String someValue = myBundle.getString("some.key");
Run Code Online (Sandbox Code Playgroud)
可能的陷阱:
ResourceBundle 需要完全合格的类名(因此包名称).Locale参数,Locale则将使用default(表示Server).确保Locale在实例化时始终通过ResourceBundle.myBundle.getString()MissingResourceException如果你按照我的建议,可能会抛出.您需要使用try-catch块来避免问题.相反,如果丢失密钥(例如return "!" + key + "!"),您可能决定从数据库访问层返回一些虚拟字符串,但无论哪种方式,它都应该记录为错误.MyBundle_pl.java,而不是MyBundle_pl_PL.java它仍然有效.此外,MyBundle.java如果没有给定语言的资源类,ResourceBundle将自动回退到Enlish-US()这就是我使用这种奇怪的类层次结构的原因).编辑
关于如何使它更加令人敬畏的一些随机想法.
静态工厂(避免直接使用ResourceBundle)
您可以添加静态工厂方法,而不是使用ResourceBundle直接实例化包.
public static ResourceBundle getInstance(Locale aLocale) {
return ResourceBundle.getBundle("com.example.i18n.MyBundle", aLocale);
}
Run Code Online (Sandbox Code Playgroud)
如果您决定将WeakResourceBundle类的名称更改为更合适的(我决定使用LocalizationProvider),您现在可以通过使用代码轻松实例化您的bundle:
ResourceBundle myBundle = LocalizationProvider.getInstance(polishLocale);
Run Code Online (Sandbox Code Playgroud)
自动生成的资源类
MyBundle可以通过构建脚本轻松生成本地化类.该脚本可以是配置文件或数据库驱动的 - 它需要知道系统中正在使用哪个Locale.无论哪种方式,类共享非常相似的代码,因此自动生成它们确实有意义.
自动检测区域设置
由于您是实现该类的人,因此您可以完全控制其行为.因此(了解您的应用程序架构)您可以在此处包含区域设置检测并进行修改getInstance()以自动加载适当的语言资源.
实现其他与本地化相关的方法
在本地化应用程序中需要完成常见任务 - 格式化和解析日期,数字,货币等是常见示例.拥有最终用户的Locale后,您只需将此类方法包装在LocalizationProvider中即可.
哎呀,我真的很喜欢我的工作:)
| 归档时间: |
|
| 查看次数: |
2735 次 |
| 最近记录: |