Translator plugin: imporve preferences panel

This commit is contained in:
Sergey Ponomarev
2026-07-28 21:47:27 +03:00
parent f99f58dd0c
commit cdc16bbc29
6 changed files with 82 additions and 78 deletions

View File

@ -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) {

View File

@ -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

View File

@ -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<Language> _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<Language> _myLanguage = new JComboBox<>(Language.values());
private final JComboBox<String> _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);
}

View File

@ -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) {

View File

@ -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;

View File

Before

Width:  |  Height:  |  Size: 436 B

After

Width:  |  Height:  |  Size: 436 B