2012-04-13 35 views
66

Tôi vừa bắt đầu viết ứng dụng JavaFX 2 đầu tiên của mình sau khi tìm hiểu các khái niệm cơ bản và muốn quốc tế hóa nó.JavaFX 2 và Quốc tế hóa

Tôi nhận thấy rằng trong JavaFX 1.x, ngôn ngữ kịch bản cho phép quốc tế hóa rất đơn giản của các chuỗi. Có bất kỳ tính năng tương tự nào trong JavaFX 2 không?

Về cơ bản: thực tiễn tốt nhất để quốc tế hóa ứng dụng JavaFX 2 là gì?

+0

Đối với chuyển đổi giữa các ngôn ngữ là một số thông tin ở đây: [http://stackoverflow.com/a/26318795/2131257] [ 1] [1]: http://stackoverflow.com/a/26318795/2131257 – Androdos

Trả lời

139

Các bước cơ bản (trong số những người khác) của một ứng dụng java quốc tế hóa, là Locale thu thập dữ liệu và gói tài nguyên. Trong JavaFX, bạn có thể sử dụng FXMLLoader#setResources() cho các mục đích đó. Đây là một bản demo SSCCE để chứng minh nó. Các mã tự mô tả.
Demo gói cấu trúc:

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> 

MyCo ntroller.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); 
    } 
} 

Ảnh chụp màn hình:

enter image description here

+0

Excellen t trả lời và tôi sẽ chấp nhận nó như là nhưng tôi nên đã đề cập rằng tôi đang xây dựng giao diện trong mã chứ không phải là FXML. Có một cách nhanh chóng và dễ dàng để quốc tế hóa trong mã, tôi nhận ra tôi có thể làm một tra cứu ResourceBundle.getBundle + nhưng tôi đã hy vọng có một cái gì đó giống như ký hiệu phím% mà tôi có thể được sử dụng để thay thế. – wobblycogs

+7

Sau đó, bạn có thể làm điều đó theo cách thông thường như trong bất kỳ ứng dụng Java nào khác. Xác định miền địa phương của người dùng/khách hàng sau đó thay đổi miền địa phương của ứng dụng cho phù hợp (lấy dữ liệu lang cụ thể từ DB so với). Tải gói thích hợp bằng 'ResourceBundle.getBundle (" bundles.MyBundle ", ngôn ngữ)'. Thay đổi mọi văn bản bạn đã sử dụng trong khung nhìn/trang của bạn bằng 'bundle.getString (" key ")'. –

+1

Nó không hoạt động đối với tôi nếu tôi cung cấp ResourceBundle trên phương thức setResources(). Nó hoạt động khi tôi cung cấp ResourceBundle thông qua phương thức load(). –

12

này làm việc cho tôi:

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

Trong gói bó là

LangBundle_en.properties 
LangBundle_de.properties 

nội dung mẫu:

enter_pwd=Enter your password: 

Để tải chúng tôi sử dụng đoạn mã sau:

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

    tvSetupPwd.setText(lngBndl.getString("enter_pwd")); 
    // ... 
} 
2

Nhìn vào ví dụ của tôi enter image description here

More tôi đã mô tả here hoặc trên GitHub

Cập nhật:

giải pháp là trong 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; 
    } 
} 

và trong 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; 
    } 
} 
+0

@Moritz bạn đã nhấp vào liên kết và thấy phản hồi chi tiết và các tệp nguồn đầy đủ, tôi đã bao gồm một liên kết để phản hồi lại stackoverflow.com. Bởi vì Bạn, tôi phải chèn ở khắp mọi nơi cùng một mã. Tôi mong bạn thích và không thích –

Các vấn đề liên quan