JavaFX 2 et l’internationalisation

Je viens de commencer à écrire ma première application JavaFX 2 après avoir appris les bases et souhaite l’internationaliser.

Je remarque que dans JavaFX 1.x, le langage de script permettait une internationalisation très simple des chaînes. Existe-t-il des fonctionnalités similaires dans JavaFX 2?

Fondamentalement, quelle est la meilleure pratique pour internationaliser une application JavaFX 2?

Les étapes de base (parmi d’autres) d’une internationalisation d’applications Java sont la génération de parameters Locale et le regroupement de ressources. Dans JavaFX, vous pouvez utiliser FXMLLoader#setResources() à cette fin. Voici une démo du SSCCE pour le démontrer. Les codes sont auto-descriptifs.
Structure du package de démonstration:

 bundledemo |------ BundleDemo.java |------ MyController.java |------ MyView.fxml bundles |------ MyBundle_en.properties |------ MyBundle_kg.properties 

MyBundle_en.properties

 key1=Name Surname key2=How are you? 

MyBundle_kg.properties

 key1=Aты Жөнү key2=Кандайсың? 

MyView.fxml

          

MyController.java

 package bundledemo; import java.net.URL; import java.util.ResourceBundle; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.Label; public class MyController implements Initializable { @FXML private Label lblTextByController; private ResourceBundle bundle; @Override public void initialize(URL location, ResourceBundle resources) { bundle = resources; lblTextByController.setText(bundle.getSsortingng("key1")); } } 

BundleDemo.java

 package bundledemo; // imports are ignored. public class BundleDemo extends Application { private Stage stage; @Override public void start(Stage primaryStage) { stage = primaryStage; Button btnEN = new Button(); btnEN.setText("English"); btnEN.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { loadView(new Locale("en", "EN")); } }); Button btnKG = new Button(); btnKG.setText("Kyrgyz"); btnKG.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { loadView(new Locale("kg", "KG")); } }); VBox root = new VBox(20); root.getChildren().add(HBoxBuilder.create().spacing(10).style("-fx-background-color: gray").padding(new Insets(5)).children(btnEN, btnKG).build()); root.getChildren().add(new StackPane()); primaryStage.setScene(new Scene(root, 300, 250)); primaryStage.show(); } private void loadView(Locale locale) { try { FXMLLoader fxmlLoader = new FXMLLoader(); fxmlLoader.setResources(ResourceBundle.getBundle("bundles.MyBundle", locale)); Pane pane = (BorderPane) fxmlLoader.load(this.getClass().getResource("MyView.fxml").openStream()); // replace the content StackPane content = (StackPane) ((VBox) stage.getScene().getRoot()).getChildren().get(1); content.getChildren().clear(); content.getChildren().add(pane); } catch (IOException ex) { ex.printStackTrace(); } } public static void main(Ssortingng[] args) { launch(args); } } 

Capture d’écran:

entrer la description de l'image ici

Cela fonctionne pour moi:

 └───src ├───app ├───bundles // <- here the "bundles" ├───dicts ├───images ├───libs └───resources 

Dans le paquet de paquets sont

 LangBundle_en.properties LangBundle_de.properties 

Contenu de l'échantillon:

 enter_pwd=Enter your password: 

Pour les charger, j'utilise le code suivant:

 @Override public void initialize(URL location, ResourceBundle resources) { ResourceBundle lngBndl = ResourceBundle .getBundle("bundles.LangBundle", new Locale("en", "EN")); tvSetupPwd.setText(lngBndl.getSsortingng("enter_pwd")); // ... } 

Regardez mon exemple entrer la description de l'image ici

Plus j’ai décrit ici ou sur GitHub

Mettre à jour:

la solution est dans Messages.java

 /** * The class with all messages of this application. */ public abstract class Messages { private static ResourceBundle BUNDLE; private static final Ssortingng FIELD_NAME = "lookup"; private static final Ssortingng BUNDLE_NAME = "messages/messages"; private static final Ssortingng CONTROLS_BUNDLE_NAME = "com/sun/javafx/scene/control/skin/resources/controls"; public static final Ssortingng MAIN_APP_TITLE; public static final Ssortingng DIALOG_HEADER; public static final Ssortingng MAIN_CONTROLLER_CONTENT_TEXT; public static final Ssortingng MAIN_CONTROLLER_HELLO_TEXT; public static final Ssortingng MAIN_CONTROLLER_GOODBYE_TEXT; static { final Locale locale = Locale.getDefault(); final ClassLoader classLoader = ControlResources.class.getClassLoader(); final ResourceBundle controlBundle = getBundle(CONTROLS_BUNDLE_NAME, locale, classLoader, PropertyLoader.getInstance()); final ResourceBundle overrideBundle = getBundle(CONTROLS_BUNDLE_NAME, PropertyLoader.getInstance()); final Map override = getUnsafeFieldValue(overrideBundle, FIELD_NAME); final Map original = getUnsafeFieldValue(controlBundle, FIELD_NAME); //noinspection ConstantConditions,ConstantConditions,unchecked original.putAll(override); BUNDLE = getBundle(BUNDLE_NAME, PropertyLoader.getInstance()); MAIN_APP_TITLE = BUNDLE.getSsortingng("MainApp.title"); DIALOG_HEADER = BUNDLE.getSsortingng("Dialog.information.header"); MAIN_CONTROLLER_CONTENT_TEXT = BUNDLE.getSsortingng("MainController.contentText"); MAIN_CONTROLLER_HELLO_TEXT = BUNDLE.getSsortingng("MainController.helloText"); MAIN_CONTROLLER_GOODBYE_TEXT = BUNDLE.getSsortingng("MainController.goodbyeText"); } public static ResourceBundle GetBundle() { return BUNDLE; } } 

et dans PropertyLoader.java

 public class PropertyLoader extends ResourceBundle.Control { private static final Ssortingng PROPERTIES_RESOURCE_NAME = "properties"; private static final PropertyLoader INSTANCE = new PropertyLoader(); public static PropertyLoader getInstance() { return INSTANCE; } @Override public ResourceBundle newBundle(final Ssortingng baseName, final Locale locale, final Ssortingng format, final ClassLoader loader, final boolean reload) throws IllegalAccessException, InstantiationException, IOException { final Ssortingng bundleName = toBundleName(baseName, locale); final Ssortingng resourceName = toResourceName(bundleName, PROPERTIES_RESOURCE_NAME); ResourceBundle bundle = null; InputStream stream = null; if (reload) { final URL url = loader.getResource(resourceName); if (url != null) { final URLConnection connection = url.openConnection(); if (connection != null) { connection.setUseCaches(false); stream = connection.getInputStream(); } } } else { stream = loader.getResourceAsStream(resourceName); } if (stream != null) { try { bundle = new PropertyResourceBundle(new InputStreamReader(stream, StandardCharsets.UTF_8)); } finally { stream.close(); } } return bundle; } }