How to implement multilanguage in Java/Swing applications?

时光毁灭记忆、已成空白 提交于 2020-01-01 05:43:06

问题


What are the different ways of implementing multilingual support in Swing applications?

Are you using ResourceBundle with property file and implementing it in every frame? Does it work good for you? What if you use some kind of GUI editor? Is there any other way around?

At work we are using Matisse4MyEclipse and the code gets regenerated every time we save the screen, so simply using Externalize Strings won't work here. One way is to define it as custom property for each component, which is very annoying. Another way is to go over the multilanguage components and their properties again after matisse's generated code, which is a pain, too.


回答1:


Well, you had to use ResourceBundles. But if you are setting the componet text property use instead of human readable text the text for RB.getString(). Then if the Matisse regenerates form the bundle key will stay and localization will work. Example:

I will use this image from Matisse pages:

(source: myeclipseide.com) .

there you can see the the property text. There is value "My New Label". Instead of this you can use rb.getString("myNewLabel.my.message") where rb is ResourceBundle. The only problem should be too intelligent properties editor going against you. I never work with any wysiwyg editor (personal preference, I do always UI design by hand).




回答2:


This is how I implemented the internationalization :

  • give a name to every component which has an internationalized text
  • at runtime, take the container(frame, dialog, applet) ,iterate all the components and build an i18n key for every component using its name and all parent names.
  • for every component type(JTextField, JLable, etc) define some keys for every internationalize field(text, label, hint, etc).
  • take this i18n key and query your ResourceBundle, take the results and populate the component fields.

It works with generated code or with manual created code.

Edit: Here it is :

public void buildIds() {
    buildId(true);
    int count = getComponentCount();
    if (count == 0) {
        return;
    }
    for (int i = 0; i < count; i++) {
        Component component = getComponent(i);
        if (component instanceof AbstractComponent) {
            ((AbstractComponent) component).buildIds();
        }
    }
}

protected void buildId(boolean fireChange) {
    String prevId = this.id;
    String computedId;
    if (getName() == null) {
        computedId = ClassUtilities.shortClassName(getClass()).toLowerCase() + "_" + Long.toHexString(ID_GENERATOR.getAndIncrement());
    } else {
        java.util.List<Component> parents = null;
        Component parent = getParent();
        if (parent != null) {
            StringBuilder buider = new StringBuilder(80);
            parents = new ArrayList<Component>();
            while (parent != null) {
                if (parent.getName() != null) {
                    parents.add(parent);
                }
                parent = parent.getParent();
            }
            Collections.reverse(parents);
            if (parents.size() > 0) {
                for (Component component : parents) {
                    if (buider.length() > 0) {
                        buider.append('.');
                    }
                    buider.append(component.getName());
                }
                buider.append('.');
            }
            buider.append(name);
            computedId = buider.toString().toLowerCase();
        } else {
            computedId = name;
        }
    }
    this.id = computedId;
    if (fireChange && prevId != null && !prevId.equals(computedId)) {
        componentIdChanged(this, prevId);
    }
}



回答3:


I don't know of any way besides ResourceBundle.

Why do you keep regenerating code? I would imagine that it would be fine once you got a page started, but after that it'd be largely unnecessary. Sounds like code generation is your real problem. It's not saving you anything.

Do you try to compose pages out of several Components? I can imagine a common header, footer, and menu that wouldn't have to change all the time. It could be a design issue.

Spring has very nice support for I18N. Maybe it can help you here.




回答4:


Use ResourceBundle class and set the language to locale:

Following is code in java

private static Map<String, ResourceBundle> resourceBundles;

private static ResourceBundle loadBundle(String language) {
    if (resourceBundles == null) {
        resourceBundles = new HashMap<String, ResourceBundle>();
    }

    ResourceBundle currentBundle = resourceBundles.get(language);

    if (currentBundle == null) {

        Locale locale = new Locale(language);
        currentBundle = ResourceBundle.getBundle("i18n.Messages", locale);
        resourceBundles.put(language, currentBundle);
    }

    return currentBundle;
}

public static String messageForKey(String key, String language) {
    ResourceBundle currentBundle = loadBundle(language);
    return currentBundle.getString(key);
}


来源:https://stackoverflow.com/questions/902031/how-to-implement-multilanguage-in-java-swing-applications

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!