【问题标题】:How to internationalize a converter or renderer in Wicket?如何在 Wicket 中国际化转换器或渲染器?
【发布时间】:2014-02-20 08:08:11
【问题描述】:

我正在翻译一个 Web 应用程序,并且 wicket:message 和属性文件通常进展顺利。但是 Wicket 总是希望有一个用于查找字符串的组件。
如何翻译在其方法中无法访问任何 Wicket 组件的转换器和渲染器(即 IConverterIChoiceRenderer 的实现)?

到目前为止,我找到了一种方法 - Application.get().getResourceSettings().getLocalizer().getString(key, null) - 但我必须将字符串设置为“全局”,即与应用程序类相关联。这不利于分离和重用。我怎样才能做得更好?

【问题讨论】:

    标签: localization internationalization wicket translation


    【解决方案1】:

    我认为您应该发明自己的方式来实现这一目标。在我当前的项目中,我们像这样注册了自己的 IStringResourceLoader:

    IStringResourceLoader stringResourceLoader = new OurOwnResourceLoaderImpl();               
    Application.get().getResourceSettings().getStringResourceLoaders().add(stringResourceLoader);
    

    然后例如在 IChoiceRenderer 中我们只需调用 Application.get().getLocalizer().getString("key", null)。

    在我们的 IStringResourceLoader 中,我们正在根据我们自己的约定寻找带有某种字符串模式的包(属性文件)。

    或者您可以通过 org.apache.wicket.resource.loader.BundleStringResourceLoader 在 Application#init 中注册分布在您库的 jar 中的本地化包(即属性文件)。

    Afaik 没有标准的方法来做到这一点,所以这取决于你选择什么路径。

    更新:

    我找到了另一种解决方案,您的库/扩展可以自己注册自己的本地化,因此您无需触摸 Application#init 或创建自己的 IStringResourceLoaders。

    有预注册的字符串资源加载器 org.apache.wicket.resource.loader.InitializerStringResourceLoader(参见 wicket 默认 IResourceSetting 实现,即 ResourceSetting 及其构造函数),它使用 wicket 的 Initializer 机制 - 参见 IInitializer javadoc - 基本上你添加 wicket.properties 文件在你的 jar 类根目录中(即它在 default/none 包中)和里面的文件有:

    initializer=i.am.robot.MyInitilizer
    

    然后是 i.am.robot.MyInitilizer:

    public class MyInitializer implements IInitializer {
    
        /**
         * @param application
         *            The application loading the component
         */
        void init(Application application) {
            // do whatever want
        }
    
        /**
         * @param application
         *            The application loading the component
         */
         void destroy(Application application) {
    
         }
    
    }
    

    现在您在与 IInitializer 实现(在我们的示例中为 MyInitializer)相同的包和名称中创建本地化包

    【讨论】:

    • 好吧,这样属性文件还是全局注册的吧?它们可以位于不同的文件中,但仍与整个 Web 应用程序相关联。
    • 这取决于您将使用什么方式。当您调用 Localizer#getString(...) 时,它会尝试询问每个已注册的 IStringResourceLoader 是否有该本地化键的本地化文本。如果您将使用 org.apache.wicket.resource.loader.BundleStringResourceLoader 而不是 yes,它将以与您的应用程序本地化文件相同的方式注册。
    • 是的,好吧,如果我打电话给getString(key, null),那么我认为它将是全球性的,因为没有任何特定的(例如类)可以附加。但我找到了一个不同的解决方案,检查我刚刚发布的答案。 IInitializer 的东西挺有意思的,我觉得可以结合思路。
    【解决方案2】:

    我想我找到了另一种方式......

    我注意到IStringResourceLoader 也有一个不需要组件的方法String loadStringResource(Class<?> clazz, String key, Locale locale, String style);(以及一个用于在较新的 Wicket 版本中变化的参数)。 clazz 应该是一个组件类,但是......它实际上必须是:)

    我能够用一种新方法实现我自己的class MyLocalizer extends Localizer
    getString(String key, Class<?> cl, IModel<?> model, Locale locale, String defaultValue)
    其工作方式类似于
    getString(String key, Component component, IModel<?> model, String defaultValue)
    但直接使用类而不是组件。它仍然使用相同的属性缓存和资源加载器。

    然后我写了一个abstract class MyConverter implements IConverter,它有一个MyLocalizer getLocalizer() 和一些getString 方法,比如Component 类。基本上它是getLocalizer().getString(key, getClass(), model, locale, defaultValue),所以现在可以将属性附加到转换器类。

    似乎工作:)

    【讨论】:

    • 有趣的方式。我也在考虑它,但这似乎很尴尬,因为您每次都必须投射定位器,或者您必须引入类似于 MyConverter 的东西。反正最后看起来没那么糟糕......
    【解决方案3】:

    如果我明白你的问题...

    您可以使用基于包的属性,这意味着如果您将键/值放入包中的属性文件“package.properties”中。该包下任何子包的每个本地化资源都会返回与请求的键关联的值,直到您在另一个属性文件中覆盖它为止。

    在 1.6.x 之前的 Wicket 中文件名为“package.properties”,在 Wicket 1.6+ 中为“wicket-package.properties

    https://cwiki.apache.org/confluence/display/WICKET/Migration+to+Wicket+6.0#MigrationtoWicket6.0-package.propertiesrenamedtowicket-package.properties

    但是它只适用于组件,在组件之外(当组件参数为空时),可以使用:

    WicketApplication.properties(WebApplication类为WicketApplication.class,该属性文件在同一个包中)。

    applicationGlobalProperty=My Global Localized Property
    

    wicket-package.properties(基于包,与页面放在同一个包中)

    localText=Localized text: A local component text based on wicket-package.properties
    

    LocalizedPage.html(标记模板)

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Localized Page</title>
    </head>
    <body xmlns:wicket="http://wicket.apache.org">
    
    <div>
        <div>
    
            <h2>Texts</h2>
                <div>
                    <wicket:message key="localText"/> <br/>
                    <span wicket:id="localizedLabel"></span>
                </div>
    
        </div>
    
    </div>
    
    </body>
    </html>
    

    LocalizePage.java(代码)

    public class LocalizedPage extends WebPage {
    
        private static final long serialVersionUID = 1L;
    
        public LocalizedPage() {
            super();
        }
    
        @Override
        protected void onInitialize() {
            super.onInitialize();
    
            add(new Label("localizedLabel", new AbstractReadOnlyModel<String>() {
    
                private static final long serialVersionUID = 1L;
    
                @Override
                public String getObject() {
                    return WicketApplication.get().getResourceSettings().getLocalizer().getString("applicationGlobalProperty", null);
                }
            }));
    
        }
    
    }
    

    查看https://repo.twinstone.org/projects/WISTF/repos/wicket-examples-6.x/browse上的完整示例

    【讨论】:

    • Afaik 这不适用于 Application.get().getResourceSettings().getLocalizer().getString(key, null)。它适用于层次结构中的包,从组件所在的包开始,然后向上爬到父包。 IE。它必须知道何时开始在包的层次结构中查找,但是当您告诉该组件为空时它不会。
    • 那么,我如何从基于包的属性中获取字符串?
    • 是的,你是对的,不能使用getString(key, null)。在这种情况下,全局属性文件位于以应用程序类命名的属性文件中,例如WicketApplication,我在repo.twinstone.org/projects/WISTF/repos/wicket-examples-6.x/…做了一个小例子@
    • 查看在标记中使用 的 LocalizedPage(它使用属性本身),而不是标签 'localizedLabel'调用 WicketApplication.get().getResourceSettings().getLocalizer().getString("applicationGlobalProperty", null);在代码中。
    • 我找不到任何本地化页面
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多