diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml
index dca774ce..32ae04dc 100644
--- a/.github/workflows/gradle.yml
+++ b/.github/workflows/gradle.yml
@@ -23,13 +23,13 @@ jobs:
steps:
- uses: actions/checkout@v3
- - name: Set up JDK 11
+ - name: Set up JDK 21
uses: actions/setup-java@v3
with:
- java-version: '11'
+ java-version: '21'
distribution: 'temurin'
- name: Build with Gradle
uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1
with:
- gradle-version: 7.5
+ gradle-version: 8.7
arguments: build
diff --git a/README.md b/README.md
index 3b059804..da70d72f 100644
--- a/README.md
+++ b/README.md
@@ -26,7 +26,7 @@ Usage
Java 8 or later is recommended to run JPass.
You can run the application from the command line by typing (the password file is optional):
- java -jar jpass-1.0.6-SNAPSHOT.jar [password_file]
+ java -jar jpass-1.0.7-SNAPSHOT.jar [password_file]
For convenience, batch/shell scripts are also available for launching JPass for various platforms (i.e. `jpass.bat` for Windows, `jpass.sh` for Linux, `jpass.command` for macOS).
Please make sure `PATH`, or `JAVA_HOME` environment variables point to a valid Java installation.
@@ -56,14 +56,14 @@ Configuration
Default configurations can be overridden in `jpass.properties` file:
| Configuration key | Value type | Default value |
-| ---------------------------------- | ---------- | ---------------- |
+| ---------------------------------- | ---------- |------------------|
| ui.theme.dark.mode.enabled | boolean | `false` |
| clear.clipboard.on.exit.enabled | boolean | `false` |
| default.password.generation.length | integer | `14` |
| date.format | string | `yyyy-MM-dd` |
| entry.details | list | `TITLE,MODIFIED` |
| file.chooser.directory | string | `./` |
-| language.languageSetting | string | en-US |
+| language.languageSetting | string | `en-US` |
Regarding `language.languageSetting` please check
[languages](https://github.com/gaborbata/jpass/tree/master/src/main/resources/resources/languages)
@@ -71,5 +71,5 @@ resources folder for possible configuration values.
Each configuration property can be overridden by system properties, with the `jpass.` key prefix, e.g.
- java -Djpass.entry.details=TITLE -jar jpass-1.0.6-SNAPSHOT.jar
+ java -Djpass.entry.details=TITLE -jar jpass-1.0.7-SNAPSHOT.jar
diff --git a/build.gradle b/build.gradle
index 1a419c3d..aed42ebd 100644
--- a/build.gradle
+++ b/build.gradle
@@ -11,15 +11,15 @@ plugins {
compileJava.options.encoding = 'UTF-8'
-version = '1.0.6-SNAPSHOT'
+version = '1.0.7-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
- implementation group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-xml', version: '2.16.1'
- implementation group: 'com.formdev', name: 'flatlaf', version: '3.4'
+ implementation group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-xml', version: '2.16.2'
+ implementation group: 'com.formdev', name: 'flatlaf', version: '3.4.1'
implementation group: 'com.formdev', name: 'svgSalamander', version: '1.1.4'
}
diff --git a/jpass.json b/jpass.json
index af56f2f3..5a6e1310 100644
--- a/jpass.json
+++ b/jpass.json
@@ -1,5 +1,5 @@
{
- "version": "1.0.2",
+ "version": "1.0.6",
"description": "Password manager application with strong encryption (AES-256)",
"homepage": "https://github.com/gaborbata/jpass",
"license": {
@@ -17,8 +17,8 @@
"java/openjdk11"
]
},
- "url": "https://github.com/gaborbata/jpass/releases/download/v1.0.5/jpass-1.0.5-RELEASE.zip",
- "hash": "0c6fc348b55c21e69c2c34d042316fa023773ef42fb8b8ec478e59ed0658be51",
+ "url": "https://github.com/gaborbata/jpass/releases/download/v1.0.6/jpass-1.0.6-RELEASE.zip",
+ "hash": "ba390f0cc63aa88c5b667c3fe6d2c69d15aad2afa5f196beca110a331309173b",
"bin": "jpass.bat",
"shortcuts": [
[
diff --git a/pom.xml b/pom.xml
index 72debf49..d1d88cd4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
jpass
jpass
jar
- 1.0.6-SNAPSHOT
+ 1.0.7-SNAPSHOT
JPass
UTF-8
@@ -13,12 +13,12 @@
com.fasterxml.jackson.dataformat
jackson-dataformat-xml
- 2.16.1
+ 2.16.2
com.formdev
flatlaf
- 3.4
+ 3.4.1
com.formdev
diff --git a/src/main/config/jpass.properties b/src/main/config/jpass.properties
index 702c7dbd..5df42fb7 100644
--- a/src/main/config/jpass.properties
+++ b/src/main/config/jpass.properties
@@ -44,4 +44,4 @@ date.format=yyyy-MM-dd
file.chooser.directory=./
# Locale ID to set the program language
-language.languageSetting=en-US
\ No newline at end of file
+language.languageSetting=en-US
diff --git a/src/main/distribution/install.sh b/src/main/distribution/install.sh
index 56184f43..f1e439f3 100644
--- a/src/main/distribution/install.sh
+++ b/src/main/distribution/install.sh
@@ -2,21 +2,6 @@
# JPass installation script for Linux
-# check if java executable exists
-if [ -d "$JAVA_HOME" -a -x "$JAVA_HOME/bin/java" ]; then
- JAVACMD="$JAVA_HOME/bin/java"
-else
- JAVACMD=java
-fi
-
-$JAVACMD -version >/dev/null 2>&1
-if [ "$?" != "0" ]; then
- echo "Install Java (JDK or JRE) if you do not already have. JPass will not work without it."
- echo "Please make sure PATH, or JAVA_HOME environment variables point to a valid Java installation."
- echo "Could not execute JPass (exit: $?)"
- exit
-fi
-
# detect the absolute path of jpass
JPASS_HOME=`dirname "$0"`
diff --git a/src/main/distribution/jpass.bat b/src/main/distribution/jpass.bat
index 35ddf235..1ab5e448 100644
--- a/src/main/distribution/jpass.bat
+++ b/src/main/distribution/jpass.bat
@@ -27,7 +27,7 @@ pause
goto end
:launch
-start "JPass" /B "%JAVA_EXE%" -jar "%JPASS_HOME%\jpass-1.0.6-SNAPSHOT.jar" %*
+start "JPass" /B "%JAVA_EXE%" -jar "%JPASS_HOME%\jpass-1.0.7-SNAPSHOT.jar" %*
goto end
:end
diff --git a/src/main/distribution/jpass.command b/src/main/distribution/jpass.command
index 1931113d..cc2d44ca 100644
--- a/src/main/distribution/jpass.command
+++ b/src/main/distribution/jpass.command
@@ -33,4 +33,4 @@ else
fi
# execute jpass
-exec "$JAVACMD" "$LAF_OPTS" -jar "$JPASS_HOME/jpass-1.0.6-SNAPSHOT.jar" "$@"
+exec "$JAVACMD" "$LAF_OPTS" -jar "$JPASS_HOME/jpass-1.0.7-SNAPSHOT.jar" "$@"
diff --git a/src/main/distribution/jpass.desktop b/src/main/distribution/jpass.desktop
index 199c90f5..27489c6e 100644
--- a/src/main/distribution/jpass.desktop
+++ b/src/main/distribution/jpass.desktop
@@ -6,4 +6,4 @@ Comment=Password manager with strong encryption
Exec=/opt/jpass/jpass.sh
Icon=/opt/jpass/jpass.png
Terminal=false
-
+StartupWMClass=jpass-JPass
diff --git a/src/main/distribution/jpass.sh b/src/main/distribution/jpass.sh
index f5058126..4a914869 100644
--- a/src/main/distribution/jpass.sh
+++ b/src/main/distribution/jpass.sh
@@ -33,4 +33,4 @@ else
fi
# execute jpass
-exec "$JAVACMD" -jar "$JPASS_PATH/jpass-1.0.6-SNAPSHOT.jar" "$@"
+exec "$JAVACMD" -jar "$JPASS_PATH/jpass-1.0.7-SNAPSHOT.jar" "$@"
diff --git a/src/main/distribution/readme.txt b/src/main/distribution/readme.txt
index f40bf139..6c217a94 100644
--- a/src/main/distribution/readme.txt
+++ b/src/main/distribution/readme.txt
@@ -1,4 +1,4 @@
-# JPass - Password Manager 1.0.6-SNAPSHOT
+# JPass - Password Manager 1.0.7-SNAPSHOT
Overview
--------
@@ -21,7 +21,7 @@ Java 8 or later is recommended to run JPass.
You can run the application from the command line by typing (the password
file is optional):
- java -jar jpass-1.0.6-SNAPSHOT.jar [password_file]
+ java -jar jpass-1.0.7-SNAPSHOT.jar [password_file]
For convenience, batch/shell scripts are also available for launching JPass
for various platforms (i.e. `jpass.bat` for Windows, `jpass.sh` for Linux,
@@ -42,6 +42,11 @@ Default configurations can be overridden in `jpass.properties` file:
| file.chooser.directory | string | ./ |
| language.languageSetting | string | en-US |
+Each configuration property can be overridden by system properties,
+with the `jpass.` key prefix, e.g.
+
+ java -Djpass.entry.details=TITLE -jar jpass-1.0.7-SNAPSHOT.jar
+
License
-------
Copyright (c) 2009-2024 Gabor Bata
diff --git a/src/main/java/jpass/ui/EntryDetailsTable.java b/src/main/java/jpass/ui/EntryDetailsTable.java
index 388cc650..b01cb124 100644
--- a/src/main/java/jpass/ui/EntryDetailsTable.java
+++ b/src/main/java/jpass/ui/EntryDetailsTable.java
@@ -60,12 +60,12 @@ public class EntryDetailsTable extends JTable {
private static final DateTimeFormatter FORMATTER
= DateUtils.createFormatter(Configuration.getInstance().get("date.format", "yyyy-MM-dd"));
- private enum DetailType {
- TITLE(getLocalizedMessages().getString(VIEW_WINDOW_TITLE), Entry::getTitle),
- URL(getLocalizedMessages().getString(VIEW_WINDOW_URL), Entry::getUrl),
- USER(getLocalizedMessages().getString(VIEW_WINDOW_USER), Entry::getUser),
- MODIFIED(getLocalizedMessages().getString(VIEW_WINDOW_MODIFIED), entry -> DateUtils.formatIsoDateTime(entry.getLastModification(), FORMATTER)),
- CREATED(getLocalizedMessages().getString(VIEW_WINDOW_CREATED), entry -> DateUtils.formatIsoDateTime(entry.getCreationDate(), FORMATTER));
+ public enum DetailType {
+ TITLE(VIEW_WINDOW_TITLE, Entry::getTitle),
+ URL(VIEW_WINDOW_URL, Entry::getUrl),
+ USER(VIEW_WINDOW_USER, Entry::getUser),
+ MODIFIED(VIEW_WINDOW_MODIFIED, entry -> DateUtils.formatIsoDateTime(entry.getLastModification(), FORMATTER)),
+ CREATED(VIEW_WINDOW_CREATED, entry -> DateUtils.formatIsoDateTime(entry.getCreationDate(), FORMATTER));
private final String description;
private final Function valueMapper;
@@ -111,7 +111,7 @@ public EntryDetailsTable() {
}
tableModel = new DefaultTableModel();
- detailsToDisplay.forEach(detail -> tableModel.addColumn(detail.getDescription()));
+ detailsToDisplay.forEach(detail -> tableModel.addColumn(getLocalizedMessages().getString(detail.getDescription())));
setModel(tableModel);
getTableHeader().setReorderingAllowed(false);
addMouseListener(new TableListener());
@@ -135,6 +135,10 @@ public Component prepareRenderer(TableCellRenderer renderer, int row, int column
return component;
}
+ public List getDetailsToDisplay() {
+ return detailsToDisplay;
+ }
+
public void clear() {
tableModel.setRowCount(0);
}
@@ -144,8 +148,4 @@ public void addRow(Entry entry) {
.map(detail -> detail.getValue(entry))
.toArray(Object[]::new));
}
-
- public int rowCount() {
- return tableModel.getRowCount();
- }
}
diff --git a/src/main/java/jpass/ui/JPassFrame.java b/src/main/java/jpass/ui/JPassFrame.java
index 300f1366..1e1d32ed 100644
--- a/src/main/java/jpass/ui/JPassFrame.java
+++ b/src/main/java/jpass/ui/JPassFrame.java
@@ -37,20 +37,26 @@
import jpass.xml.bind.Entry;
import java.awt.BorderLayout;
+import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
+import java.util.HashMap;
import java.util.List;
import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
+import javax.swing.JButton;
import javax.swing.JFrame;
+import javax.swing.JMenuItem;
import javax.swing.JTable;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
@@ -58,7 +64,9 @@
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JToolBar;
+import javax.swing.UIManager;
import javax.swing.WindowConstants;
+import javax.swing.table.TableColumn;
import static jpass.ui.MessageDialog.NO_OPTION;
import static jpass.ui.MessageDialog.YES_NO_CANCEL_OPTION;
@@ -67,10 +75,21 @@
import static jpass.ui.MessageDialog.showQuestionMessage;
import static jpass.util.Constants.BOTTOM_MENU_ENTRIES_COUNT;
import static jpass.util.Constants.BOTTOM_MENU_ENTRIES_FOUND;
+import static jpass.util.Constants.BUTTON_MESSAGE_CANCEL;
import static jpass.util.Constants.EDIT_MENU;
+import static jpass.util.Constants.FILE_CHOOSER_CANCEL_BUTTON_TEXT;
import static jpass.util.Constants.FILE_MENU;
import static jpass.util.Constants.HELP_MENU;
+import static jpass.util.Constants.LANGUAGE_EN_US;
+import static jpass.util.Constants.LANGUAGE_ES_MX;
+import static jpass.util.Constants.LANGUAGE_HU_HU;
+import static jpass.util.Constants.LANGUAGE_IT_IT;
+import static jpass.util.Constants.LANGUAGE_LANGUAGE_CHANGED;
+import static jpass.util.Constants.LANGUAGE_LANGUAGE_SETTING;
+import static jpass.util.Constants.PANEL_FIND;
import static jpass.util.Constants.PANEL_SAVE_MODIFIED_QUESTION_MESSAGE;
+import static jpass.util.Constants.SETTINGS_MENU;
+import static jpass.util.Constants.SETTINGS_MENU_LANGUAGE;
import static jpass.util.Constants.TOOLS_MENU;
/**
@@ -81,13 +100,14 @@
*/
public final class JPassFrame extends JFrame {
- private static ResourceBundle localizedMessages;
private static final Logger LOG = Logger.getLogger(JPassFrame.class.getName());
private static JPassFrame instance;
+ private static ResourceBundle localizedMessages;
+ private static final Map SUPPORTED_LANGUAGES = new HashMap<>();
public static final String PROGRAM_NAME = "JPass Password Manager";
- public static final String PROGRAM_VERSION = "1.0.6-SNAPSHOT";
+ public static final String PROGRAM_VERSION = "1.0.7-SNAPSHOT";
private final JPopupMenu popup;
private final JPanel topContainerPanel;
@@ -96,6 +116,7 @@ public final class JPassFrame extends JFrame {
private final JMenu fileMenu;
private final JMenu editMenu;
private final JMenu toolsMenu;
+ private final JMenu settingsMenu;
private final JMenu helpMenu;
private final JToolBar toolBar;
private final JScrollPane scrollPane;
@@ -103,9 +124,10 @@ public final class JPassFrame extends JFrame {
private final EntryDetailsTable entryDetailsTable;
private final DataModel model = DataModel.getInstance();
private final StatusPanel statusPanel;
+ private static String currentLanguage;
private volatile boolean processing = false;
- private JPassFrame(String fileName, Locale locale) {
+ private JPassFrame(String fileName) {
try {
setIconImages(Stream.of(16, 20, 32, 40, 64, 80, 128, 160)
.map(size -> getIcon("jpass", size, size).getImage())
@@ -114,7 +136,9 @@ private JPassFrame(String fileName, Locale locale) {
LOG.log(Level.CONFIG, "Could not set application icon.", e);
}
- localizedMessages = ResourceBundle.getBundle("resources.languages.languages", locale);
+ setSupportedLanguages();
+ setLocalizedMessages(Locale.forLanguageTag(getCurrentLanguage()));
+ UIManager.put(FILE_CHOOSER_CANCEL_BUTTON_TEXT, localizedMessages.getString(BUTTON_MESSAGE_CANCEL));
this.toolBar = new JToolBar();
this.toolBar.setFloatable(false);
@@ -182,6 +206,25 @@ private JPassFrame(String fileName, Locale locale) {
this.toolsMenu.add(MenuActionType.CLEAR_CLIPBOARD.getAction());
this.jpassMenuBar.add(this.toolsMenu);
+ this.settingsMenu = new JMenu(localizedMessages.getString(SETTINGS_MENU));
+ this.settingsMenu.setMnemonic(KeyEvent.VK_S);
+
+ JMenu languageMenu = new JMenu(localizedMessages.getString(SETTINGS_MENU_LANGUAGE));
+ languageMenu.setActionCommand(SETTINGS_MENU_LANGUAGE);
+ languageMenu.setIcon(getIcon("language"));
+
+ SUPPORTED_LANGUAGES.forEach((key, value) -> {
+ JMenuItem language = new JMenuItem(localizedMessages.getString(key));
+ if (Objects.equals(getCurrentLanguage(), value)) {
+ language.setIcon(getIcon("selection_checked"));
+ }
+ language.setActionCommand(key);
+ language.addActionListener(e -> refreshComponentsWithLanguageSelected(e.getActionCommand()));
+ languageMenu.add(language);
+ });
+ settingsMenu.add(languageMenu);
+ this.jpassMenuBar.add(this.settingsMenu);
+
this.helpMenu = new JMenu(localizedMessages.getString(HELP_MENU));
this.helpMenu.setMnemonic(KeyEvent.VK_H);
this.helpMenu.add(MenuActionType.LICENSE.getAction());
@@ -215,7 +258,7 @@ private JPassFrame(String fileName, Locale locale) {
setJMenuBar(this.jpassMenuBar);
setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
- setSize(450, 400);
+ setSize(490, 400);
setMinimumSize(new Dimension(420, 200));
addWindowListener(new CloseListener());
setLocationRelativeTo(null);
@@ -232,8 +275,10 @@ public static JPassFrame getInstance() {
public static synchronized JPassFrame getInstance(String fileName) {
if (instance == null) {
- String languageTag = Configuration.getInstance().get("language.languageSetting", "en-US");
- instance = new JPassFrame(fileName, Locale.forLanguageTag(languageTag));
+ String languageTag = Configuration.getInstance().get(LANGUAGE_LANGUAGE_SETTING, "en-US");
+ Configuration.getInstance().set(LANGUAGE_LANGUAGE_SETTING, languageTag);
+ setCurrentLanguage(languageTag);
+ instance = new JPassFrame(fileName);
}
return instance;
}
@@ -313,6 +358,109 @@ public void refreshAll() {
refreshEntryTitleList(null);
}
+ /**
+ * Refresh UI components with new translated strings from language selected
+ *
+ * @param actionCommand key to differentiate a component
+ */
+ private void refreshComponentsWithLanguageSelected(String actionCommand) {
+ String newLanguage = getSupportedLanguages().get(actionCommand);
+ if (Objects.equals(getCurrentLanguage(), newLanguage)) {
+ return;
+ }
+ setCurrentLanguage(newLanguage);
+ setLocalizedMessages(Locale.forLanguageTag(newLanguage));
+
+ UIManager.put(FILE_CHOOSER_CANCEL_BUTTON_TEXT, localizedMessages.getString(BUTTON_MESSAGE_CANCEL));
+
+ fileMenu.setText(localizedMessages.getString(FILE_MENU));
+ editMenu.setText(localizedMessages.getString(EDIT_MENU));
+ toolsMenu.setText(localizedMessages.getString(TOOLS_MENU));
+ settingsMenu.setText(localizedMessages.getString(SETTINGS_MENU));
+ helpMenu.setText(localizedMessages.getString(HELP_MENU));
+
+ updateMenuComponents(fileMenu);
+ updateMenuComponents(editMenu);
+ updateMenuComponents(toolsMenu);
+ updateMenuComponents(settingsMenu);
+ updateMenuComponents(helpMenu);
+ updateToolbarComponents(toolBar);
+
+ updateJPopupMenu(popup);
+ getSearchPanel().setLabelText(String.format("%s: ", getLocalizedMessages().getString(PANEL_FIND)));
+
+ updateTable();
+
+ Configuration.getInstance().set(LANGUAGE_LANGUAGE_SETTING, newLanguage);
+ MessageDialog.showInformationMessage(this, getLocalizedMessages().getString(LANGUAGE_LANGUAGE_CHANGED));
+ }
+
+ /**
+ * Updates JMenu components and its children with new translated strings
+ *
+ * @param menu to update
+ */
+ private void updateMenuComponents(JMenu menu) {
+ for (int i = 0; i < menu.getItemCount(); i++) {
+ JMenuItem item = menu.getItem(i);
+ if (null != item) {
+ String actionCommand = item.getActionCommand();
+ if (null != actionCommand) {
+ item.setText(localizedMessages.getString(actionCommand));
+
+ if (getSupportedLanguages().containsKey(actionCommand)) {
+ item.setIcon(null);
+ if (Objects.equals(getSupportedLanguages().get(actionCommand), getCurrentLanguage())) {
+ item.setIcon(getIcon("selection_checked"));
+ }
+ }
+ }
+
+ if (item instanceof JMenu) {
+ updateMenuComponents((JMenu) item);
+ }
+ }
+ }
+ }
+
+ /**
+ * Updates JPopupMenu components with new translated strings
+ * @param jPopupMenu
+ */
+ private void updateJPopupMenu(JPopupMenu jPopupMenu) {
+ for (Component comp : jPopupMenu.getComponents()) {
+ if (comp instanceof JMenuItem) {
+ JMenuItem item = (JMenuItem) comp;
+ item.setText(localizedMessages.getString(item.getActionCommand()));
+ }
+ }
+ }
+
+ /**
+ * Updates JToolBar components with new translated strings
+ * @param toolBar
+ */
+ private void updateToolbarComponents(JToolBar toolBar) {
+ for (Component comp : toolBar.getComponents()) {
+ if (comp instanceof JButton) {
+ JButton jButton = (JButton) comp;
+ jButton.setToolTipText(localizedMessages.getString(jButton.getActionCommand()));
+ }
+ }
+ }
+
+ /**
+ * Updates main JTable columns headers with new translated strings
+ */
+ private void updateTable() {
+ for (int i = 0; i < getEntryTitleTable().getColumnModel().getColumnCount(); i++) {
+ TableColumn column = getEntryTitleTable().getColumnModel().getColumn(i);
+ column.setHeaderValue(getLocalizedMessages().getString(entryDetailsTable.getDetailsToDisplay().get(i).getDescription()));
+ }
+ getEntryTitleTable().getTableHeader().repaint();
+ refreshEntryTitleList(null);
+ }
+
/**
* Exits the application.
*/
@@ -354,6 +502,24 @@ public void setProcessing(boolean processing) {
this.statusPanel.setProcessing(processing);
}
+ /**
+ * Sets the resource bundle for localization
+ *
+ * @param locale locale for the resources bundle
+ */
+ public static void setLocalizedMessages(Locale locale) {
+ JPassFrame.localizedMessages = ResourceBundle.getBundle("resources.languages.languages", locale);
+ }
+
+ /**
+ * Sets the current language for the program
+ *
+ * @param newLanguage
+ */
+ private static void setCurrentLanguage(String newLanguage) {
+ currentLanguage = newLanguage;
+ }
+
/**
* Gets the processing state of this frame.
*
@@ -364,7 +530,7 @@ public boolean isProcessing() {
}
/**
- * Get search panel.
+ * Gets search panel.
*
* @return the search panel
*/
@@ -374,9 +540,39 @@ public SearchPanel getSearchPanel() {
/**
* Gets the resource bundle for localization
+ *
* @return resource bundle
*/
public static ResourceBundle getLocalizedMessages() {
return localizedMessages;
}
+
+ /**
+ * Gets current language selected
+ *
+ * @return currentLanguage
+ */
+ private static String getCurrentLanguage() {
+ return currentLanguage;
+ }
+
+ /**
+ * Set supported languages currently
+ *
+ */
+ private static void setSupportedLanguages() {
+ SUPPORTED_LANGUAGES.put(LANGUAGE_EN_US, "en-US");
+ SUPPORTED_LANGUAGES.put(LANGUAGE_ES_MX, "es-MX");
+ SUPPORTED_LANGUAGES.put(LANGUAGE_HU_HU, "hu-HU");
+ SUPPORTED_LANGUAGES.put(LANGUAGE_IT_IT, "it-IT");
+ }
+
+ /**
+ * Gets supported languages
+ *
+ * @return Map of supported languages
+ */
+ private static Map getSupportedLanguages() {
+ return SUPPORTED_LANGUAGES;
+ }
}
diff --git a/src/main/java/jpass/ui/SearchPanel.java b/src/main/java/jpass/ui/SearchPanel.java
index 711c434c..8ca8aef1 100644
--- a/src/main/java/jpass/ui/SearchPanel.java
+++ b/src/main/java/jpass/ui/SearchPanel.java
@@ -144,6 +144,14 @@ public void actionPerformed(ActionEvent e) {
}
}
+ /**
+ * Sets text for label
+ * @param text of the label
+ */
+ public void setLabelText(String text) {
+ this.label.setText(text);
+ }
+
/**
* Get search criteria.
*
diff --git a/src/main/java/jpass/ui/action/AbstractMenuAction.java b/src/main/java/jpass/ui/action/AbstractMenuAction.java
index 8e61d602..56ea1ad4 100644
--- a/src/main/java/jpass/ui/action/AbstractMenuAction.java
+++ b/src/main/java/jpass/ui/action/AbstractMenuAction.java
@@ -43,12 +43,14 @@ public abstract class AbstractMenuAction extends AbstractAction {
/**
* Creates a new menu action.
*
- * @param text title of the action that appears on UI
- * @param icon icon of action
- * @param accelerator accelerator key
+ * @param text title of the action that appears on UI
+ * @param actionCommandKey
+ * @param icon icon of action
+ * @param accelerator accelerator key
*/
- public AbstractMenuAction(String text, Icon icon, KeyStroke accelerator) {
+ public AbstractMenuAction(String text, String actionCommandKey, Icon icon, KeyStroke accelerator) {
super(text, icon);
+ putValue(ACTION_COMMAND_KEY, actionCommandKey);
putValue(SHORT_DESCRIPTION, text);
if (accelerator != null) {
putValue(ACCELERATOR_KEY, accelerator);
diff --git a/src/main/java/jpass/ui/action/MenuActionType.java b/src/main/java/jpass/ui/action/MenuActionType.java
index 58714f13..250908a1 100644
--- a/src/main/java/jpass/ui/action/MenuActionType.java
+++ b/src/main/java/jpass/ui/action/MenuActionType.java
@@ -41,7 +41,6 @@
import jpass.ui.JPassFrame;
import jpass.ui.MessageDialog;
import jpass.ui.helper.EntryHelper;
-import jpass.util.Constants;
import jpass.xml.bind.Entry;
import static javax.swing.KeyStroke.getKeyStroke;
@@ -56,8 +55,6 @@
import static java.awt.event.InputEvent.CTRL_DOWN_MASK;
import static java.awt.event.InputEvent.ALT_DOWN_MASK;
-import static jpass.util.Constants.PASSWORD_PASSWORD_NOT_MODIFIED;
-import static jpass.util.Constants.PASSWORD_SUCCESSFULLY_MODIFIED;
import static jpass.util.Constants.EDIT_MENU_ADD_ENTRY;
import static jpass.util.Constants.EDIT_MENU_CLEAR_CLIPBOARD;
import static jpass.util.Constants.EDIT_MENU_COPY_PASSWORD;
@@ -71,11 +68,14 @@
import static jpass.util.Constants.FILE_MENU_EXIT;
import static jpass.util.Constants.FILE_MENU_EXPORT_TO_XML;
import static jpass.util.Constants.FILE_MENU_IMPORT_FROM_XML;
+import static jpass.util.Constants.FILE_MENU_OPEN_FILE;
import static jpass.util.Constants.FILE_MENU_NEW;
import static jpass.util.Constants.FILE_MENU_SAVE;
import static jpass.util.Constants.FILE_MENU_SAVE_AS;
import static jpass.util.Constants.HELP_MENU_ABOUT_JPASS;
import static jpass.util.Constants.HELP_MENU_LICENSE;
+import static jpass.util.Constants.PASSWORD_PASSWORD_NOT_MODIFIED;
+import static jpass.util.Constants.PASSWORD_SUCCESSFULLY_MODIFIED;
import static jpass.util.Constants.TOOLS_MENU_GENERATE_PASSWORD;
/**
@@ -85,43 +85,43 @@
*
*/
public enum MenuActionType {
- NEW_FILE(new AbstractMenuAction(getLocalizedMessages().getString(FILE_MENU_NEW), getIcon("new"), getKeyStroke(KeyEvent.VK_N, CTRL_DOWN_MASK)) {
+ NEW_FILE(new AbstractMenuAction(getLocalizedMessages().getString(FILE_MENU_NEW), FILE_MENU_NEW, getIcon("new"), getKeyStroke(KeyEvent.VK_N, CTRL_DOWN_MASK)) {
@Override
public void actionPerformed(ActionEvent ev) {
createNew(JPassFrame.getInstance());
}
}),
- OPEN_FILE(new AbstractMenuAction(getLocalizedMessages().getString(Constants.FILE_MENU_OPEN_FILE), getIcon("open"), getKeyStroke(KeyEvent.VK_O, CTRL_DOWN_MASK)) {
+ OPEN_FILE(new AbstractMenuAction(getLocalizedMessages().getString(FILE_MENU_OPEN_FILE), FILE_MENU_OPEN_FILE, getIcon("open"), getKeyStroke(KeyEvent.VK_O, CTRL_DOWN_MASK)) {
@Override
public void actionPerformed(ActionEvent ev) {
openFile(JPassFrame.getInstance());
}
}),
- SAVE_FILE(new AbstractMenuAction(getLocalizedMessages().getString(FILE_MENU_SAVE), getIcon("save"), getKeyStroke(KeyEvent.VK_S, CTRL_DOWN_MASK)) {
+ SAVE_FILE(new AbstractMenuAction(getLocalizedMessages().getString(FILE_MENU_SAVE), FILE_MENU_SAVE, getIcon("save"), getKeyStroke(KeyEvent.VK_S, CTRL_DOWN_MASK)) {
@Override
public void actionPerformed(ActionEvent ev) {
saveFile(JPassFrame.getInstance(), false);
}
}),
- SAVE_AS_FILE(new AbstractMenuAction(getLocalizedMessages().getString(FILE_MENU_SAVE_AS), getIcon("save_as"), null) {
+ SAVE_AS_FILE(new AbstractMenuAction(getLocalizedMessages().getString(FILE_MENU_SAVE_AS), FILE_MENU_SAVE_AS, getIcon("save_as"), null) {
@Override
public void actionPerformed(ActionEvent ev) {
saveFile(JPassFrame.getInstance(), true);
}
}),
- EXPORT_XML(new AbstractMenuAction(getLocalizedMessages().getString(FILE_MENU_EXPORT_TO_XML), getIcon("export"), null) {
+ EXPORT_XML(new AbstractMenuAction(getLocalizedMessages().getString(FILE_MENU_EXPORT_TO_XML), FILE_MENU_EXPORT_TO_XML, getIcon("export"), null) {
@Override
public void actionPerformed(ActionEvent ev) {
exportFile(JPassFrame.getInstance());
}
}),
- IMPORT_XML(new AbstractMenuAction(getLocalizedMessages().getString(FILE_MENU_IMPORT_FROM_XML), getIcon("import"), null) {
+ IMPORT_XML(new AbstractMenuAction(getLocalizedMessages().getString(FILE_MENU_IMPORT_FROM_XML), FILE_MENU_IMPORT_FROM_XML, getIcon("import"), null) {
@Override
public void actionPerformed(ActionEvent ev) {
importFile(JPassFrame.getInstance());
}
}),
- CHANGE_PASSWORD(new AbstractMenuAction(getLocalizedMessages().getString(FILE_MENU_CHANGE_PASSWORD), getIcon("lock"), null) {
+ CHANGE_PASSWORD(new AbstractMenuAction(getLocalizedMessages().getString(FILE_MENU_CHANGE_PASSWORD), FILE_MENU_CHANGE_PASSWORD, getIcon("lock"), null) {
@Override
public void actionPerformed(ActionEvent ev) {
JPassFrame parent = JPassFrame.getInstance();
@@ -137,19 +137,19 @@ public void actionPerformed(ActionEvent ev) {
}
}
}),
- GENERATE_PASSWORD(new AbstractMenuAction(getLocalizedMessages().getString(TOOLS_MENU_GENERATE_PASSWORD), getIcon("generate"), getKeyStroke(KeyEvent.VK_Z, CTRL_DOWN_MASK)) {
+ GENERATE_PASSWORD(new AbstractMenuAction(getLocalizedMessages().getString(TOOLS_MENU_GENERATE_PASSWORD), TOOLS_MENU_GENERATE_PASSWORD, getIcon("generate"), getKeyStroke(KeyEvent.VK_Z, CTRL_DOWN_MASK)) {
@Override
public void actionPerformed(ActionEvent ev) {
new GeneratePasswordDialog(JPassFrame.getInstance());
}
}),
- EXIT(new AbstractMenuAction(getLocalizedMessages().getString(FILE_MENU_EXIT), getIcon("exit"), getKeyStroke(KeyEvent.VK_F4, ALT_DOWN_MASK)) {
+ EXIT(new AbstractMenuAction(getLocalizedMessages().getString(FILE_MENU_EXIT), FILE_MENU_EXIT, getIcon("exit"), getKeyStroke(KeyEvent.VK_F4, ALT_DOWN_MASK)) {
@Override
public void actionPerformed(ActionEvent ev) {
JPassFrame.getInstance().exitFrame();
}
}),
- ABOUT(new AbstractMenuAction(getLocalizedMessages().getString(HELP_MENU_ABOUT_JPASS), getIcon("info"), getKeyStroke(KeyEvent.VK_F1, 0)) {
+ ABOUT(new AbstractMenuAction(getLocalizedMessages().getString(HELP_MENU_ABOUT_JPASS), HELP_MENU_ABOUT_JPASS, getIcon("info"), getKeyStroke(KeyEvent.VK_F1, 0)) {
@Override
public void actionPerformed(ActionEvent ev) {
StringBuilder sb = new StringBuilder();
@@ -162,37 +162,37 @@ public void actionPerformed(ActionEvent ev) {
MessageDialog.showInformationMessage(JPassFrame.getInstance(), sb.toString());
}
}),
- LICENSE(new AbstractMenuAction(getLocalizedMessages().getString(HELP_MENU_LICENSE), getIcon("license"), null) {
+ LICENSE(new AbstractMenuAction(getLocalizedMessages().getString(HELP_MENU_LICENSE), HELP_MENU_LICENSE, getIcon("license"), null) {
@Override
public void actionPerformed(ActionEvent ev) {
MessageDialog.showTextFile(JPassFrame.getInstance(), getLocalizedMessages().getString(HELP_MENU_LICENSE), "license.txt");
}
}),
- ADD_ENTRY(new AbstractMenuAction(getLocalizedMessages().getString(EDIT_MENU_ADD_ENTRY), getIcon("entry_new"), getKeyStroke(KeyEvent.VK_Y, CTRL_DOWN_MASK)) {
+ ADD_ENTRY(new AbstractMenuAction(getLocalizedMessages().getString(EDIT_MENU_ADD_ENTRY), EDIT_MENU_ADD_ENTRY, getIcon("entry_new"), getKeyStroke(KeyEvent.VK_Y, CTRL_DOWN_MASK)) {
@Override
public void actionPerformed(ActionEvent ev) {
EntryHelper.addEntry(JPassFrame.getInstance());
}
}),
- EDIT_ENTRY(new AbstractMenuAction(getLocalizedMessages().getString(EDIT_MENU_EDIT_ENTRY), getIcon("entry_edit"), getKeyStroke(KeyEvent.VK_E, CTRL_DOWN_MASK)) {
+ EDIT_ENTRY(new AbstractMenuAction(getLocalizedMessages().getString(EDIT_MENU_EDIT_ENTRY), EDIT_MENU_EDIT_ENTRY, getIcon("entry_edit"), getKeyStroke(KeyEvent.VK_E, CTRL_DOWN_MASK)) {
@Override
public void actionPerformed(ActionEvent ev) {
EntryHelper.editEntry(JPassFrame.getInstance());
}
}),
- DUPLICATE_ENTRY(new AbstractMenuAction(getLocalizedMessages().getString(EDIT_MENU_DUPLICATE_ENTRY), getIcon("entry_duplicate"), getKeyStroke(KeyEvent.VK_K, CTRL_DOWN_MASK)) {
+ DUPLICATE_ENTRY(new AbstractMenuAction(getLocalizedMessages().getString(EDIT_MENU_DUPLICATE_ENTRY), EDIT_MENU_DUPLICATE_ENTRY, getIcon("entry_duplicate"), getKeyStroke(KeyEvent.VK_K, CTRL_DOWN_MASK)) {
@Override
public void actionPerformed(ActionEvent ev) {
EntryHelper.duplicateEntry(JPassFrame.getInstance());
}
}),
- DELETE_ENTRY(new AbstractMenuAction(getLocalizedMessages().getString(EDIT_MENU_DELETE_ENTRY), getIcon("entry_delete"), getKeyStroke(KeyEvent.VK_D, CTRL_DOWN_MASK)) {
+ DELETE_ENTRY(new AbstractMenuAction(getLocalizedMessages().getString(EDIT_MENU_DELETE_ENTRY), EDIT_MENU_DELETE_ENTRY, getIcon("entry_delete"), getKeyStroke(KeyEvent.VK_D, CTRL_DOWN_MASK)) {
@Override
public void actionPerformed(ActionEvent ev) {
EntryHelper.deleteEntry(JPassFrame.getInstance());
}
}),
- COPY_URL(new AbstractMenuAction(getLocalizedMessages().getString(EDIT_MENU_COPY_URL), getIcon("url"), getKeyStroke(KeyEvent.VK_U, CTRL_DOWN_MASK)) {
+ COPY_URL(new AbstractMenuAction(getLocalizedMessages().getString(EDIT_MENU_COPY_URL), EDIT_MENU_COPY_URL, getIcon("url"), getKeyStroke(KeyEvent.VK_U, CTRL_DOWN_MASK)) {
@Override
public void actionPerformed(ActionEvent ev) {
JPassFrame parent = JPassFrame.getInstance();
@@ -202,7 +202,7 @@ public void actionPerformed(ActionEvent ev) {
}
}
}),
- COPY_USER(new AbstractMenuAction(getLocalizedMessages().getString(EDIT_MENU_COPY_USERNAME), getIcon("user"), getKeyStroke(KeyEvent.VK_B, CTRL_DOWN_MASK)) {
+ COPY_USER(new AbstractMenuAction(getLocalizedMessages().getString(EDIT_MENU_COPY_USERNAME), EDIT_MENU_COPY_USERNAME, getIcon("user"), getKeyStroke(KeyEvent.VK_B, CTRL_DOWN_MASK)) {
@Override
public void actionPerformed(ActionEvent ev) {
JPassFrame parent = JPassFrame.getInstance();
@@ -212,7 +212,7 @@ public void actionPerformed(ActionEvent ev) {
}
}
}),
- COPY_PASSWORD(new AbstractMenuAction(getLocalizedMessages().getString(EDIT_MENU_COPY_PASSWORD), getIcon("keyring"), getKeyStroke(KeyEvent.VK_C, CTRL_DOWN_MASK)) {
+ COPY_PASSWORD(new AbstractMenuAction(getLocalizedMessages().getString(EDIT_MENU_COPY_PASSWORD), EDIT_MENU_COPY_PASSWORD, getIcon("keyring"), getKeyStroke(KeyEvent.VK_C, CTRL_DOWN_MASK)) {
@Override
public void actionPerformed(ActionEvent ev) {
JPassFrame parent = JPassFrame.getInstance();
@@ -222,13 +222,13 @@ public void actionPerformed(ActionEvent ev) {
}
}
}),
- CLEAR_CLIPBOARD(new AbstractMenuAction(getLocalizedMessages().getString(EDIT_MENU_CLEAR_CLIPBOARD), getIcon("clear"), getKeyStroke(KeyEvent.VK_X, CTRL_DOWN_MASK)) {
+ CLEAR_CLIPBOARD(new AbstractMenuAction(getLocalizedMessages().getString(EDIT_MENU_CLEAR_CLIPBOARD), EDIT_MENU_CLEAR_CLIPBOARD, getIcon("clear"), getKeyStroke(KeyEvent.VK_X, CTRL_DOWN_MASK)) {
@Override
public void actionPerformed(ActionEvent ev) {
EntryHelper.copyEntryField(JPassFrame.getInstance(), null);
}
}),
- FIND_ENTRY(new AbstractMenuAction(getLocalizedMessages().getString(EDIT_MENU_FIND_ENTRY), getIcon("find"), getKeyStroke(KeyEvent.VK_F, CTRL_DOWN_MASK)) {
+ FIND_ENTRY(new AbstractMenuAction(getLocalizedMessages().getString(EDIT_MENU_FIND_ENTRY), EDIT_MENU_FIND_ENTRY, getIcon("find"), getKeyStroke(KeyEvent.VK_F, CTRL_DOWN_MASK)) {
@Override
public void actionPerformed(ActionEvent ev) {
JPassFrame.getInstance().getSearchPanel().setVisible(true);
diff --git a/src/main/java/jpass/util/Configuration.java b/src/main/java/jpass/util/Configuration.java
index 7f86f94f..d88bde64 100644
--- a/src/main/java/jpass/util/Configuration.java
+++ b/src/main/java/jpass/util/Configuration.java
@@ -30,11 +30,14 @@
import java.io.File;
import java.io.FileInputStream;
+import java.io.IOException;
import java.io.InputStream;
-import java.util.Optional;
-import java.util.Properties;
+import java.io.OutputStream;
+import java.nio.file.Files;
import java.util.logging.Level;
import java.util.logging.Logger;
+import java.util.Optional;
+import java.util.Properties;
/**
* Class for loading configurations from {@code jpass.properties} or system properties.
@@ -50,7 +53,7 @@ public final class Configuration {
private static final Logger LOG = Logger.getLogger(Configuration.class.getName());
private static Configuration instance;
- private Properties properties = new Properties();
+ private final Properties properties = new Properties();
private Configuration() {
try {
@@ -110,6 +113,20 @@ public String get(String key, String defaultValue) {
return prop != null ? prop : defaultValue;
}
+ public void set(String key, String value) {
+ properties.setProperty(key, value);
+ saveProperties();
+ }
+
+ private void saveProperties() {
+ File filePath = new File(getConfigurationFolderPath(), "jpass.properties");
+ try (OutputStream os = Files.newOutputStream(filePath.toPath())) {
+ properties.store(os, "Configuration properties");
+ } catch (IOException e) {
+ LOG.log(Level.WARNING, "Could not save configuration to file.", e);
+ }
+ }
+
public String[] getArray(String key, String[] defaultValue) {
String prop = getProperty(key);
if (prop != null) {
diff --git a/src/main/java/jpass/util/Constants.java b/src/main/java/jpass/util/Constants.java
index a150f6bb..10503d91 100644
--- a/src/main/java/jpass/util/Constants.java
+++ b/src/main/java/jpass/util/Constants.java
@@ -5,9 +5,12 @@ private Constants() {
// not intended to be instantiated
}
+ public static final String FILE_CHOOSER_CANCEL_BUTTON_TEXT = "FileChooser.cancelButtonText";
+
public static final String FILE_MENU = "menuBar.fileMenu";
public static final String EDIT_MENU = "menuBar.editMenu";
public static final String TOOLS_MENU = "menuBar.toolsMenu";
+ public static final String SETTINGS_MENU = "menuBar.settingsMenu";
public static final String HELP_MENU = "menuBar.helpMenu";
public static final String FILE_MENU_NEW = "fileMenu.new";
@@ -41,6 +44,8 @@ private Constants() {
public static final String TOOLS_MENU_GENERATE_PASSWORD = "toolsMenu.generatePassword";
+ public static final String SETTINGS_MENU_LANGUAGE = "settingsMenu.language";
+
public static final String HELP_MENU_LICENSE = "helpMenu.license";
public static final String HELP_MENU_ABOUT_JPASS = "helpMenu.aboutJpass";
@@ -93,4 +98,11 @@ private Constants() {
public static final String PANEL_OPEN = "panel.open";
public static final String PANEL_SAVE_MODIFIED_QUESTION_MESSAGE = "panel.saveModifiedQuestionMessage";
public static final String PANEL_UNENCRYPTED_DATA_WARNING_MESSAGE = "panel.unencryptedDataWarningMessage";
+
+ public static final String LANGUAGE_LANGUAGE_SETTING = "language.languageSetting";
+ public static final String LANGUAGE_LANGUAGE_CHANGED = "language.languageChanged";
+ public static final String LANGUAGE_EN_US = "language.en.us";
+ public static final String LANGUAGE_ES_MX = "language.es.mx";
+ public static final String LANGUAGE_HU_HU = "language.hu.hu";
+ public static final String LANGUAGE_IT_IT = "language.it.it";
}
diff --git a/src/main/resources/resources/images/language.svg b/src/main/resources/resources/images/language.svg
new file mode 100644
index 00000000..a705061c
--- /dev/null
+++ b/src/main/resources/resources/images/language.svg
@@ -0,0 +1,50 @@
+
+
diff --git a/src/main/resources/resources/images/language_dark.svg b/src/main/resources/resources/images/language_dark.svg
new file mode 100644
index 00000000..a705061c
--- /dev/null
+++ b/src/main/resources/resources/images/language_dark.svg
@@ -0,0 +1,50 @@
+
+
diff --git a/src/main/resources/resources/images/selection_checked.svg b/src/main/resources/resources/images/selection_checked.svg
new file mode 100644
index 00000000..5ed423bb
--- /dev/null
+++ b/src/main/resources/resources/images/selection_checked.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/main/resources/resources/images/selection_checked_dark.svg b/src/main/resources/resources/images/selection_checked_dark.svg
new file mode 100644
index 00000000..5ed423bb
--- /dev/null
+++ b/src/main/resources/resources/images/selection_checked_dark.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/main/resources/resources/languages/languages_en_US.properties b/src/main/resources/resources/languages/languages_en_US.properties
index 9dd7bca7..5c588dac 100644
--- a/src/main/resources/resources/languages/languages_en_US.properties
+++ b/src/main/resources/resources/languages/languages_en_US.properties
@@ -2,6 +2,7 @@
menuBar.fileMenu=File
menuBar.editMenu=Edit
menuBar.toolsMenu=Tools
+menuBar.settingsMenu=Settings
menuBar.helpMenu=Help
fileMenu.new=New
@@ -35,6 +36,8 @@ editMenu.findEntry=Find Entry
toolsMenu.generatePassword=Generate Password...
+settingsMenu.language=Language
+
helpMenu.license=License
helpMenu.aboutJpass=About JPass...
@@ -87,3 +90,9 @@ panel.save=Save
panel.open=Open
panel.saveModifiedQuestionMessage=The current file has been modified.\nDo you want to save the changes before closing?
panel.unencryptedDataWarningMessage=Please note that all data will be stored unencrypted.\nMake sure you keep the exported file in a secure location.
+
+language.languageChanged=Language has changed successfully.
+language.en.us=English
+language.es.mx=Spanish
+language.hu.hu=Hungarian
+language.it.it=Italian
diff --git a/src/main/resources/resources/languages/languages_es_MX.properties b/src/main/resources/resources/languages/languages_es_MX.properties
index c2efa1ad..c09546bc 100644
--- a/src/main/resources/resources/languages/languages_es_MX.properties
+++ b/src/main/resources/resources/languages/languages_es_MX.properties
@@ -2,6 +2,7 @@
menuBar.fileMenu=Archivo
menuBar.editMenu=Editar
menuBar.toolsMenu=Herramientas
+menuBar.settingsMenu=Ajustes
menuBar.helpMenu=Ayuda
fileMenu.new=Nuevo
@@ -14,6 +15,7 @@ fileMenu.changePassword=Cambiar Contrase
fileMenu.exitMenu=Salir
password.enterPasswordRequest=Por favor, introduce una contraseńa.
+password.generatePasswordRequest=Por favor, genere una contraseńa.
password.passwordNotModified=La contraseńa no ha sido modificada.
password.successfullyModified=La contraseńa ha sido modificada exitosamente.\n\nGuarda el archivo ahora para asegurarse que la nueva contraseńa fue aplicada.
password.passwordsNotIdentical=La contraseńa y contraseńa de confirmación no son identicas.
@@ -34,6 +36,8 @@ editMenu.findEntry=Buscar Entrada
toolsMenu.generatePassword=Generar Contraseńa...
+settingsMenu.language=Idioma
+
helpMenu.license=Licencia
helpMenu.aboutJpass=Acerca de JPass...
@@ -67,7 +71,7 @@ buttonMessage.close=Cerrar
entryDialog.showEntry=Mostrar
entryDialog.generateEntry=Generar
entryDialog.copyEntry=Copiar
-entryDialog.fillTitleField=Please fill the title field.
+entryDialog.fillTitleField=Por favor, complete el campo de título.
entryDialog.titleAlreadyExists=El título ya existe,\nPor favor introduzca un título diferente.
entryDialog.pleaseSelectEntry=Por favor, selecciona una entrada.
entryDialog.wantDeleteEntry=żRealmente quieres eliminar esta entrada?
@@ -86,3 +90,9 @@ panel.save=Guardar
panel.open=Abrir
panel.saveModifiedQuestionMessage=El archivo actual ha sido modificado.\nżDeseas guardar los cambios antes de cerrar el programa?
panel.unencryptedDataWarningMessage=Note que toda la data se almancenará sin cifrar.\nAsegúrese de guardar el archivo exportado en un lugar seguro.
+
+language.languageChanged=El idioma ha cambiado correctamente.
+language.en.us=Inglés
+language.es.mx=Espańol
+language.hu.hu=Húngaro
+language.it.it=Italiano
diff --git a/src/main/resources/resources/languages/languages_hu_HU.properties b/src/main/resources/resources/languages/languages_hu_HU.properties
index ac609949..e89032cc 100644
--- a/src/main/resources/resources/languages/languages_hu_HU.properties
+++ b/src/main/resources/resources/languages/languages_hu_HU.properties
@@ -1,6 +1,7 @@
menuBar.fileMenu=Fájl
menuBar.editMenu=Szerkesztés
menuBar.toolsMenu=Eszközök
+menuBar.settingsMenu=BeállĂtások
menuBar.helpMenu=SĂşgĂł
fileMenu.new=Ăšj
@@ -34,6 +35,8 @@ editMenu.findEntry=Bejegyzés keresése
toolsMenu.generatePassword=Jelszó generálás...
+settingsMenu.language=Nyelv
+
helpMenu.license=Licenc
helpMenu.aboutJpass=JPass névjegy...
@@ -87,3 +90,8 @@ panel.open=Megnyitás
panel.saveModifiedQuestionMessage=A jelenlegi fájl mĂłdosĂtva lett.\nMenteni szeretnĂ© a változtatásokat bezárás elĹ‘tt?
panel.unencryptedDataWarningMessage=FelhĂvjuk figyelmĂ©t, hogy az adatok titkosĂtás nĂ©lkĂĽl lesznek tárolva.\nBizonyosodjon meg rĂłla, hogy az exportált fájlt biztonságos helyre menti.
+language.languageChanged=A nyelv sikeresen megváltozott.
+language.en.us=Angol
+language.es.mx=Spanyol
+language.hu.hu=Magyar
+language.it.it=Olasz
diff --git a/src/main/resources/resources/languages/languages_it_IT.properties b/src/main/resources/resources/languages/languages_it_IT.properties
index 5a3f1d79..e7d6408c 100644
--- a/src/main/resources/resources/languages/languages_it_IT.properties
+++ b/src/main/resources/resources/languages/languages_it_IT.properties
@@ -2,6 +2,7 @@
menuBar.fileMenu=File
menuBar.editMenu=Modifica
menuBar.toolsMenu=Strumenti
+menuBar.settingsMenu=Impostazioni
menuBar.helpMenu=Aiuto
fileMenu.new=Nuovo
@@ -35,6 +36,8 @@ editMenu.findEntry=Trova elemento
toolsMenu.generatePassword=Genera password...
+settingsMenu.language=Lingua
+
helpMenu.license=Licenza
helpMenu.aboutJpass=Info su JPass...
@@ -87,3 +90,9 @@ panel.save=Salva
panel.open=Apri
panel.saveModifiedQuestionMessage=Il file attuale è stato modificato.\nVuoi salvare le modifiche prima della chiusura?
panel.unencryptedDataWarningMessage=Nota che tutti i dati verranno archiviati non crittografati.\nAssicurati di conservare il file esportato in un luogo sicuro.
+
+language.languageChanged=Impostazione lingua completata.
+language.en.us=Inglese
+language.es.mx=Spagnolo
+language.hu.hu=Ungherese
+language.it.it=Italiano
diff --git a/src/test/java/jpass/util/ConfigurationTest.java b/src/test/java/jpass/util/ConfigurationTest.java
index ded9b60b..f4de4e3c 100644
--- a/src/test/java/jpass/util/ConfigurationTest.java
+++ b/src/test/java/jpass/util/ConfigurationTest.java
@@ -44,38 +44,57 @@ public void setup() {
}
@Test
- public void configurationIsDarkModeEnabledTest() {
+ void configurationIsDarkModeEnabledTest() {
Boolean result = configuration.is("ui.theme.dark.mode.enabled", false);
assertFalse(result);
}
@Test
- public void configurationGetIntegerClearClipboardOnExitWrongConfigTest() {
+ void configurationGetIntegerClearClipboardOnExitWrongConfigTest() {
int result = configuration.getInteger("clear.clipboard.on.exit.enabled", 0);
assertEquals(0, result);
}
@Test
- public void configurationIsDefaultPasswordGenerationNullConfigTest() {
+ void configurationIsDefaultPasswordGenerationNullConfigTest() {
Boolean result = configuration.is("default.password.generation.size", false);
assertFalse(result);
}
@Test
- public void configurationGetDateFormatTest() {
+ void configurationGetDateFormatTest() {
String result = configuration.get("date.format", "yyyy-MM-dd");
assertEquals("yyyy-MM-dd", result);
}
@Test
- public void configurationGetArrayEntryDetailsTest() {
+ void configurationGetLanguageTestSupportedLanguages() {
+ configuration.set("language.languageSetting", "en-US");
+ String result = configuration.get("language.languageSetting", null);
+ assertEquals("en-US", result);
+
+ configuration.set("language.languageSetting", "es-MX");
+ result = configuration.get("language.languageSetting", null);
+ assertEquals("es-MX", result);
+
+ configuration.set("language.languageSetting", "hu-HU");
+ result = configuration.get("language.languageSetting", null);
+ assertEquals("hu-HU", result);
+
+ configuration.set("language.languageSetting", "it-IT");
+ result = configuration.get("language.languageSetting", null);
+ assertEquals("it-IT", result);
+ }
+
+ @Test
+ void configurationGetArrayEntryDetailsTest() {
String[] defaultValue = new String[]{"TITLE", "MODIFIED"};
String[] result = configuration.getArray("entry.details", defaultValue);
assertArrayEquals(defaultValue, result);
}
@Test
- public void configurationGetArrayEntryDetailsWrongKeyTest() {
+ void configurationGetArrayEntryDetailsWrongKeyTest() {
String[] defaultValue = new String[]{"TITLE", "MODIFIED"};
String[] result = configuration.getArray("entry.detail", defaultValue);
assertArrayEquals(defaultValue, result);