JavaFX: Implementierung des ResourceBundle

Die Unterstützung einer Mehrsprachigkeit in Java Anwendungen wird mit dem ResourceBundle umgesetzt dabei ist unter JavaFX eine kleine Besonderheit zu beachten welche ich hier gerne erläutern möchte.

Am Anfang einer JavaFX Anwendung steht immer eine Stage welche als erstes gestartet wird.

public class Main extends Application {
   public static void main(String[] args) {
    launch(args);
   }

   @Override
   public void start(Stage primaryStage) throws IOException {
      primaryStage.setTitle(„JTaskEditor by Stefan Draeger ® 2016 http://www.stefan-draeger-software.de“);
      Pane myPane = (Pane) FXMLLoader.load(getClass().getClassLoader().getResource(„views/main.fxml“));
      Scene myScene = new Scene(myPane);
      primaryStage.setScene(myScene);
      primaryStage.show();
   }
}

Für das laden dieser Stage wird der javafx.fxml FXMLLoader benötigt dieser kann im einfachsten Fall ein einzeiliger Aufruf werden. (Wie im Beispiel oben zu sehen.)

Wenn man jedoch ein ResourceBundle für die Mehrsprachigkeit verwenden möchte so muss der javafx.fxml.FXMLLoader wie folgt verwendet werden.

FXMLLoader loader = new FXMLLoader();
ResourceBundle bundle = ResourceBundle.getBundle("bundle.jtaskeditor", getSystemLocale());
loader.setResources(bundle);


private Locale getSystemLocale(){
   String country = System.getProperty("user.country");
   return new Locale(String.format("%s_%s", country.toLowerCase(),country.toUpperCase()));
}

Es wird in Zeile 2 das ResourceBundle aus dem Ordner „src/main/resources/bundle“ mit der aktuellen System Sprache (java.util.Locale) geladen. Dazu habe ich eine kleine Methode geschrieben welche die aktuelle java.util.Locale aus den Systempropertys läd.

Die Verwendung dieses ResourceBundle in einer FXML Datei ist relativ einfach wie dieses Beispiel zeigt.

<?xml version="1.0" encoding="UTF-8"?>


<?import java.net.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.MenuItem?>


<MenuBar>
   <menus>
      <Menu mnemonicParsing="false" text="%file">
<items>
   <MenuItem text="%new" />
</items>
      </Menu>
   </menus>
</MenuBar>

Der Key einer Textresource wird mit einem Prozentzeichen eingeleitet, dadurch wird das korrekte Key/Value Paar gefunden und „geladen“. Die Local wird vorher programmatisch eingestellt (auf die Systemsprache), hier könnte man noch über ein Einstellungsfeld in der Anwendung nachdenken jedoch wäre dieses für dieses Tutorial zuviel.

Möchte man nun das ResourceBundle programmatisch im Java Quellcode verwenden so bietet das Objekt java.util.ResourceBundle die Methode bundle.getString(String key) an welche wiederum das korrekte Key / Value Paar findet.

Wenn jedoch der Key nicht existiert, so wird eine MissingResourceException geworfen, bzw in einer FXML Datei eine LoadException: Resource „<<key>>“ not found.

3 Gedanken zu „JavaFX: Implementierung des ResourceBundle

  • 19. Januar 2020 um 13:27
    Permalink

    Genau das ist mein Problem.

    Was tun wenn der Key nicht gefunden wird, wie kann ich dann einen Standardwert eintragen ohne das die App abstürzt.

    Antwort
    • 19. Januar 2020 um 13:55
      Permalink

      Hi,

      es gibt immer eine „Default“ Resourcebundle diese lautet einfach nur wie die Anwendung heißt qusi ohne eine Locale im Format de_DE am ende. Die Datei wird im gleichen Ordner abgelegt wo auch die anderen Resourcebundles (*.properties Dateien) liegen.

      Gruß,

      Stefan Draeger

      Antwort
  • 1. Februar 2020 um 13:17
    Permalink

    Das kann man machen, aber sicher wäre eine Lösung in der für jeden nicht gefunden Key ein DefaultValue ausgegeben wird.

    Der Fehler im Key muss ja nicht unbedingt in der Rescourcendatei liegen, er kann auch durch eine Tippfehler im fxml sein und dann hilft das Default nicht weiter.

    Antwort

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.