I'm translating a web application and things are generally going smoothly with wicket:message and properties files. But Wicket always wants to have a component for looking up strings.
How can I translate converters and renderers (i.e. implementations of IConverter and IChoiceRenderer) which don't have access to any Wicket component in their methods?

So far I found one way - Application.get().getResourceSettings().getLocalizer().getString(key, null) - but I have to make the strings "global", i.e. associated with the application class. That's not nice for separation and reuse. How can I do it better?

有帮助吗?

解决方案 2

I think I found another way...

I noticed that IStringResourceLoader also has a method String loadStringResource(Class<?> clazz, String key, Locale locale, String style); (and one more parameter for variation in newer Wicket versions) which does not require a component. clazz is supposed to be a component class, but... it doesn't actually have to be :)

I was able to implement my own class MyLocalizer extends Localizer with a new method
getString(String key, Class<?> cl, IModel<?> model, Locale locale, String defaultValue)
which works in a similar way to
getString(String key, Component component, IModel<?> model, String defaultValue)
but uses the class directly instead of a component. It still uses the same properties cache and resource loaders.

Then I wrote an abstract class MyConverter implements IConverter which has a MyLocalizer getLocalizer() and a few getString methods like the Component class. Basically it does getLocalizer().getString(key, getClass(), model, locale, defaultValue), so the properties can now be attached to the converter class.

Seems to work :)

其他提示

I think you should invent you own way how to achieve this. Here in my current project we registered our own IStringResourceLoader like this:

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

Then for example in IChoiceRenderer we just call Application.get().getLocalizer().getString("key", null).

Inside our IStringResourceLoader we are looking for bundles (property files) with some string pattern according our own conventions.

Or you can just register localization bundle (ie. properties file) distributed inside your library's jar in Application#init through org.apache.wicket.resource.loader.BundleStringResourceLoader.

Afaik there is no standard way to do that so it's up to you what path you choose.

Updated:

I found another solution how your library/extension can register it's own localization by itself so you needn't to touch Application#init or create your own IStringResourceLoaders.

There is preregistered string resource loader org.apache.wicket.resource.loader.InitializerStringResourceLoader (see wickets default IResourceSetting implementation ie. ResourceSetting and it's constructor) which uses wicket's Initializer mechanism - see IInitializer javadoc - basically you add wicket.properties file in your jar class root (ie. it is in default/none package) and inside file there is:

initializer=i.am.robot.MyInitilizer

then 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) {

     }

}

and now you create your localization bundles in same package and same name as IInitializer implementation (in our example MyInitializer)

If I understand your question...

You can use package based properties that means if you put your keys/values into a property file 'package.properties' in a package. Each localized resource of any subpackage under that package returns the value associated to the requested key until you override it in another property file.

The file name is 'package.properties' in Wicket prior to 1.6.x and 'wicket-package.properties' in Wicket 1.6+

See

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

However it works just for componet, outside the componet (when component argument is null), it is possible to use:

WicketApplication.properties (the WebApplication class is WicketApplication.class, this property file is in the same package).

applicationGlobalProperty=My Global Localized Property

wicket-package.properties (package based, place it in the same package as the page)

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

LocalizedPage.html (markup template)

<!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 (code)

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);
            }
        }));

    }

}

See the full example on https://repo.twinstone.org/projects/WISTF/repos/wicket-examples-6.x/browse

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top