Internationalisierung (i18n) in einer Vaadin-Anwendung

Sven Ruppert

Moderne Webanwendungen werden selten nur von Benutzern derselben Sprache verwendet. Selbst interne Werkzeuge erreichen häufig internationale Teams oder werden in verschiedenen Ländern eingesetzt. Eine mehrsprachige Benutzeroberfläche ist daher keine Luxusfunktion, sondern ein wichtiger Bestandteil der Benutzerfreundlichkeit.

Auch das Open‑Source‑Projekt URL‑Shortener profitiert von einer klaren Internationalisierungsstrategie. Die Anwendung richtet sich an Entwickler, Administratoren und andere Benutzer, die Links verwalten, analysieren oder verteilen möchten. Damit die Oberfläche unabhängig von der Herkunft der Benutzer verständlich bleibt, unterstützt die Anwendung mehrere Sprachen.

Das Projekt befindet sich auf GitHub unter der URL: https://3g3.eu/url

In diesem Artikel wird gezeigt, wie die Benutzeroberfläche des URL‑Shorteners um eine einfache und robuste Internationalisierung erweitert wurde. Die Implementierung basiert vollständig auf den Möglichkeiten von Vaadin Flow und setzt bewusst nur wenige zusätzliche Hilfsklassen ein, um die Architektur übersichtlich zu halten.

Die Lösung verfolgt mehrere zentrale Ziele. Zum einen soll die Sprache der Benutzer automatisch anhand der vom Browser übermittelten Locale erkannt werden. Darüber hinaus müssen mehrere Übersetzungen über Resource Bundles verwaltet werden können, ohne dass zusätzlicher Verwaltungsaufwand im Anwendungscode entsteht. Gleichzeitig soll der Benutzer jederzeit die Möglichkeit haben, die Sprache während einer laufenden Session zu wechseln. Ein weiteres wichtiges Ziel besteht darin, die Implementierung bewusst schlank zu halten und auf zusätzliche Frameworks zu verzichten, sodass die Internationalisierung ohne komplexe Infrastruktur direkt innerhalb der bestehenden Anwendung umgesetzt werden kann.

Aktuell unterstützt die Anwendung drei Sprachen:

  • Englisch
  • Deutsch
  • Finnisch

Die Auswahl dieser Sprachen ist bewusst pragmatisch. Englisch dient als Standardsprache, während Deutsch und Finnisch reale Nutzungsszenarien aus dem Umfeld des Projekts abbilden.

Der Fokus dieses Artikels liegt nicht nur auf der technischen Umsetzung, sondern auch auf der Frage, wie Internationalisierung in einer Java‑Webanwendung so integriert werden kann, dass der Quellcode weiterhin klar strukturiert und wartbar bleibt. Dazu betrachten wir sowohl die Organisation der Übersetzungsressourcen als auch den Umgang mit Locales in der Anwendung.

Im weiteren Verlauf wird Schritt für Schritt erläutert, wie Vaadin Übersetzungsressourcen erkennt und lädt, wie Übersetzungsschlüssel sinnvoll strukturiert werden können und wie die Sprache eines Benutzers anhand der Browser‑Locale bestimmt wird. Darüber hinaus wird gezeigt, wie sich eine einfache Sprachumschaltung direkt in die Benutzeroberfläche integrieren lässt, sodass Benutzer die gewünschte Sprache während einer laufenden Session wechseln können.

Damit entsteht eine Internationalisierungslösung, die bewusst einfach gehalten ist, sich aber problemlos erweitern lässt, falls später weitere Sprachen hinzukommen.

Internationalisierung in Vaadin

Vaadin Flow bietet bereits grundlegende Unterstützung für die Internationalisierung. Anwendungen können Übersetzungen über sogenannte Resource Bundles bereitstellen, die von der Laufzeitumgebung automatisch erkannt und geladen werden. Auf diese Weise lassen sich Benutzeroberflächen ohne großen zusätzlichen Aufwand in mehreren Sprachen betreiben.

Der zentrale Mechanismus basiert auf Übersetzungsdateien, die im Rahmen des Projekts in einem speziellen Verzeichnis abgelegt werden. Vaadin sucht standardmäßig im Ordner vaadin-i18n im Klassenpfad nach Übersetzungsressourcen. Alle dort abgelegten Dateien werden automatisch erkannt und stehen der Anwendung während der Laufzeit zur Verfügung.

Die Übersetzungsdateien folgen der bekannten Struktur von Java-Resource-Bundles. Eine Basisdatei enthält die Standardübersetzungen, während zusätzliche Dateien sprachspezifische Varianten bereitstellen. Die Sprache wird durch ein Sprachsuffix im Dateinamen definiert.

Ein typischer Aufbau sieht beispielsweise so aus:

vaadin-i18n/

  translations.properties

  translations_de.properties

  translations_fi.properties

Die Datei ohne Sprachsuffix dient als Standardressource. In vielen Projekten enthält sie englische Texte. Sobald Vaadin eine aktive Locale bestimmt hat, versucht das Framework automatisch, die passende Übersetzungsdatei zu laden. Existiert eine sprachspezifische Variante, wird diese verwendet. Andernfalls greift Vaadin auf die Standardressource zurück.

Dieses Verhalten entspricht dem klassischen Fallback-Mechanismus von Java-Resource-Bundles. Dadurch bleibt die Anwendung auch dann funktionsfähig, wenn einzelne Übersetzungen noch nicht vollständig vorliegen.

Für die Benutzeroberfläche bedeutet das, dass Texte nicht mehr direkt im Quellcode definiert werden, sondern über eindeutige Übersetzungsschlüssel referenziert werden. Diese Schlüssel werden anschließend während der Laufzeit über die aktive Locale aufgelöst.

Vaadin stellt dafür die Methode getTranslation() bereit, die in UI-Komponenten direkt verwendet werden kann. Mit dieser Methode wird ein Übersetzungsschlüssel an das Framework übergeben, woraufhin Vaadin den passenden Text aus den geladenen Ressourcen ermittelt.

Damit bildet das Resource-Bundle-System die Grundlage für alle weiteren Internationalisierungsmechanismen innerhalb der Anwendung. Auf dieser Basis lassen sich anschließend zusätzliche Konzepte wie Sprachumschaltung, sessionbasierte Locale-Verwaltung oder strukturierte Übersetzungsschlüssel aufbauen.

Übersetzungsressourcen strukturieren

Nachdem im vorherigen Kapitel die grundlegende Unterstützung für die Internationalisierung von Vaadin betrachtet wurde, stellt sich in der Praxis schnell eine wichtige Frage: Wie sollten Übersetzungsressourcen innerhalb eines Projekts organisiert werden, damit sie langfristig wartbar bleiben?

Im URL-Shortener-Projekt werden sämtliche Übersetzungen in sogenannten Resource Bundles abgelegt. Diese befinden sich im Verzeichnis src/main/resources/vaadin-i18n/. Vaadin erkennt diesen Ordner automatisch und lädt die darin enthaltenen Übersetzungsdateien zur Laufzeit.

Die Dateistruktur orientiert sich an den Konventionen von Java Resource Bundles. Eine Basisdatei enthält die Standardübersetzungen, während zusätzliche Dateien sprachspezifische Varianten bereitstellen.

src/main/resources/vaadin-i18n/

  translations.properties

  translations_de.properties

  translations_fi.properties

Die Datei translations.properties dient als Standardressource. In diesem Projekt sind englischsprachige Texte enthalten. Für weitere Sprachen werden zusätzliche Dateien mit einem Sprachsuffix angelegt. Die Sprache wird dabei über den ISO-Sprachcode im Dateinamen festgelegt.

Beispielsweise enthält die deutsche Variante die Datei translations_de.properties, während finnische Übersetzungen in translations_fi.properties abgelegt werden.

Innerhalb dieser Dateien werden die eigentlichen Übersetzungen über Schlüssel-Wert-Paare definiert. Jeder Schlüssel repräsentiert einen bestimmten Text in der Benutzeroberfläche.

main.appTitle=URL Shortener

main.logout=Logout

nav.overview=Overview

nav.create=Create

nav.youtube=Youtube

nav.about=About

Die Schlüssel selbst folgen einer einfachen Namenskonvention. Häufig werden sie nach dem Musterbereich bereitgestellt bereich.element aufgebaut. Dadurch lassen sich zusammengehörige Texte logisch gruppieren.

Diese Struktur erleichtert es, auch bei einer größeren Anzahl an Übersetzungen den Überblick zu behalten. Gleichzeitig verhindert sie Namenskonflikte zwischen den verschiedenen Bereichen der Anwendung.

Ein weiterer Vorteil dieser Struktur besteht darin, dass Übersetzungen vollständig vom Anwendungscode getrennt bleiben. Der Quellcode verweist lediglich auf die Schlüssel, während die eigentlichen Texte in den Resource Bundles definiert werden.

Dadurch können Übersetzungen später erweitert oder korrigiert werden, ohne dass Änderungen im Anwendungscode notwendig sind.

Diese klare Trennung zwischen Code und Übersetzungsressourcen bildet eine wichtige Grundlage für die weitere Internationalisierung der Anwendung. Im nächsten Schritt wird daher untersucht, wie diese Übersetzungsschlüssel in der Benutzeroberfläche komfortabel verwendet werden können.

Vereinfachter Zugriff auf Übersetzungen mit I18n-Support

Nachdem die Struktur der Übersetzungsressourcen festgelegt wurde, stellt sich in der praktischen Entwicklung eine weitere Frage: Wie können diese Übersetzungen möglichst komfortabel innerhalb der Benutzeroberfläche verwendet werden?

Vaadin stellt grundsätzlich die Methode getTranslation() bereit, über die Übersetzungsschlüssel zur Laufzeit übersetzt werden können. Diese Methode steht beispielsweise innerhalb von UI-Komponenten zur Verfügung und ermöglicht, anhand eines Schlüssels den passenden Text aus den geladenen Resource-Bundles zu ermitteln.

In der Praxis führt die direkte Anwendung dieser Methode jedoch häufig zu wiederkehrendem Boilerplate-Code. Besonders in größeren Benutzeroberflächen müssen Übersetzungen an vielen verschiedenen Stellen aufgelöst werden. Dadurch entstehen schnell redundante Aufrufe und weniger lesbarer Code.

Um diesen Zugriff zu vereinfachen, verwendet das URL-Shortener-Projekt eine kleine Hilfsschnittstelle namens I18nSupport. Diese Schnittstelle begrenzt den Zugriff auf die Übersetzungsfunktion und stellt eine kompakte Methode bereit, über die innerhalb der UI-Komponenten abgefragte Übersetzungen ermittelt werden können.

Ein vereinfachtes Beispiel dieser Schnittstelle sieht folgendermaßen aus:

public interface I18nSupport {
  default String tr(String key, String fallback) {
    return UI.getCurrent().getTranslation(key);
  }
}

Durch diese Hilfsmethode lassen sich Übersetzungen in der Anwendung deutlich kompakter verwenden. Statt direkt mit der Vaadin-API zu arbeiten, genügt ein einfacher Methodenaufruf.

Ein Beispiel aus dem MainLayout der Anwendung verdeutlicht dies:

H1 appTitle = new H1(tr(“main.appTitle”, “URL Shortener”));

Der Quellcode bleibt dadurch übersichtlich und die eigentlichen Texte sind vollständig von der Implementierung der Benutzeroberfläche getrennt.

Ein weiterer Vorteil dieser Lösung besteht darin, dass sich der Zugriff auf Übersetzungen zentral steuern lässt. Sollte sich die Implementierung später ändern – beispielsweise durch zusätzliche Fallback-Mechanismen oder Logging – kann dies innerhalb der Hilfsschnittstelle erfolgen, ohne dass sämtliche UI-Komponenten angepasst werden müssen.

Damit bildet I18nSupport eine kleine, aber wirkungsvolle Abstraktionsschicht über der Vaadin-i18n-API. Sie sorgt dafür, dass Übersetzungen konsistent und mit möglichst wenig Boilerplate-Code in der gesamten Anwendung verwendet werden.

Ermittlung der Benutzer-Locale

Nachdem Übersetzungsressourcen strukturiert und ein komfortabler Zugriff über I18nSupport geschaffen wurden, stellt sich als nächster Schritt die zentrale Frage: Welche Sprache soll die Anwendung beim ersten Aufruf verwenden?

In Webanwendungen wird diese Entscheidung in der Regel anhand der vom Browser übermittelten Sprachpräferenzen getroffen. Moderne Browser senden bei jeder HTTP-Anfrage einen sogenannten Accept-Language-Header, der eine priorisierte Liste bevorzugter Sprachen enthält. Auf dieser Basis kann die Anwendung entscheiden, welche Locale initial verwendet werden soll.

Vaadin Flow berücksichtigt diese Information bereits bei der Initialisierung der Benutzeroberfläche. Beim Aufbau einer neuen UI wird die Locale des Browsers automatisch erkannt und als aktuelle Locale gesetzt. Dadurch kann eine Anwendung bereits beim ersten Mal die Oberfläche rendern, um die passende Sprache auszuwählen.

In der Praxis ist es jedoch selten sinnvoll, jede vom Browser gemeldete Sprache vollständig zu unterstützen. Viele Anwendungen bieten nur eine begrenzte Anzahl an Übersetzungen an. Deshalb muss die vom Browser gemeldete Locale zunächst mit den tatsächlich unterstützten Sprachen der Anwendung abgeglichen werden.

Im URL-Shortener-Projekt wird dieser Abgleich über eine kleine Hilfsklasse namens LocaleSelection umgesetzt. Diese Klasse definiert die unterstützten Sprachen der Anwendung und stellt Methoden bereit, um eine angefragte Locale in eine der verfügbaren Varianten umzuwandeln.

Ein vereinfachtes Beispiel sieht folgendermaßen aus:

public static Locale match(Locale requested) {
  if (requested == null) {
    return EN;
  }
  String language = requested.getLanguage();
  return SUPPORTED.stream()
      .filter(l -> l.getLanguage().equals(language))
      .findFirst()
      .orElse(EN);
}

Die Methode prüft zunächst, welche Sprache vom Browser angefragt wurde. Anschließend wird geprüft, ob diese Sprache zu den unterstützten Sprachen der Anwendung gehört. Ist dies der Fall, wird die entsprechende Locale übernommen. Andernfalls wird auf die Standardsprache der Anwendung zurückgegriffen.

Diese Strategie stellt sicher, dass die Anwendung auch dann konsistent bleibt, wenn ein Browser eine Sprache meldet, für die keine vollständigen Übersetzungen verfügbar sind. Gleichzeitig bleibt die Implementierung übersichtlich und leicht erweiterbar.

Im nächsten Schritt stellt sich die Frage, wie die gewählte Sprache während einer Sitzung stabil gehalten werden kann. Daher betrachten wir im folgenden Kapitel, wie die Locale eines Benutzers innerhalb der Vaadin-Session gespeichert und verwaltet wird.

Session-basierte Sprachverwaltung

Nachdem im vorherigen Kapitel beschrieben wurde, wie die initiale Sprache einer Anwendung anhand der Browser-Locale bestimmt werden kann, stellt sich in der Praxis eine weitere wichtige Frage: Wie bleibt diese Entscheidung während der gesamten Nutzung der Anwendung stabil?

In einer typischen Webanwendung besteht eine Benutzersitzung aus mehreren HTTP-Anfragen. Während dieser Zeit erwartet der Benutzer, dass die Oberfläche in derselben Sprache konsistent angezeigt wird. Würde die Sprache bei jeder Anfrage erneut ausschließlich anhand der Browser-Locale bestimmt, könnte dies zu unerwarteten Änderungen führen – insbesondere dann, wenn ein Benutzer die Sprache manuell innerhalb der Anwendung wechselt.

Aus diesem Grund wird im URL-Shortener-Projekt die gewählte Sprache in der Vaadin-Session gespeichert. Die Session stellt dabei einen serverseitigen Kontext dar, der über mehrere Requests hinweg erhalten bleibt und damit ideal geeignet ist, benutzerspezifische Einstellungen wie die aktuelle Locale zu speichern.

Vaadin bietet hierfür bereits grundlegende Unterstützung. Jede VaadinSession besitzt eine zugehörige Locale, die von der Anwendung gesetzt und abgefragt werden kann. Wird diese Locale verändert, wirkt sich dies unmittelbar auf die Auflösung der Übersetzungsschlüssel innerhalb der Benutzeroberfläche aus.

Im Projekt wird die Verwaltung der Session-Locale ebenfalls über die Hilfsklasse LocaleSelection abgewickelt. Neben der zuvor gezeigten Methode zur Auswahl einer unterstützten Sprache stellt diese Klasse auch Methoden bereit, um die Locale in der Session abzulegen oder wieder auszulesen.

Ein vereinfachtes Beispiel zum Speichern der Locale sieht folgendermaßen aus:

public static void setToSession(VaadinSession session, Locale locale) {
  session.setAttribute(SESSION_KEY, locale);
}

Beim Sprachwechsel wird die gewählte Locale sowohl in der Session gespeichert als auch direkt in der aktuellen UI gesetzt. Dadurch wird sichergestellt, dass die neue Sprache unmittelbar aktiv wird und gleichzeitig für alle weiteren Interaktionen innerhalb derselben Session erhalten bleibt.

Diese Vorgehensweise hat mehrere Vorteile. Zum einen bleibt die Sprache eines Benutzers während der gesamten Sitzung konsistent. Zum anderen lässt sich die Sprache jederzeit durch eine Benutzeraktion ändern, ohne dass zusätzliche Persistenzmechanismen wie Cookies oder Datenbankeinträge erforderlich sind.

Darüber hinaus bleibt die Implementierung bewusst einfach. Die Anwendung nutzt ausschließlich die vorhandenen Mechanismen von Vaadin und ergänzt diese lediglich um eine kleine Hilfsklasse zur zentralen Verwaltung der unterstützten Locales.

Im nächsten Kapitel wird gezeigt, wie diese Session-basierte Locale schließlich mit der Benutzeroberfläche verknüpft wird und wie Benutzer die Sprache direkt innerhalb der Anwendung wechseln können.

Sprachumschaltung in der Benutzeroberfläche

Nachdem im vorherigen Kapitel beschrieben wurde, wie die gewählte Sprache innerhalb der Vaadin-Session gespeichert wird, stellt sich nun die praktische Frage, wie Benutzer diese Sprache überhaupt ändern können. Eine Internationalisierung ist nur dann wirklich nützlich, wenn Benutzer die Möglichkeit haben, die Sprache der Oberfläche aktiv zu wechseln.

Im URL-Shortener-Projekt wurde die Sprachumschaltung direkt in das MainLayout integriert. Dieses Layout bildet die zentrale Struktur der Benutzeroberfläche und enthält unter anderem die Navigationsleiste sowie verschiedene Status- und Steuerungselemente. Dadurch eignet es sich ideal, um dort auch eine kompakte Sprachumschaltung zu platzieren.

Anstelle eines klassischen Dropdown-Menüs verwendet die Anwendung eine kleine Gruppe von Schaltflächen, die jeweils eine Sprache repräsentieren. Die Schaltflächen werden über Flaggen dargestellt, sodass die gewünschte Sprache auf einen Blick erkennbar ist.

Die Benutzeroberfläche zeigt dabei drei Optionen:

  • Deutsch
  • Englisch
  • Finnisch

Jede dieser Schaltflächen löst beim Anklicken einen Wechsel der aktuellen Locale aus. Technisch wird zunächst überprüft, welche Sprache gewählt wurde. Anschließend wird diese Sprache sowohl in der aktuellen UI als auch in der Vaadin-Session gesetzt.

Der konkrete Aufbau des Schalters ist bewusst kompakt gehalten und kommt ohne zusätzliche Komponenten oder Abhängigkeiten aus. Statt einer ComboBox wird eine horizontale Button-Gruppe gerendert, die wie ein „Segmented Control“ wirkt: drei runde Buttons in einer leicht abgesetzten Leiste. Die Leiste selbst ist lediglich ein HorizontalLayout, dessen Styling über Lumo-CSS-Variablen erfolgt, sodass sich die Optik harmonisch in das übrige Theme einfügt.

Beim Erzeugen des Schalters wird zunächst die aktuell wirksame Locale bestimmt. Entscheidend ist dabei, dass nicht nur die Browser-Locale berücksichtigt wird, sondern ein bereits in der Session gespeicherter Wert Vorrang hat. Genau dafür wird LocaleSelection.resolveAndStore(…) verwendet. Das Ergebnis ist die „current“-Locale, anhand deren der aktive Button markiert wird.

private Component createLanguageSwitch() {
  Locale current = LocaleSelection.resolveAndStore(
      VaadinSession.getCurrent(),
      UI.getCurrent().getLocale()
  );
  Button de = flagButton(LocaleSelection.DE, current);
  Button en = flagButton(LocaleSelection.EN, current);
  Button fi = flagButton(LocaleSelection.FI, current);
  HorizontalLayout bar = new HorizontalLayout(de, en, fi);
  bar.setSpacing(false);
  bar.getStyle()
      .set("gap", "6px")
      .set("padding", "2px")
      .set("border-radius", "999px")
      .set("background", "var(--lumo-contrast-5pct)");
  return bar;
}

Die eigentliche Logik liegt in der Erzeugung eines einzelnen Buttons. Jeder Button bekommt als Inhalt lediglich einen Span mit einem Emoji-Flag. Das wirkt trivial, ist aber praktisch: Es benötigt keine Assets, keine zusätzlichen Dateien und keine Build-Schritte. Styling und Interaktion erfolgen direkt am Button.

Wichtig sind dabei drei Punkte: Erstens werden die Buttons auf eine kompakte, runde Form gebracht, sodass sie visuell als zusammengehörige Gruppe wahrgenommen werden. Zweitens wird der aktive Zustand anhand der Sprache (getLanguage()) berechnet, da regionale Varianten wie de-DE oder de-AT für die UI keine Rolle spielen sollen. Drittens löst ein Klick den tatsächlichen Locale-Wechsel aus.

private Button flagButton(Locale locale, Locale current) {
  String flag = flagEmoji(locale);
  Button b = new Button(new Span(flag));
  b.addThemeVariants(ButtonVariant.LUMO_TERTIARY_INLINE);
  b.getStyle()
      .set("width", "38px")
      .set("height", "32px")
      .set("min-width", "38px")
      .set("border-radius", "999px")
      .set("padding", "0")
      .set("line-height", "1")
      .set("font-size", "18px");
  boolean active = locale.getLanguage().equalsIgnoreCase(current.getLanguage());
  applyActiveStyle(b, active);
  b.addClickListener(e -> switchLocale(locale));
  // Tooltip (optional)
  b.getElement().setProperty("title", locale.getLanguage().toUpperCase());
  return b;
}

Für den aktiven Zustand wird bewusst keine zusätzliche Theme-Variante eingeführt, sondern ein minimaler Style angewandt: eine leichte Hintergrundtönung und ein Outline-Ring in der Primärfarbe. Damit bleibt die Komponente optisch zurückhaltend, aber eindeutig.

private void applyActiveStyle(Button b, boolean active) {
  if (active) {
    b.getStyle()
        .set("background", "var(--lumo-primary-color-10pct)")
        .set("outline", "2px solid var(--lumo-primary-color-50pct)");
  } else {
    b.getStyle()
        .remove("background")
        .remove("outline");
  }
}

Der Locale-Wechsel selbst ist bewusst „robust“ umgesetzt. Zuerst wird die ausgewählte Locale mit einer der unterstützten Sprachen verknüpft. Anschließend wird sie sowohl in der Session als auch in der UI gesetzt. Der abschließende reload() sorgt dafür, dass alle Views, Dialoge und Komponenten ihre Texte erneut aus den Resource Bundles auflösen. Das spart zusätzliche Komplexität, die sonst durch LocaleChangeObserver-Implementierungen in vielen Komponenten entstehen würde.

private void switchLocale(Locale selected) {
  UI ui = UI.getCurrent();
  VaadinSession session = VaadinSession.getCurrent();
  Locale effective = LocaleSelection.match(selected);
  LocaleSelection.setToSession(session, effective);
  session.setLocale(effective);
  ui.setLocale(effective);
  ui.getPage().reload();
}

Zuletzt wird die Anzeige der Flaggen über eine kleine Mapping-Methode abgedeckt. Dadurch bleibt die Darstellung an einer zentralen Stelle und lässt sich später leicht anpassen – beispielsweise, wenn statt EN lieber US verwendet werden soll oder weitere Sprachen hinzukommen.

<IMG DE> – Hierbei handelt es sich um ein Replacement des Emojis —

private String flagEmoji(Locale locale) {
  return switch (locale.getLanguage()) {
    case "de" -> "<IMG DE>";
    case "fi" -> "<IMG FI>";
    default -> "<IMG EN>"; // EN
  };
}

Der Ablauf umfasst mehrere Schritte. Zunächst wird die gewünschte Sprache mit den unterstützten Sprachen der Anwendung abgeglichen. Anschließend wird die Locale sowohl in der Session als auch in der aktuellen UI gesetzt. Dadurch steht die neue Sprache sofort zur Verfügung.

Der abschließende Seitenreload sorgt dafür, dass sämtliche UI-Komponenten neu gerendert werden und alle Übersetzungen konsistent mit der neuen Locale aufgelöst werden. Dieser Ansatz ist bewusst einfach gehalten und vermeidet zusätzliche Komplexität in der Komponentenlogik.

Durch die Integration der Sprachumschaltung in den MainLayout steht diese Funktion in jeder Ansicht der Anwendung zur Verfügung. Benutzer können die Sprache jederzeit wechseln, ohne die aktuelle Seite verlassen zu müssen.

Damit ist die Internationalisierung der Benutzeroberfläche vollständig in die Anwendung integriert. Übersetzungsressourcen, Locale-Ermittlung, Session-Verwaltung und Sprachumschaltung greifen nun ineinander und ermöglichen eine mehrsprachige Oberfläche mit vergleichsweise geringem Implementierungsaufwand.

Fazit und Ausblick

Mit der Internationalisierung ist der URL-Shortener an einer Stelle angekommen, an der sich gute Benutzerfreundlichkeit und saubere Architektur unmittelbar treffen. Die Anwendung unterstützt mehrere Sprachen, ohne dass der Quellcode unübersichtlich wird oder zusätzliche Abhängigkeiten eingeführt werden müssen. Stattdessen wird auf die vorhandenen Mechanismen von Vaadin Flow gesetzt und lediglich dort ergänzt, wo es für das Projekt sinnvoll ist.

Die wesentlichen Bausteine greifen dabei sauber ineinander. Übersetzungen liegen als Resource Bundles im vaadin-i18n-Verzeichnis, sodass Vaadin sie automatisch erkennt. Über klar strukturierte Schlüssel werden Texte aus der Oberfläche herausgelöst und zentral verwaltet. I18nSupport reduziert den Zugriff auf Übersetzungen auf eine kompakte, überall einsetzbare Methode und hält damit die UI-Klassen lesbar.

Die Locale-Ermittlung folgt einem pragmatischen Prinzip. Standardmäßig wird die vom Browser übermittelte Locale verwendet, jedoch auf die tatsächlich unterstützten Sprachen reduziert. Dadurch bleibt das System vorhersehbar und vermeidet unvollständige Übersetzungszustände. Gleichzeitig wird die gewählte Sprache session-basiert gespeichert, sodass Benutzer während einer Sitzung eine konsistente Oberfläche behalten und ihre Auswahl nicht bei jedem Request neu „ausgehandelt“ werden muss.

Schließlich wird das Ganze besonders sichtbar in der Benutzeroberfläche. Der Language Switch im MainLayout ist bewusst minimalistisch umgesetzt, aber UX-seitig deutlich angenehmer als ein verschachteltes Menü. Drei Flag-Buttons reichen aus, um die Sprache schnell zu wechseln, und der aktive Zustand ist sofort erkennbar. Der technische Wechsel der Locale wird dabei robust über die Session und die UI umgesetzt. Der abschließende Reload ist kein Workaround, sondern eine bewusste Designentscheidung: Er stellt sicher, dass alle Views, Dialoge und Komponenten konsistent in der neuen Sprache gerendert werden, ohne dass jede Komponente zusätzliche Observer-Logik implementieren muss.

Damit ist eine solide Grundlage geschaffen, die sich bei Bedarf erweitern lässt. Ein naheliegender nächster Schritt wäre die Ergänzung um weitere Sprachen oder die Verfeinerung der Übersetzungen, ohne dass sich am Code etwas ändern muss. Für komplexere Sprachfälle – etwa Pluralisierung, Formatierung von Zahlen und Datumswerten oder sprachabhängige Satzbausteine – könnte später ICU-basierte Formatierung ergänzt werden. Ebenso wäre es möglich, die Sprachwahl nicht nur session-basiert zu speichern, sondern dauerhaft an ein Benutzerprofil zu koppeln. Für den aktuellen Stand des URL-Shorteners ist die Lösung jedoch bewusst auf das Wesentliche reduziert: Sie ist klein genug, um wartbar zu bleiben, aber vollständig genug, um im Alltag echten Nutzen zu bieten. Genau darin liegt der praktische Wert einer guten Internationalisierung – sie fällt im Code kaum auf, macht sich für Benutzer aber sofort bemerkbar.

Total
0
Shares
Previous Post

Schluss mit YAML: Cloud-Infrastruktur in purem Java definieren, testen und deployen

Next Post

Produktionsreife KI-Agenten mit Java und Spring AI entwickeln

Related Posts