added translation capabilities
This commit is contained in:
parent
ad279a6b15
commit
83f92f1ef3
|
@ -3,6 +3,7 @@ package me.teridax.jcash;
|
|||
import me.teridax.jcash.gui.Loader;
|
||||
import me.teridax.jcash.gui.account.AccountController;
|
||||
import me.teridax.jcash.gui.login.LoginController;
|
||||
import me.teridax.jcash.lang.Locales;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Objects;
|
||||
|
@ -12,6 +13,7 @@ import static javax.swing.JOptionPane.ERROR_MESSAGE;
|
|||
import static javax.swing.JOptionPane.showMessageDialog;
|
||||
import static me.teridax.jcash.Logging.LOGGER;
|
||||
import static me.teridax.jcash.Logging.initializeSystemLogger;
|
||||
import static me.teridax.jcash.lang.Translator.translate;
|
||||
|
||||
public final class Main {
|
||||
|
||||
|
@ -28,7 +30,7 @@ public final class Main {
|
|||
private Main() {
|
||||
// create main window and set defaults
|
||||
this.window = new JFrame();
|
||||
this.window.setTitle("Bankautomat");
|
||||
this.window.setTitle(translate("Cashmachine"));
|
||||
this.window.setLocationByPlatform(true);
|
||||
this.window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
}
|
||||
|
@ -36,6 +38,8 @@ public final class Main {
|
|||
public static void main(String[] args) {
|
||||
initializeSystemLogger(Level.FINE);
|
||||
|
||||
Locales.autodetectDefaultLocale();
|
||||
|
||||
// create main instance and show the login screen
|
||||
instance();
|
||||
getInstance().showLoginScreen();
|
||||
|
@ -97,7 +101,7 @@ public final class Main {
|
|||
|
||||
} catch (IllegalStateException e) {
|
||||
LOGGER.fine("Unable to show login mask: " + e.getMessage());
|
||||
showMessageDialog(null, e.getMessage(), "Closing JCash", ERROR_MESSAGE);
|
||||
showMessageDialog(null, e.getMessage(), translate("Closing JCash"), ERROR_MESSAGE);
|
||||
System.exit(0);
|
||||
}
|
||||
});
|
||||
|
@ -107,7 +111,7 @@ public final class Main {
|
|||
* Logs the user out of the database, hiding the main window.
|
||||
*/
|
||||
public void logout() {
|
||||
window.setContentPane(new JLabel("you're logged out"));
|
||||
window.setContentPane(new JLabel(translate("you're logged out")));
|
||||
window.setVisible(false);
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ package me.teridax.jcash.gui;
|
|||
|
||||
import me.teridax.jcash.Logging;
|
||||
import me.teridax.jcash.banking.management.BankingManagementSystem;
|
||||
import me.teridax.jcash.lang.Translator;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||
|
@ -34,7 +35,7 @@ public class Loader {
|
|||
fileChooser.setDialogType(JFileChooser.OPEN_DIALOG);
|
||||
fileChooser.setAcceptAllFileFilterUsed(false);
|
||||
|
||||
if (fileChooser.showDialog(null, "Load database") == APPROVE_OPTION) {
|
||||
if (fileChooser.showDialog(null, Translator.translate("Load database")) == APPROVE_OPTION) {
|
||||
// parse file content
|
||||
try {
|
||||
return BankingManagementSystem.loadFromCsv(fileChooser.getSelectedFile().toPath());
|
||||
|
|
|
@ -10,6 +10,7 @@ import javax.swing.*;
|
|||
import java.awt.*;
|
||||
|
||||
import static javax.swing.SwingConstants.RIGHT;
|
||||
import static me.teridax.jcash.lang.Translator.translate;
|
||||
|
||||
public class AccountView extends JPanel {
|
||||
|
||||
|
@ -52,10 +53,10 @@ public class AccountView extends JPanel {
|
|||
|
||||
this.type.setText(account.getClass().getSimpleName());
|
||||
if (account instanceof CurrentAccount) {;
|
||||
this.typeSpecialLabel.setText("Overdraft");
|
||||
this.typeSpecialLabel.setText(translate("Overdraft"));
|
||||
this.typeSpecialProperty.setText( StringDecoder.LOCAL_NUMBER_FORMAT.format(((CurrentAccount) account).getOverdraft()) + " €");
|
||||
} else if (account instanceof SavingsAccount) {
|
||||
this.typeSpecialLabel.setText("Interest rate");
|
||||
this.typeSpecialLabel.setText(translate("Interest rate"));
|
||||
this.typeSpecialProperty.setText( ((SavingsAccount) account).getInterest() + " %" );
|
||||
} else {
|
||||
Logging.LOGGER.severe("Type of new primary account cannot be determined: " + account.getClass().getName());
|
||||
|
@ -84,14 +85,14 @@ public class AccountView extends JPanel {
|
|||
accountSelectionPanel.add(iban, BorderLayout.CENTER);
|
||||
accountSelectionPanel.add(accountSelection, BorderLayout.EAST);
|
||||
|
||||
addInputRow(constraints, content, accountSelectionPanel, 1, new JLabel("IBAN", RIGHT));
|
||||
addInputRow(constraints, content, name, 2, new JLabel("Name/Family-name", RIGHT));
|
||||
addInputRow(constraints, content, address, 3, new JLabel("Address", RIGHT));
|
||||
addInputRow(constraints, content, bankName, 4, new JLabel("Bank", RIGHT));
|
||||
addInputRow(constraints, content, blz, 5, new JLabel("BLZ", RIGHT));
|
||||
addInputRow(constraints, content, type, 6, new JLabel("Account", RIGHT));
|
||||
addInputRow(constraints, content, accountSelectionPanel, 1, new JLabel(translate("IBAN"), RIGHT));
|
||||
addInputRow(constraints, content, name, 2, new JLabel(translate("Name/Family-name"), RIGHT));
|
||||
addInputRow(constraints, content, address, 3, new JLabel(translate("Address"), RIGHT));
|
||||
addInputRow(constraints, content, bankName, 4, new JLabel(translate("Bank"), RIGHT));
|
||||
addInputRow(constraints, content, blz, 5, new JLabel(translate("BLZ"), RIGHT));
|
||||
addInputRow(constraints, content, type, 6, new JLabel(translate("Account"), RIGHT));
|
||||
addInputRow(constraints, content, typeSpecialProperty, 7, typeSpecialLabel);
|
||||
addInputRow(constraints, content, balance, 8, new JLabel("Balance", RIGHT));
|
||||
addInputRow(constraints, content, balance, 8, new JLabel(translate("Balance"), RIGHT));
|
||||
|
||||
var buttonPanel = Box.createHorizontalBox();
|
||||
buttonPanel.add(Box.createHorizontalStrut(4));
|
||||
|
@ -129,10 +130,10 @@ public class AccountView extends JPanel {
|
|||
|
||||
this.accountSelection = new JComboBox<>();
|
||||
|
||||
this.logout = new JButton("Logout");
|
||||
this.transfer = new JButton("Transfer");
|
||||
this.deposit = new JButton("Deposit");
|
||||
this.takeoff = new JButton("Takeoff");
|
||||
this.logout = new JButton(translate("Logout"));
|
||||
this.transfer = new JButton(translate("Transfer"));
|
||||
this.deposit = new JButton(translate("Deposit"));
|
||||
this.takeoff = new JButton(translate("Takeoff"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -8,6 +8,8 @@ import java.awt.*;
|
|||
import java.text.NumberFormat;
|
||||
import java.text.ParseException;
|
||||
|
||||
import static me.teridax.jcash.lang.Translator.translate;
|
||||
|
||||
public class DepositView {
|
||||
|
||||
private JDialog dialog;
|
||||
|
@ -22,7 +24,7 @@ public class DepositView {
|
|||
|
||||
public void showDialog() {
|
||||
dialog.setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
|
||||
dialog.setTitle("Deposit money");
|
||||
dialog.setTitle(translate("Deposit money"));
|
||||
dialog.pack();
|
||||
dialog.setResizable(false);
|
||||
dialog.setLocationRelativeTo(null);
|
||||
|
@ -43,7 +45,7 @@ public class DepositView {
|
|||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
c.anchor = GridBagConstraints.CENTER;
|
||||
c.insets = new Insets(4, 4, 4, 4);
|
||||
dialog.getContentPane().add(new JLabel("Deposit money"), c);
|
||||
dialog.getContentPane().add(new JLabel(translate("Deposit money")), c);
|
||||
|
||||
c.gridx = 0;
|
||||
c.gridy = 1;
|
||||
|
@ -51,7 +53,7 @@ public class DepositView {
|
|||
c.fill = GridBagConstraints.NONE;
|
||||
c.anchor = GridBagConstraints.LAST_LINE_END;
|
||||
c.weightx = 0;
|
||||
dialog.getContentPane().add(new JLabel("Value", SwingConstants.RIGHT), c);
|
||||
dialog.getContentPane().add(new JLabel(translate("Value"), SwingConstants.RIGHT), c);
|
||||
|
||||
c.gridx = 1;
|
||||
c.gridy = 1;
|
||||
|
@ -83,8 +85,8 @@ public class DepositView {
|
|||
private void createComponents() {
|
||||
this.dialog = new JDialog();
|
||||
|
||||
this.cancel = new JButton("Cancel");
|
||||
this.deposit = new JButton("Deposit");
|
||||
this.cancel = new JButton(translate("Cancel"));
|
||||
this.deposit = new JButton(translate("Deposit"));
|
||||
this.value = new JFormattedTextField(StringDecoder.LOCAL_NUMBER_FORMAT);
|
||||
|
||||
this.dialog.setContentPane(new JPanel(new GridBagLayout()));
|
||||
|
|
|
@ -8,6 +8,7 @@ import java.util.Optional;
|
|||
|
||||
import static javax.swing.JOptionPane.ERROR_MESSAGE;
|
||||
import static javax.swing.JOptionPane.showMessageDialog;
|
||||
import static me.teridax.jcash.lang.Translator.translate;
|
||||
|
||||
public class LoginController {
|
||||
|
||||
|
@ -52,14 +53,14 @@ public class LoginController {
|
|||
var iban = this.getIban();
|
||||
if (iban.isEmpty()) {
|
||||
Logging.LOGGER.severe("IBAN is invalid: " + iban);
|
||||
showMessageDialog(null, "invalid IBAN", "Faulty login attempt", ERROR_MESSAGE);
|
||||
showMessageDialog(null, translate("Invalid IBAN"), translate("Faulty login attempt"), ERROR_MESSAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
var pin = this.getPin();
|
||||
if (pin.isEmpty()) {
|
||||
Logging.LOGGER.severe("PIN is invalid: " + pin);
|
||||
showMessageDialog(null, "invalid pin", "Faulty login attempt", ERROR_MESSAGE);
|
||||
showMessageDialog(null, translate("Invalid pin"), translate("Faulty login attempt"), ERROR_MESSAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -68,7 +69,7 @@ public class LoginController {
|
|||
this.listener.onAccountSelected(account.get());
|
||||
} else {
|
||||
Logging.LOGGER.severe("invalid login credentials: " + iban + " / " + pin);
|
||||
showMessageDialog(null, "invalid login credentials", "Faulty login attempt", ERROR_MESSAGE);
|
||||
showMessageDialog(null, translate("Invalid login credentials"), translate("Faulty login attempt"), ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,8 @@ import javax.swing.text.NumberFormatter;
|
|||
import java.awt.*;
|
||||
import java.text.NumberFormat;
|
||||
|
||||
import static me.teridax.jcash.lang.Translator.translate;
|
||||
|
||||
public class LoginView extends JPanel {
|
||||
|
||||
private JFormattedTextField blz;
|
||||
|
@ -23,16 +25,16 @@ public class LoginView extends JPanel {
|
|||
this.setBorder(BorderFactory.createEmptyBorder(8,8,8,8));
|
||||
this.setLayout(new BorderLayout(16, 16));
|
||||
this.add(new JScrollPane(content), BorderLayout.CENTER);
|
||||
this.add(new JLabel("Bankautomat"), BorderLayout.NORTH);
|
||||
this.add(new JLabel(translate("Cashmachine")), BorderLayout.NORTH);
|
||||
|
||||
var constraints = new GridBagConstraints();
|
||||
|
||||
constraints.gridwidth = 4;
|
||||
constraints.insets = new Insets(12,12,12,12);
|
||||
|
||||
addInputRow(constraints, content, blz, 1, "BLZ");
|
||||
addInputRow(constraints, content, iban, 2, "IBAN");
|
||||
addInputRow(constraints, content, pin, 3, "PIN");
|
||||
addInputRow(constraints, content, blz, 1, translate("BLZ"));
|
||||
addInputRow(constraints, content, iban, 2, translate("IBAN"));
|
||||
addInputRow(constraints, content, pin, 3, translate("PIN"));
|
||||
|
||||
constraints.gridy = 4;
|
||||
constraints.anchor = GridBagConstraints.PAGE_END;
|
||||
|
@ -46,7 +48,7 @@ public class LoginView extends JPanel {
|
|||
this.blz = new JFormattedTextField();
|
||||
this.iban = new JFormattedTextField(getNumberFormat());
|
||||
this.pin = new JPasswordField();
|
||||
this.login = new JButton("Login");
|
||||
this.login = new JButton(translate("Login"));
|
||||
}
|
||||
|
||||
private NumberFormatter getNumberFormat() {
|
||||
|
|
|
@ -5,6 +5,7 @@ import me.teridax.jcash.banking.accounts.Account;
|
|||
|
||||
import static javax.swing.JOptionPane.ERROR_MESSAGE;
|
||||
import static javax.swing.JOptionPane.showMessageDialog;
|
||||
import static me.teridax.jcash.lang.Translator.translate;
|
||||
|
||||
public class TakeoffDialog {
|
||||
|
||||
|
@ -30,7 +31,7 @@ public class TakeoffDialog {
|
|||
view.dispose();
|
||||
} catch (IllegalArgumentException ex) {
|
||||
Logging.LOGGER.severe("Could not take off money: " + ex.getMessage());
|
||||
showMessageDialog(null, "Reason: " + ex.getMessage(), "Could not take off money", ERROR_MESSAGE);
|
||||
showMessageDialog(null, "Reason: " + ex.getMessage(), translate("Could not take off money"), ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import java.text.ParseException;
|
|||
|
||||
import static javax.swing.JOptionPane.ERROR_MESSAGE;
|
||||
import static javax.swing.JOptionPane.showMessageDialog;
|
||||
import static me.teridax.jcash.lang.Translator.translate;
|
||||
|
||||
public class TakeoffView {
|
||||
|
||||
|
@ -24,7 +25,7 @@ public class TakeoffView {
|
|||
|
||||
public void showDialog() {
|
||||
dialog.setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
|
||||
dialog.setTitle("Takeoff money");
|
||||
dialog.setTitle(translate("Takeoff money"));
|
||||
dialog.pack();
|
||||
dialog.setResizable(false);
|
||||
dialog.setLocationRelativeTo(null);
|
||||
|
@ -43,7 +44,7 @@ public class TakeoffView {
|
|||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
c.anchor = GridBagConstraints.CENTER;
|
||||
c.insets = new Insets(4, 4, 4, 4);
|
||||
dialog.getContentPane().add(new JLabel("Takeoff money"), c);
|
||||
dialog.getContentPane().add(new JLabel(translate("Takeoff money")), c);
|
||||
|
||||
c.gridx = 0;
|
||||
c.gridy = 1;
|
||||
|
@ -51,7 +52,7 @@ public class TakeoffView {
|
|||
c.fill = GridBagConstraints.NONE;
|
||||
c.anchor = GridBagConstraints.LAST_LINE_END;
|
||||
c.weightx = 0;
|
||||
dialog.getContentPane().add(new JLabel("Value", SwingConstants.RIGHT), c);
|
||||
dialog.getContentPane().add(new JLabel(translate("Value"), SwingConstants.RIGHT), c);
|
||||
|
||||
c.gridx = 1;
|
||||
c.gridy = 1;
|
||||
|
@ -83,8 +84,8 @@ public class TakeoffView {
|
|||
private void createComponents() {
|
||||
this.dialog = new JDialog();
|
||||
|
||||
this.cancel = new JButton("Cancel");
|
||||
this.takeoff = new JButton("Takeoff");
|
||||
this.cancel = new JButton(translate("Cancel"));
|
||||
this.takeoff = new JButton(translate("Takeoff"));
|
||||
this.value = new JFormattedTextField(StringDecoder.LOCAL_NUMBER_FORMAT);
|
||||
|
||||
this.dialog.setContentPane(new JPanel(new GridBagLayout()));
|
||||
|
@ -92,7 +93,7 @@ public class TakeoffView {
|
|||
|
||||
public double getAmount() {
|
||||
if (value.getText().isBlank()) {
|
||||
showMessageDialog(null, "invalid amount", "currency must not be blank", ERROR_MESSAGE);
|
||||
showMessageDialog(null, translate("Invalid amount"), translate("Currency must not be blank"), ERROR_MESSAGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,9 +3,11 @@ package me.teridax.jcash.gui.transfer;
|
|||
import me.teridax.jcash.Logging;
|
||||
import me.teridax.jcash.banking.accounts.Account;
|
||||
import me.teridax.jcash.banking.management.BankingManagementSystem;
|
||||
import me.teridax.jcash.lang.Translator;
|
||||
|
||||
import static javax.swing.JOptionPane.ERROR_MESSAGE;
|
||||
import static javax.swing.JOptionPane.showMessageDialog;
|
||||
import static me.teridax.jcash.lang.Translator.translate;
|
||||
|
||||
public class TransferDialog {
|
||||
|
||||
|
@ -35,7 +37,7 @@ public class TransferDialog {
|
|||
transferView.dispose();
|
||||
} catch (IllegalArgumentException ex) {
|
||||
Logging.LOGGER.severe("Could not transfer: " + ex.getMessage());
|
||||
showMessageDialog(null, "invalid account", "Could not transfer", ERROR_MESSAGE);
|
||||
showMessageDialog(null, translate("Invalid account"), translate("Could not transfer"), ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import java.awt.*;
|
|||
|
||||
import static javax.swing.JOptionPane.ERROR_MESSAGE;
|
||||
import static javax.swing.JOptionPane.showMessageDialog;
|
||||
import static me.teridax.jcash.lang.Translator.translate;
|
||||
|
||||
public class TransferView {
|
||||
|
||||
|
@ -25,7 +26,7 @@ public class TransferView {
|
|||
|
||||
public void showDialog() {
|
||||
dialog.setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
|
||||
dialog.setTitle("Transfer money");
|
||||
dialog.setTitle(translate("Transfer money"));
|
||||
dialog.pack();
|
||||
dialog.setSize(dialog.getWidth() * 2, dialog.getHeight());
|
||||
dialog.setResizable(false);
|
||||
|
@ -45,7 +46,7 @@ public class TransferView {
|
|||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
c.anchor = GridBagConstraints.CENTER;
|
||||
c.insets = new Insets(4, 4, 4, 4);
|
||||
dialog.getContentPane().add(new JLabel("Transfer money"), c);
|
||||
dialog.getContentPane().add(new JLabel(translate("Transfer money")), c);
|
||||
|
||||
c.gridx = 0;
|
||||
c.gridy = 1;
|
||||
|
@ -53,7 +54,7 @@ public class TransferView {
|
|||
c.fill = GridBagConstraints.NONE;
|
||||
c.anchor = GridBagConstraints.LAST_LINE_END;
|
||||
c.weightx = 0;
|
||||
dialog.getContentPane().add(new JLabel("BLZ", SwingConstants.RIGHT), c);
|
||||
dialog.getContentPane().add(new JLabel(translate("BLZ"), SwingConstants.RIGHT), c);
|
||||
|
||||
c.gridx = 1;
|
||||
c.gridy = 1;
|
||||
|
@ -67,7 +68,7 @@ public class TransferView {
|
|||
c.fill = GridBagConstraints.NONE;
|
||||
c.anchor = GridBagConstraints.LAST_LINE_END;
|
||||
c.weightx = 0;
|
||||
dialog.getContentPane().add(new JLabel("IBAN", SwingConstants.RIGHT), c);
|
||||
dialog.getContentPane().add(new JLabel(translate("IBAN"), SwingConstants.RIGHT), c);
|
||||
|
||||
c.gridx = 3;
|
||||
c.gridy = 1;
|
||||
|
@ -81,7 +82,7 @@ public class TransferView {
|
|||
c.fill = GridBagConstraints.NONE;
|
||||
c.anchor = GridBagConstraints.LAST_LINE_END;
|
||||
c.weightx = 0;
|
||||
dialog.getContentPane().add(new JLabel("Betrag", SwingConstants.RIGHT), c);
|
||||
dialog.getContentPane().add(new JLabel(translate("Betrag"), SwingConstants.RIGHT), c);
|
||||
|
||||
c.gridx = 1;
|
||||
c.gridy = 2;
|
||||
|
@ -106,8 +107,8 @@ public class TransferView {
|
|||
private void createComponents() {
|
||||
this.dialog = new JDialog();
|
||||
|
||||
this.cancel = new JButton("Cancel");
|
||||
this.transfer = new JButton("Transfer");
|
||||
this.cancel = new JButton(translate("Cancel"));
|
||||
this.transfer = new JButton(translate("Transfer"));
|
||||
this.value = new JFormattedTextField(StringDecoder.LOCAL_NUMBER_FORMAT);
|
||||
this.iban = new JFormattedTextField();
|
||||
this.blz = new JFormattedTextField();
|
||||
|
@ -118,7 +119,7 @@ public class TransferView {
|
|||
public double getAmount() {
|
||||
if (value.getText().isBlank()) {
|
||||
Logging.LOGGER.severe("Amount is empty");
|
||||
showMessageDialog(null, "invalid amount", "currency must not be blank", ERROR_MESSAGE);
|
||||
showMessageDialog(null, translate("invalid amount"), translate("currency must not be blank"), ERROR_MESSAGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
package me.teridax.jcash.lang;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Class for storing static information about the locale used by the application instance at runtime.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class Locales {
|
||||
|
||||
/**
|
||||
* Locale string used to identify a certain locale
|
||||
*/
|
||||
private static String defaultLocale = "en_EN";
|
||||
|
||||
/**
|
||||
* Sets the default locale to use for the application instance.
|
||||
* This will instruct the translator to use the default locale as well as
|
||||
* Java swing components.
|
||||
* @param language the locale to use for language
|
||||
* @param country the locale to use for country
|
||||
*/
|
||||
public static void setDefaultLocale(String language, String country) {
|
||||
var locale = language + "_" + country;
|
||||
|
||||
if (Translator.setTranslationLocale(locale)) {
|
||||
// apply locale to JVM
|
||||
Locale.setDefault(new Locale(language, country));
|
||||
defaultLocale = locale;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getDefaultLocale() {
|
||||
return defaultLocale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to automatically detect the default locale.
|
||||
* This will prefer the users locale over the systems locale.
|
||||
* If both fail, the JVMs default locale will be used.
|
||||
*/
|
||||
public static void autodetectDefaultLocale() {
|
||||
var country = System.getProperty("user.country");
|
||||
var language = System.getProperty("user.language");
|
||||
|
||||
var jvmLocale = Locale.getDefault();
|
||||
|
||||
if (null == country)
|
||||
country = jvmLocale.getCountry();
|
||||
|
||||
if (null == language)
|
||||
language = jvmLocale.getLanguage();
|
||||
|
||||
setDefaultLocale(language, country);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
package me.teridax.jcash.lang;
|
||||
|
||||
import me.teridax.jcash.Logging;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public final class Translator {
|
||||
|
||||
/**
|
||||
* Precomputed index of the locale used to statically translate a phrase
|
||||
*/
|
||||
private static int localeTranslationIndex = 0;
|
||||
|
||||
/**
|
||||
* List of all supported locales in the format: language_country. Examples: en_EN, fr_FR
|
||||
* The index inside the list is directly related to the index of the translation array inside the list translations.
|
||||
*/
|
||||
private static final List<String> languages = new ArrayList<>();
|
||||
/**
|
||||
* Mapping of a default english phrase of the code en_EN which is associated with a list of possible translations.
|
||||
* Index 0 of the translation is equivalent to the key itself since locale 0 is always en_EN.
|
||||
*/
|
||||
private static final Map<String, String[]> translations = new HashMap<>();
|
||||
|
||||
static {
|
||||
// read language file and parse
|
||||
try (var stream = Objects.requireNonNull(Translator.class.getResourceAsStream("languages.csv"))) {
|
||||
var text = new String(stream.readAllBytes(), StandardCharsets.UTF_8);
|
||||
|
||||
// parse each line
|
||||
text.lines().forEach(line -> {
|
||||
// read header i.e. the locales identifier
|
||||
if (languages.isEmpty()) {
|
||||
// split string into columns by comma and trim each column
|
||||
languages.addAll(Arrays.stream(line.split(",")).map(String::trim).collect(Collectors.toList()));
|
||||
|
||||
// check if default locale is present
|
||||
if (!languages.contains("en_EN")) {
|
||||
Logging.LOGGER.severe("Missing default en_EN locale");
|
||||
throw new IllegalArgumentException("Missing en_EN locale");
|
||||
}
|
||||
|
||||
Logging.LOGGER.info("Read locales: " + Arrays.deepToString(languages.toArray()));
|
||||
return;
|
||||
}
|
||||
|
||||
var translation = Arrays.stream(line.split(",")).map(String::trim).toArray(String[]::new);
|
||||
|
||||
// check if all translations are present
|
||||
// it may happen at a locale does not provide a translation
|
||||
if (translation.length != languages.size())
|
||||
Logging.LOGGER.warning("invalid translations: " + translation.length + " " + languages.size());
|
||||
|
||||
translations.put(translation[0], translation);
|
||||
});
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates the given phrase into the corresponding phrase of the selected locale of the translator.
|
||||
* If no translation is found or no locale is defined for the translator this function will return the given phrase.
|
||||
* @param phrase the text to translate
|
||||
* @return the translated phrase, or the phrase itself in case no translation can be found
|
||||
*/
|
||||
public static String translate(String phrase) {
|
||||
try {
|
||||
return translations.get(phrase)[localeTranslationIndex];
|
||||
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
Logging.LOGGER.severe("Locale does not exist with index: " + localeTranslationIndex);
|
||||
} catch (NullPointerException e) {
|
||||
Logging.LOGGER.severe("No translation found for phrase: " + phrase);
|
||||
}
|
||||
return phrase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all available locales for this translator
|
||||
* @return an array of all available locales for this translator
|
||||
*/
|
||||
public static String[] availableLocales() {
|
||||
return languages.toArray(String[]::new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Map the given locale string to an index indicating which array location to choose when fetching a result from
|
||||
* the translation map.
|
||||
* @param locale the locale string
|
||||
* @return a matching index of the locale
|
||||
* @throws IllegalArgumentException if the given locale is not part of the available locales
|
||||
*/
|
||||
private static int mapLocaleToIndex(String locale) throws IllegalArgumentException {
|
||||
for (int i = 0; i < languages.size(); i++) {
|
||||
if (languages.get(i).equals(locale)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Locale does not exist: " + locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default locale to use when translating.
|
||||
* The locale must have the format language_COUNTRY like en_EN
|
||||
* @param locale the locale to use when translating
|
||||
* @return if the specified locale can be used by the translator
|
||||
*/
|
||||
public static boolean setTranslationLocale(String locale) {
|
||||
try {
|
||||
localeTranslationIndex = Translator.mapLocaleToIndex(locale);
|
||||
return true;
|
||||
} catch (IllegalArgumentException ex) {
|
||||
Logging.LOGGER.severe("unable to set locale for translation: " + locale + " because: " + ex.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
en_EN,de_DE,es_ES,fr_FR,zh_Hans
|
||||
Bank,Bank,Banco,Banque,银行
|
||||
BLZ,BLZ,BLZ,CODE BANCAIRE,分类代码
|
||||
PIN,PIN,PIN,CODE PIN,密码
|
||||
Balance,Kontostand,Saldo,Solde du compte,账户余额
|
||||
Account type,Kontoart,Tipo de cuenta,Type de compte,账户类型
|
||||
Interest,Zins,Interés,Intérêt,利息
|
||||
Overdraft,Überziehungsbetrag,Importe del descubierto,Montant du découvert,透支金额
|
||||
Customer number,Kundennummer,Número de cliente,Numéro de client,客户编号
|
||||
Name,Name,Nombre,Nom,客户姓名
|
||||
Name,Vorname,Nombre,Prénom,姓名
|
||||
Street,Straße,Calle,Rue,街道
|
||||
PLZ,PLZ,PLZ,NPA,邮政编码
|
||||
City,Ort,Ubicación,Ville,城市
|
||||
Password,Passwort,contraseña,Mot de passe,密码
|
||||
Login,Anmelden,Inicio de sesión,S'inscrire,登录
|
||||
Current account,Girokonto,Cuenta corriente,Compte courant,活期账户
|
||||
Savings account,Sparkonto,Cuenta de ahorro,Compte d'épargne,储蓄账户
|
||||
Address,Adresse,Dirección,Adresse,地址
|
||||
Logout,Abmelden,desconectarse,Se désinscrire,退出登录
|
||||
Transfer,Überweisen,transferencia,Virement bancaire,转账
|
||||
Deposit,Einzahlen,depósito,Dépôt,存款
|
||||
Take off,Abheben,despegar,Retrait,取款
|
||||
Value,Betrag,Importe,Montant,金额
|
||||
Cancel,Abbrechen,Cancelar,Annuler,取消
|
||||
Load database,Datenbank auswählen,Seleccionar base de datos,Sélectionner la base de données,选择数据库
|
||||
Invalid account,Ungültiges Benutzerkonto,Cuenta de usuario no válida,Compte utilisateur non valide,用户账户无效
|
||||
Could not transfer,Überweiung fehlgeschlagen,Transferencia fallida,Échec du transfert,转账失败
|
||||
Transfer,Überweisen,Transferencia,Transfert,转帐
|
||||
invalid amount,Ungültiger Betrag,Importe no válido,Montant non valide,金额无效
|
||||
currency must not be blank,Betrag darf nicht leer sein,El importe no debe estar vacío,Le montant ne doit pas être vide,金额不能为空
|
||||
Transfer money,Geld überweisen,Transferencia de dinero,Transférer de l'argent,汇款
|
||||
Could not take off money,Geld konnte nicht abgehoben werden,No se ha podido retirar dinero,L'argent n'a pas pu être retiré,无法取款
|
||||
Takeoff money,Geld abheben,Retirar dinero,Retirer de l'argent,取款
|
||||
Takeoff,Abheben,Retirar,Retrait,取款
|
||||
Currency must not be blank,Betrag darf nicht leer sein,El importe no debe estar vacío,Le montant ne doit pas être vide,金额不能为空
|
||||
Cashmachine,Bankautomat,CAJERO,Distributeur automatique de billets,ATM
|
||||
Invalid IBAN,Ungültige IBAN,IBAN no válido,IBAN non valide,无效的IBAN
|
||||
Faulty login attempt,Ungültiger Authentifizierungsverzuch,Solicitud de autenticación no válida,Demande d'authentification non valide,验证请求无效
|
||||
Invalid PIN,Ungültiger PIN,PIN no válido,Code PIN non valide,密码无效
|
||||
Invalid login credentials,Ungültiges Passwort oder Nutzername,Contraseña o nombre de usuario no válidos,Mot de passe ou nom d'utilisateur non valide,密码或用户名无效
|
||||
Deposit money,Geld einzahlen,Depositar dinero,Dépôt d'argent,存款金额
|
||||
Interest rate,Zinsbetrag,Importe de los intereses,Montant des intérêts,利息金额
|
||||
Name/Family-name,Vorname/Name,Nombre y apellidos,Prénom/nom,名/姓
|
||||
Address,Adresse,Dirección,Adresse,地址
|
||||
Account,Konto,Cuenta,Compte,账户
|
||||
Closing JCash,JCash wird geschlossen,JCash está cerrado,JCash est fermé,JCash 已关闭
|
||||
you're logged out,Du bist abgemeldet,Ha cerrado la sesión,Tu es déconnecté,您已注销
|
|
Loading…
Reference in New Issue