Here's a diff on my quick hack in Parser.java that does the trick for me, at least:
685,690d682 < // Begin BF < String key = attr.getValue(); < String value = getChainedLocalizer().getString(key); < if (!key.equals(value)) < attr.setValue(value); < // End BF 974,1120d965 < < private ChainedProperties getChainedLocalizer() < { < if (chainedLocalizer == null) < chainedLocalizer < = ChainedProperties.createInstance(engine.getLocalizer()); < return chainedLocalizer; < } < private ChainedProperties chainedLocalizer; < } < < < < < < /** < * Released under the terms of the above license... < * < * Utility for chaining property values. For example, if a < * properties file contains < * <pre> < * font.general = SansSerif--12 < * menu.font = @font.general < * </pre> < * then looking up <code>menu.font</code> gives you < * "SansSerif--12". < * < * @author Babak Farhang < */ < abstract class ChainedProperties { < < private final String prefix; < < protected ChainedProperties(String prefix) { < if (prefix == null) < throw new IllegalArgumentException("Null prefix"); < this.prefix = prefix; < } < < public final String getString(String key) { < if (key == null) < throw new IllegalArgumentException("Null key"); < return getStringImpl(key, 0); < } < < private String getStringImpl(String key, int depth) < { < if (depth > 64) < throw new IllegalStateException("Indirection overflow. key: " + key); < final String tkey = translateKey(key); < if (tkey == null) < return key; < final String value = findValue(tkey); < if (value == null) < return key; < return getStringImpl(value, depth + 1); < } < < private String translateKey(String key) { < return key.startsWith(prefix) ? key.substring(prefix.length()) : null; < } < < protected abstract String findValue(String key); < < < private static class ResourceBundleImpl extends ChainedProperties < { < private final ResourceBundle bundle; < < ResourceBundleImpl(ResourceBundle bundle, String prefix) { < super(prefix); < this.bundle = bundle; < } < < protected String findValue(String key) { < return bundle.getString(key); < } < } < < < private static class PropertiesImpl extends ChainedProperties < { < private final Properties properties; < < PropertiesImpl(Properties properties, String prefix) { < super(prefix); < this.properties = properties; < } < < protected String findValue(String key) { < return properties.getProperty(key); < } < < } < < < private static class LocalizerImpl extends ChainedProperties < { < private final Localizer localizer; < < LocalizerImpl(Localizer localizer, String prefix) { < super(prefix); < this.localizer = localizer; < } < < protected String findValue(String key) { < return localizer.getString(key); < } < < } < < < < public static ChainedProperties createInstance(Properties properties) { < return createInstance(properties, "@"); < } < < public static ChainedProperties createInstance(Properties properties, < String prefix) < { < return new PropertiesImpl(properties, prefix); < } < < < < public static ChainedProperties createInstance(ResourceBundle bundle) { < return createInstance(bundle, "@"); < } < < public static ChainedProperties createInstance(ResourceBundle bundle, < String prefix) < { < return new ResourceBundleImpl(bundle, prefix); < } < < < < public static ChainedProperties createInstance(Localizer localizer) { < return createInstance(localizer, "@"); < } < < public static ChainedProperties createInstance(Localizer localizer, < String prefix) < { < return new LocalizerImpl(localizer, prefix); < } < Actually, the above does a little more. (See the "javadoc" comment.) I suggest that the Localizer should not be a parameter of Converter.convert(). By the time Converter.convert(Class type, Attribute attr) would be called, any kind of localization / indirection will have already taken place in the Parser. That would be better separation of concerns for the Converter implementations... Regards, -b. On 10/10/05, List for Users of Carlsbad Cubes' Technologies and Products <Forum@carlsbadcubes.com> wrote: > Hi all, > > This does sound as a not bad idea to me. > The main reason is that it makes localization (or more generally > indirection) explicit. > Indeed, looking at the following snippet you can't really say whether > "ok" is a text or a key in the localization file. > ... > <button text="ok" /> > .. > while this is selfexplained > <button text="@ok" /> > > Second, this approach makes it very easy to write some automated tool > to check whether every key in swixml descriptor has corresponding > entry in localization file. > This could be an issue while refactoring large applications. > > Thanks, > Vitali > > > 2005/9/26, List for Users of Carlsbad Cubes' Technologies and Products > <Forum@carlsbadcubes.com>: > > Hi there, > > > > I'm a new SwixML user and would like to submit > > a proposal. > > > > The Need: > > ======== > > > > Looking at how the StringConverter classes localizes > > attribute values using essentially a properties file, it > > seems to me it would be useful if we could extend this > > model so that *all* attribute values could be indirected, > > when necessary. > > > > In the following snippet ... > > > > <frame name="mainframe" > > size="640,480" > > title="S W I X M L" > > defaultCloseOperation="JFrame.EXIT_ON_CLOSE" > > defaultLookAndFeelDecorated="true" > > bundle="ui.locale.swix"> > > > > <menubar name="menubar"> > > <menu name="filemenu" text="mus_File" font="SansSerif--12"> > > <menuitem name="mi_new" > > text="mus_New" font="SansSerif--12" > > icon="ui/icons/new.gif" > > mnemonic="VK_N" > > accelerator="control N" > > action="newAction" /> > > > > ...the font attribute assignment (font="SansSerif--12") > > will likely be sprinkled liberally elsewhere across the > > file. If I change that font value in one place, I will > > likely need to change the other font values elsewhere > > in the file, also. So you can see a basic need for > > indirection: I need a central place to be able to assign > > font values to a whole bunch of components. > > > > Besides fonts, other component attributes might need > > to be centralized in one place (e.g. the background > > color). > > > > The Problem: > > ========== > > > > I *could* try... > > > > <frame name="mainframe" > > size="640,480" > > title="S W I X M L" > > defaultCloseOperation="JFrame.EXIT_ON_CLOSE" > > defaultLookAndFeelDecorated="true" > > bundle="ui.locale.swix"> > > > > <menubar name="menubar"> > > <menu name="filemenu" text="mus_File" font="menu.font"> > > <menuitem name="mi_new" > > text="mus_New" font="menu.font" > > icon="ui/icons/new.gif" > > mnemonic="VK_N" > > accelerator="control N" > > action="newAction" /> > > > > ...with... > > > > menu.font = SansSerif--12 > > > > ...defined in the swix.properties file. > > > > This wont work of course, because only StringConverter > > applies the PropertyResourceBundle to the parsed attribute > > values. > > > > > > Proposal: > > ======= > > > > If an attribute value starts with an escape character, say '@' > > (perhaps with '@@' escaping itself), then the *parser*--not the > > converter, attempts to "localize" the XML attribute value before > > passing it off to the converter. > > > > Alternatively, we could forget about the special escape character > > and attempt to "localize" all attribute values, willy nilly. Personally, > > I'm not for this: it would be better to make the indirection more > > explicit: right now, in order to see if a string is localized, you have > > to check the properties file; you can't tell just from looking at the > > XML. > > > > What do you think? > > > > -Babak > > > > _______________________________________________ > > Forum mailing list > > Forum@carlsbadcubes.com > > http://carlsbadcubes.com/mailman/listinfo/forum_carlsbadcubes.com > > > > _______________________________________________ > Forum mailing list > Forum@carlsbadcubes.com > http://carlsbadcubes.com/mailman/listinfo/forum_carlsbadcubes.com > _______________________________________________ Forum mailing list Forum@carlsbadcubes.com http://carlsbadcubes.com/mailman/listinfo/forum_carlsbadcubes.com