国际化Java Swing桌面应用程序的最佳实践是什么?

6
我相信有很多方法,但最推荐的方法是什么,对你的代码影响最小?
显而易见的是,你需要创建属性文件,但如何在渲染中交换值呢?在 J2EE 中,你只需重新渲染整个页面,所以这很容易。但在 Swing 应用程序中,你是否只需在 paintComponent(Graphics g) 方法中添加 .getProperty() 代码?
如果是这样,那么现在你将不得不在以前不需要的地方重写此方法,这似乎很繁重...
另外:如何设置通知系统以重新渲染所有当前可见的组件,而不强制执行某种注册模式?
我想,如果我覆盖 paintComponent(Graphics g),我所要做的就是触发一个事件,表明已经发生了更改,然后 paintComponent(Graphics g) 方法将被调用...

1
最简单的方法:要求用户重新启动程序,以使更改生效。 - Untitled
5个回答

3
据我所知,一些应用程序使用布局/组件构建器(由Karsten Lentzsch建议,并作为JGoodies API的一部分)。这些构建器包括本地化组件的代码(在幕后使用ResourceBundle)。
其他人(包括我)更喜欢资源注入;这通常是最不侵入的方法。这是Swing Application Framework(JSR-296)和其他GUI框架(如Guts-GUI)选择的方式。
您可能还想看看this question,它与您的问题非常相似。
关于“即时”语言更改(Locale更改通知),我认为使用资源注入更容易实现(我已经在Guts-GUI中实现了这一点,Swing Application Framework可能也有,但我不确定)。

Java没有提供监听Locale更改的方法,因此您需要创建自己的“Locale服务”(任何Locale更改请求都应发送到其中)。在这个服务中,您需要枚举所有可见窗口(可以使用Window.getWindows()实现,无需在注册可见组件之前),然后重新注入资源。

如果您想要一个例子,请查看Guts-GUI源代码中的resource包:

  • ResourceInjector显示了资源注入和更改Locale的方法,它发送了一个通知事件(为此使用了事件总线,但简单的侦听器也可以)
  • WindowController侦听Locale更改事件

更新所有可见窗口的有趣代码如下所示:

for (Window window: Window.getWindows())
{
    if (window.isVisible())
    {
        injectResources(window);
        window.repaint();
        if (window instanceof RootPaneContainer)
        {
            ((RootPaneContainer) window).getRootPane().revalidate();
        }
    }
}

1
我想到的唯一解决方案是创建一个包含所有需要重新渲染的组件的大型注册表。然后,如果调用切换语言环境的函数,只需调用该注册表,它将遍历所有已注册的组件并调整它们的值。例如,对于所有已注册的JLabel,它将执行以下操作:
for(JLabel specificJLabel : REGISTRY.registeredJLabels)
{
  String localeKey = specificJLabel.getActionCommand();
  specificJLabel.setText(ResourceBundle.getString(localeKey)); 
}

Locale键存储在组件ActionCommand中。然后,无论当前呈现的屏幕是什么,主父面板都负责重新呈现它。此外,这种方式注册表不必管理Locale键,这些键与注册表完全解耦。每个组件负责管理其自己的Locale键到ResourceBundle。


1
支持动态语言更改是一个棘手的问题。最简单的解决方案是以这样的方式组织您的用户界面,以便您可以重新创建任何可见面板。这避免了在语言更改时注册或更新组件的需要,您只需重新创建视图即可。
显然,您会失去所有可见组件的状态,这可能是一个问题 - 但通常在Web应用程序刷新页面时也是如此。

1

Java 6 SE 允许您动态重新加载资源包。 只需调用 ResourceBundle 类的 clearCache() 静态函数。 然后再次调用 getBundle()

请参见缓存控件下的 本文


0

1
我明白这一点,但问题并不在于此。问题是在组件中何处调用ResourceBundle以便在需要时呈现(或重新呈现)。除了在每个JComponent上重写paintComponent(Graphics g)之外,是否还有其他方法? - Stephane Grenier
通常情况下,用户在不同国家启动程序时需要根据所在的Locale使用不同的语言。由于在构造中添加I18n的例子很难处理。您需要更改本地设置,并至少关闭窗口并重新创建它,或者根据小部件调用setText()或其他操作。 - Romain Hippeau
不幸的是,我需要能够在实时环境下完成它,这是我正在开发的一个信息亭应用。我认为我可以通过重写paintComponent方法并经过一些慎重考虑来实现它。我只是希望有一种更简单的方法。 - Stephane Grenier

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接