How to I18n in JavaFX and IntelliJ IDEA


Posted by Steven

Yesterday I noticed there is an important topic missing in my JavaFX workshop: Internationalization. So here is a SSCCE for that. It's basically a copy of my recent commit to my JavaFX workshop.

This simple sample consists of two UI parts. In the north, there is a combo box with languages to choose from. In the center, there is a label that gets translated according to the selection in the combo box.

This is the main class that loads the simple UI and implements the language switch:

  1. package de.stevenschwenke.java.javafx.workshop.chapter_3_advanced_basics;
  2.  
  3. import java.io.IOException;
  4. import java.util.Locale;
  5. import java.util.ResourceBundle;
  6.  
  7. import javafx.application.Application;
  8. import javafx.collections.FXCollections;
  9. import javafx.collections.ObservableList;
  10. import javafx.fxml.FXMLLoader;
  11. import javafx.scene.Scene;
  12. import javafx.scene.control.ComboBox;
  13. import javafx.scene.control.ListCell;
  14. import javafx.scene.layout.BorderPane;
  15. import javafx.scene.layout.Pane;
  16. import javafx.stage.Stage;
  17. import javafx.util.StringConverter;
  18.  
  19. /**
  20.  * JavaFX offers a simple way to translate UI components. In this example, a simple gui implements
  21.  * a language switch. The switch is basically a {@link ComboBox} with two languages to choose. The
  22.  * content-part of the UI is loaded from an fxml file. In this file, the label's text is set to
  23.  * "%label" which means that the text is going to be translated to whatever the set resource
  24.  * bundle provides.
  25.  */
  26. public class E_13_Internationalization extends Application {
  27.  
  28. BorderPane borderPane = new BorderPane();
  29.  
  30. public static void main(String[] args) {
  31. launch(args);
  32. }
  33.  
  34. @Override
  35. public void start(Stage stage) throws Exception {
  36. loadView(new Locale("en", "EN"));
  37. borderPane.setTop(createComboBox());
  38. stage.setScene(new Scene(borderPane));
  39. stage.setTitle("Internationalization");
  40. stage.show();
  41. }
  42.  
  43. private ComboBox<Locale> createComboBox() {
  44. ComboBox<Locale> comboBox = new ComboBox<>();
  45. ObservableList<Locale> options = FXCollections.observableArrayList(Locale.ENGLISH, Locale.GERMAN);
  46. comboBox.setItems(options);
  47. comboBox.setConverter(new StringConverter<Locale>() {
  48. @Override
  49. public String toString(Locale object) {
  50. return object.getDisplayLanguage();
  51. }
  52.  
  53. @Override
  54. public Locale fromString(String string) {
  55. return null;
  56. }
  57. });
  58. comboBox.setCellFactory(p -> new LanguageListCell());
  59. comboBox.getSelectionModel().selectFirst();
  60.  
  61. comboBox.setOnAction(event -> loadView(comboBox.getSelectionModel().getSelectedItem()));
  62. return comboBox;
  63. }
  64.  
  65. private void loadView(Locale locale) {
  66. try {
  67. FXMLLoader fxmlLoader = new FXMLLoader();
  68.  
  69. // Here, just the resource bundles name is mentioned. You can add support for more languages
  70. // by adding more properties-files with language-specific endings like
  71. // "E_13_Internationalization_fr.properties".
  72. fxmlLoader.setResources(ResourceBundle.getBundle("E_13_Internationalization", locale));
  73.  
  74. Pane pane = (BorderPane) fxmlLoader.load(this.getClass().getResource("/E_13_Internationalization.fxml").openStream());
  75. borderPane.setCenter(pane);
  76. } catch (IOException ex) {
  77. ex.printStackTrace();
  78. }
  79. }
  80.  
  81. class LanguageListCell extends ListCell<Locale> {
  82. @Override protected void updateItem(Locale item, boolean empty) {
  83. super.updateItem(item, empty);
  84. if (item != null) {
  85. setText(item.getDisplayLanguage());
  86. }
  87. }
  88. }
  89. }

This fxml-file is the center part of the UI. It just holds a label that gets translated:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2.  
  3. <?import javafx.scene.control.Label?>
  4. <?import javafx.scene.layout.BorderPane?>
  5. <BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.45" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.stevenschwenke.java.javafx.workshop.chapter_3_advanced_basics.E_13_Internationalization">
  6. <center>
  7.  
  8. <!-- The "%" in the text-tag means that the text is going to be translated -->
  9. <Label text="%label" BorderPane.alignment="CENTER" />
  10. </center>
  11. </BorderPane>

And finally the two properties-files for english and german language support:

  1. label="Hier steht ein Text"
  1. label="This is a text"

Intellij IDEA provides a really nice resource bundle editor for managing your translations. This thing allows you to manage the text of all your languages without having to crawl through your properties-files:

TL;DR

JavaFX provides an easy way to translate your UI texts in different languages. When using the resource bundle editor of IntelliJ IDEA, the management of UI texts is a piece of cake.

Category: 
Share: