Question

I'm trying to understand more about Java's MessageFormat utilities, and in examples in our codebase and elsewhere I see both {0} and {0,number,integer} being used for numbers, but I'm not sure which, if either, is preferable.

A quick test printing the differences:

import java.text.MessageFormat;
import java.text.NumberFormat;
import java.util.Locale;

public class MessageFormatTest
{
    public static void main(String[] args){
        MessageFormat simpleChoiceTest = new MessageFormat("{0}");
        MessageFormat explicitChoiceTest = new MessageFormat("{0,number,integer}");
        int[] set = new int[]{0,1,4,5,6,10,10000,24345};
        Locale[] locs = new Locale[]{Locale.US,Locale.UK,Locale.FRANCE,Locale.GERMANY};
        for(Locale loc : locs){
            simpleChoiceTest.setLocale(loc);
            explicitChoiceTest.setLocale(loc);
            for(int i : set){
                String simple = simpleChoiceTest.format(new Object[]{i});
                String explicit = explicitChoiceTest.format(new Object[]{i});
                if(!simple.equals(explicit)){
                    System.out.println(loc+" - "+i+":\t"+simple+
                        "\t"+NumberFormat.getInstance(loc).format(i));
                    System.out.println(loc+" - "+i+":\t"+explicit+
                        "\t"+NumberFormat.getIntegerInstance(loc).format(i));
                }
            }
        }
    }
}

Outputs:

fr_FR - 10000:  10 000  10 000
fr_FR - 10000:  10,000  10 000
fr_FR - 24345:  24 345  24 345
fr_FR - 24345:  24,345  24 345
de_DE - 10000:  10.000  10.000
de_DE - 10000:  10,000  10.000
de_DE - 24345:  24.345  24.345
de_DE - 24345:  24,345  24.345

Which surprised me, if anything I would have expected the {0} to not do anything to the number, and for {0,number,integer} to localize it properly. Instead, both get localized, but it seems the explicit form always uses en_US localization.

According to the linked documentation, {0} gets put through NumberFormat.getInstance(getLocale()) while while the explicit form uses NumberFormat.getIntegerInstance(getLocale()). Yet when I call those directly (the last column in the output) both seem identical, and both localize correctly.

What am I missing here?

Was it helpful?

Solution

You are right. When you use "MessageFormat("{0,number,integer}")", formatter uses default locale(en_US) at the time of initialization and numbers are marked to use Integer format in default locale(en_US) as the code below is executed during the initialization time itself.

// this method is internally called at the time of initialization
MessageFormat.makeFormat()
// line below uses default locale if locale is not
// supplied at initialization (constructor argument) 
newFormat = NumberFormat.getIntegerInstance(locale);

Since you are setting the locale afterwards, there is no impact on the format pattern assigned to numbers. If you want to use the desire locale in the format for numbers, please use the locale argument at the time of initialization itself e.g. below:

MessageFormat test = new MessageFormat("{0,number,integer}", Locale.FRANCE);

OTHER TIPS

In my opinion, this is a Java bug (the interface is wrong) or a documentation problem. You should open a new issue at Oracle to correct that.

As Yogendra Singh, said the instance of the formatter (DecimalFormat) is created when the MessageFormat constructor.

MessageFormat simpleChoiceTest = new MessageFormat("{0}");
System.out.println(simpleChoiceTest.getFormatsByArgumentIndex()[0]);
//Prints null
MessageFormat explicitChoiceTest = new MessageFormat("{0,number,currency}");
System.out.println(explicitChoiceTest.getFormatsByArgumentIndex()[0]);
//Prints java.text.DecimalFormat@67500

When the MessageFormat.setLocale is called it does not change the locale of its internal formatters.

At least the documentation should be changed to reflect this issue.

That is my java version: java version "1.7.0_07" Java(TM) SE Runtime Environment (build 1.7.0_07-b11)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top