Search code examples
javalocalizationinternationalizationpropertiespreferences

Java Preferences and Internationalization (i18n)


The Java tutorials recommend using the Preferences API over Properties files. Properties files and ResourceBundles are the recommended way to handle Internalization requirements in applications.

I am considering using both for a desktop application that will display preferences in a locale specific way.

Can anyone point out problems with this approach?

Maybe I should just use Properties files period?


Solution

  • I am considering using both for a desktop application that will display preferences in a locale specific way.

    OK, so what you want is translated configuration file in form of:

    some_translated_key=some_value
    

    Well, unless you want to support MUI at some point it should not be a big deal. However, if you do, so that different users on the same computer could use different languages, or user might be able to switch language, you would have troubles in matching key to a property. You would have to scan all translations while reading the key, and you would surely end up with multiple entries for the same key. How to resolve that? Well, that's a good question.

    From my experience, configuration files should be language-independent (neutral culture) and should never be edited by hand (that is translating keys doesn't really matter).

    I thought there could be a problem with character encoding, but following code snippet works without an issue (files are UTF-8 encoded):

    public class Main {
        private static final String FILE_NAME = "i18ned.properties";
        private File propertiesFile;
        private Properties properties;
    
        public Main() {
            properties = new Properties();
            propertiesFile = new File(FILE_NAME);
            if (propertiesFile.exists()) {
                try {
                    properties.load(new BufferedReader(new FileReader(
                            propertiesFile)));
                } catch (FileNotFoundException e) {
                    // not likely, but should be logged either way
                } catch (IOException e) {
                    // logger should be used instead
                    e.printStackTrace();
                }
            }
        }
    
        public void saveProperties() {
            try {
                properties
                        .store(new BufferedWriter(new FileWriter(propertiesFile)), "");
            } catch (IOException e) {
                // oops, use logger instead
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) {
            Main main = new Main();
            main.storeSome();
            main.readSome();
        }
    
        private void readSome() {
            String highAsciiKey = "żółć";
            String value = properties.getProperty(highAsciiKey);
            System.out.println(value);
        }
    
        private void storeSome() {
            String highAsciiKey = "żółć";
            String highAsciiValue = "łąkę";
            properties.setProperty(highAsciiKey, highAsciiValue);
            saveProperties();
        }
    
    }