When developing applications for global audiences, it's essential to adapt them to various languages and regions. Java provides several classes and APIs for internationalization (i18n) and localization (l10n), allowing your application to present itself appropriately based on the user's locale.
The Locale
class represents a specific geographical, political, or cultural region. The most common use of Locale
is to define the language and region in which the program should operate.
The Locale
class provides several ways to create a Locale
object:
-
Using Language Code
Locale locale = new Locale("en"); // English
-
Using Language and Country Code
Locale locale = new Locale("en", "US"); // English (United States) Locale localeFR = new Locale("fr", "FR"); // French (France)
-
Using predefined constants
Locale localeCanada = Locale.CANADA; Locale localeJapan = Locale.JAPAN;
Locale locale = new Locale("fr", "FR");
System.out.println("Language: " + locale.getLanguage()); // Output: fr
System.out.println("Country: " + locale.getCountry()); // Output: FR
Java provides several tools to help developers localize their applications. The Locale
class, combined with classes like NumberFormat
, DateFormat
, and ResourceBundle
, allows developers to tailor their application's output to a particular locale.
Java provides NumberFormat
for formatting numbers according to a specific locale:
double number = 12345.67;
NumberFormat nf = NumberFormat.getInstance(Locale.FRANCE);
String formattedNumber = nf.format(number); // 12 345,67 in French
System.out.println(formattedNumber);
You can format dates using DateTimeFormatter
with LocalDateTime
:
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class DateFormattingExample {
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter germanFormatter = DateTimeFormatter.ofPattern("dd MMMM yyyy, HH:mm", Locale.GERMANY);
String formattedDateGermany = now.format(germanFormatter);
System.out.println("Formatted Date (Germany): " + formattedDateGermany);
}
}
The ResourceBundle
class allows you to define locale-specific resources, such as text strings, that can be dynamically loaded based on the user's locale.
- Create a properties file for each locale. For example, for English and French, create the following files:
-
messages_en_US.properties:
greeting = Hello farewell = Goodbye
-
messages_fr_FR.properties:
greeting = Bonjour farewell = Au revoir
-
Access Resource Bundles in Java:
import java.util.Locale; import java.util.ResourceBundle; public class LocalizationExample { public static void main(String[] args) { Locale enLocale = new Locale("en", "US"); Locale frLocale = new Locale("fr", "FR"); ResourceBundle bundleEn = ResourceBundle.getBundle("messages", enLocale); ResourceBundle bundleFr = ResourceBundle.getBundle("messages", frLocale); System.out.println("English Greeting: " + bundleEn.getString("greeting")); System.out.println("French Greeting: " + bundleFr.getString("greeting")); } }
Output:
English Greeting: Hello French Greeting: Bonjour
If a specific locale resource bundle is not found, Java falls back to the default resource bundle.
For example, if you request a bundle for "es_ES"
(Spanish), and no "messages_es_ES.properties"
exists, it will fall back to the default "messages.properties"
file.
Let's create a complete example that uses the Locale, ResourceBundle, and NumberFormat
for localization.
import java.text.NumberFormat;
import java.util.Locale;
import java.util.ResourceBundle;
public class InternationalizationDemo {
public static void main(String[] args) {
// Define different locales
Locale usLocale = new Locale("en", "US");
Locale franceLocale = new Locale("fr", "FR");
// Get the resource bundles for each locale
ResourceBundle usBundle = ResourceBundle.getBundle("messages", usLocale);
ResourceBundle frBundle = ResourceBundle.getBundle("messages", franceLocale);
// Retrieve localized messages
System.out.println(usLocale.getDisplayLanguage() + " greeting: " + usBundle.getString("greeting"));
System.out.println(franceLocale.getDisplayLanguage() + " greeting: " + frBundle.getString("greeting"));
// Formatting numbers in different locales
double price = 12345.67;
NumberFormat usCurrencyFormat = NumberFormat.getCurrencyInstance(usLocale);
NumberFormat frCurrencyFormat = NumberFormat.getCurrencyInstance(franceLocale);
System.out.println("Price in US: " + usCurrencyFormat.format(price));
System.out.println("Price in France: " + frCurrencyFormat.format(price));
}
}
-
messages_en_US.properties:
greeting = Hello
-
messages_fr_FR.properties:
greeting = Bonjour
-
Output:
English greeting: Hello French greeting: Bonjour Price in US: $12,345.67 Price in France: 12 345,67 €
Java’s Locale
, ResourceBundle
, and formatting classes provide robust support for creating internationalized applications. By using these tools, you can easily customize your application’s behavior for different languages, countries, and regions.