Traduction 25.12
webforJ inclut un système de traduction intégré pour rechercher des chaînes localisées par clé. Le système se compose d'un résolveur de traduction qui mappe les clés aux textes localisés, d'une interface de préoccupation HasTranslation qui fournit une méthode pratique t(), App.getTranslation() pour un accès direct partout, une détection automatique de la locale depuis le navigateur, et un support pour des sources de traduction personnalisées telles que des bases de données.
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."
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 les traductions depuis les fichiers de propriétés Java ResourceBundle sur le classpath. Cela fonctionne dès la sortie de la boîte sans dépendances supplémentaires.
Fichiers de bundle 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 Java ResourceBundle :
messages.properties # Traductions par défaut
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=Boîte aux lettres
menu.inbox=Boîte de réception
menu.outbox=Boîte d'envoi
greeting=Bonjour {0}, vous avez {1} nouveaux 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 ResourceBundle de Java, 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 supporte. 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 lorsque 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 le 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 plutôt que de lancer une exception. Cela signifie que votre application ne plantera 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 initial traduit. Pour prendre en charge 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 des données prend en charge les messages de validation et de transformation traduits en utilisant Supplier<String> avec t(). Voir messages de validation dynamiques, messages de transformateur dynamiques, et validation Jakarta consciente de la locale.
Résolveurs de traduction personnalisés
Le résolveur par défaut charge les traductions depuis des fichiers de propriétés Java ResourceBundle. Pour charger des traductions depuis une source différente, telle qu'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 standard, définissez le résolveur avant le démarrage de l'application, 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 depuis application.properties.