Swing 国际化 - 如何在运行时更新语言

2022-01-18 00:00:00 internationalization java swing

I've followed Googles howto for its Window Builder Pro extension to internationalize my app. Strings that will be shown in labels are now stored in property-files that were created by the "Externalize Strings" wizard (I've used classic eclipse message files).

Inside my initialize method, all my lables are initialized and their text is set like this:

JLabel lblLanguage = new JLabel(Messages.getString("App.lblLanguage.text")); //$NON-NLS-1$

I have created an enum type inside my class App which holds the GUI:

private enum Lang { German(Locale.GERMAN), English(Locale.ENGLISH);

    private Locale loc;
    Lang (Locale l) {
        loc = l;
    }

    Locale getLocale() {
        return loc;
    }
}

The language will be set with a combobox that uses the enum type Lang to show the languages available:

    JComboBox cboLanguage = new JComboBox();
    cboLanguage.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            JComboBox cb = (JComboBox)e.getSource();
            Lang l = (Lang)cb.getSelectedItem();
            // TODO: update language
        }
    });
    cboLanguage.setModel(new DefaultComboBoxModel(Lang.values()));


I've found many other howtos and tutorials covering the internationalization of swing applications but none of them covers how to update all labels (and possible other controls with text in them). There's this answer here on SO that might have been helpful if the links weren't dead.
Because I'm kind of new to GUI programming in java, I don't really know what to do now and here are my questions:

  • What is the best way, to change the language of all controls at runtime if a new language is set?
  • Is it ok (recommended) to declare all controls as private members of my App class to have a method update their text property (-> an updateLanguage method would do that)

解决方案

I solve this by extending JLabel and overwriting getText to return the evaluation of the language selection.

You will also need some pub/sub mechanism to 'tell' your labels that the language has changed.

Here i´m using Guava event bus

import com.google.common.eventbus.EventBus;

public class EventBusHolder {

    private static EventBus bus = new EventBus();

    public static EventBus get() {
        return bus;
    }
}

When the user change the language you fire the event:

JComboBox cboLanguage = new JComboBox();
cboLanguage.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        JComboBox cb = (JComboBox)e.getSource();
        Lang l = (Lang)cb.getSelectedItem();
        // this is the event fire
        ChangeEvent event = getChangeEvent(l);
        EventBusHolder.get().post(event);
    }
});

the label component to be used:

public class MyLabel extends JLabel {

    private static final long serialVersionUID = 1L;

    public MyLabel (String key) {
        super(key);
        // register this in event bus
        EventBusHolder.get().register(this);
    }

    @Override
    public String getText() {
        return Messages.getString(super.getText());
    }

    @Subscribe 
    public void recordCustomerChange(ChangeEvent e) {
        revalidate();
    }

}

And when you instanciate the Label you must pass the key for translation:

JLabel lbl = new JLabel("App.lblLanguage.text");

more usage examples on guava event bus

相关文章