25

I have some resource bundles packaged in my main jar

widget_en.properties
widget_de.properties

I retrieve a resource bundle based on my default locale as folows

ResourceBundle.getBundle("widget", Locale.getDefault());

But I want to present the user with a list of available languages supported so that can select a language that may be different to their computers default

But I can't find a method in ResourceBundle that would list available locales, I don't want to hardcode a list as I may forget to update it when another resource bundle is added.

EDIT

As I only resource bundles for different language (I dont have country refinements) so I have got generated a list by iterating through all the known language codes and check for each one as a resource.

String[]langs = Locale.getISOLanguages();
for(String lang:langs)
{
      URL rb = ClassLoader.getSystemResource("widget_"+lang+".properties");
      if(rb!=null)
      {
            System.out.println("Found:"+rb.toString());
      }
}
4

4 に答える 4

6

本当にリソース ファイルをJAR内にパッケージ化する場合は、次のようにします。

public static void main(String[] args) {
  Set<ResourceBundle> resourceBundles = getResourceBundles(A.class.getName());
  if (resourceBundles.isEmpty())
    // ...
}

public static Set<ResourceBundle> getResourceBundles(String baseName) {
  Set<ResourceBundle> resourceBundles = new HashSet<>();

  for (Locale locale : Locale.getAvailableLocales()) {
    try {
      resourceBundles.add(ResourceBundle.getBundle(baseName, locale));
    } catch (MissingResourceException ex) {
      // ...
    }
  }

  return Collections.unmodifiableSet(resourceBundles);
}

JAR に関心がある場合は、少なくとも、特定の .xml のデフォルト リソースを含むセットを取得できますbaseName

JAR に存在するリソースのみがセットに追加されるbaseName_<country>ため、このメソッドのような名前のリソースしかない場合は完全に機能します。前代未聞ではない別のリソースResourceBundlesが必要であると判断した場合でも、それは機能します。baseName_en_USbaseName_en_UK

恥知らずな自己プラグ: 私は引数として aResourceBundle.Controlを取る aを書きましたCharset。UTF-8 でエンコードされたリソース ファイルをロードしたい場合は、それに興味があるかもしれません。GitHub で入手できます。

于 2012-08-22T13:04:56.250 に答える
5

新しい有効なロケール オブジェクトをオンザフライで作成できるため、このための API はないと思います。

Locale locale = new Locale("abcd");

どこかに登録する必要はありません。widget_abcd.propertiesその後、制限なしでリソース バンドルを使用できます 。

ResourceBundle resource= ResourceBundle.getBundle("widget", new Locale("abcd"));

java.util.LocaleAPI ドキュメントから:

Locale オブジェクトは地域の単なる識別子であるため、Locale を構築するときに有効性チェックは実行されません。構築した Locale で特定のリソースが利用可能かどうかを確認したい場合は、それらのリソースを照会する必要があります。

この問題を解決するには、リソース ディレクトリ内の「widget_」という名前のすべてのファイルを繰り返し処理し、新しく追加されたリソース バンドルを検出します。

上記の理由からLocale.getAvailableLocales() 100% 確実ではないことに注意してください: いつの日か非標準のロケールを定義するかもしれません。ただし、いくつかの標準ロケールのみを追加する場合は、この静的メソッドを使用してシステム ロケールを反復処理し、対応するバンドルを取得できます。

于 2012-08-22T12:14:16.643 に答える
2

ファイルを一覧表示して解決します。

public class JavaApplication1 {

    public static final ArrayList<String> 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();
    }

    ...

}
于 2015-12-31T20:21:09.737 に答える
2

2 つの基本的な仮定を立てることができる場合:

1) ロケールのないデフォルトのリソース バンドルがあるか、少なくとも 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.

これにより、vfs が処理してくれるので、jar: スタイルの URL などの複雑さに対処する手間が省けます。

于 2012-08-22T12:48:56.683 に答える