6 Replies Latest reply: Apr 11, 2013 1:29 PM by 990211 RSS

    text not updated when changing the ResourceBundle

    990211
      this is an abstraction of what i have on my code:

      controller
      public class controller extends VBox{
           @FXML protected Label ex2;
           
           public CtrlMainMenu() throws Exception{
                FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/view/View.fxml"));
                fxmlLoader.setController(this);
                fxmlLoader.setRoot(this);
                fxmlLoader.setResources(CtrlLanguage.resource);
                fxmlLoader.load();
           }
           @Override public void initialize(URL arg0, ResourceBundle arg1) {
                ex2.setText(arg1.getString("ex2"));
           }
      }
      View
      <fx:root type="VBox" xmlns:fx="http://javafx.com/fxml">
           <children>
                <Label text="%ex1"/>
                <Label fx:id="ex2"/>
           <children>
      </fx:root>
      Language controller
      public class CtrlLanguage{
           private static String PATH =
                new File(
                     CtrlImageLoader.class.getProtectionDomain().getCodeSource().getLocation().getPath()
                ).getParentFile().getPath() + "/language/";
           
           public static ResourceBundle resource;
           
           public static void setLanguage(String file) throws Exception{
                try {
                     if(new File(PATH + file).exists())
                          resource = new PropertyResourceBundle(new FileInputStream(PATH + file));
                     else
                          resource = new PropertyResourceBundle(CtrlLanguage.class.getResourceAsStream("/language/"+file));
                } catch (Exception e) {
                     resource = new PropertyResourceBundle(CtrlLanguage.class.getResourceAsStream("/language/EN"));
                }
           }
           public static String get(String key){
                try {
                     return resource.getString(key);
                } catch (Exception e) {
                     return key;
                }
           }
      }
      problem comes when I try to change the language without changing the current root
      the elements of the view are not updated when the bundle is changed (CtrlLanguage.setLanguage("file");) until the root is changed/loaded again

      is there any way so i can make the content change without having to reload again the root?
        • 1. Re: text not updated when changing the ResourceBundle
          jsmith
          is there any way so i can make the content change without having to reload again the root?
          There is nothing in the JavaFX core implementation which supports this feature.
          • 2. Re: text not updated when changing the ResourceBundle
            990211
            so the only ways to do it would be either:
            1-changing all text="%ex" to fx:id="ex", wrapping the resource into a ObjectProperty and add a listener (quite a lot of work to have to modify manually each text)
            2-reload the whole scene while keeping how the elementes were arranged, added, etc (is this even possible?)

            or is there any other way to do it?
            • 3. Re: text not updated when changing the ResourceBundle
              csh
              We are doing this with an ObjectProperty<Locale> and then listening to changes and bind textProperties of Labels.

              it looks something like this:

              label.textProperty().bind(localeManager.createLocalizeableString("resourceBundlePath", "key");
              • 4. Re: text not updated when changing the ResourceBundle
                990211
                what is this createLocalizeableString?
                • 5. Re: text not updated when changing the ResourceBundle
                  csh
                  A method which returns an instance of the following class:
                  /**
                   * A localizable read only property for internationalization of string properties.
                   *
                   * @author Christian Schudt
                   */
                  public final class LocalizableStringProperty extends ReadOnlyStringProperty {
                  
                      private String resourceKey;
                      private StringProperty text;
                      private String baseName;
                      private ClassLoader classLoader;
                  
                      // Keep the listener as hard reference in the class, so that it won't get GCed, until this class has no references any more.
                      private ChangeListener<Locale> changeListener;
                  
                      public LocalizableStringProperty(LocaleManager localeManager, String baseName, String resourceKey) {
                          this(localeManager, baseName, resourceKey, null);
                      }
                  
                      public LocalizableStringProperty(LocaleManager localeManager, String baseName, String resourceKey, ClassLoader classLoader) {
                  
                          changeListener = new ChangeListener<Locale>() {
                              @Override
                              public void changed(ObservableValue<? extends Locale> observableValue, Locale locale, Locale locale1) {
                                  localeChanged(locale1);
                              }
                          };
                          localeManager.localeProperty().addListener(new WeakChangeListener<Locale>(changeListener));
                          this.baseName = baseName;
                          this.classLoader = classLoader;
                          this.resourceKey = resourceKey;
                          text = new SimpleStringProperty();
                          localeChanged(localeManager.getLocale());
                      }
                  
                  
                      private void localeChanged(Locale locale) {
                          ResourceBundle resourceBundle;
                          Locale.setDefault(locale);
                  
                          if (classLoader == null) {
                              resourceBundle = ResourceBundle.getBundle(baseName, locale);
                          } else {
                              resourceBundle = ResourceBundle.getBundle(baseName, locale, classLoader);
                          }
                          text.set(resourceBundle.getString(resourceKey));
                      }
                  
                      @Override
                      public String get() {
                          return text.get();
                      }
                  
                      @Override
                      public Object getBean() {
                          return text.getBean();
                      }
                  
                      @Override
                      public String getName() {
                          return text.getName();
                      }
                  
                      @Override
                      public void addListener(ChangeListener<? super String> changeListener) {
                          text.addListener(changeListener);
                      }
                  
                      @Override
                      public void removeListener(ChangeListener<? super String> changeListener) {
                          text.removeListener(changeListener);
                      }
                  
                      @Override
                      public void addListener(InvalidationListener invalidationListener) {
                          text.addListener(invalidationListener);
                      }
                  
                      @Override
                      public void removeListener(InvalidationListener invalidationListener) {
                          text.removeListener(invalidationListener);
                      }
                  }
                  • 6. Re: text not updated when changing the ResourceBundle
                    990211
                    ummm so i will have to add the localeManager and LocalizableStringProperty into my code?

                    i think it may be much simpler to just change the public static ResourceBundle resource; into public static ObectProperty<ResourceBundle> resource;

                    and on initialize add a listener to the resource to update all the all the texts, since i wont be able to use text="%ex" will have to fill all the controller with lots of variables from the fx:id