На Java как узнать, какие языки у меня есть? - программирование
Подтвердить что ты не робот

На Java как узнать, какие языки у меня есть?

У меня есть некоторые пакеты ресурсов, упакованные в мою главную банку

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());
      }
}
4b9b3361

Ответ 1

Я не думаю, что для этого есть API, потому что новые действительные локальные объекты могут быть созданы на лету:

Locale locale = new Locale("abcd");

без необходимости регистрировать его где-нибудь. И тогда вы можете использовать ресурсный пакет widget_abcd.properties без ограничений:

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

В документах java.util.Locale API:

Поскольку объект Locale является только идентификатором для региона, нет проверка достоверности выполняется при создании локали. Если ты хочешь чтобы узнать, доступны ли определенные ресурсы для Locale, construct, вы должны запросить эти ресурсы.

Чтобы решить проблему, вы все равно можете перебирать все файлы с именем "widget_" в каталоге ресурсов и открывать новые добавленные пакеты ресурсов.

Обратите внимание, что Locale.getAvailableLocales() не уверен на 100% по вышеуказанной причине: в какой-то день вы можете определить нестандартную локаль. Но если вы добавите только несколько стандартных локалей, вы можете использовать этот статический метод для перебора локалей системы и получения соответствующих пакетов.

Ответ 2

Если вы действительно упаковываете файлы ресурсов внутри своего 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, вы, по крайней мере, получите набор, содержащий ресурс по умолчанию для данного baseName.

Если у вас есть только ресурсы с такими именами, как baseName_<country>, этот метод работает отлично, потому что только те ResourceBundles будут добавлены в набор, который присутствует в вашем JAR. Он будет работать, даже если вы решите, что вам нужны отдельные ресурсы baseName_en_US и baseName_en_UK, что не является неслыханным.

Бесстыдный самозапуск: я написал ResourceBundle.Control, который принимает Charset в качестве аргумента, вы можете быть заинтересованы в нем, если хотите загрузить файлы ресурсов с кодировкой UTF-8. Он доступен в GitHub.

Ответ 3

Если вы можете сделать два основных предположения:

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 обработает это для вас.

Ответ 4

Решите это, указав файлы.

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

    ...

}