Traducción 25.12
webforJ incluye un sistema de traducción integrado para buscar cadenas localizadas por clave. El sistema consta de un resolutor de traducción que asigna claves a texto localizado, una interfaz de preocupación HasTranslation que proporciona un conveniente método t(), App.getTranslation() para acceso directo en cualquier lugar, detección automática de la configuración regional desde el navegador y soporte para fuentes de traducción personalizadas como bases de datos.
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."
Resolutor de traducción
El resolutor de traducción es el sistema que busca cadenas localizadas para una clave y configuración regional dada. webforJ proporciona un resolutor predeterminado, BundleTranslationResolver, que carga traducciones de archivos de propiedades ResourceBundle de Java en el classpath. Esto funciona directamente sin dependencias adicionales.
Archivos de paquetes de recursos
Coloca tus archivos de traducción en el directorio src/main/resources. El resolutor predeterminado busca archivos llamados messages con sufijos de configuración regional siguiendo la convención de nomenclatura estándar de ResourceBundle de Java:
messages.properties # Traducciones predeterminadas/por defecto
messages_en.properties # Inglés
messages_de.properties # Alemán
messages_fr_CA.properties # Francés (Canadá)
Cada archivo contiene pares de clave-valor. Las claves son identificadores que usas en el código y los valores son las cadenas traducidas. Puedes incluir marcadores de posición de MessageFormat como {0}, {1} para valores dinámicos:
app.title=Mailbox
menu.inbox=Inbox
menu.outbox=Outbox
greeting=Hello {0}, you have {1} new messages
app.title=Postfach
menu.inbox=Posteingang
menu.outbox=Postausgang
greeting=Hallo {0}, Sie haben {1} neue Nachrichten
El resolutor delega en la cadena de resolución estándar de ResourceBundle de Java, que maneja la coincidencia de configuración regional y la caída automáticamente.
Configurando configuraciones regionales soportadas
La configuración supported-locales le indica a webforJ qué configuraciones regionales soporta tu aplicación. Esta lista es utilizada por la detección automática para comparar la configuración regional del navegador del usuario con las traducciones disponibles. La primera configuración regional de la lista se utiliza como el fallback predeterminado cuando no se encuentra una coincidencia mejor. La clave de propiedad es webforj.i18n.supported-locales y acepta una lista de etiquetas de idiomas BCP 47, por ejemplo en, de.
Consulta la sección Configuración para aprender cómo establecer propiedades para diferentes entornos.
El método t()
Los componentes que implementan la interfaz de preocupación HasTranslation obtienen acceso al método t() para traducir texto. El método toma una clave de traducción y devuelve la cadena localizada para la configuración regional actual de la aplicación:
public class MainLayout extends Composite<AppLayout> implements HasTranslation {
public MainLayout() {
// Traducción simple
String title = t("app.title");
// Traducción con parámetros de MessageFormat
String greeting = t("greeting", userName, messageCount);
// Traducción para una configuración regional específica
String germanTitle = t(Locale.GERMAN, "app.title");
}
}
También puedes usar App.getTranslation() directamente en cualquier lugar sin implementar la interfaz:
String title = App.getTranslation("app.title");
Si no se encuentra una clave de traducción, t() devuelve la clave en sí en lugar de lanzar una excepción. Esto significa que tu aplicación no se romperá si falta una traducción. La clave se muestra tal cual, y se registra una advertencia para que puedas rastrear traducciones faltantes durante el desarrollo.
Implementando componentes traducidos
Un componente traducido combina típicamente HasTranslation con LocaleObserver. Utiliza t() al crear elementos de la interfaz de usuario para establecer el texto traducido inicial. Para soportar el cambio de idioma en tiempo de ejecución, implementa LocaleObserver y actualiza el mismo texto en 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"));
}
}
El sistema de vinculación de datos soporta mensajes de validación y transformación traducidos utilizando Supplier<String> con t(). Consulta mensajes de validación dinámicos, mensajes de transformador dinámicos, y validación consciente de la configuración regional de Jakarta.
Resolutores de traducción personalizados
El resolutor predeterminado carga traducciones de archivos de propiedades ResourceBundle de Java. Para cargar traducciones de una fuente diferente, como una base de datos o un servicio remoto, implementa 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;
}
}
Registrando un resolutor personalizado
En una aplicación webforJ normal, establece el resolutor antes de que la aplicación se inicie, por ejemplo, usando un escuchador del ciclo de vida de la aplicación:
App.setTranslationResolver(new DatabaseTranslationResolver(repository, supportedLocales));
En una aplicación de Spring Boot, expón el resolutor como un 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);
}
}
Cuando no se define un bean TranslationResolver personalizado, la auto-configuración de Spring proporciona un BundleTranslationResolver predeterminado configurado con las configuraciones regionales soportadas de application.properties.