Translate Java .properties files
A .properties file is a bundle of key=value lines where the values hold {0} arguments for MessageFormat. KAERIS translates the values, keeps your comments and key order, and writes the file in pure ASCII so Java reads it everywhere.
How a .properties file is built
key=value, key: value or key value, comments with # or !, line continuation with a trailing backslash. Older Java versions read bundles as ISO-8859-1, so non-Latin text is written as \uXXXX, which every version reads.
# Login form login.title=Sign in to {0} login.attempts=You have {0} attempts left cart.total=Total: {0,number,currency} about.url=https\://example.com/about help.text=Need help?\nWrite to [email protected]
What to watch for in .properties translations
MessageFormat arguments
{0},{1}and typed ones like{0,number,currency}must come back whole. In the real run below{0,number,currency}came back typed; a changed or lost argument would be reported.Encoding
Output is ASCII: a German “ö” or a Japanese character is written as a
\uescape, which every Java version reads.Quotes in MessageFormat
In Java's MessageFormat a single quote starts a quoted section, so a pattern that uses arguments needs
''for an apostrophe. Check strings with apostrophes in the app after translating.Escapes and URLs
\nin a value stays a line break. A\:in a URL is written back as a plain colon, which is also valid.
A real run: translated to German and checked
A real run, 27 October 2026, nothing edited by hand: kaeris translate messages.properties --langs de with kaeris 0.2.35, 3.3 seconds, model openai/gpt-4.1-mini (the service's fallback model answered this job). Below, the German file it wrote and what kaeris check says about it.
# Generated by KAERIS i18n Tool - de # Login form login.title=Anmelden bei {0} login.attempts=Sie haben noch {0} Versuche cart.total=Gesamt: {0,number,currency} about.url=https://example.com/about help.text=Brauchen Sie Hilfe?\nSchreiben Sie an [email protected]
$ kaeris check --source messages.properties --langs de ✓ de: complete & placeholder-safe ✓ all locales complete & placeholder-safe
What KAERIS does with it
Comments and order kept
Comment lines, blank lines and the key order are re-emitted around the translated values, and a one-line header with the language is added.
Arguments counted
A lost
{0}or a changed type is found without a model.Free check for this format
The free check on /check reads this format and runs without a key or an account. The terminal command
kaeris checkreads it too: it takes all 13 formats since kaeris 0.2.35, with the same rules and nothing sent anywhere.
Run it in three steps
Install the CLI
Run
pip install kaeris.Translate the bundle
Run
kaeris translate messages.properties --langs de,ja.Check the result
Upload the source and the translated bundle on the free check page.
pip install kaeris kaeris translate src/main/resources/messages.properties --langs de,ja --verify
Questions
Does it write UTF-8 or \u escapes?
Escapes. The output file is ASCII, with non-ASCII characters written as \uXXXX.
Are my comments kept?
Yes. Comment and blank lines of the source are written back in place, and a header line naming the language is added.
Is it free?
Yes, without an account: 10,000 characters per file and up to 8 languages per run. A free API key raises the file limit to 50,000 characters. Lifetime is $79 once, on your own OpenRouter key; monthly plans start at $19. Pricing
Can I run it from the terminal or in CI?
Yes. pip install kaeris, then kaeris translate messages.properties --langs de,ja. The GitHub Action runs the same translation in a pull request. CLI docs · GitHub Action
Keep going
CLI reference · Check reference · Translate in the browser · Free check · Convert formats · Pseudo-localization
Other formats: JSON · YAML · .po · ARB · XLIFF · .strings · .xcstrings · .resx · CSV · Markdown · Fluent · Android XML