Skip to content

Lesson 01 · Locale & Resource Bundles

Objectives

After this lesson you will be able to:

  • Create and read a Locale.
  • Load a ResourceBundle (property or class based).
  • Explain the lookup and fallback algorithm.

Locale

A Locale identifies a language + region (and optionally script/variant). Build one with the builder, the constants, or forLanguageTag.

java
Locale fr = Locale.FRANCE;                  // language fr, country FR
Locale us = Locale.US;                      // en_US
Locale custom = new Locale.Builder()
        .setLanguage("en").setRegion("GB").build();
Locale tag = Locale.forLanguageTag("pt-BR");
fr.getLanguage();   // "fr"
fr.getCountry();    // "FR"

Gotcha

The language code is lowercase, the country code UPPERCASE (en_US, fr_CA). The legacy constructor new Locale("en", "US") still works but the Locale.Builder / forLanguageTag are preferred.

ResourceBundle

A ResourceBundle maps keys to locale-specific values. The common kind is a property bundle: a set of .properties files sharing a base name.

messages.properties           # default (fallback)
messages_fr.properties        # French
messages_fr_CA.properties     # French (Canada)
properties
# messages_fr.properties
greeting=Bonjour
java
ResourceBundle rb = ResourceBundle.getBundle("messages", Locale.FRANCE);
String hello = rb.getString("greeting");    // "Bonjour"

A class bundle instead subclasses ListResourceBundle and returns an Object[][] of key/value pairs — useful for non-string values.

Lookup and fallback

For getBundle("messages", fr_CA), Java searches most-specific to least, and falls back to the default locale's bundles, then the base bundle:

messages_fr_CA  →  messages_fr  →  messages_<defaultLocale...>  →  messages   (base)

The first bundle that contains the key wins; a missing key throws MissingResourceException. Within a found bundle, keys also fall back up the chain.

Exam trap

Bundle selection picks the most specific file available, but key lookup then walks up the parent chain — so messages_fr_CA automatically inherits keys from messages_fr and the base messages. A key missing from all levels throws MissingResourceException (unchecked).

SDET note

A ListResourceBundle subclass needs no external files, which makes it ideal for deterministic tests of localization logic — you control the data in code instead of depending on classpath resources.

Key Takeaways

  • A Locale is language (lowercase) + country (UPPERCASE); prefer Locale.Builder / forLanguageTag over the legacy constructor.
  • ResourceBundle.getBundle(base, locale) loads .properties (property bundle) or a ListResourceBundle subclass (class bundle).
  • Selection is most-specific-first with fallback to the default locale then the base; key lookup walks up the parent chain.
  • A key absent from every level throws MissingResourceException.

Lesson Quiz

Lesson Quiz · Locale & Resource Bundles0 / 4
  1. What is the correct case for the locale en_US?

    • AEN_us
    • Ben_US (lowercase language, UPPERCASE country)
    • CEN_US
    • Den_us
  2. For getBundle("m", fr_CA), which is searched FIRST?

    • Am (base)
    • Bm_fr
    • Cm_fr_CA
    • Dm_en
  3. A key exists only in messages.properties (base). You load messages_fr. Does getString find it?

    • ANo — MissingResourceException
    • BYes — key lookup falls back up to the base
    • COnly in French
    • DOnly if reloaded
  4. A key missing from every bundle level throws...

    • AIOException
    • BMissingResourceException
    • Cnull
    • DNoSuchElementException

Next: Formatting & Parsing. Run the matching code in labs/src/main/java/com/jse21/m09_localization/.