Localizing JavaFx Controls

后端 未结 4 1625
悲哀的现实
悲哀的现实 2020-12-10 19:11

I am trying add a ResourceBundle for my language for the JavaFx controls but am failing to do so.

I tried to add controls_fi_FI.properties in the classpath.. and hop

4条回答
  •  一个人的身影
    2020-12-10 19:20

    I reversed bundle loading and came up with a dirty solution in case putting a jar to jre/lib/ext is not an option. Default algorithm requires a bundle file to be ISO-8859-1 encoded and doesn't provide any means to specify encoding. My solution addresses encoding issue too.

    The following method loads resource with application classloader and puts resulting bundle to the bundle cache using extension classloader (which is used in runtime by javafx classes to lookup bundles).

    import com.sun.javafx.scene.control.skin.resources.ControlResources;
    import java.util.Locale;
    import java.util.PropertyResourceBundle;
    import java.util.ResourceBundle;
    // rest of the imports is ommitted
    
    private void putResourceBundleInCache(String baseName, Charset cs) throws ReflectiveOperationException, IOException {
        Locale currentLocale = Locale.getDefault();
        ResourceBundle.Control control = ResourceBundle.Control.getControl(ResourceBundle.Control.FORMAT_DEFAULT);
        String resourceName = control.toResourceName(control.toBundleName(baseName, currentLocale), "properties");
        ResourceBundle bundle;
        try (Reader reader = new InputStreamReader(getClass().getClassLoader().getResourceAsStream(resourceName), cs)) {
            bundle = new PropertyResourceBundle(reader);
        }
        Class cacheKeyClass = Class.forName("java.util.ResourceBundle$CacheKey");
        Constructor cacheKeyClassConstructor = cacheKeyClass.getDeclaredConstructor(String.class, Locale.class, ClassLoader.class);
        cacheKeyClassConstructor.setAccessible(true);
        Object cacheKey = cacheKeyClassConstructor.newInstance(baseName, currentLocale, ControlResources.class.getClassLoader());
        Method putBundleInCache = ResourceBundle.class.getDeclaredMethod("putBundleInCache", cacheKeyClass, ResourceBundle.class, ResourceBundle.Control.class);
        putBundleInCache.setAccessible(true);
        putBundleInCache.invoke(null, cacheKey, bundle, control);
    }
    

    I call it from start method like this:

    public void start(Stage primaryStage) throws Exception {
        putResourceBundleInCache("com/sun/javafx/scene/control/skin/resources/controls", StandardCharsets.UTF_8);
        // mian logic here
    }
    

提交回复
热议问题