【问题标题】:What are the best practices for internationalizing a Java Swing desktop application?将 Java Swing 桌面应用程序国际化的最佳实践是什么?
【发布时间】:2010-07-23 19:38:15
【问题描述】:

我敢肯定有很多方法,但是推荐的方法是什么,对您的代码影响最小?

很明显,您创建了属性文件,但是如何交换渲染中的值?在 J2EE 中,您总是只是重新呈现整个页面,因此很容易。但是在 Swing 应用程序中,您是否只需在 paintComponent(Graphics g) 方法中添加 .getProperty() 的代码?

如果是这样的话,它看起来不是很重,因为现在你必须在你不需要的地方重写这个方法......

附加:如何设置通知系统来重新渲染所有当前可见的组件,而不强制使用某种注册模式?

我想如果我覆盖了paintComponent(Graphics g),我所要做的就是触发一个事件发生变化,然后调用paintComponent(Graphics g) 方法......

【问题讨论】:

  • 最简单的方法:要求用户重新启动程序,以使更改生效。

标签: java swing internationalization desktop locale


【解决方案1】:

据我所知,一些应用程序使用布局/组件builders(由 Karsten Lentzsch 建议,并且是 JGoodies API 的一部分)。这些构建器包含用于本地化组件的代码(在后台使用 ResourceBundle)。

其他人(包括我)更喜欢资源注入;这通常是侵入性最小的方法。这是 Swing Application Framework (JSR-296) 和其他 GUI 框架(如 Guts-GUI)选择的方式。

您可能还想查看与您的非常相似的this question

关于“即时”更改语言(Locale 更改通知),我认为使用资源注入时更容易实现(我已经在 Guts-GUI 中实现了这个,Swing 应用程序框架也可能有它但是我不确定)。

Java 无法监听Locale 的更改,因此您必须创建自己的“区域设置服务”(任何区域设置更改请求都应发送到该服务)。在此服务中,您必须枚举所有可见窗口(这可以通过Window.getWindows() 实现,之前无需注册可见组件)然后再次注入资源。

如果您想要一个示例,请查看resource 中的 Guts-GUI source code 包:

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

下面复制了用于更新所有可见窗口的有趣代码:

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

【讨论】:

    【解决方案2】:

    支持动态语言更改是一个棘手的问题。最简单的解决方案是以您可以重新创建任何可见面板的方式组织您的 UI。这避免了注册或更新组件的需要,当语言发生变化时,您只需重新创建视图。

    显然,您会丢失所有可见组件的状态,这可能是个问题 - 但在网页应用程序中刷新页面时,这通常是相同的。

    【讨论】:

      【解决方案3】:

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

      查看缓存控制下的this article

      【讨论】:

        【解决方案4】:

        我想出的唯一解决方案是为所有需要重新渲染的组件创建一个庞大的注册表。然后,如果调用切换区域设置,您只需调用注册表,它将遍历所有已注册的组件并调整它们的值。因此,例如,对于所有已注册的 JLabels,它会按照以下方式做一些事情:

        for(JLabel specificJLabel : REGISTRY.registeredJLabels)
        {
          String localeKey = specificJLabel.getActionCommand();
          specificJLabel.setText(ResourceBundle.getString(localeKey)); 
        }
        

        Locale 键存储在组件 ActionCommand 中的位置。然后无论当前正在渲染什么屏幕,主父面板都负责重新渲染它。同样通过这种方式,注册表不必管理 Locale 键,这些键与注册表完全分离。每个组件负责管理它自己的 ResourceBundle 的 Locale Keys。

        【讨论】:

          【解决方案5】:

          您需要的是一个 ResourceBundle,它允许您拥有基于 Locale 的属性文件,您可以像访问属性文件一样访问它。

          Here is a sample on how to do it

          【讨论】:

          • 我明白,这不是真正的问题。问题是您在组件中的何处调用 ResourceBundle 以便在需要时对其进行渲染(或重新渲染)。除了在每个 JComponent 上覆盖 paintComponent(Graphics g) 之外,还有其他方法吗?
          • @Stephane Grenier - 通常用户在不同的国家启动一个程序,并且需要根据他所在的区域设置不同的语言。因为在示例中,您在构建它时添加了 I18 的东西会很艰难。您需要更改语言环境并至少关闭窗口并重新创建它,或者取决于小部件调用 setText() 或其他。
          • 不幸的是,我需要能够实时进行,这是针对我正在开发的信息亭应用程序。我想我可以通过重写 paintComponent 方法来做到这一点,并且需要仔细考虑。我只是希望有一个更简单的方法。
          猜你喜欢
          • 2010-09-13
          • 2010-09-14
          • 1970-01-01
          • 1970-01-01
          • 2011-11-17
          • 2013-02-18
          • 1970-01-01
          • 2014-04-22
          • 1970-01-01
          相关资源
          最近更新 更多