PTC

Java-Internationalisierungs-Leitfaden: .properties-Dateien mit KI übersetzen

Richten Sie ResourceBundle ein, strukturieren Sie .properties-Dateien, übersetzen Sie diese mit KI in über 40 Sprachen und lassen Sie PTC (Private Translation Cloud) die laufende Java-App über Screenshots oder eine Browser-Erweiterung prüfen. Am Ende verfügen Sie über eine mehrsprachige JAR-Datei, die für den Versand bereit ist, wobei jede Zielsprache vor dem Release verifiziert wurde. Eine Übersicht über den eigenständigen Java-Service finden Sie unter Java-Apps mit KI übersetzen.

ResourceBundle lädt zur Laufzeit die richtige .properties-Datei

Das i18n-System von Java basiert auf zwei Komponenten: .properties-Dateien, in denen Ihre übersetzten Strings gespeichert sind, und der Klasse ResourceBundle, die zur Laufzeit basierend auf der Locale des Benutzers die richtige Datei lädt.

Wenn Ihre App ausgeführt wird, prüft ResourceBundle die Locale des Benutzers und lädt automatisch die passende Datei. Falls eine Übersetzung fehlt, wird geräuschlos auf die Standarddatei zurückgegriffen. Es kommt zu keinem Abbruch, aber fehlende Übersetzungen werden auch nicht als Fehler angezeigt. Aufruf eines Strings im Code:

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

Das ist der gesamte Mechanismus. Der Rest der Lokalisierungsarbeit findet in den .properties-Dateien selbst statt, weshalb eine korrekte Strukturierung entscheidend ist.

Richten Sie Ihr Resource Bundle mit messages_{locale}.properties ein

Ein Resource Bundle ist ein Satz von .properties-Dateien, die einen gemeinsamen Basisnamen haben. Der Basisname ist der Teil des Dateinamens vor dem Locale-Suffix. Er wird von ResourceBundle.getBundle() verwendet, um zur Laufzeit die richtige Datei zu finden.

src/main/resources/
  messages.properties        # default (usually English)
  messages_fr.properties     # French
  messages_de.properties     # German
  messages_es.properties     # Spanish
  messages_ja.properties     # Japanese
  messages_zh_CN.properties  # Simplified Chinese (note underscore, not hyphen)

Größere Anwendungen verwenden oft mehrere Resource Bundles, um die Übersicht zu behalten:

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

Java erwartet ein bestimmtes Benennungsmuster: basename_language.properties oder basename_language_COUNTRY.properties für regionale Varianten:

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

Sprachcodes folgen ISO 639-1. Ländercodes folgen ISO 3166-1. Die Verwendung des falschen Formats führt dazu, dass ResourceBundle die Datei zur Laufzeit nicht findet.

Laden und verwenden Sie das Bundle im Code, mit MessageFormat für die Platzhalter-Ersetzung:

import java.util.Locale;
import java.util.ResourceBundle;
import java.text.MessageFormat;

public class App {
    public static void main(String[] args) {
        Locale locale = Locale.of("es");
        ResourceBundle messages = ResourceBundle.getBundle("messages", locale);

        String welcome = MessageFormat.format(
            messages.getString("app.welcome"),
            "My App"
        );
        System.out.println(welcome);
        // -> "Bienvenido a My App"
    }
}

Für einfache Strings ohne Platzhalter ist messages.getString("key") ausreichend.

Sechs Konventionen, die Ihre .properties-Dateien bereit für die Übersetzung machen

Jede Zeile ist ein Schlüssel-Wert-Paar, getrennt durch =. Wie Sie Ihre Quelldatei schreiben, beeinflusst direkt die Qualität Ihrer Übersetzungen. Dies gilt unabhängig davon, ob Sie manuell oder mit einem KI-Tool wie PTC übersetzen.

1. Verwenden Sie klare, beschreibende Schlüssel, die den Ort des Strings benennen

Schlüssel sollten offensichtlich machen, wo und wie ein String verwendet wird. Dies ist wichtig, wenn Sie hunderte von Strings über mehrere Dateien hinweg verwalten.

# Incorrect
btn1 = Submit
msg2 = Error

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

Ändern Sie einen Schlüssel niemals, nachdem die Übersetzung begonnen hat. Das Ändern eines Schlüssels führt dazu, dass die vorhandene Übersetzung nicht mehr zugeordnet werden kann.

2. Verwenden Sie nummerierte Platzhalter statt String-Verkettung im Code

Schreiben Sie den vollständigen Satz in Ihre .properties-Datei und verwenden Sie nummerierte Platzhalter für variablen Inhalt, anstatt Strings im Code zu verketten.

// Incorrect (in code)
"Hello, " + username + "! You have " + count + " new messages."
# Correct (in .properties)
dashboard.greeting = Hello, {0}! You have {1} new messages.

In vielen Sprachen ändern sich die Wortreihenfolge und die Kongruenzregeln. Das Aufteilen von Sätzen in Fragmente macht eine korrekte Übersetzung unmöglich.

3. Behandeln Sie die Pluralisierung mit ChoiceFormat, ICU oder Suffix-Schlüsseln

Für die Pluralisierung im Standard-Java funktioniert ChoiceFormat direkt innerhalb von .properties:

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

Java verarbeitet dies zur Laufzeit und gibt die richtige Form basierend auf dem übergebenen Wert zurück. ChoiceFormat ist einfach, aber auf den Abgleich von numerischen Bereichen beschränkt. Es unterstützt nativ keine komplexen Pluralregeln.

Für sprachabhängige Plurale (Polnisch mit one/few/many/other, Arabisch mit sechs Formen) verwenden Sie das MessageFormat von ICU4J:

String pattern = "{0, plural, one {# note} other {# notes}}";
String result = new com.ibm.icu.text.MessageFormat(pattern, locale).format(new Object[]{count});

Oder kodieren Sie Plurale als separate Schlüssel mit konventionellen Suffixen, damit PTC die richtigen Pluralkategorien pro Sprache generieren kann:

notes.count.zero=No notes yet
notes.count.one={0} note
notes.count.other={0} notes

PTC generiert die richtigen Pluralkategorien pro Zielsprache. Polnisch erhält one / few / many / other. Japanisch erhält nur other.

4. Maskieren Sie =, :, # und \ mit einem Backslash

Zeichen wie =, :, # und \ haben in .properties-Dateien eine besondere Bedeutung:

  • = oder : trennt Schlüssel von Werten.
  • # oder ! leitet einen Kommentar ein.
  • \ leitet Escape-Sequenzen ein (wie \n für einen Zeilenumbruch).

Maskieren Sie diese bei Bedarf mit einem Backslash:

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

5. Speichern Sie .properties-Dateien als UTF-8

Speichern Sie .properties-Dateien immer in UTF-8. Ohne UTF-8 werden Nicht-ASCII-Zeichen fehlerhaft dargestellt und Übersetzungen unlesbar. Historisch gesehen waren Java-.properties-Dateien in ISO-8859-1 kodiert, was \uXXXX-Maskierungen für Nicht-ASCII-Zeichen erforderte. Java 9+ liest sie standardmäßig als UTF-8. Prüfen Sie daher Ihre Laufzeitversion, bevor Sie UTF-8 ohne Maskierung verwenden.

6. Halten Sie sämtliche für Benutzer sichtbaren Texte aus dem Code fern

Wenn ein String für Benutzer sichtbar ist, gehört er in eine .properties-Datei. Hardcodierte Strings werden nicht übersetzt. Ihre App würde am Ende eine Mischung aus verschiedenen Sprachen anzeigen.

Formatieren Sie Daten, Zeiten, Zahlen und Währungen mit Locale-bewussten Helfern

Nicht alles, was lokalisiert werden muss, befindet sich in einer .properties-Datei. Daten, Zeiten, Zahlen und Währungswerte werden zur Laufzeit im Code formatiert. Diese korrekt darzustellen, ist genauso wichtig wie Ihre übersetzten Strings.

Daten mit DateTimeFormatter:

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;

LocalDate today = LocalDate.now();
DateTimeFormatter formatter = DateTimeFormatter
    .ofLocalizedDate(FormatStyle.LONG)
    .withLocale(Locale.of("fr"));
System.out.println(today.format(formatter));
// -> "27 mai 2026"

Währung mit NumberFormat:

import java.text.NumberFormat;
import java.util.Currency;

NumberFormat formatter = NumberFormat.getCurrencyInstance(Locale.of("de", "DE"));
formatter.setCurrency(Currency.getInstance("EUR"));
System.out.println(formatter.format(1999.99));
// -> "1.999,99 €"

Verwenden Sie immer Locale-bewusste Formatierer. Hardcodieren Sie niemals "$", "," als Tausendertrenner oder "MM/DD/YYYY"-Muster.

Binden Sie ResourceBundle mit MessageSource in Spring Boot ein

Spring Boot kapselt ResourceBundle in einer MessageSource-Bean, die in die i18n-Funktionen des Frameworks integriert ist. Dies deckt auch Validierungsmeldungen, Thymeleaf-Templates und die Locale-Auflösung von Web-Anfragen ab.

Konfiguration in application.properties:

spring.messages.basename=messages
spring.messages.encoding=UTF-8
spring.messages.fallback-to-system-locale=false

Platzieren Sie messages.properties, messages_es.properties usw. unter src/main/resources/.

Verwendung in einem Controller:

import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;

@RestController
public class GreetingController {
    private final MessageSource messageSource;

    public GreetingController(MessageSource messageSource) {
        this.messageSource = messageSource;
    }

    @GetMapping("/greeting")
    public String greeting(@RequestParam String name) {
        return messageSource.getMessage(
            "app.greeting",
            new Object[]{name},
            LocaleContextHolder.getLocale()
        );
    }
}

Konfigurieren Sie den Locale Resolver so, dass er aus dem Accept-Language-Header oder einem URL-Parameter liest:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;

@Configuration
public class I18nConfig implements WebMvcConfigurer {
    @Bean
    public LocaleResolver localeResolver() {
        AcceptHeaderLocaleResolver resolver = new AcceptHeaderLocaleResolver();
        resolver.setDefaultLocale(Locale.ENGLISH);
        return resolver;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        LocaleChangeInterceptor interceptor = new LocaleChangeInterceptor();
        interceptor.setParamName("lang");
        registry.addInterceptor(interceptor);
    }
}

Nun gibt GET /greeting?name=World&lang=es die spanische Version zurück.

Java .properties-Dateien mit PTC in 5 Schritten übersetzen

  1. Starten Sie ein PTC-Projekt und wählen Sie Ihre Ausgangssprache (Englisch / messages.properties).
  2. Laden Sie Ihre .properties-Datei(en) hoch und legen Sie die Ausgabepfade fest. PTC analysiert die Schlüssel-Wert-Struktur, erkennt MessageFormat-Platzhalter ({0}, {1}) sowie ChoiceFormat-Muster und liest alle #-Kommentare als Kontext für Übersetzer.
  3. Fügen Sie eine kurze Beschreibung Ihrer Java-Anwendung und Zielgruppe hinzu. PTC nutzt dies, um mit der richtigen Tonalität und Terminologie zu übersetzen.
  4. Wählen Sie die Zielsprachen aus und bestätigen Sie. Die kostenlose Testphase umfasst 20.000 Wörter in 2 Sprachen, ohne Kreditkarte.
  5. Laden Sie die übersetzten .properties-Dateien über den Tab Ressourcendateien herunter. Eine pro Sprache, mit dem richtigen Suffix (messages_es.properties, messages_fr.properties). Strukturell identisch mit der Quelle: gleiche Schlüssel, gleiche Platzhalter, übersetzte Werte.

Kopieren Sie diese in src/main/resources/, bauen Sie das Projekt neu, und ResourceBundle.getBundle("messages", locale) erkennt die neuen Sprachen automatisch. Die gesamte Einrichtung dauert etwa 5 Minuten.

Java-Übersetzung bei jedem Release mit Git oder der PTC API automatisieren

Einmaliges Übersetzen ist unkompliziert. Die Übersetzungen aktuell zu halten, während sich Ihre Anwendung weiterentwickelt, ist schwieriger. Jeder neue String, jede Textaktualisierung und jeder entfernte Schlüssel muss in jede Sprache einfließen. PTC bietet zwei Wege zur Automatisierung an.

Git-Integration. Verbinden Sie Ihr GitHub-, GitLab- oder Bitbucket-Repository mit PTC. PTC überwacht Ihre .properties-Quelldatei auf Änderungen. Wenn ein String hinzugefügt oder aktualisiert wird, übersetzt PTC diesen und liefert die aktualisierten Dateien über einen Pull Request zurück.

CI/CD-Integration. Wenn Sie es vorziehen, alles innerhalb Ihres bestehenden Build-Prozesses zu belassen, ermöglicht die PTC API das Hochladen Ihrer Quelldatei und das Abrufen von Übersetzungen als Teil Ihres CI-Jobs:

# .github/workflows/translate.yml
name: PTC translate
on:
  push:
    branches: [main]
    paths:
      - 'src/main/resources/messages.properties'
jobs:
  translate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Trigger PTC translation
        run: |
          curl -X POST https://api.ptc.wpml.org/v1/projects/${{ secrets.PTC_PROJECT_ID }}/sync \
            -H "Authorization: Bearer ${{ secrets.PTC_API_KEY }}"

PTC synchronisiert die neuen Quell-Strings, übersetzt nur das, was sich geändert hat, und öffnet einen PR mit den aktualisierten Dateien messages_es.properties, messages_fr.properties usw. Für Maven- und Gradle-Projekte funktioniert derselbe Flow. PTC ist unabhängig von Ihrem Build-Tool. Beide Ansätze bedeuten, dass das spätere Hinzufügen einer neuen Sprache eine reine Konfigurationsänderung ist und kein neuer manueller Prozess.

Visuelle Übersetzungsprüfung Ihrer übersetzten Java-App – Release ohne manuelle QA pro Sprache

Eine übersetzte .properties-Datei ist notwendig, aber nicht ausreichend. Egal, ob Ihre Java-App ein Spring Boot-Webservice ist, der HTML ausliefert, eine Desktop-Swing-App oder ein serverseitiges CLI-Tool – das gerenderte Ergebnis kann Fehler aufweisen, die keine Prüfung auf String-Ebene erfassen kann:

  • Ein deutsches Label, das über einen Swing-Button hinausläuft (Überlauf).
  • Eine französische Validierungsmeldung mit der falschen grammatikalischen Form.
  • Ein hardcodierter englischer String außerhalb von messageSource.getMessage(), der unübersetzt bleibt.

Die AI Visual QA von PTC deckt beide Arten von Java-Apps ab:

  • Für Spring Boot oder jede webbasierte Java-App: Installieren Sie die PTC Browser-Erweiterung und zeichnen Sie einen Rundgang durch die kritischen Seiten Ihrer App auf. PTC spielt diesen nach jedem Übersetzungs-Update in jeder Zielsprache ab.
  • Für Desktop (Swing, JavaFX), Server (CLI) oder jede Nicht-Browser-Java-App: Laden Sie Screenshots der laufenden Java-App in jeder Zielsprache hoch. Die Vision-KI von PTC inspiziert jeden Bildschirm.

Fehler, die PTC in den .properties-Dateien beheben kann (Verb/Substantiv, Layout-Überlauf, falsche Bedeutung), werden automatisch korrigiert. Fehler in Ihrem Java-Code (fehlender messageSource.getMessage()-Aufruf, hardcodierter String, Satzverkettung, die MessageFormat verwenden sollte) werden als kopierfertige Prompts für Cursor oder Claude Code zurückgegeben.

Das Ergebnis: eine verifizierte, mehrsprachige JAR-Datei pro Release. Nicht nur übersetzte Property-Dateien.

Übersetzen Sie Release Notes, READMEs und Kunden-E-Mails

Ihre Release Notes, READMEs in Ihrem internen Maven-Repository oder auf GitHub, kundenorientierte E-Mails, Support-Dokumentationen und interne Wiki-Seiten befinden sich außerhalb von .properties. Die Funktion Paste to Translate von PTC verarbeitet diese Texte im selben Projekt. Fügen Sie den Ausgangstext im PTC Dashboard ein, wählen Sie die Zielsprachen und erhalten Sie Übersetzungen zurück, die dasselbe Glossar und dieselbe Markenstimme verwenden wie Ihre In-App-Strings.

Übersetzen Sie Unternehmensdaten, Support-Tickets und Kundeninhalte mit der PTC API

Unternehmensdaten, Support-Tickets, Knowledge-Base-Einträge und von Kunden eingereichte Inhalte müssen übersetzt werden, sobald sie eingehen. Die PTC REST API übersetzt diese Inhalte auf Abfrage mit Bearer-Token-Authentifizierung unter Verwendung desselben Glossars und derselben Markenstimme wie Ihre .properties-Übersetzungen.

PTC übersetzt Ihre Java-App UND prüft das laufende Ergebnis

Starten Sie Ihre kostenlose 30-Tage-Testphase – 20.000 Wörter in 2 Sprachen, keine Kreditkarte erforderlich. Laden Sie Ihre .properties-Dateien hoch, erhalten Sie in wenigen Minuten übersetzte Versionen, laden Sie dann Screenshots hoch (oder installieren Sie die Browser-Erweiterung für Spring Boot) und lassen Sie PTC die laufende App verifizieren.

Verwandte Themen: