在我正在开发的项目中,我想根据当前的语言环境加载不同的资源。使用字符串,这非常简单:只需通过添加一些文件来创建资源包,例如Localization.properties
和Localization_de.properties
,然后通过ResourceBundle.getBundle("domain.project.Localization")
加载它。
但是如何加载不是简单字符串的本地化资源?
具体来说,我想根据语言环境加载图像和HTML文件。只需获取该资源的正确URL即可。例如,我想要一个Welcome.html
和Welcome_de.html
文件,并在当前区域设置为德语时加载更晚的文件。
简单地使用getClass().getResource("Welcome.html")
不起作用,它总是返回该文件并且不进行语言环境处理。除了根据当前语言环境手动搞乱文件名之外,我还没有找到解决这个问题的便捷方法。
我提出的一个解决方案是在我的Localization.properties
文件中添加一个包含正确本地化HTML文件名称的密钥。但这感觉很糟糕而且错了。
请注意,这不是Android应用程序,只是标准的Java 8桌面应用程序。
答案 0 :(得分:2)
事实证明,与ResourceBundle.getBundle
相同的行为非常容易。我looked at the code发现处理语言环境和文件名最重要的部分是ResourceBundle.Control。
所以这是一个简单的方法,它将URL返回到本地化资源(遵循与资源包相同的文件名方案),而不需要缓存并仅支持当前的语言环境:
/** Load localized resource for current locale.
*
* @param baseName Basename of the resource. May include a path.
* @param suffix File extension of the resource.
* @return URL for the localized resource or null if none was found.
*/
public static URL getLocalizedResource(String baseName, String suffix) {
Locale locale = Locale.getDefault();
ResourceBundle.Control control = ResourceBundle.Control.getControl(ResourceBundle.Control.FORMAT_DEFAULT);
List<Locale> candidateLocales = control.getCandidateLocales(baseName, locale);
for (Locale specificLocale : candidateLocales) {
String bundleName = control.toBundleName(baseName, specificLocale);
String resourceName = control.toResourceName(bundleName, suffix);
// Replace "Utils" with the name of your class!
URL url = Utils.class.getResource(resourceName);
if (url != null) {
return url;
}
}
return null;
}
如果有人想扩展它以支持通用语言环境作为参数:ResourceBundle.getBundleImpl
实现中的重要部分是:
for (Locale targetLocale = locale;
targetLocale != null;
targetLocale = control.getFallbackLocale(baseName, targetLocale)) {
List<Locale> candidateLocales = control.getCandidateLocales(baseName, targetLocale);
...
}
getCandidateLocales
的最后一个条目是空的区域设置(Locale.ROOT
)。在测试回退区域设置之前,在第一次for
迭代中找到自默认资源以来的区域设置时,应该忽略它。
答案 1 :(得分:1)
(这是我的评论的补充,以便有更详细的解释)
您可以根据他们的语言将资源放在不同的文件夹中。
文件树可能如下所示:
pathToRessources
DE
EN
使用像“文件本地化路径 - 建设者类”(声称有史以来最好的名字)
public static Locale currentLocale = Locale.GERMAN;
public static String baseRessourcePath = "Path to your basic folder for ressources";
public static String getLocalizedPathToFile(String ressourcePath)
{
return Paths.get(currentLocale.getLanguage(), ressourcePath).toString();
}
无论您何时需要加载ressource,只需使用
调用您的加载程序getLocalizedPath(PathToFile)
其中 PathToFile 类似于 /Images/Image1.png 或其他内容。
这也应该很容易用于客户端应用程序。
希望这会有所帮助:)
答案 2 :(得分:0)
拥有保存本地化文件名称的资源确实是一种有效的解决方案,但正如您所提到的那样繁琐。如果您需要在应用程序中显示HTML页面,为什么不嵌入小型Web服务器,并拥有服务器JSP页面?这样,整个HTML将保持不变,并且页面本身将被本地化。
另一种选择是使用本地模板引擎(如FreeMarker)并在提供HTML之前动态生成HTML。
答案 3 :(得分:0)
定义捆绑包:
public class MyBundle_fr_FR extends ListResourceBundle
{
public Object[][] getContents()
{
return new Object[][]
{
{ "welcome_file", getClass().getResource("Welcome_fr.html") },
{ "another_file", getClass().getResource("foo_fr.html") }
};
}
}
public class MyBundle_de_DE extends ListResourceBundle
{
public Object[][] getContents()
{
return new Object[][]
{
{ "welcome_file", getClass().getResource("Welcome_de.html") },
{ "another_file", getClass().getResource("foo_de.html") }
};
}
}
然后像这样使用它:
ResourceBundle bundle = ResourceBundle.getBundle("MyBundle", Locale.GERMANY);
URL url = (URL) bundle.getObject("welcome_file");
答案 4 :(得分:0)
你这样做的方式对我来说有点奇怪。我开发了一些国际应用程序,从未使用过这种方法您的方法的维护成本非常高。想象一下,您想要更改welcome.html
文件的一部分,您需要更改所有其他欢迎文件,这是一项巨大的努力。
java中这个问题的常见解决方案是使用JSTL fmt taglib来获取包含键值对的一些属性文件的帮助,键值是固定的,值会根据你所在的语言环境而改变。例如,你在Localization.properties
文件您有以下键值:
page.welcome.welcome=welcome
并且您有另一个名称为Localization_de.properties
且具有相同键且值不同的文件
page.welcome.welcome=willkommen
现在,在您的welcome.jsp
中,您可以使用类似<fmt:message key="page.welcome.welcome"/>
之类的内容,以便在您的网页中呈现正确的值。对于图像,您可以采用相同的方法。只需将图像名称作为键导入每个属性文件,并将其正确命名为其值,并使用jsp中的键。
对于i18n,使用eclipse插件(如Resource Bundel Editor)可以让您的生活更轻松。
在我使用的其他语言框架中,像django我看到了与上面相同的方法。