JavaFX在整个应用程序中更改Locale

时间:2016-12-23 15:10:40

标签: javafx locale resourcebundle

这是我的# For more information on configuration, see: # * Official English Documentation: http://nginx.org/en/docs/ # * Official Russian Documentation: http://nginx.org/ru/docs/ user nginx; worker_processes auto; error_log /var/log/nginx/error.log; pid /run/nginx.pid; # Load dynamic modules. See /usr/share/nginx/README.dynamic. # include /usr/share/nginx/modules/*.conf; events { worker_connections 1024; } http { log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; include /etc/nginx/mime.types; default_type application/octet-stream; # Load modular configuration files from the /etc/nginx/conf.d directory. # See http://nginx.org/en/docs/ngx_core_module.html#include # for more information. include /etc/nginx/conf.d/*.conf; server { listen 80 default_server; listen [::]:80 default_server; server_name _; root /srv/www/main/htdocs; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; location /vcheck { proxy_pass http://127.0.0.1:8080$is_args$query_string; # proxy_buffer_size 128k; # proxy_buffers 4 256k; # proxy_busy_buffers_size 256k; # proxy_http_version 1.1; # proxy_set_header Upgrade $http_upgrade; # proxy_set_header Connection 'upgrade'; # proxy_set_header Host $host; # proxy_cache_bypass $http_upgrade; # proxy_redirect off; proxy_read_timeout 600s; } location ~ \.php$ { include fastcgi.conf; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock; fastcgi_index routes.php$is_args$query_string; } location / { if (-f $request_filename) { expires max; break; } if ($request_filename !~ "\.(js|htc|ico|gif|jpg|png|css)$") { rewrite ^(.*) /routes.php last; } } } } ,我申请的入口点。

StartApp.java

然后在public class StartApp extends Application { private Locale locale = new Locale("en"); public Locale getLocale(){ return locale; } public void setLocale(Locale locale){ this.locale = locale; } @Override public void start(Stage primaryStage) throws Exception{ ResourceBundle bundle = ResourceBundle.getBundle("resources.bundles/MyBundle", locale); FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("../view/LoginView.fxml"), bundle); Parent root = fxmlLoader.load(); primaryStage.setTitle("Title"); primaryStage.setScene(new Scene(root, 750, 400)); primaryStage.setResizable(false); primaryStage.show(); } public static void main(String[] args) throws SQLException { launch(args); } 上创建StartApp实例并为2个按钮设置onActions

LoginController.java

这是我的StartApp startApp = new StartApp(); @Override public void initialize(URL location, ResourceBundle resources) { bundle = resources; plBtn.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { try { startApp.setLocale(new Locale("pl")); changeLanguage(event); } catch (Exception e) { e.printStackTrace(); } } }); enBtn.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { try { startApp.setLocale(new Locale("en")); changeLanguage(event); } catch (Exception e) { e.printStackTrace(); } } }); 方法,它刷新当前窗口并更改其语言

changeLanguage

到目前为止一切正常,一旦点击按钮就会改变语言。但我现在要做的是用选择的语言打开新窗口(阶段),但不幸的是,它始终打开StartApp上设置语言的新场景。

这是public void changeLanguage(ActionEvent event) throws Exception{ ((Node)event.getSource()).getScene().getWindow().hide(); Stage primaryStage = new Stage(); ResourceBundle bundle = ResourceBundle.getBundle("resources.bundles/MyBundle", startApp.getLocale()); FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("../view/LoginView.fxml"), bundle); Parent root = fxmlLoader.load(); primaryStage.setTitle("Title2"); primaryStage.setScene(new Scene(root, 750, 400)); primaryStage.setResizable(false); primaryStage.show(); } 中的方法,而不是打开新阶段。

LoginController

顺便说一下。 Iv尝试将StartApp扩展到LoginController,使locale公开等等,每次结束时都是如此。当我创建

public void register(ActionEvent event) throws Exception{
    ((Node)event.getSource()).getScene().getWindow().hide();
    Stage primaryStage = new Stage();
    ResourceBundle bundle = ResourceBundle.getBundle("resources.bundles/MyBundle", startApp.getLocale());
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("../view/RegisterView.fxml"), bundle);
    Parent root = fxmlLoader.load();        
    primaryStage.setTitle("Title2");
    primaryStage.setScene(new Scene(root, 750, 400));

    primaryStage.setResizable(false);
    primaryStage.show();
}
Locale newLocale = null;

,然后在我点击LoginController中定义的按钮后尝试为其赋值,我得到了nullpointerexception。

1 个答案:

答案 0 :(得分:0)

我不知道如何通过一个命令更改所有文本。 为了保持简单,我只是分别重命名每个元素。

示例:

i18n/messages.properties

label.welcome = Welcome

i18n/messages_ukr.properties

label.welcome = Ласкаво просимо

i18n/messages_rus.properties

label.welcome = Добро пожаловать

Singleton Context.java 将包含当前语言环境:

public class Context {

    private final List<Locale> availableLocales;

    private Locale currentLocale;

    private static Context instance;

    public static Context getInstance() {
        if (instance == null) {
            instance = new Context();
        }
        return instance;
    }

    private Context() {
        availableLocales = new LinkedList<>();
        availableLocales.add(new Locale("eng"));
        availableLocales.add(new Locale("ukr"));
        availableLocales.add(new Locale("rus"));
        currentLocale = new Locale("eng");  // default locale
    }

    /**
     * This method is used to return available locales
     *
     * @return available locales
     */
    public List<Locale> getAvailableLocales() {
        return availableLocales;
    }

    /**
     * This method is used to return current locale setting
     *
     * @return current locale
     */
    public Locale getCurrentLocale() {
        return currentLocale;
    }

    /**
     * This method is used to set current locale setting
     *
     * @param currentLocale locale to set
     */
    public void setCurrentLocale(Locale currentLocale) {
        this.currentLocale = currentLocale;
    }

Util 类 MessageUtil.java 将在当前语言环境中返回消息(在上下文中设置):

/**
 * This class is used to provide methods to work with localized messages
 *
 * @author manfredi
 */
public abstract class MessageUtil {
    private final static Logger logger = LoggerFactory.getLogger(MessageUtil.class);
    private final static String RESOURCE_NAME = "i18n.messages";

    /**
     * This method is used to return resource bundle with current locale
     *
     * @return resource bundle with current locale. Otherwise resource bundle with default locale.
     */
    public static ResourceBundle getResourceBundle() {
        return ResourceBundle.getBundle(RESOURCE_NAME, Context.getInstance().getCurrentLocale());
    }

    /**
     * This method is used to return localized message by it`s {@code key}
     *
     * @param key message key
     * @return localized message
     */
    public static String getMessage(String key) {
        String message;
        try {
            message = getResourceBundle().getString(key);
        } catch (MissingResourceException e) {
            logger.error("{}", e.getMessage());
            message = key;
        }
        return message;
    }

    /**
     * This method is used to format localized message by it`s {@code key} using {@code args} as arguments list
     *
     * @param key  message key by which the corresponding message will be found
     * @param args list of arguments used in the message
     * @return formatted localized message
     */
    public static String formatMessage(String key, Object... args) {
        MessageFormat messageFormat = new MessageFormat(getMessage(key), getResourceBundle().getLocale());
        return messageFormat.format(args);
    }

}

我使用 SceneBuilder 工具来创建 *.fxml 文件。 例如,包含用于语言更改的 Label 和 ChoiceBox 的文件之一的屏幕控制器可能如下所示:

public class LanguageChangeScreenController implements Initializable {
    @FXML
    private Label welcomeLabel;
    
    @FXML
    private ChoiceBox<Locale> languageChoiceBox;
    
    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
        initLanguageChangeListener();
        refreshLocalization(); // I use %key.name syntax in .fxml files to initialize component's names instead of calling this method here
    }
    
    **
     * This method is used to update the name of each component on the screen
     */
    private void refreshLocalization() {
        welcomeLabel.setText(MessageUtil.getMessage("label.welcome"));
    }
    
    private void initLanguageChangeListener() {
        languageChoiceBox.getItems().addAll(Context.getInstance().getAvailableLocales());
        languageChoiceBox.getSelectionModel().select(Context.getInstance().getCurrentLocale());
        languageChoiceBox.setOnAction(actionEvent -> {
            Context.getInstance().setCurrentLocale(languageChoiceBox.getSelectionModel().getSelectedItem());
            refreshLocalization();
        });
    }
}