Как изменить язык во время выполнения в java swing

Я пытаюсь изменить Locale во время выполнения в моем приложении swing.
Но я не могу понять, как он должен работать, или нет генерального плана?

Я могу думать только о двух вариантах:
1. Перезапустите приложение, а не лучший пользовательский интерфейс.
2. Создайте менеджер локализации, который может регистрировать/отменять регистрацию компонентов, при изменении он просто перебирает все компоненты и меняет текст.

Оба 1 и 2 чувствуют себя неловко.

Дополнительная информация:
На данный момент ориентация не является целью.
Приложение запутано.

Пример:

LocRes_en.properties:

    text1 = English text

LocRes_ja.properties

    text1 = Japanese text

ChangeLocale.java:

    import java.awt.EventQueue;
    import java.awt.FlowLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.Locale;
    import java.util.ResourceBundle;

    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;

    public class ChangeLocale {

        private JFrame frame;

        public static void main(String[] args) {
            EventQueue.invokeLater(new Runnable() {
                public void run() {
                    try {
                        ChangeLocale window = new ChangeLocale();
                        window.frame.setVisible(true);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }

        public ChangeLocale() {
            initialize();
        }

        private void initialize() {
            frame = new JFrame();
            frame.setBounds(100, 100, 450, 300);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            FlowLayout flowLayout = new FlowLayout(FlowLayout.CENTER, 5, 5);
            frame.getContentPane().setLayout(flowLayout);

            JButton btnChangeLoc = new JButton("Change Locale");
            frame.getContentPane().add(btnChangeLoc);

            final JLabel lblLabel1 = new JLabel("New label");
            frame.getContentPane().add(lblLabel1);
            Locale.setDefault(new Locale("en"));
            ResourceBundle r = ResourceBundle.getBundle("LocRes");
            lblLabel1.setText(r.getString("text1"));

            btnChangeLoc.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    Locale.setDefault(new Locale("ja"));
                    ResourceBundle r = ResourceBundle.getBundle("LocRes");
                    // Manually iterate through all components :(
                    lblLabel1.setText(r.getString("text1"));
                    //
                }
            });
        }
    }

Ответ 2

Я реализовал это с помощью ResourceBundles и EventBus.

Когда локаль изменена, EventBus запускает localeChangedEvent. Все окна JFrame, у которых есть локализованные строки, должны подписаться на это событие. Они также должны реализовать метод changeLocale(), который выполняется, когда событие получено.

В этом методе все строки будут обновлены до текущей локали.

public void changeLocale(ResourceBundle rb) {
    lblLabel1.setText(rb.getString("text1"));
    lblLabel2.setText(rb.getString("text2"));
    ...
}

Ответ 3

Я сделал что-то подобное однажды. Хотя моя задача была проще: это было приложение в системном трее, поэтому мне просто пришлось изменить текст пунктов меню.

Но в вашем случае я думаю, что это выполнимо. Во-первых, избегайте жестко закодированных строк в вашем графическом интерфейсе. Создайте класс, который изменяет локаль, а затем выполняет итерацию по всем видимым фреймам и переходит к всем панелям и компонентам и изменяет текст, написанный на них. Единственная проблема, которую я могу ожидать здесь, - это текст, нарисованный на холсте.

Ответ 4

Определите GUI и выпадающий список с поддерживаемыми языками. Добавьте ItemListener, поэтому, когда поле со списком будет изменено, тексты будут обновлены.

LanguageGUIClient.java:

import javax.swing.*;

public class LanguageGUIClient
{
    public static void main(String[] arguments) throws Exception
    {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

        SwingUtilities.invokeLater(() ->
        {
            LanguageGUI languageGUI = new LanguageGUI();
            languageGUI.setVisible(true);
        });
    }
}

LanguageGUI.java:

import javax.swing.*;
import java.util.Locale;
import java.util.ResourceBundle;

public class LanguageGUI extends JFrame
{
    public static ResourceBundle resourceBundle;

    private JPanel rootPanel;
    private JComboBox<Locale> languageComboBox;
    private JLabel languageLabel;

    public LanguageGUI()
    {
        configureFrameProperties();
    }

    private void configureFrameProperties()
    {
        add(rootPanel);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        languageComboBox.addItem(Locale.US);
        languageComboBox.addItem(Locale.GERMANY);
        languageComboBox.addItem(Locale.FRANCE);
        setTexts();
        languageComboBox.addItemListener(itemEvent -> setTexts());
        setSize(300, 100);
    }

    private void setTexts()
    {
        Locale locale = languageComboBox.getItemAt(languageComboBox.getSelectedIndex());
        resourceBundle = ResourceBundle.getBundle("Bundle", locale);
        setTitle(resourceBundle.getString("application.title"));
        languageLabel.setText(resourceBundle.getString("language") + ":");
        languageComboBox.setToolTipText(resourceBundle.getString("language.tooltip"));
    }
}

Обратите внимание, что я использую IntelliJ form designer, поэтому необходимо содержимое файла .form.

LanguageGUI.form:

<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="LanguageGUI">
  <grid id="27dc6" binding="rootPanel" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
    <margin top="0" left="0" bottom="0" right="0"/>
    <constraints>
      <xy x="20" y="20" width="500" height="400"/>
    </constraints>
    <properties/>
    <border type="none"/>
    <children>
      <component id="eb651" class="javax.swing.JComboBox" binding="languageComboBox">
        <constraints>
          <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
        </constraints>
        <properties>
          <toolTipText value=""/>
        </properties>
      </component>
      <vspacer id="977c1">
        <constraints>
          <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
        </constraints>
      </vspacer>
      <component id="e59f" class="javax.swing.JLabel" binding="languageLabel">
        <constraints>
          <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
        </constraints>
        <properties>
          <text value=""/>
        </properties>
      </component>
    </children>
  </grid>
</form>

Кроме того, вам необходимо создать соответствующие файлы пакета ресурсов в каталоге ресурсов: ></a> <a href=

Результатом является GUI со списком, позволяющим сразу же сменить язык: