在Java中,我如何找到我的Resource Bundle可用的语言
我在主jar中打包了一些资源包
widget_en.properties widget_de.properties
我根据我的默认语言环境检索资源包作为folows
ResourceBundle.getBundle("widget", Locale.getDefault());
但我想向用户提供支持的可用语言列表,以便选择可能与其计算机默认的语言不同的语言
但我在ResourceBundle中找不到列出可用语言环境的方法,我不想对列表进行硬编码,因为我可能忘记在添加另一个资源包时更新它。
编辑
由于我只使用不同语言的资源包(我没有国家改进)所以我通过迭代所有已知的语言代码生成了一个列表,并检查每一个作为资源。
String[]langs = Locale.getISOLanguages(); for(String lang:langs) { URL rb = ClassLoader.getSystemResource("widget_"+lang+".properties"); if(rb!=null) { System.out.println("Found:"+rb.toString()); } }
我不认为有这样的API,因为可以动态创建新的有效区域设置对象:
Locale locale = new Locale("abcd");
无需在某处注册。 然后您可以使用资源包widget_abcd.properties
而不受任何限制:
ResourceBundle resource= ResourceBundle.getBundle("widget", new Locale("abcd"));
来自java.util.Locale
API文档:
由于Locale对象只是区域的标识符,因此在构造Locale时不会执行有效性检查。 如果要查看特定资源是否可用于您构造的区域设置,则必须查询这些资源。
要解决此问题,您仍然可以迭代资源目录中名为“widget_”的所有文件,并发现新添加的资源包。
请注意,由于上述原因, Locale.getAvailableLocales()
不是100%确定 :您可能有一天会定义非标准语言环境。 但是,如果您只添加一些标准语言环境,则可以使用此静态方法迭代系统语言环境并获取相应的包。
如果您确实将资源文件打包在JAR中,那么我会这样做:
public static void main(String[] args) { Set resourceBundles = getResourceBundles(A.class.getName()); if (resourceBundles.isEmpty()) // ... } public static Set getResourceBundles(String baseName) { Set resourceBundles = new HashSet<>(); for (Locale locale : Locale.getAvailableLocales()) { try { resourceBundles.add(ResourceBundle.getBundle(baseName, locale)); } catch (MissingResourceException ex) { // ... } } return Collections.unmodifiableSet(resourceBundles); }
如果你关心你的JAR,那么你至少会得到一个包含给定baseName
的默认资源的集合。
如果您只有名称类似baseName_
资源,则此方法可以正常工作,因为只有那些ResourceBundles
将添加到JAR中存在的集合中。 即使您决定需要单独的baseName_en_US
和baseName_en_UK
资源,它也会起作用,这是闻所未闻的。
无耻的自我插件:我写了一个以Charset
为参数的ResourceBundle.Control
,如果你想加载UTF-8编码的资源文件,你可能会对它感兴趣。 它可以在GitHub上找到。
如果您可以做出两个基本假设:
1)您有一个没有语言环境的默认资源包,或者至少有一个您知道的语言环境。
2)所有资源都在同一个位置(即一个jar文件中的相同路径)
然后,您可以获取单个资源的URL:
URL url = SomeClass.class.getClassLoader().getResource("widget.properties");
一旦你有了,你应该能够解析URL。
如果使用commons-vfs,则应该能够将URL转换为FileObject:
FileSystemManager manager = VFS.getManager(); FileObject resource = manager.resolveFile(url.toExternalForm()); FileObject parent = resource.getParent(); FileObject children[] = parent.getChildren(); // figure out which ones are bundles, and parse the names into a list of locales.
这将为您省去处理jar:style url等复杂性的麻烦,因为vfs会为您处理。
通过列出文件来解决它。
public class JavaApplication1 { public static final ArrayList LOCALES = new ArrayList<>(); static { try { File f = new File(JavaApplication1.class.getResource("/l10n").toURI()); final String bundle = "widget_";// Bundle name prefix. for (String s : f.list(new FilenameFilter() { @Override public boolean accept(File dir, String name) { return name.startsWith(bundle); } })) { LOCALES.add(s.substring(bundle.length(), s.indexOf('.'))); } } catch (URISyntaxException x) { throw new RuntimeException(x); } LOCALES.trimToSize(); } ... }