Каковы лучшие практики интернационализации настольного приложения Java Swing?

Я уверен, что существует множество методов, но какой рекомендуемый способ сделать это минимально повлияет на ваш код?

Очевидно, что вы создаете файлы свойств, но как вы меняете местами значения при рендеринге? В J2EE вы всегда просто повторно визуализируете всю страницу, так что это легко. Но в приложениях Swing вы просто добавляете код для .getProperty () в метод paintComponent (Graphics g)?

Если это так, разве это не кажется тяжелым, поскольку теперь вам придется переопределить этот метод везде, где раньше вам не нужно было ...

Дополнительно: Как настроить систему уведомлений для повторной визуализации всех видимых в данный момент компонентов без принудительного использования какого-либо шаблона регистрации?

Думаю, если я перезапишу paintComponent (Graphics g), все, что мне нужно сделать, это запустить событие, что что-то изменилось, и будет вызван метод paintComponent (Graphics g) ...


person Stephane Grenier    schedule 23.07.2010    source источник
comment
Самый простой способ: попросить пользователя перезапустить программу, чтобы изменения вступили в силу.   -  person Untitled    schedule 26.11.2012


Ответы (5)


Насколько мне известно, в некоторых приложениях используются конструкторы макетов / компонентов (рекомендованные Карстеном Ленчшем, а также часть JGoodies API). Эти компоновщики включают код для локализации компонентов (используя ResourceBundle под капотом).

Другие люди (в том числе и я) предпочитают инъекцию ресурсов; обычно это наименее навязчивый метод. Это путь, выбранный Swing Application Framework (JSR-296) и другими структурами GUI, такими как Guts-GUI.

Вы также можете взглянуть на этот вопрос, который очень похож на ваш.

Что касается изменения языка «на лету» (Locale уведомление об изменении), я думаю, что это проще реализовать при использовании инъекции ресурсов (я уже реализовал это в Guts-GUI, Swing Application Framework также может иметь это, но я не уверен в Это).

Java не предлагает возможности прослушивать Locale изменения, поэтому вы должны создать свою собственную «службу языковых стандартов» (к которой должен быть адресован любой запрос на изменение локали). В этом сервисе вам нужно будет перечислить все видимые окна (это возможно с Window.getWindows(), нет необходимости регистрировать видимые компоненты раньше), а затем снова ввести ресурсы.

Если вам нужен пример, взгляните на пакет resource в исходном коде Guts-GUI :

  • ResourceInjector показывает внедрение ресурсов и метод изменить Locale, который отправляет событие уведомления (для этого используется шина событий, но подойдут и простые слушатели) об этом изменении
  • WindowController прослушивает события изменения языкового стандарта.

Интересный код для обновления всех видимых окон скопирован ниже:

for (Window window: Window.getWindows())
{
    if (window.isVisible())
    {
        injectResources(window);
        window.repaint();
        if (window instanceof RootPaneContainer)
        {
            ((RootPaneContainer) window).getRootPane().revalidate();
        }
    }
}
person jfpoilpret    schedule 26.07.2010

Поддержка динамических изменений языка - сложная проблема. Самое простое решение - организовать пользовательский интерфейс таким образом, чтобы можно было воссоздать любые видимые панели. Это позволяет избежать необходимости регистрировать или обновлять компоненты, когда при изменении языка вы просто воссоздаете представление.

Очевидно, что вы теряете состояние всех видимых компонентов, что может быть проблемой, но это обычно то же самое в веб-приложении при обновлении страницы.

person Russ Hayward    schedule 24.07.2010

Java 6 SE позволяет перезагружать пакеты ресурсов на лету. Просто вызовите статическую функцию clearCache() класса ResourceBundle. Затем снова позвоните getBundle ().

См. эту статью в разделе «Управление кешем».

person kikouk    schedule 10.11.2011

Единственное решение, которое я придумал, состояло в том, чтобы создать массивный реестр всех компонентов, которые нужно было бы повторно визуализировать. Затем, если выполняется вызов для переключения языкового стандарта, вы можете просто вызвать реестр, и он пройдет через все зарегистрированные компоненты и скорректирует их значения. Так, например, для всех зарегистрированных JLabels он будет делать что-то вроде

for(JLabel specificJLabel : REGISTRY.registeredJLabels)
{
  String localeKey = specificJLabel.getActionCommand();
  specificJLabel.setText(ResourceBundle.getString(localeKey)); 
}

где ключ Locale хранится в компонентах ActionCommand. Затем, какой бы экран не отображался в данный момент, за его повторную визуализацию отвечает основная родительская панель. Также таким образом реестр не должен управлять ключами Locale, они полностью отделены от реестра. Каждый компонент отвечает за управление своими собственными ключами локали для ResourceBundle.

person Stephane Grenier    schedule 26.11.2012

Что вам нужно, так это ResourceBundle, который позволяет вам иметь файл свойств на основе Locale, к которому вы просто получаете доступ, как к файлу свойств.

Вот пример того, как это сделать

person Romain Hippeau    schedule 23.07.2010
comment
Я понимаю, что вопрос не в этом. Вопрос в том, где вы вызываете ResourceBundle в компонентах, чтобы он отображался (или повторно отображался) при необходимости. Есть ли другой способ, кроме как перезаписать paintComponent (Graphics g) на каждом JComponent? - person Stephane Grenier; 24.07.2010
comment
@Stephane Grenier - Обычно пользователь запускает программу в другой стране и ему нужен другой язык в зависимости от Локали, в которой он находится. Поскольку, как в примере, вы добавляете материал I18 при создании, это будет сложно. Вам нужно будет изменить языковой стандарт и, по крайней мере, закрыть окно и воссоздать его, или в зависимости от вызова виджета setText () или чего-то еще. - person Romain Hippeau; 24.07.2010
comment
К сожалению, мне нужно сделать это вживую, это для киоск-приложения, над которым я работаю. Я думаю, что смогу сделать это, переопределив методы paintComponent и тщательно обдумав. Я просто надеялся, что есть способ попроще. - person Stephane Grenier; 25.07.2010