Traduction 25.12
webforJ inclut un système de traduction intégré permettant de rechercher des chaînes localisées par clé. Le système se compose d'un résolveur de traduction qui associe des clés à des textes localisés, d'une interface de préoccupation HasTranslation qui fournit une méthode t() pratique, App.getTranslation() pour un accès direct partout, la détection automatique de la locale depuis le navigateur et un support pour des sources de traduction personnalisées comme les bases de données.
Résolveur de traduction
Le résolveur de traduction est le système qui recherche des chaînes localisées pour une clé et une locale données. webforJ fournit un résolveur par défaut, BundleTranslationResolver, qui charge des traductions à partir de fichiers de propriétés Java ResourceBundle sur le classpath. Cela fonctionne immédiatement sans dépendances supplémentaires.
Fichiers de paquet de ressources
Placez vos fichiers de traduction dans le répertoire src/main/resources. Le résolveur par défaut recherche des fichiers nommés messages avec des suffixes de locale suivant la convention de nommage standard des ResourceBundle Java :
messages.properties # Traductions par défaut/de secours
messages_en.properties # Anglais
messages_de.properties # Allemand
messages_fr_CA.properties # Français (Canada)
Chaque fichier contient des paires clé-valeur. Les clés sont des identifiants que vous utilisez dans le code, et les valeurs sont les chaînes traduites. Vous pouvez inclure des espaces réservés MessageFormat comme {0}, {1} pour des valeurs dynamiques :
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
Le résolveur délègue à la chaîne de résolution standard de Java ResourceBundle, qui gère automatiquement la correspondance des locales et les secours.
Configuration des locales prises en charge
Le paramètre supported-locales indique à webforJ quelles locales votre application prend en charge. Cette liste est utilisée par la détection automatique pour faire correspondre la locale du navigateur de l'utilisateur aux traductions disponibles. La première locale de la liste est utilisée comme secours par défaut lorsqu'aucune meilleure correspondance n'est trouvée. La clé de propriété est webforj.i18n.supported-locales et accepte une liste de balises de langue BCP 47, par exemple en, de.
Voir la section Configuration pour apprendre comment définir des propriétés pour différents environnements.
La méthode t()
Les composants qui implémentent l'interface de préoccupation HasTranslation ont accès à la méthode t() pour traduire du texte. La méthode prend une clé de traduction et retourne la chaîne localisée pour la locale actuelle de l'application :
public class MainLayout extends Composite<AppLayout> implements HasTranslation {
public MainLayout() {
// Traduction simple
String title = t("app.title");
// Traduction avec des paramètres MessageFormat
String greeting = t("greeting", userName, messageCount);
// Traduction pour une locale spécifique
String germanTitle = t(Locale.GERMAN, "app.title");
}
}
Vous pouvez également utiliser App.getTranslation() directement n'importe où sans implémenter l'interface :
String title = App.getTranslation("app.title");
Si une clé de traduction n'est pas trouvée, t() retourne la clé elle-même au lieu de lancer une exception. Cela signifie que votre application ne se cassera pas si une traduction est manquante. La clé est affichée telle quelle et un avertissement est enregistré afin que vous puissiez suivre les traductions manquantes pendant le développement.
Implémentation de composants traduits
Un composant traduit combine généralement HasTranslation avec LocaleObserver. Utilisez t() lors de la création d'éléments d'interface utilisateur pour définir le texte traduit initial. Pour supporter le changement de langue à l'exécution, implémentez LocaleObserver et mettez à jour le même texte dans 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"));
}
}
Le système de liaison de données prend en charge les messages de validation et de transformation traduits utilisant Supplier<String> avec t(). Voir messages de validation dynamiques, messages de transformation dynamiques, et validation Jakarta consciente de la locale.
Résolveurs de traduction personnalisés
Le résolveur par défaut charge des traductions à partir de fichiers de propriétés Java ResourceBundle. Pour charger des traductions à partir d'une source différente, comme une base de données ou un service distant, implémentez 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;
}
}
Enregistrement d'un résolveur personnalisé
Dans une application webforJ classique, définissez le résolveur avant que l'application ne démarre, par exemple en utilisant un écouteur de cycle de vie de l'application:
App.setTranslationResolver(new DatabaseTranslationResolver(repository, supportedLocales));
Dans une application Spring Boot, exposez le résolveur en tant que 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);
}
}
Lorsque aucun bean TranslationResolver personnalisé n'est défini, la configuration automatique de Spring fournit un résolveur par défaut BundleTranslationResolver configuré avec les locales prises en charge à partir de application.properties.