Formatting Compound Messages

If the application is intended for an international audience, we need to take the locale into consideration when formatting compound messages.

Example 18.8 illustrates formatting compound messages for different locales, where locale-sensitive data is contained in resource bundles (p. 1102). The program output shows stock information about an item according to the requested locale, showing how formatting of number, currency, date, and time is localized. A resource bundle file is created for each locale. The resource bundle for the US locale is shown in Example 18.8. The program output shows stock information for the US locale and the locale for Spain.

Example 18.8 Formatting Compound Messages

Click here to view code image

# File: StockInfoBundle.properties
pattern = Stock date: {3,time,short}, {4,date,long}\n\
          Item name: {0}\n\
          Item price: {1,number,currency}\n\
          Number of items: {2,number,integer}
item.name = Frozen pizza
item.price = 9.99

Click here to view code image

import java.text.*;
import java.time.*;
import java.util.*;
public class CompoundMessageFormatting {
  static void displayStockInfo(Locale requestedLocale) {                  // (1)
    System.out.println(“Requested Locale: ” + requestedLocale);
    // Fetch the relevant resource bundle:                                   (2)
    ResourceBundle bundle =
        ResourceBundle.getBundle(“resources.StockInfoBundle”, requestedLocale);
    // Create a formatter, given the pattern and the locale:                 (3)
    MessageFormat mf = new MessageFormat(bundle.getString(“pattern”),
                                                requestedLocale);
    // Argument values:                                                      (4)
    String itemName = bundle.getString(“item.name”);
    double itemPrice = Double.parseDouble(bundle.getString(“item.price”));
    int numOfItems = 1234;
    Date timeOnly = ConvertToLegacyDate.ltToDate(LocalTime.of(14,30));
    Date dateOnly = ConvertToLegacyDate.ldToDate(LocalDate.of(2021,3,1));
    // Create argument array:                                                (5)
    Object[] messageArguments = {
        itemName,       // {0}
        itemPrice,      // {1,number,currency}
        numOfItems,     // {2,number,integer}
        timeOnly,       // {3,time,short}
        dateOnly,       // {4,date,long}
    };
    // Apply the formatter to the arguments:                                 (6)
    String result = mf.format(messageArguments);
    System.out.println(result);
  }
  public static void main(String[] args) {
    displayStockInfo(Locale.US);
    System.out.println();
    displayStockInfo(new Locale(“es”, “ES”));
    System.out.println();
  }
}

Output from the program:

Click here to view code image

Requested Locale: en_US
Stock date: 2:30 PM, March 1, 2021
Item name: Frozen pizza
Item price: $9.99
Number of items: 1,234

Requested Locale: es_ES
Fecha de stock: 14:30, 1 de marzo de 2021

Nombre del árticulo: Pizza congelada
Precio del articulo: 8,99 ?
Número de artículos: 1.234

In Example 18.8, the method displayStockInfo() at (1) epitomizes the basic steps for using MessageFormat for formatting compound messages. The method is passed the requested locale for which the stock information should be displayed. It goes without saying that the stock information is printed only if the relevant resource bundle files can be found.

The MessageFormat instance created at (2) is locale-specific. The pattern is read from the resource bundle. It is composed of several lines, and appropriate format elements for each kind of value in the pattern are specified, as shown in the resource bundle for the US locale. The MessageFormat instance implicitly creates the necessary formatters for type and style specified in the format elements, and applies them to the corresponding arguments.

The arguments to format are set up at (4). We convert LocalTime and LocalDate instances to Date instances. Another solution is to convert these instances to their text representation beforehand using an appropriate DateTimeFormatter. It is also possible to set specific formatters for any argument that is to be formatted. We leave the curious reader to explore these solutions for formatting compound messages.

At (5), an Object array is initialized with the arguments. Finally, at (6), the format() method is invoked on the formatter, passing the argument array. Again note that the currency delimiter for ? (euro) is a nbsp in the formatted output, as discussed earlier (p. 1116).

Keep in mind that a MessageFormat can be reused, with a new locale, a new pattern, and new arguments:

Click here to view code image

MessageFormat mf = new MessageFormat(previousPattern);
mf.setLocale(newLocale);
mf.applyPattern(newPattern);
String output = mf.format(newMessageArguments);

Leave a Reply

Your email address will not be published. Required fields are marked *