Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 260
user697750 Avatar asked Apr 07 '11 23:04

user697750


2 Answers

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

}
like image 68
Paweł Dyda Avatar answered Oct 16 '22 19:10

Paweł Dyda


Using resource bundle for localizing applications is the standard way in java. The problems of this way are:

  1. there is no compile time check of number and type of parameters required by resource.
  2. It is hard to hold files clean, e.g. there is no mechanism the helps to remove unused strings
  3. It is hard to make all texts translated to all supported languages.

etc....

The probably better internationalization mechanism is suggested by Google in their GWT. They generate class with method per string. For example if you have text Hello, {0} they will generate method String hello(String name);

So, you cannot pass neither 0 nor 2 arguments to this method. Only one.

This partially solves the second problem also. It is easier to see if method is not used in whole project. It does not solve the 3rd problem anyway.

like image 44
AlexR Avatar answered Oct 16 '22 20:10

AlexR