How to Internationalize and Localize Java Applications

Learn how to set up Java internationalization, translate .properties files, and automate your Java localization workflow.

How Java Internationalization Works

Java’s i18n system is built around two things: 

  • .properties files that store your translated strings
  • The ResourceBundle class that loads the right file at runtime based on the user’s locale

When your app runs, ResourceBundle checks the user’s locale and loads the matching file automatically. If a translation is missing, it falls back to the default file so nothing breaks.

Calling a string in code is straightforward:

ResourceBundle bundle = ResourceBundle.getBundle("messages", Locale.FRENCH);
String greeting = bundle.getString("welcome.message");

That’s the whole mechanism. The rest of localization work happens in the .properties files themselves, which is why structuring them correctly matters.

Setting Up Your Resource Bundle

A resource bundle is a set of .properties files that share a common base name. The base name is the part of the filename before the locale suffix, and it’s what ResourceBundle.getBundle() uses to find the right file at runtime.

messages.properties         # default (usually English)
messages_fr.properties      # French
messages_de.properties      # German
messages_es.properties      # Spanish

Here, messages is the base name. You can name it anything, but it should reflect what the file contains. Larger applications often use multiple resource bundles to keep things organized:

src/main/resources/
  messages.properties
  errors.properties
  emails.properties

Java expects a specific naming pattern: basename_language.properties or basename_language_COUNTRY.properties for regional variants.

messages_fr.properties       # French
messages_fr_CA.properties    # French (Canada)
messages_pt_BR.properties    # Portuguese (Brazil)

Language codes follow ISO 639-1 and country codes follow ISO 3166-1. Using the wrong format means ResourceBundle won’t find the file at runtime.

Structuring Java .properties Files

Each line in a .properties file is a key-value pair separated by =.

welcome.message = Welcome to our application
error.login.invalid_credentials = Invalid username or password
form.submit.button = Submit

Besides using key-value pairs, it’s important to know that how you write your source file directly affects the quality of your translations. Certain best practices always apply, no matter if you’re translating manually or using an AI translation tool like PTC.

1

Use Clear, Descriptive Keys

Keys should make it obvious where and how a string is used. This matters when you’re managing hundreds of strings across multiple files.

Incorrect usage of keys:

btn1 = Submit 
msg2 = Error

Correct usage of keys:

form.submit.button = Submit 
error.login.invalid_credentials = Invalid username or password

2

Use Placeholders for Dynamic Content

Write the full sentence in your .properties file and use numbered placeholders for variable content instead of concatenating strings in code.

Incorrect (in code):

"Hello, " + username + "! You have " + count + " new messages." 

Correct  (in .properties file):

dashboard.greeting = Hello, {0}! You have {1} new messages.

Many languages change word order and agreement rules, so splitting sentences into fragments makes correct translation impossible.

3

Handle Pluralization with ChoiceFormat

Some strings change depending on a numeric value. Instead of writing separate keys for singular and plural, use a ChoiceFormat pattern directly in your .properties file:

messages.count = {0,choice,0#no messages|1#one message|1<{0} messages}

Java processes this pattern at runtime and returns the right form based on the value passed in.

4

Escape Special Characters

Characters like =, :, #, and \ have special meaning in .properties files:

  • = or :separates keys from values
  • # or ! starts a comment
  • \ introduces escape sequences (like \n for newline)

If you need to use these characters in a string, escape them with a backslash.

support.link = Visit us at https\://support.example.com

5

Save Files in UTF-8

Always save .properties files in UTF-8. Without it, non-ASCII characters become corrupted and translations become unreadable.

6

Keep All User-facing Text Out of Your Code

If a string is visible to users, it belongs in a .properties file. Hardcoded strings won’t get translated, and your app will end up showing a mix of languages.

Other Java Localization Considerations

Not everything that needs localizing lives in a .properties file. Dates, times, numbers, and currency values are formatted in code at runtime, and getting them right matters just as much as your translated strings.

Java provides built-in classes for this:

  • DateTimeFormatter for locale-aware date and time formatting
  • NumberFormat for numbers, percentages, and currency values

Since this guide focuses on .properties files and their translation, we won’t cover these in depth here. The official Java documentation for DateTimeFormatter and NumberFormat is a good place to start.

Translating Java .properties Files

As the examples above show, properly internationalizing a Java app takes effort. Getting your resource bundles structured correctly, handling placeholders, and managing pluralization all have to be right before translation can even begin. PTC is built to take it from there.

Why PTC?

PTC is an AI translation system designed for software teams. It understands your product, your terminology, and your audience. With PTC you get:

  • Context-aware translations — PTC reads your file structure and descriptions to translate strings accurately, not literally
  • Placeholder and format preservation — your {0}, {1} patterns and ChoiceFormat strings come back intact
  • Pay-As-You-Go pricing — no monthly subscription fees, and a pricing calculator so you know your costs before you commit
  • Git and CI/CD integration — connect your repository and keep translations in sync automatically
  • Free trial — 20,000 words into two languages, no credit card required

Getting Started

  1. Sign up for a free trial — no credit card needed
  2. Upload your source .properties file and set your output paths
  3. Select your target languages
  4. Add a short description of your application and its audience
  5. Download your translated files from the Resource files tab and add them to src/main/resources

The whole setup takes about 5 minutes. For a full walkthrough, see the Getting Started Guide.

A Continuous Translation Workflow for Java Projects

Translating your .properties file once is straightforward. What about keeping translations up to date as your application evolves? Every time you add a new string, update existing copy, or remove a key, your translated files need to reflect that change.

Doing this manually means exporting files, sending them out for translation, waiting, and re-integrating them every time, which is why most teams eventually automate it.

PTC offers two ways to automate the translation process:

Git Integration

Connect your GitHub, GitLab, or Bitbucket repository to PTC and it will monitor your source .properties file for changes. When a string is added or updated, PTC automatically translates it and delivers the updated translation files back via a pull request. Your translations stay in sync without any manual steps.

CI/CD Integration

If you prefer to keep everything inside your existing build process, PTC’s API lets you upload your source file and retrieve translations as part of your CI job. Every build produces up-to-date translations automatically.

Both approaches mean that adding a new language later is just a configuration change, not a new manual process.

Ready to Localize Your Java App?

Your .properties files are the foundation of your Java localization workflow. Get the structure right, keep your translations in sync, and your app can support new languages without slowing down your release cycle.

If you haven’t tried PTC yet, the free trial is a good place to start. 20,000 words, two languages, no credit card required.

Scroll to Top