Why Your Java Application Should Start Speaking Human?
\n\nHave you ever wondered why the applications we use every day — from Spotify to Notion — immediately "understand" which language to speak with you? They don't read minds, they don't guess by IP address. They use internationalization (i18n).
\n\nFor a Java developer, the ability to make applications multilingual is not just a "feature," but a mandatory skill if you are targeting the global market. Imagine: you wrote a cool task management service. It took off in Russia. But as soon as you want to sell it in Germany or Japan — users will see the "Create Task" button in Russian. And they will close the tab. Sad, right?
\n\nIn this article, we won't just talk about theory. We'll take a Java application (a very ordinary one, console or web) and step by step add support for Russian, English, and German. You will see that Java internationalization is not scary, but rather elegant. Let's go!
\n\nWhat is Internationalization and Localization? Don't Confuse Them!
\n\nThese concepts are often mixed up. Let's dot the i's.
\n\n- \n
- Internationalization (i18n) is the process of designing an application so that it can be adapted to different languages and regions without changing the code. You lay down "hooks" for translation. \n
- Localization (l10n) is the actual filling of these "hooks" with specific translations, date formats, currencies, and sorting rules for a particular country. \n
In Java, the classes from the java.util package are responsible for internationalization: Locale and ResourceBundle. Remember them — they are your best friends.
Step 1. Getting to Know Locale — the Heart of Internationalization
\n\nThe Locale class represents a specific region (language + country). For example:
- \n
Locale.US— English (USA) \n Locale.GERMANY— German (Germany) \n new Locale("ru", "RU")— Russian (Russia) \n
Locale is used to select the correct translation of strings, formatting of numbers, dates, currencies. Without it, internationalization is impossible.
\n\nHow to get the current locale?
\n\nimport java.util.Locale;\n\npublic class Main {\n public static void main(String[] args) {\n // Default locale (usually matches the system one)\n Locale defaultLocale = Locale.getDefault();\n System.out.println("Current locale: " + defaultLocale);\n\n // Available locales in the JVM\n Locale[] available = Locale.getAvailableLocales();\n System.out.println("Total available: " + available.length);\n }\n}\n\nThe output could be, for example: Current locale: ru_RU. But we won't rely on the system locale — in a web application, it is usually passed by the user's browser.
Step 2. ResourceBundle — Your Translator
\n\nNow for the interesting part: how to store translations? In Java, property files (.properties) are used for this. Each file is a set of key=value pairs.
Creating translation files
\n\nCreate three files in the src/main/resources directory (or simply in the source folder):
1. Messages.properties (default language — English)
\ngreeting=Hello, {0}!\nfarewell=Goodbye!\napp.title=Task Manager\n\n2. Messages_ru_RU.properties (Russian)
\ngreeting=Привет, {0}!\nfarewell=До свидания!\napp.title=Менеджер задач\n\n3. Messages_de_DE.properties (German)
\ngreeting=Hallo, {0}!\nfarewell=Auf Wiedersehen!\napp.title=Aufgabenverwaltung\n\nPay attention to the suffixes: _ru_RU, _de_DE. Java searches for a file using the pattern: Base