5

Window Builder Pro拡張機能のGoogleのハウツーに従って、アプリを国際化しました。ラベルに表示される文字列は、"Externalize Strings" ウィザードによって作成されたプロパティ ファイルに格納されるようになりました (私は従来の Eclipse メッセージ ファイルを使用しました)。

メソッド内initializeで、すべてのラベルが初期化され、テキストが次のように設定されます。

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

AppGUI を保持するクラス内に列挙型を作成しました。

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

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

    Locale getLocale() {
        return loc;
    }
}

言語は、列挙型 Lang を使用して使用可能な言語を表示するコンボボックスで設定されます。

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

私は、swing アプリケーションの国際化をカバーするハウツーやチュートリアルを他にもたくさん見つけましたが、すべてのラベル (およびテキストを含むその他のコントロール) を更新する方法をカバーしているものはありません。リンクが死んでいない場合に役立つかもしれない SO に関するこの回答があります。
私はJavaでのGUIプログラミングが初めてなので、今何をすべきかよくわかりません。ここに私の質問があります:

  • 新しい言語が設定されている場合、実行時にすべてのコントロールの言語を変更する最良の方法は何ですか?
  • メソッドにテキスト プロパティを更新させるために、すべてのコントロールを App クラスのプライベート メンバーとして宣言しても問題ありませんか (->updateLanguageメソッドがそれを行います)。
4

4 に答える 4

3

私がこれをしたとき、私はそれをするための組み込みの方法も見つけることができませんでした。

そこで、独自のLocaleChangeListenerインターフェイスを作成しました。すべてのUI画面/パネルはそれを実装し、中央のUIコントローラークラスにリスナーとして登録しました。その後localeChanged(lang)、言語が変更されるたびに、それぞれに電話がかけられました。ただし、コンポーネントの初期化は個別に行いました。すべてを再度実行する必要はありません。

彼らはちょうどこのようなコードを持っていました:

public void localeChanged(Lang lang){
    nameLabel.setText(lang.getText( "label.name"));
    submitButton.setText(lang.getText( "button.submit"));
    等...

    //一部の画面では、奇妙なJTable/JTabbedPaneレイアウトの問題を修正するためにこれが必要だと思います。
    this.revalidate();
}
于 2013-02-11T10:54:18.893 に答える
1

コア Swing には、痛みを和らげるものは何もありません。fi (Better)SwingApplicationFramework.

すべてのテキストが通常どおりプロパティ ファイルで宣言されていると仮定すると、以下のスニペットのようなものがうまくいきます。

public static class ToggleLocaleAction extends AbstractAction {

    private boolean isAlternative;
    private SingleFrameApplication app;

    public ToggleLocaleAction(SingleFrameApplication app) {
        super("Locale");
        this.app = app;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        // just toggling as an example
        Locale.setDefault(isAlternative ? Locale.GERMAN : Locale.ENGLISH);
        isAlternative = !isAlternative;
        injectResources(app);
    }

    public void injectResources(SingleFrameApplication app) {
        app.getContext().getResourceMap().injectComponents(app.getMainFrame());
    }
}

いくつかの不具合に気付きました:

  • フレームのタイトルを更新しません (おそらくそれは Bean のプロパティではないためです)
  • アクションテキストを更新しません(コンテキストアクションの更新を強制する必要があるかもしれませんが、わかりません)
于 2013-02-11T13:06:25.237 に答える
1

ユーザーが言語を変更することはめったにないため、再起動はかろうじて受け入れられます。これには、古い言語のアーティファクトをレイアウトしてもテキストが混乱しないという利点があります。

これには、アプリケーションの保存可能な状態が必要です。

JLabelnew JLabel(Messages.getString("App.lblLanguage.text"));はすぐにローカライズされたテキストに評価され、そのテキストの幅にレイアウトされる場合があります。そのため、動的な言語変更には適していません。

もう 1 つの方法は、name 属性またはリフレクションに依存して、すべてのテキスト値を埋めることです。またはコード:

JLabel lblLanguage = new JLabel();
Nls.setText(lblLanguage, "App.lblLanguage");

一部の Nls.setText では、セット内の lblLanguage の弱参照が作成されます。

于 2013-02-11T12:17:50.960 に答える