我正在尝试为JavaFx控件添加我的语言的ResourceBundle,但失败了。
我尝试在类路径中添加controls_fi_FI.properties。并希望它能起作用,但不是。
然后,我查看了负责本地化控件的JavaFx的ControlResources类,并注意到包的基名是"com\sun\javafx\scene\control\skin\resources\controls".
如何将我的properties-file添加到这个包中?我觉得很奇怪,几乎没有任何关于如何做到这一点的信息?
发布于 2014-09-12 01:51:43
我只能通过一个相当大的黑客才能让它工作,这甚至不是远程便携的。然而,也许它会给你足够的工作来创建一个可行的解决方案。(这可以在Java 8下运行。)
我创建了一个包com.sun.javafx.scene.control.skin.resources,并在其中创建了一个controls_fi_FI.properties文件,只有一行
ProgressIndicator.doneString=Valmis我创建了一个包含以下内容的测试应用程序:
import java.util.Locale;
import java.util.ResourceBundle;
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.layout.BorderPane;
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
System.out.println(ResourceBundle.getBundle("com/sun/javafx/scene/control/skin/resources/controls").getString("ProgressIndicator.doneString"));
BorderPane root = new BorderPane();
ProgressIndicator progressIndicator = new ProgressIndicator(1);
root.setCenter(progressIndicator);
Scene scene = new Scene(root,400,400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
Locale.setDefault(new Locale("fi", "FI"));
launch(args);
}
}以大多数方式运行此应用程序并不能达到预期效果:虽然System.out.println(...)会生成正确的结果,但进度指示器中显示的文本却是错误的。
但是,如果我将com/sun/javafx/control/skin/resources/controls_fi_FI.properties捆绑到一个jar文件中,并将该jar文件移动到我的jre/lib/ext安装目录的JDK子目录中(即.与jfxrt.jar相同的位置),它按要求运行(至少在我的简单测试中是这样;正如我所说的,我不认为这是一种健壮的解决方案)。
问题似乎是ControlsResources是由扩展类加载器加载的,所以使用相同的类加载器来加载资源包。
有了比我更好的类加载器知识,您也许能够将其转化为一个合理的解决方案……
发布于 2017-08-31 19:19:53
我创建了简单的"Hello,world!“展示使用多语言支持的现成JavaFX项目的示例是为那些需要更多异国语言(be-BY,ru-RU等)的人准备的。
下面是我解决这个问题的方法,它对我很有效
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;
}
}在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;
}
}以下是白俄罗斯语的演示:

发布于 2018-02-14 02:30:50
我反向加载了包,并想出了一个糟糕的解决方案,以防将jar放到jre/lib/ext中是不可取的。默认算法要求捆绑包文件采用ISO-8859-1编码,并且不提供任何指定编码的方法。我的解决方案也解决了编码问题。
以下方法使用应用程序类加载器加载资源,并使用扩展类加载器( javafx类在运行时使用扩展类加载器查找包)将生成的包放入包缓存中。
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);
}我从start方法调用它,如下所示:
public void start(Stage primaryStage) throws Exception {
putResourceBundleInCache("com/sun/javafx/scene/control/skin/resources/controls", StandardCharsets.UTF_8);
// mian logic here
}https://stackoverflow.com/questions/25791416
复制相似问题