2

i18nからプロパティ ファイルを取得しようとしていますBuildPath。を取得しようとしている場合はPropertiesFileResourceBundle.getBundleがスローされjava.util.MissingResourceExceptionます。i18n外部からファイルをロードする方法はありBuildPathますが、ロケールを検出するのは快適ですか?

編集:

Paweł Dydaの助けを借りて作成できたソリューションを次に示します。多分誰かがそれを必要とするでしょう。おそらくいくつかの改善が行われる可能性がありますが、うまくいきます;)

import java.io.File;
import java.io.FileNotFoundException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.List;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle.Control;

import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.io.FilenameUtils;
import org.apache.log4j.Logger;

public class GlobalConfigurationProvider {

    Logger logger = Logger.getLogger(GlobalConfigurationProvider.class);

    private static GlobalConfigurationProvider instance;

    PropertiesConfiguration i18n;


    private GlobalConfigurationProvider() {
        String path = GlobalConfigurationProvider.class.getProtectionDomain().getCodeSource().getLocation().getPath();
        String decodedPath = "";
        try {
            decodedPath = URLDecoder.decode(path, "UTF-8");
            // This ugly thing is needed to get the correct
            // Path
            File f = new File(decodedPath);
            f = f.getParentFile().getParentFile();
            decodedPath = f.getAbsolutePath();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            this.logger.error("Failed to decode the Jar path", e);
        }
        this.logger.debug("The Path of the jar is: " + decodedPath);

        String configFolder = FilenameUtils.concat(decodedPath, "cfg");
        String i18nFolder = FilenameUtils.concat(configFolder, "i18n");
        File i18nFile = null;
        try {
            i18nFile = this.getFileForLocation(new File(i18nFolder), Locale.getDefault());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            this.logger.error("Can't find the LocaleFile", e);
        }
        if (!i18nFile.exists()) {
            // If this can't be found something is wrong
            i18nFile = new File(i18nFolder, "eng.i18n");
            if (!i18nFile.exists()) {
                this.logger.error("Can't find the i18n File at the Location: " + i18nFile.getAbsolutePath());
            }
        }

        this.logger.debug("The Path to the i18n File is: " + i18nFile);

        try {
            this.i18n = new PropertiesConfiguration(i18nFile);
        } catch (ConfigurationException e) {
            this.logger.error("Couldn't Initialize the i18nPropertiesFile", e);
        }
    }

    private File getFileForLocation(File i18nFolder, Locale locale) throws FileNotFoundException {
        Control control = Control.getControl(Control.FORMAT_DEFAULT);
        List<Locale> locales = control.getCandidateLocales(this.getBaseName(), locale);
        File f = null;
        for (Locale l : locales) {
            String i18nBundleName = control.toBundleName(this.getBaseName(), l);
            String i18nFileName = control.toResourceName(i18nBundleName, "properties");
            f = new File(i18nFolder, i18nFileName);
            this.logger.debug("Looking for the i18n File at: " + f);
            if (f.exists()) {
                return f;
            }
        }
        // Last try for a File that should exist
        if (!locale.equals(Locale.US)) {
            return this.getFileForLocation(i18nFolder, Locale.US);
        }
        throw new FileNotFoundException("Can't find any i18n Files in the Folder " + i18nFolder.getAbsolutePath());
    }

    private String getBaseName() {
        // TODO: Get this from the Settings later
        return "messages";
    }

    public static GlobalConfigurationProvider getInstance() {
        if (GlobalConfigurationProvider.instance == null) {
            GlobalConfigurationProvider.instance = new GlobalConfigurationProvider();
        }
        return GlobalConfigurationProvider.instance;
    }

    public String getI18nString(String key) {
        try {
            return this.i18n.getString(key);
        } catch (MissingResourceException e) {
            return '!' + key + '!';
        }
    }

}
4

1 に答える 1

2

もちろん、それを行う方法はあります。とにかく、あなたの問題は、ロードしようとしているリソースへの間違ったパスだと思います。

それにもかかわらず、ロケール フォールバック メカニズムを使用して非常に特定のリソースをロードする方法を探していることは確かです。それはできます。ResourceBundle.Controlクラスを確認してください。たとえば、フォールバック ロケールのリストを取得できます。

Control control = Control.getControl(Control.FORMAT_DEFAULT);
List<Locale> locales = control.getCandidateLocales("messages",
           Locale.forLanguageTag("zh-TW"));

そこから、探しているリソース ファイルの名前を実際に作成できます。

for (Locale locale : locales) {
      String bundleName = control.toBundleName("messages", locale);
      String resourceName = control.toResourceName(bundleName, "properties");
      // break if resource under given name exist
}

次に、何らかの方法でリソースをロードする必要があります。ClassLoader の getResourceAsStream(String)を使用して を開きたい場合がありInputStreamます。最後のステップでは、実際にストリームをPropertyResourceBundleへの入力として使用できます。

ResourceBundle bundle = new PropertyResourceBundle(inputStream);

または、ではなくReaderを渡すこともできますInputStream。これには、少なくとも 1 つの利点があります。通常の ISO8859-1 ではなく、プロパティ ファイルを UTF-8 でエンコードすることを実際に許可することができます。

于 2012-11-16T16:58:10.543 に答える