Memra

Locale, NumberFormat & resource bundles

Adapting output for different regions and externalising strings for i18n.

Internationalisation basics

Locale represents a language/region combination:

Locale us      = Locale.US;                        // en_US
Locale germany = Locale.GERMANY;                   // de_DE
Locale custom  = new Locale("fr", "CA");            // fr_CA — French Canada
Locale tag     = Locale.forLanguageTag("pt-BR");    // BCP 47 tag — preferred in modern code

NumberFormat formats numbers, currencies, and percentages according to a locale:

NumberFormat nf  = NumberFormat.getNumberInstance(Locale.GERMANY);
String s         = nf.format(1_234_567.89);  // "1.234.567,89" (Germany uses . for grouping, , for decimal)

NumberFormat cf  = NumberFormat.getCurrencyInstance(Locale.US);
String money     = cf.format(9.99);          // "$9.99"

NumberFormat pf  = NumberFormat.getPercentInstance(Locale.US);
String pct       = pf.format(0.75);          // "75%"

DecimalFormat is a NumberFormat subclass for custom patterns (useful on the exam):

DecimalFormat df = new DecimalFormat("#,###.00");
df.format(1234.5);  // "1,234.50"

Resource bundles externalise user-facing strings so the same code runs in any language:

// messages_en.properties
greeting = Hello

// messages_de.properties
greeting = Hallo
ResourceBundle rb = ResourceBundle.getBundle("messages", Locale.GERMANY);
System.out.println(rb.getString("greeting"));  // Hallo

The JVM walks a search order: messages_de_DE.propertiesmessages_de.propertiesmessages.properties (the default bundle). If the specific bundle is not found, it falls back to the default.

NORMAL ~/memra/learn/java-from-zero/locale-numberformat-resourcebundle utf-8 LF