Issue
I need to localize JavaFX built-in controls. Prior to Jigsaw there were to ways to achieve this:
- Via additional properties file which has to be placed into
com.sun.javafx...
package - Via reflection API, like shown here
Both methods aren't compatible with Java modules, because com/sun/javafx/scene/control/*
isn't the part of the public API and there is no way to create two packages with identical name even if they belong to the different projects.
Any chance to hack this issue to get access to the internal package? More specifically ControlResources classloader.
Related questions:
Solution
Ok, I've lost the whole day digging this topic.
Short answer: it's not possible.
Long answer
You can use add-exports
and add-opens
to get access to the com.sun.javafx.scene.control.skin.resources
, but it will only work if you are not using named modules, in other words, your app must not be modularized.
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<configuration>
<mainClass>${bld.mainClass}</mainClass>
<executable>${java.home}/bin/java</executable>
<options>
<option>--add-exports</option>
<option>javafx.controls/com.sun.javafx.scene.control.skin.resources=app.module</option>
<option>--add-opens</option>
<option>javafx.controls/com.sun.javafx.scene.control.skin.resources=app.module</option>
</options>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerArgs>
<arg>--add-exports</arg>
<arg>javafx.controls/com.sun.javafx.scene.control.skin.resources=app.module</arg>
<arg>--add-opens</arg>
<arg>javafx.controls/com.sun.javafx.scene.control.skin.resources=app.module</arg>
</compilerArgs>
</configuration>
</plugin>
If your app is modularized, you'll get this.
Caused by: java.lang.UnsupportedOperationException: ResourceBundle.Control not supported in named modules
at java.base/java.util.ResourceBundle.checkNamedModule(ResourceBundle.java:1547)
at java.base/java.util.ResourceBundle.getBundle(ResourceBundle.java:1508)
This is because the only way to get access to the resources that are located in another module is SPI (docs here). OpenJFX doesn't implement ResourceBundleProvider
to provide access to controls internationalization, because it's a part of internal API.
So, this problem can only be solved by OpenJFX devs, but judging to the last OpenJFX changelogs, they're highly concentrated on fixing typos, not features.
Answered By - Evan