在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_USbaseName_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(); } ... }