2

我正在尝试i18n从我的BuildPath. 如果您试图PropertiesFile获得. 有没有一种方法可以从外部加载文件但仍然可以轻松检测您的语言环境?ResourceBundle.getBundlejava.util.MissingResourceExceptioni18nBuildPath

编辑:

这是我在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

当然,有一些方法可以做到这一点。无论如何,我相信您的问题是您尝试加载的资源的错误路径。

Nonetheless, for sure you are looking the way to use Locale fall-back mechanism to load very specific resource. It can be done. You may want to take a look at ResourceBundle.Control class. For example you can get the list of fall-back locales:

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

From there, you can actually create names of the resource files you are looking for:

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

Then, you need to load the resource somehow - you may want to use ClassLoader's getResourceAsStream(String) to open the InputStream for you. The last step could be actually use the stream as an input to PropertyResourceBundle:

ResourceBundle bundle = new PropertyResourceBundle(inputStream);

You can alternatively pass a Reader rather than InputStream, which has at least one advantage - you may actually allow properties file to be encoded in UTF-8, rather than regular ISO8859-1.

于 2012-11-16T16:58:10.543 回答