From cdc16bbc29041cb607df739c403466094679aaf3 Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Tue, 28 Jul 2026 21:47:27 +0300 Subject: [PATCH] Translator plugin: imporve preferences panel --- .../spark/translator/TranslatorPlugin.java | 13 +- .../translator/TranslatorPreference.java | 10 +- .../translator/TranslatorPreferencePanel.java | 113 +++++++++--------- .../translator/TranslatorProperties.java | 15 +-- .../spark/translator/TranslatorResource.java | 9 +- .../{ => translation}/translator.png | Bin 6 files changed, 82 insertions(+), 78 deletions(-) rename plugins/translator/src/main/resources/{ => translation}/translator.png (100%) diff --git a/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorPlugin.java b/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorPlugin.java index 6e59d9e77..635deafe4 100644 --- a/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorPlugin.java +++ b/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorPlugin.java @@ -15,25 +15,26 @@ */ package org.jivesoftware.spark.translator; -import java.awt.*; +import java.awt.Color; +import java.awt.Component; import java.util.Locale; import javax.swing.JCheckBox; import javax.swing.JComboBox; +import org.jivesoftware.spark.ui.ChatRoom; +import org.jivesoftware.spark.ui.MessageFilter; import org.jivesoftware.spark.ui.transctipt.TranscriptWindow; import org.jivesoftware.spark.util.log.Log; import space.dynomake.libretranslate.Language; import space.dynomake.libretranslate.Translator; -import org.apache.commons.lang3.StringUtils; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.MessageBuilder; import org.jivesoftware.spark.ChatManager; import org.jivesoftware.spark.SparkManager; import org.jivesoftware.spark.plugin.Plugin; -import org.jivesoftware.spark.ui.*; -import static org.apache.commons.lang3.StringUtils.isEmpty; +import static org.apache.commons.lang3.StringUtils.isBlank; /** * A plugin that uses external translation service API to translate instant messages between two users. @@ -88,7 +89,7 @@ public class TranslatorPlugin implements Plugin { return; } // Set server LibreTranslate API - if (properties.getUseCustomUrl() && !StringUtils.isBlank(properties.getUrl())) { + if (properties.getUseCustomUrl() && !isBlank(properties.getUrl())) { Translator.setUrlApi(properties.getUrl()); Translator.setApiKey(properties.getApiKey()); } else { @@ -216,7 +217,7 @@ public class TranslatorPlugin implements Plugin { private Language getMyLanguage() { // the setting may be changed any time, so we have to always check it String myLanguageSetting = TranslatorProperties.getInstance().getMyLanguage(); - return !isEmpty(myLanguageSetting) ? Language.fromCode(myLanguageSetting) : localeLanguage; + return !isBlank(myLanguageSetting) ? Language.fromCode(myLanguageSetting) : localeLanguage; } private Component findTranslatorComponent(ChatRoom room, String compName) { diff --git a/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorPreference.java b/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorPreference.java index 515641950..1d5d4bff8 100644 --- a/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorPreference.java +++ b/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorPreference.java @@ -1,10 +1,11 @@ package org.jivesoftware.spark.translator; import org.jivesoftware.spark.preference.Preference; -import org.jivesoftware.spark.util.log.Log; -import javax.swing.*; -import java.awt.*; +import javax.swing.Icon; +import javax.swing.JComponent; + +import static org.jivesoftware.spark.translator.TranslatorResource.ICON_TRANSLATOR; public class TranslatorPreference implements Preference { private static final String NAMESPACE = "translator"; @@ -18,8 +19,7 @@ public class TranslatorPreference implements Preference { @Override public Icon getIcon() { - ClassLoader cl = getClass().getClassLoader(); - return new ImageIcon(cl.getResource("translator.png")); + return ICON_TRANSLATOR; } @Override diff --git a/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorPreferencePanel.java b/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorPreferencePanel.java index dedd0578a..c21e00066 100644 --- a/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorPreferencePanel.java +++ b/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorPreferencePanel.java @@ -1,66 +1,65 @@ package org.jivesoftware.spark.translator; import org.jivesoftware.spark.component.VerticalFlowLayout; +import org.jivesoftware.spark.util.GraphicUtils; +import space.dynomake.libretranslate.ApiProviders; import space.dynomake.libretranslate.Language; -import javax.swing.*; -import java.awt.*; +import javax.swing.BorderFactory; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextField; +import java.awt.BorderLayout; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; import static java.awt.GridBagConstraints.BOTH; +import static java.awt.GridBagConstraints.NORTHWEST; import static java.awt.GridBagConstraints.WEST; +import static org.apache.commons.lang3.StringUtils.isBlank; public class TranslatorPreferencePanel extends JPanel { - - private final JCheckBox _enabledCheckbox; - private final JComboBox _myLanguage; - private final JTextField _url; - private final JTextField _apiKey; - private final JCheckBox _useCustomUrl; - private final Insets INSETS = new Insets(5, 5, 5, 5); + private final JCheckBox _enabledCheckbox = new JCheckBox(TranslatorResource.getString("translator.enabled")); + private final JComboBox _myLanguage = new JComboBox<>(Language.values()); + private final JComboBox _url = new JComboBox<>(); + private final JTextField _apiKey = new JTextField(); + private final JCheckBox _useCustomUrl = new JCheckBox(TranslatorResource.getString("translator.custom.url")); + private final JLabel labelMyLangs = new JLabel(TranslatorResource.getString("translator.myLanguage")); + private final JLabel labelUrl = new JLabel(TranslatorResource.getString("translator.url")); + private final JLabel labelApiKey = new JLabel(TranslatorResource.getString("translator.apiKey")); public TranslatorPreferencePanel() { - - this.setLayout(new BorderLayout()); - - _enabledCheckbox = new JCheckBox(TranslatorResource.getString("translator.enabled")); - _myLanguage = new JComboBox<>(Language.values()); - _useCustomUrl = new JCheckBox(TranslatorResource.getString("translator.custom.url")); - _url = new JTextField(); - _apiKey = new JTextField(); + setLayout(new BorderLayout()); updateGUI(); add(makeGeneralSettingsPanel()); } private JComponent makeGeneralSettingsPanel() { - JPanel generalPanel = new JPanel(); generalPanel.setLayout(new GridBagLayout()); generalPanel.setBorder(BorderFactory.createTitledBorder(TranslatorResource.getString("translator.settings"))); - int rowcount = 0; - generalPanel.add(_enabledCheckbox, - new GridBagConstraints(0, rowcount, 1, 1, 0.0, 0.0, WEST, BOTH, INSETS, 0, 0)); - rowcount++; - generalPanel.add(new JLabel(TranslatorResource.getString("translator.myLanguage")), - new GridBagConstraints(0, rowcount, 1, 1, 0.0, 0.0, WEST, BOTH, INSETS, 0, 0)); - generalPanel.add(_myLanguage, - new GridBagConstraints(1, rowcount, 1, 1, 0.0, 0.0, WEST, BOTH, INSETS, 0, 0)); - rowcount++; - generalPanel.add(_useCustomUrl, - new GridBagConstraints(0, rowcount, 1, 1, 0.0, 0.0, WEST, BOTH, INSETS, 0, 0)); - rowcount++; - generalPanel.add(new JLabel(TranslatorResource.getString("translator.url")), - new GridBagConstraints(0, rowcount, 1, 1, 0.0, 0.0, WEST, BOTH, INSETS, 0, 0)); - generalPanel.add(_url, - new GridBagConstraints(1, rowcount, 1, 1, 0.0, 0.0, WEST, BOTH, INSETS, 0, 0)); - rowcount++; - generalPanel.add(new JLabel(TranslatorResource.getString("translator.apiKey")), - new GridBagConstraints(0, rowcount, 1, 1, 0.0, 0.0, WEST, BOTH, INSETS, 0, 0)); - generalPanel.add(_apiKey, - new GridBagConstraints(1, rowcount, 1, 1, 0.0, 0.0, WEST, BOTH, INSETS, 0, 0)); - rowcount++; + Insets insets = new Insets(5, 5, 5, 5); + int row = 0; + generalPanel.add(_enabledCheckbox, new GridBagConstraints(0, row, 1, 1, 0, 0, WEST, BOTH, insets, 0, 0)); + row++; + generalPanel.add(labelMyLangs, new GridBagConstraints(0, row, 1, 1, 0, 0, WEST, BOTH, insets, 0, 0)); + generalPanel.add(_myLanguage, new GridBagConstraints(1, row, 1, 1, 0, 0, WEST, BOTH, insets, 0, 0)); + row++; + generalPanel.add(_useCustomUrl, new GridBagConstraints(0, row, 1, 1, 0, 0, WEST, BOTH, insets, 0, 0)); + row++; + generalPanel.add(labelUrl, new GridBagConstraints(0, row, 1, 1, 0, 0, WEST, BOTH, insets, 0, 0)); + generalPanel.add(_url, new GridBagConstraints(1, row, 1, 1, 0, 0, WEST, BOTH, insets, 0, 0)); + row++; + generalPanel.add(labelApiKey, new GridBagConstraints(0, row, 1, 1, 0, 0, WEST, BOTH, insets, 0, 0)); + generalPanel.add(_apiKey, new GridBagConstraints(1, row, 1, 1, 0, 0, WEST, BOTH, insets, 0, 0)); + row++; JLabel placeHolder = new JLabel(); - generalPanel.add(placeHolder, - new GridBagConstraints(1, rowcount, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, BOTH, INSETS, 0, 0)); + generalPanel.add(placeHolder, new GridBagConstraints(1, row, 1, 1, 1, 0, NORTHWEST, BOTH, insets, 0, 0)); JPanel panel = new JPanel(new VerticalFlowLayout()); panel.add(generalPanel); @@ -74,23 +73,30 @@ public class TranslatorPreferencePanel extends JPanel { Language myLanguage = Language.fromCode(props.getMyLanguage()); _myLanguage.setSelectedItem(myLanguage); _useCustomUrl.setSelected(props.getUseCustomUrl()); - _url.setText(props.getUrl()); + _url.setEditable(true); + for (String apiUrl : ApiProviders.API_URLS) { + GraphicUtils.addItemIfNotExists(_url, apiUrl); + } + if (!isBlank(props.getUrl())) { + GraphicUtils.addItemIfNotExists(_url, props.getUrl()); + _url.setSelectedItem(props.getUrl()); + } _apiKey.setText(props.getApiKey()); } - public void storeValues(){ + public void storeValues() { TranslatorProperties props = TranslatorProperties.getInstance(); props.setEnabledTranslator(_enabledCheckbox.isSelected()); Language selectedMyLanguage = (Language) _myLanguage.getSelectedItem(); props.setMyLanguage(selectedMyLanguage != null && selectedMyLanguage != Language.NONE ? selectedMyLanguage.getCode() : ""); props.setUseCustomUrl(_useCustomUrl.isSelected()); - props.setUrl(_url.getText()); + props.setUrl(_url.getSelectedItem() != null ? _url.getSelectedItem().toString() : null); props.setApiKey(_apiKey.getText()); props.save(); } - private void updateGUI(){ - _enabledCheckbox.addActionListener( e -> { + private void updateGUI() { + _enabledCheckbox.addActionListener(e -> { if (_enabledCheckbox.isSelected()) { _myLanguage.setEnabled(true); _useCustomUrl.setEnabled(true); @@ -104,14 +110,9 @@ public class TranslatorPreferencePanel extends JPanel { } }); - _useCustomUrl.addActionListener( e -> { - if (_useCustomUrl.isSelected()){ - _url.setEnabled(true); - _apiKey.setEnabled(true); - } else { - _url.setEnabled(false); - _apiKey.setEnabled(false); - } + _useCustomUrl.addActionListener(e -> { + _url.setEnabled(_useCustomUrl.isSelected()); + _apiKey.setEnabled(_useCustomUrl.isSelected()); }); if (!TranslatorProperties.getInstance().getEnabledTranslator()) { @@ -121,7 +122,7 @@ public class TranslatorPreferencePanel extends JPanel { _useCustomUrl.setEnabled(false); } - if(!TranslatorProperties.getInstance().getUseCustomUrl()){ + if (!TranslatorProperties.getInstance().getUseCustomUrl()) { _url.setEnabled(false); _apiKey.setEnabled(false); } diff --git a/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorProperties.java b/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorProperties.java index 095a3eef0..2810aa1df 100644 --- a/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorProperties.java +++ b/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorProperties.java @@ -18,17 +18,17 @@ public class TranslatorProperties { * returns the Instance of this Properties file */ public static TranslatorProperties getInstance() { + if (instance != null) { + return instance; + } synchronized (LOCK) { - if (instance == null) { - instance = new TranslatorProperties(); - } + instance = new TranslatorProperties(); return instance; } } private TranslatorProperties() { this.props = new Properties(); - try { props.load(new FileInputStream(getConfigFile())); } catch (IOException e) { @@ -43,9 +43,9 @@ public class TranslatorProperties { public void save() { try { - props.store(new FileOutputStream(getConfigFile()), "Storing Translator properties"); + props.store(new FileOutputStream(getConfigFile()), null); } catch (Exception e) { - Log.error(e); + Log.error("Unable to store Translator properties", e); } } @@ -90,7 +90,8 @@ public class TranslatorProperties { } private boolean getBoolean(String property, boolean defaultValue) { - return Boolean.parseBoolean(props.getProperty(property, Boolean.toString(defaultValue))); + String propertyVal = props.getProperty(property); + return propertyVal != null ? Boolean.parseBoolean(propertyVal) : defaultValue; } public void setBoolean(String property, boolean value) { diff --git a/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorResource.java b/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorResource.java index cc6c7053c..299bf6578 100644 --- a/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorResource.java +++ b/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorResource.java @@ -2,16 +2,17 @@ package org.jivesoftware.spark.translator; import org.jivesoftware.spark.util.log.Log; +import javax.swing.*; import java.text.MessageFormat; import java.util.PropertyResourceBundle; import java.util.ResourceBundle; public class TranslatorResource { private static final PropertyResourceBundle prb = (PropertyResourceBundle) ResourceBundle.getBundle("i18n/translator_i18n"); + private static ClassLoader cl = TranslatorResource.class.getClassLoader(); + static ImageIcon ICON_TRANSLATOR = new ImageIcon(cl.getResource("translation/translator.png")); - static ClassLoader cl = TranslatorResource.class.getClassLoader(); - - public static String getString(String propertyName) { + static String getString(String propertyName) { try { return prb.getString(propertyName); } @@ -21,7 +22,7 @@ public class TranslatorResource { } } - public static String getString(String propertyName, Object... obj) { + static String getString(String propertyName, Object... obj) { String str = prb.getString(propertyName); if (str == null) { return null; diff --git a/plugins/translator/src/main/resources/translator.png b/plugins/translator/src/main/resources/translation/translator.png similarity index 100% rename from plugins/translator/src/main/resources/translator.png rename to plugins/translator/src/main/resources/translation/translator.png