JavaFX 2和国际化

在学习基础知识之后,我开始编写第一个JavaFX 2应用程序,并希望将其国际化。

我注意到,在JavaFX 1.x中,脚本语言允许非常简单的string国际化。 JavaFX 2中有没有类似的function?

基本上:JavaFX 2应用程序国际化的最佳实践是什么?

java应用程序国际化的基本步骤(其中包括) Locale lizing和资源捆绑。 在JavaFX中,可以使用FXMLLoader#setResources()来达到此目的。 这里有一个SSCCE演示来演示它。 这些代码是自描述性的。
演示软件包结构:

 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

 <?xml version="1.0" encoding="UTF-8"?> <?import javafx.scene.layout.*?> <?import javafx.scene.control.*?> <?import javafx.scene.*?> <BorderPane fx:controller="bundledemo.MyController" xmlns:fx="http://javafx.com/fxml"> <top> <!-- This label's text will be set by the controller --> <Label fx:id="lblTextByController"/> </top> <center> <!-- This label's text will be taken from the bundle automatically --> <Label text="%key2"/> </center> </BorderPane> 

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.getString("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<ActionEvent>() { @Override public void handle(ActionEvent event) { loadView(new Locale("en", "EN")); } }); Button btnKG = new Button(); btnKG.setText("Kyrgyz"); btnKG.setOnAction(new EventHandler<ActionEvent>() { @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(String[] args) { launch(args); } } 

截图:

在这里输入图像说明

这适用于我:

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

在捆绑包中

 LangBundle_en.properties LangBundle_de.properties 

示例内容:

 enter_pwd=Enter your password: 

加载它们我使用下面的代码:

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

看看我的例子 在这里输入图像说明

更多我在这里或在GitHub上描述

更新:

该解决scheme在Messages.java

 /** * The class with all messages of this application. */ public abstract class Messages { private static ResourceBundle BUNDLE; private static final String FIELD_NAME = "lookup"; private static final String BUNDLE_NAME = "messages/messages"; private static final String CONTROLS_BUNDLE_NAME = "com/sun/javafx/scene/control/skin/resources/controls"; public static final String MAIN_APP_TITLE; public static final String DIALOG_HEADER; public static final String MAIN_CONTROLLER_CONTENT_TEXT; public static final String MAIN_CONTROLLER_HELLO_TEXT; public static final String 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.getString("MainApp.title"); DIALOG_HEADER = BUNDLE.getString("Dialog.information.header"); MAIN_CONTROLLER_CONTENT_TEXT = BUNDLE.getString("MainController.contentText"); MAIN_CONTROLLER_HELLO_TEXT = BUNDLE.getString("MainController.helloText"); MAIN_CONTROLLER_GOODBYE_TEXT = BUNDLE.getString("MainController.goodbyeText"); } public static ResourceBundle GetBundle() { return BUNDLE; } } 

并在PropertyLoader.java

 public class PropertyLoader extends ResourceBundle.Control { private static final String PROPERTIES_RESOURCE_NAME = "properties"; private static final PropertyLoader INSTANCE = new PropertyLoader(); public static PropertyLoader getInstance() { return INSTANCE; } @Override public ResourceBundle newBundle(final String baseName, final Locale locale, final String format, final ClassLoader loader, final boolean reload) throws IllegalAccessException, InstantiationException, IOException { final String bundleName = toBundleName(baseName, locale); final String 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; } }