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:
.propertiesfiles that store your translated strings- The
ResourceBundleclass 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.propertiesJava 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 = SubmitBesides 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 = ErrorCorrect usage of keys:
form.submit.button = Submit
error.login.invalid_credentials = Invalid username or password2
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\nfor newline)
If you need to use these characters in a string, escape them with a backslash.
support.link = Visit us at https\://support.example.com5
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:
DateTimeFormatterfor locale-aware date and time formattingNumberFormatfor 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
Once your source file is ready, you have a few options for getting it translated. The right choice depends on your budget, timeline, and how much automation you need.
| Option | Turnaround | Cost | Maintenance Needs |
| Professional translators | Days to weeks | High | Manual export, send, receive, and re-integrate every update |
| Translation scripts | Minutes | Low | Requires review – placeholders can break, context for translations may be wrong |
| AI translation (like PTC) | Minutes | Low | Context-aware translations sync automatically via Git or CI/CD |
With PTC, human-quality translations are ready in minutes, and there’s no subscription — you only pay for what you translate. To get started, you get 20,000 words translated into two languages for free, no credit card required.
After signing up, a setup wizard walks you through the basics: a brief description of your application, your target languages, and your .properties file. The whole process takes about 5 minutes. For a full walkthrough, check out our getting started guide.
After PTC finishes translating, go to the Resource Files tab and download a ZIP file with the translated .properties files.
Add these files back into your project’s src/main/resources folder, alongside your original source file. At runtime, ResourceBundle automatically picks the correct file based on the user’s locale. You don’t need to change your code.
Keeping Java .properties Translations in Sync
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.


Java Translation with AI
Get context-aware translations in minutes
Upload files, or automate via API or Git integration