Internationalization and Localization in Java
Internationalization is the work of designing a program so that it can be adapted to different languages and regions without changing its code. Localization is the work of actually adapting it for one specific language and region: translating the text and applying that region's formats. The two words are long, so they are usually written I18N and L10N: the first letter, the number of letters in between (18 and 10), and the last letter. A program that is internationalized well can gain a new language by adding files, with no recompiling. In this lesson, you will learn what differs between regions, why it matters, and which Java classes do the work.
Internationalization vs Localization
| Point | Internationalization (I18N) | Localization (L10N) |
|---|---|---|
| What it is | Making the program able to support many locales | Adding support for one particular locale |
| Who does it | Developers | Translators and regional experts |
| When | Once, in the design and code | Once for each language or region |
| Example | Reading every message from a resource bundle; formatting every date with the user's locale | Writing the German message file; checking German date and number formats |
What Changes Between Regions
Translation is only part of it. The same date, number and price are written differently around the world.
Let's see an example that prints one number and one date for six locales:
import java.text.NumberFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.Locale;
public class Intro {
public static void main(String[] args) {
double amount = 1234567.89;
LocalDate date = LocalDate.of(2026, 11, 13);
Locale[] locales = {
Locale.US, Locale.UK, Locale.GERMANY, Locale.FRANCE,
Locale.of("hi", "IN"), Locale.JAPAN
};
for (Locale locale : locales) {
String number = NumberFormat.getNumberInstance(locale)
.format(amount);
String day = date.format(DateTimeFormatter
.ofLocalizedDate(FormatStyle.MEDIUM).withLocale(locale));
System.out.println(locale.toLanguageTag() + " "
+ number + " | " + day);
}
}
}en-US 1,234,567.89 | Nov 13, 2026
en-GB 1,234,567.89 | 13 Nov 2026
de-DE 1.234.567,89 | 13.11.2026
fr-FR 1 234 567,89 | 13 nov. 2026
hi-IN 1,234,567.89 | 13 नव॰ 2026
ja-JP 1,234,567.89 | 2026/11/13Explanation: The number 1234567.89 uses a comma to group thousands in the US and a period in Germany, where the comma marks the decimals. France groups with a narrow space. The date 13 November 2026 puts the month first in the US and the day first in most other places, and Japan starts with the year. Hindi shows the month name in its own script. Not one of these was coded by hand: the program passed a Locale to the formatter and Java supplied the rules.
| What varies | Examples |
|---|---|
| Language of messages | "Hello", "Hallo", "Bonjour" |
| Date order and month names | 11/13/2026, 13.11.2026, 2026/11/13 |
| Time | 5:05 PM vs 17:05 |
| Number separators | 1,234.5 vs 1.234,5 |
| Currency symbol and position | $1,234.50 vs 1.234,50 € |
| Sorting order and upper/lower case rules | Letters such as ä, ñ, i and ı |
| First day of the week | Sunday or Monday |
| Text direction | Left to right, or right to left (Arabic, Hebrew) |
The Java Classes
| Class | Purpose | Lesson |
|---|---|---|
Locale | Identifies a language and region | "Locale Class in Java" |
ResourceBundle | Holds translated messages, one set per locale | "ResourceBundle Class in Java" |
MessageFormat | Fills values into a translated sentence | "ResourceBundle Class in Java" |
DateTimeFormatter | Formats dates and times for a locale | "Internationalization with Dates in Java", "Internationalization with Time in Java" |
NumberFormat | Formats numbers and percentages | "Internationalization with Numbers in Java" |
NumberFormat (currency), Currency | Formats money | "Internationalization with Currency in Java" |
Collator | Sorts text by a language's rules | (see the tip below) |
Java gets its regional data from the Unicode CLDR (Common Locale Data Repository), which the JDK includes. That is why the exact output can change slightly between JDK versions as the data is updated.
Steps to Internationalize a Program
- Move every user-visible string out of the code into resource bundles.
- Format every date, time, number and amount with a locale-aware formatter.
- Decide where the locale comes from: the user's setting, the browser's language, or the system default.
- Store data in a neutral form (ISO dates, plain numbers, UTC times) and format only when displaying.
- Use UTF-8 everywhere so every script can be stored and shown.
Common Mistakes
Joining translated fragments into sentences. Word order differs between languages. Translate whole sentences with placeholders.
Formatting dates with fixed patterns like MM/dd/yyyy. Readers outside the US will read 03/04 as 3 April.
Relying on the server's default locale. A web server serves many users; use each user's locale.
Storing formatted values. Store the raw value; format when showing it.
Interview Corner
What is the difference between internationalization and localization?
Internationalization (I18N) is designing software so it can be adapted to various languages and regions without engineering changes: externalizing text, using locale-aware formatting, and supporting Unicode. Localization (L10N) is adapting the internationalized software for a specific locale by adding translations and regional formats. Internationalization is done once by developers; localization is done for each target locale. In Java, the main tools are Locale, ResourceBundle, MessageFormat, NumberFormat and DateTimeFormatter.
Practice
- Easy: Add
Locale.ITALYandLocale.KOREAto the example and describe the differences you see. - Harder: List five places in a program you have written where text or a format is hard-coded and would need to change for another country.
Key Takeaways
Was this tutorial helpful?