Übersetzung 25.12
webforJ verfügt über ein integriertes Übersetzungssystem, um lokalisierte Strings nach Schlüssel zu suchen. Das System besteht aus einem Übersetzungsresolver, der Schlüssel auf lokalisierte Texte abbildet, einem HasTranslation-Interface, das eine bequeme t()-Methode bereitstellt, App.getTranslation() für den direkten Zugriff von überall, automatischer Lokalerkennung aus dem Browser und Unterstützung für benutzerdefinierte Übersetzungsquellen wie Datenbanken.
The webforj-localizing-apps skill can add multi-language support and translate component labels. After installing the webforJ AI plugin, ask your assistant:
- "Add multi-language support with English and Spanish."
- "Detect the user's browser locale and apply it on startup."
- "Move all hardcoded strings into a messages bundle."
Übersetzungsresolver
Der Übersetzungsresolver ist das System, das lokalisierte Strings für einen gegebenen Schlüssel und eine gegebenen Locale sucht. webforJ bietet einen Standardresolver, BundleTranslationResolver, der Übersetzungen aus Java ResourceBundle-Eigenschaftsdateien im Klassenpfad lädt. Dies funktioniert sofort ohne zusätzliche Abhängigkeiten.
Ressourcenbündeldateien
Platzieren Sie Ihre Übersetzungsdateien im Verzeichnis src/main/resources. Der Standardresolver sucht nach Dateien mit dem Namen messages und Locale-Suffixen, die der Standardbenennungskonvention von Java ResourceBundle folgen:
messages.properties # Standard-/Fallback-Übersetzungen
messages_en.properties # Englisch
messages_de.properties # Deutsch
messages_fr_CA.properties # Französisch (Kanada)
Jede Datei enthält Schlüssel-Wert-Paare. Schlüssel sind Identifikatoren, die Sie im Code verwenden, und Werte sind die übersetzten Strings. Sie können MessageFormat Platzhalter wie {0}, {1} für dynamische Werte einfügen:
app.title=Mailbox
menu.inbox=Posteingang
menu.outbox=Postausgang
greeting=Hallo {0}, Sie haben {1} neue Nachrichten
app.title=Postfach
menu.inbox=Posteingang
menu.outbox=Postausgang
greeting=Hallo {0}, Sie haben {1} neue Nachrichten
Der Resolver delegiert an die Standardauflösungskette von Java ResourceBundle, die die Lokalanpassung und Fallbacks automatisch behandelt.
Konfigurieren unterstützter Sprachen
Die Einstellung supported-locales teilt webforJ mit, welche Sprachen Ihre App unterstützt. Diese Liste wird von der automatischen Erkennung verwendet, um die Locale des Browsers des Benutzers mit den verfügbaren Übersetzungen abzugleichen. Die erste Sprache in der Liste wird als Standard-Fallback verwendet, wenn kein besserer Treffer gefunden wird. Der Eigenschaftsschlüssel lautet webforj.i18n.supported-locales und akzeptiert eine Liste von BCP 47 Sprach-Tags, zum Beispiel en, de.
Siehe den Abschnitt Konfiguration, um zu erfahren, wie Eigenschaften für verschiedene Umgebungen gesetzt werden.
Die t()-Methode
Komponenten, die das HasTranslation-Interface implementieren, erhalten Zugriff auf die t()-Methode zum Übersetzen von Text. Die Methode nimmt einen Übersetzungsschlüssel entgegen und gibt den lokalisierten String für die aktuelle Sprache der App zurück:
public class MainLayout extends Composite<AppLayout> implements HasTranslation {
public MainLayout() {
// Einfache Übersetzung
String title = t("app.title");
// Übersetzung mit MessageFormat-Parametern
String greeting = t("greeting", userName, messageCount);
// Übersetzung für eine spezifische Sprache
String germanTitle = t(Locale.GERMAN, "app.title");
}
}
Sie können auch App.getTranslation() direkt überall verwenden, ohne das Interface zu implementieren:
String title = App.getTranslation("app.title");
Wenn ein Übersetzungsschlüssel nicht gefunden wird, gibt t() den Schlüssel selbst zurück, anstatt eine Ausnahme auszulösen. Das bedeutet, dass Ihre App nicht abstürzt, wenn eine Übersetzung fehlt. Der Schlüssel wird unverändert angezeigt, und eine Warnung wird protokolliert, damit Sie fehlende Übersetzungen während der Entwicklung verfolgen können.
Implementierung übersetzter Komponenten
Eine übersetzte Komponente kombiniert typischerweise HasTranslation mit LocaleObserver. Verwenden Sie t(), wenn Sie UI-Elemente erstellen, um den anfänglichen übersetzten Text festzulegen. Um die Sprachumschaltung zur Laufzeit zu unterstützen, implementieren Sie LocaleObserver und aktualisieren Sie denselben Text in onLocaleChange().
@Route
public class MainLayout extends Composite<AppLayout>
implements HasTranslation, LocaleObserver {
private final AppLayout self = getBoundComponent();
private AppNavItem inboxItem;
private AppNavItem outboxItem;
public MainLayout() {
inboxItem = new AppNavItem(t("menu.inbox"), InboxView.class, TablerIcon.create("inbox"));
outboxItem = new AppNavItem(t("menu.outbox"), OutboxView.class, TablerIcon.create("send-2"));
AppNav appNav = new AppNav();
appNav.addItem(inboxItem);
appNav.addItem(outboxItem);
self.addToDrawer(appNav);
}
@Override
public void onLocaleChange(LocaleEvent event) {
inboxItem.setText(t("menu.inbox"));
outboxItem.setText(t("menu.outbox"));
}
}
Das Datenbindungssystem unterstützt übersetzte Validierungs- und Transformationsnachrichten mit Supplier<String> mit t(). Siehe dynamische Validierungsnachrichten, dynamische Transformationsnachrichten und locale-aware Jakarta Validation.
Benutzerdefinierte Übersetzungsresolver
Der Standardresolver lädt Übersetzungen aus Java ResourceBundle-Eigenschaftsdateien. Um Übersetzungen aus einer anderen Quelle zu laden, beispielsweise einer Datenbank oder einem Remote-Dienst, implementieren Sie TranslationResolver:
public class DatabaseTranslationResolver implements TranslationResolver {
private final TranslationRepository repository;
private final List<Locale> supportedLocales;
public DatabaseTranslationResolver(TranslationRepository repository,
List<Locale> supportedLocales) {
this.repository = repository;
this.supportedLocales = List.copyOf(supportedLocales);
}
@Override
public String resolve(String key, Locale locale, Object... args) {
String value = repository
.findByKeyAndLocale(key, locale.getLanguage())
.map(Translation::getValue)
.orElse(key);
if (args != null && args.length > 0) {
value = new MessageFormat(value, locale).format(args);
}
return value;
}
@Override
public List<Locale> getSupportedLocales() {
return supportedLocales;
}
}
Registrieren eines benutzerdefinierten Resolvers
In einer einfachen webforJ-App legen Sie den Resolver fest, bevor die App startet, zum Beispiel mithilfe eines App-Lebenszyklus-Listeners:
App.setTranslationResolver(new DatabaseTranslationResolver(repository, supportedLocales));
In einer Spring Boot-App exponieren Sie den Resolver als Bean:
@Configuration
public class MessageSourceConfig {
@Bean
TranslationResolver translationResolver(TranslationRepository repository,
SpringConfigurationProperties properties) {
List<Locale> supportedLocales = properties.getI18n().getSupportedLocales().stream()
.map(Locale::forLanguageTag)
.toList();
return new DatabaseTranslationResolver(repository, supportedLocales);
}
}
Wenn kein benutzerdefinierter TranslationResolver-Bean definiert ist, stellt die automatische Konfiguration von Spring einen Standard-BundleTranslationResolver bereit, der mit den unterstützten Sprachen aus application.properties konfiguriert ist.