Traducción 25.12
webforJ incluye un sistema de traducción integrado para buscar cadenas localizadas por clave. El sistema consiste en un resolvedor de traducción que mapea claves a texto localizado, una interfaz de preocupación HasTranslation que proporciona un conveniente método t(), App.getTranslation() para acceso directo desde 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.
Resolvedor de traducción
El resolvedor de traducción es el sistema que busca cadenas localizadas para una clave y configuración regional dada. webforJ proporciona un resolvedor predeterminado, BundleTranslationResolver, que carga traducciones desde 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 resolvedor predeterminado busca archivos llamados messages con sufijos de configuración regional que siguen la convención estándar de nomenclatura ResourceBundle de Java:
messages.properties # Traducciones predeterminadas/de respaldo
messages_en.properties # Inglés
messages_de.properties # Alemán
messages_fr_CA.properties # Francés (Canadá)
Cada archivo contiene pares 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 resolvedor delega en la cadena de resolución estándar de ResourceBundle de Java, que maneja automáticamente la coincidencia de configuraciones regionales y posibles alternativas.
Configuración de configuraciones regionales soportadas
La configuración supported-locales le dice a webforJ qué configuraciones regionales soporta tu aplicación. Esta lista se utiliza para la detección automática para hacer coincidir la configuración regional del navegador del usuario con las traducciones disponibles. La primera configuración regional de la lista se usa como el respaldo predeterminado cuando no se encuentra una mejor coincidencia. La clave de propiedad es webforj.i18n.supported-locales y acepta una lista de etiquetas de idioma 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 misma 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 las traducciones faltantes durante el desarrollo.
Implementación de componentes traducidos
Un componente traducido típicamente combina HasTranslation con LocaleObserver. Usa t() al crear elementos de UI 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 enlace de datos soporta mensajes de validación y transformación traducidos usando Supplier<String> con t(). Consulta mensajes de validación dinámicos, mensajes de error del transformador dinámico y validación consciente de la configuración regional de Jakarta.
Resolutores de traducción personalizados
El resolvedor predeterminado carga traducciones desde archivos de propiedades ResourceBundle de Java. Para cargar traducciones desde 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 resolvedor personalizado
En una aplicación webforJ básica, establece el resolvedor antes de que la aplicación inicie, por ejemplo, usando un oyente del ciclo de vida de la aplicación:
App.setTranslationResolver(new DatabaseTranslationResolver(repository, supportedLocales));
En una aplicación de Spring Boot, expone el resolvedor 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 ningún bean de TranslationResolver personalizado, la auto-configuración de Spring proporciona un BundleTranslationResolver predeterminado configurado con las configuraciones regionales soportadas de application.properties.