mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-12-27 05:56:45 +00:00
Translation implementation and translations for WelcomeDialog and Transactions Tab
This commit is contained in:
parent
31f287125f
commit
f5c79e33cd
21 changed files with 413 additions and 78 deletions
|
@ -18,6 +18,8 @@ import com.sparrowwallet.hummingbird.registry.CryptoPSBT;
|
||||||
import com.sparrowwallet.sparrow.control.*;
|
import com.sparrowwallet.sparrow.control.*;
|
||||||
import com.sparrowwallet.sparrow.event.*;
|
import com.sparrowwallet.sparrow.event.*;
|
||||||
import com.sparrowwallet.sparrow.glyphfont.FontAwesome5;
|
import com.sparrowwallet.sparrow.glyphfont.FontAwesome5;
|
||||||
|
import com.sparrowwallet.sparrow.i18n.Language;
|
||||||
|
import com.sparrowwallet.sparrow.i18n.LanguagesManager;
|
||||||
import com.sparrowwallet.sparrow.io.*;
|
import com.sparrowwallet.sparrow.io.*;
|
||||||
import com.sparrowwallet.sparrow.io.bbqr.BBQR;
|
import com.sparrowwallet.sparrow.io.bbqr.BBQR;
|
||||||
import com.sparrowwallet.sparrow.io.bbqr.BBQRType;
|
import com.sparrowwallet.sparrow.io.bbqr.BBQRType;
|
||||||
|
@ -138,6 +140,9 @@ public class AppController implements Initializable {
|
||||||
@FXML
|
@FXML
|
||||||
private ToggleGroup theme;
|
private ToggleGroup theme;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private ToggleGroup language;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private CheckMenuItem openWalletsInNewWindows;
|
private CheckMenuItem openWalletsInNewWindows;
|
||||||
private static final BooleanProperty openWalletsInNewWindowsProperty = new SimpleBooleanProperty();
|
private static final BooleanProperty openWalletsInNewWindowsProperty = new SimpleBooleanProperty();
|
||||||
|
@ -373,6 +378,15 @@ public class AppController implements Initializable {
|
||||||
selectedThemeToggle.ifPresent(toggle -> theme.selectToggle(toggle));
|
selectedThemeToggle.ifPresent(toggle -> theme.selectToggle(toggle));
|
||||||
setTheme(null);
|
setTheme(null);
|
||||||
|
|
||||||
|
Language configLanguage = Config.get().getLanguage();
|
||||||
|
if(configLanguage == null) {
|
||||||
|
configLanguage = LanguagesManager.DEFAULT_LANGUAGE;
|
||||||
|
Config.get().setLanguage(configLanguage);
|
||||||
|
}
|
||||||
|
final Language selectedLanguage = configLanguage;
|
||||||
|
Optional<Toggle> selectedLanguageToggle = language.getToggles().stream().filter(toggle -> selectedLanguage.equals(toggle.getUserData())).findFirst();
|
||||||
|
selectedLanguageToggle.ifPresent(toggle -> language.selectToggle(toggle));
|
||||||
|
|
||||||
openWalletsInNewWindowsProperty.set(Config.get().isOpenWalletsInNewWindows());
|
openWalletsInNewWindowsProperty.set(Config.get().isOpenWalletsInNewWindows());
|
||||||
openWalletsInNewWindows.selectedProperty().bindBidirectional(openWalletsInNewWindowsProperty);
|
openWalletsInNewWindows.selectedProperty().bindBidirectional(openWalletsInNewWindowsProperty);
|
||||||
hideEmptyUsedAddressesProperty.set(Config.get().isHideEmptyUsedAddresses());
|
hideEmptyUsedAddressesProperty.set(Config.get().isHideEmptyUsedAddresses());
|
||||||
|
@ -488,7 +502,7 @@ public class AppController implements Initializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showIntroduction(ActionEvent event) {
|
public void showIntroduction(ActionEvent event) {
|
||||||
WelcomeDialog welcomeDialog = new WelcomeDialog();
|
WelcomeDialog welcomeDialog = new WelcomeDialog(false);
|
||||||
welcomeDialog.initOwner(rootStack.getScene().getWindow());
|
welcomeDialog.initOwner(rootStack.getScene().getWindow());
|
||||||
Optional<Mode> optionalMode = welcomeDialog.showAndWait();
|
Optional<Mode> optionalMode = welcomeDialog.showAndWait();
|
||||||
if(optionalMode.isPresent() && optionalMode.get().equals(Mode.ONLINE)) {
|
if(optionalMode.isPresent() && optionalMode.get().equals(Mode.ONLINE)) {
|
||||||
|
@ -996,13 +1010,19 @@ public class AppController implements Initializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void restart(ActionEvent event) {
|
||||||
|
restart(event, (Network) null);
|
||||||
|
}
|
||||||
|
|
||||||
public void restart(ActionEvent event, Network network) {
|
public void restart(ActionEvent event, Network network) {
|
||||||
if(System.getProperty(JPACKAGE_APP_PATH) == null) {
|
if(System.getProperty(JPACKAGE_APP_PATH) == null) {
|
||||||
throw new IllegalStateException("Property " + JPACKAGE_APP_PATH + " is not present");
|
throw new IllegalStateException("Property " + JPACKAGE_APP_PATH + " is not present");
|
||||||
}
|
}
|
||||||
|
|
||||||
Args args = getRestartArgs();
|
Args args = getRestartArgs();
|
||||||
args.network = network;
|
if(network != null) {
|
||||||
|
args.network = network;
|
||||||
|
}
|
||||||
restart(event, args);
|
restart(event, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1760,7 +1780,7 @@ public class AppController implements Initializable {
|
||||||
subTabLabel.setTooltip(new Tooltip(label));
|
subTabLabel.setTooltip(new Tooltip(label));
|
||||||
}
|
}
|
||||||
subTab.setGraphic(subTabLabel);
|
subTab.setGraphic(subTabLabel);
|
||||||
FXMLLoader walletLoader = new FXMLLoader(getClass().getResource("wallet/wallet.fxml"));
|
FXMLLoader walletLoader = new FXMLLoader(getClass().getResource("wallet/wallet.fxml"), LanguagesManager.getResourceBundle());
|
||||||
subTab.setContent(walletLoader.load());
|
subTab.setContent(walletLoader.load());
|
||||||
WalletController controller = walletLoader.getController();
|
WalletController controller = walletLoader.getController();
|
||||||
|
|
||||||
|
@ -2337,6 +2357,15 @@ public class AppController implements Initializable {
|
||||||
EventManager.get().post(new ThemeChangedEvent(selectedTheme));
|
EventManager.get().post(new ThemeChangedEvent(selectedTheme));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setLanguage(ActionEvent event) {
|
||||||
|
Language selectedLanguage = (Language)language.getSelectedToggle().getUserData();
|
||||||
|
if(Config.get().getLanguage() != selectedLanguage) {
|
||||||
|
Config.get().setLanguage(selectedLanguage);
|
||||||
|
}
|
||||||
|
|
||||||
|
restart(event);
|
||||||
|
}
|
||||||
|
|
||||||
private void serverToggleStartAnimation() {
|
private void serverToggleStartAnimation() {
|
||||||
Node thumbArea = serverToggle.lookup(".thumb-area");
|
Node thumbArea = serverToggle.lookup(".thumb-area");
|
||||||
if(thumbArea != null) {
|
if(thumbArea != null) {
|
||||||
|
|
|
@ -14,6 +14,7 @@ import com.sparrowwallet.drongo.policy.PolicyType;
|
||||||
import com.sparrowwallet.drongo.wallet.*;
|
import com.sparrowwallet.drongo.wallet.*;
|
||||||
import com.sparrowwallet.sparrow.control.WalletPasswordDialog;
|
import com.sparrowwallet.sparrow.control.WalletPasswordDialog;
|
||||||
import com.sparrowwallet.sparrow.glyphfont.FontAwesome5;
|
import com.sparrowwallet.sparrow.glyphfont.FontAwesome5;
|
||||||
|
import com.sparrowwallet.sparrow.i18n.LanguagesManager;
|
||||||
import com.sparrowwallet.sparrow.net.Auth47;
|
import com.sparrowwallet.sparrow.net.Auth47;
|
||||||
import com.sparrowwallet.drongo.protocol.BlockHeader;
|
import com.sparrowwallet.drongo.protocol.BlockHeader;
|
||||||
import com.sparrowwallet.drongo.protocol.ScriptType;
|
import com.sparrowwallet.drongo.protocol.ScriptType;
|
||||||
|
@ -551,7 +552,7 @@ public class AppServices {
|
||||||
|
|
||||||
public static AppController newAppWindow(Stage stage) {
|
public static AppController newAppWindow(Stage stage) {
|
||||||
try {
|
try {
|
||||||
FXMLLoader appLoader = new FXMLLoader(AppServices.class.getResource("app.fxml"));
|
FXMLLoader appLoader = new FXMLLoader(AppServices.class.getResource("app.fxml"), LanguagesManager.getResourceBundle());
|
||||||
Parent root = appLoader.load();
|
Parent root = appLoader.load();
|
||||||
AppController appController = appLoader.getController();
|
AppController appController = appLoader.getController();
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,8 @@ import com.sparrowwallet.drongo.wallet.Wallet;
|
||||||
import com.sparrowwallet.sparrow.control.WalletIcon;
|
import com.sparrowwallet.sparrow.control.WalletIcon;
|
||||||
import com.sparrowwallet.sparrow.glyphfont.FontAwesome5;
|
import com.sparrowwallet.sparrow.glyphfont.FontAwesome5;
|
||||||
import com.sparrowwallet.sparrow.glyphfont.FontAwesome5Brands;
|
import com.sparrowwallet.sparrow.glyphfont.FontAwesome5Brands;
|
||||||
|
import com.sparrowwallet.sparrow.i18n.Language;
|
||||||
|
import com.sparrowwallet.sparrow.i18n.LanguagesManager;
|
||||||
import com.sparrowwallet.sparrow.io.Config;
|
import com.sparrowwallet.sparrow.io.Config;
|
||||||
import com.sparrowwallet.sparrow.io.Storage;
|
import com.sparrowwallet.sparrow.io.Storage;
|
||||||
import com.sparrowwallet.sparrow.net.PublicElectrumServer;
|
import com.sparrowwallet.sparrow.net.PublicElectrumServer;
|
||||||
|
@ -53,7 +55,7 @@ public class SparrowDesktop extends Application {
|
||||||
boolean createNewWallet = false;
|
boolean createNewWallet = false;
|
||||||
Mode mode = Config.get().getMode();
|
Mode mode = Config.get().getMode();
|
||||||
if(mode == null) {
|
if(mode == null) {
|
||||||
WelcomeDialog welcomeDialog = new WelcomeDialog();
|
WelcomeDialog welcomeDialog = new WelcomeDialog(true);
|
||||||
Optional<Mode> optionalMode = welcomeDialog.showAndWait();
|
Optional<Mode> optionalMode = welcomeDialog.showAndWait();
|
||||||
if(optionalMode.isPresent()) {
|
if(optionalMode.isPresent()) {
|
||||||
mode = optionalMode.get();
|
mode = optionalMode.get();
|
||||||
|
@ -87,6 +89,13 @@ public class SparrowDesktop extends Application {
|
||||||
mainStage.setHeight(Config.get().getAppHeight());
|
mainStage.setHeight(Config.get().getAppHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Language configLanguage = Config.get().getLanguage();
|
||||||
|
if(configLanguage == null) {
|
||||||
|
configLanguage = LanguagesManager.DEFAULT_LANGUAGE;
|
||||||
|
Config.get().setLanguage(configLanguage);
|
||||||
|
}
|
||||||
|
LanguagesManager.loadLanguage(configLanguage.getCode());
|
||||||
|
|
||||||
AppController appController = AppServices.newAppWindow(stage);
|
AppController appController = AppServices.newAppWindow(stage);
|
||||||
|
|
||||||
final boolean showNewWallet = createNewWallet;
|
final boolean showNewWallet = createNewWallet;
|
||||||
|
|
|
@ -1,22 +1,30 @@
|
||||||
package com.sparrowwallet.sparrow;
|
package com.sparrowwallet.sparrow;
|
||||||
|
|
||||||
|
import com.google.common.eventbus.Subscribe;
|
||||||
import com.sparrowwallet.sparrow.control.UnlabeledToggleSwitch;
|
import com.sparrowwallet.sparrow.control.UnlabeledToggleSwitch;
|
||||||
|
import com.sparrowwallet.sparrow.event.LanguageChangedInWelcomeEvent;
|
||||||
|
import com.sparrowwallet.sparrow.i18n.Language;
|
||||||
|
import com.sparrowwallet.sparrow.i18n.LanguagesManager;
|
||||||
|
import com.sparrowwallet.sparrow.io.Config;
|
||||||
import javafx.animation.PauseTransition;
|
import javafx.animation.PauseTransition;
|
||||||
import javafx.application.Platform;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.beans.value.ChangeListener;
|
import javafx.collections.ObservableList;
|
||||||
import javafx.beans.value.ObservableValue;
|
|
||||||
import javafx.event.ActionEvent;
|
|
||||||
import javafx.event.Event;
|
import javafx.event.Event;
|
||||||
import javafx.event.EventHandler;
|
|
||||||
import javafx.event.EventType;
|
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
|
import javafx.fxml.FXMLLoader;
|
||||||
|
import javafx.scene.control.ComboBox;
|
||||||
|
import javafx.scene.control.DialogPane;
|
||||||
import javafx.scene.control.Tooltip;
|
import javafx.scene.control.Tooltip;
|
||||||
import javafx.scene.input.MouseButton;
|
|
||||||
import javafx.scene.input.MouseEvent;
|
import javafx.scene.input.MouseEvent;
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
import javafx.util.Duration;
|
import javafx.util.Duration;
|
||||||
|
import javafx.util.StringConverter;
|
||||||
import org.controlsfx.control.StatusBar;
|
import org.controlsfx.control.StatusBar;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class WelcomeController {
|
public class WelcomeController {
|
||||||
@FXML
|
@FXML
|
||||||
private VBox welcomeBox;
|
private VBox welcomeBox;
|
||||||
|
@ -36,10 +44,13 @@ public class WelcomeController {
|
||||||
@FXML
|
@FXML
|
||||||
private StatusBar serverStatus;
|
private StatusBar serverStatus;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private ComboBox<Language> languages;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private UnlabeledToggleSwitch serverToggle;
|
private UnlabeledToggleSwitch serverToggle;
|
||||||
|
|
||||||
public void initializeView() {
|
public void initializeView(boolean isFirstExecution) {
|
||||||
step1.managedProperty().bind(step1.visibleProperty());
|
step1.managedProperty().bind(step1.visibleProperty());
|
||||||
step2.managedProperty().bind(step2.visibleProperty());
|
step2.managedProperty().bind(step2.visibleProperty());
|
||||||
step3.managedProperty().bind(step3.visibleProperty());
|
step3.managedProperty().bind(step3.visibleProperty());
|
||||||
|
@ -50,14 +61,51 @@ public class WelcomeController {
|
||||||
step4.setVisible(false);
|
step4.setVisible(false);
|
||||||
|
|
||||||
welcomeBox.getStyleClass().add("offline");
|
welcomeBox.getStyleClass().add("offline");
|
||||||
serverStatus.setText("Offline");
|
serverStatus.setText(LanguagesManager.getMessage("welcome.offline"));
|
||||||
serverToggle.addEventFilter(MouseEvent.MOUSE_RELEASED, Event::consume);
|
serverToggle.addEventFilter(MouseEvent.MOUSE_RELEASED, Event::consume);
|
||||||
Tooltip tooltip = new Tooltip("Demonstration only - you are not connected!");
|
Tooltip tooltip = new Tooltip(LanguagesManager.getMessage("welcome.offline.tooltip"));
|
||||||
tooltip.setShowDelay(Duration.ZERO);
|
tooltip.setShowDelay(Duration.ZERO);
|
||||||
serverToggle.setTooltip(tooltip);
|
serverToggle.setTooltip(tooltip);
|
||||||
serverToggle.selectedProperty().addListener((observable, oldValue, newValue) -> {
|
serverToggle.selectedProperty().addListener((observable, oldValue, newValue) -> {
|
||||||
serverStatus.setText(newValue ? "Connected (demonstration only)" : "Offline");
|
serverStatus.setText(newValue ? LanguagesManager.getMessage("welcome.server-status.online") : LanguagesManager.getMessage("welcome.offline"));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if(isFirstExecution) {
|
||||||
|
languages.setItems(getLanguagesList());
|
||||||
|
languages.setConverter(new StringConverter<>() {
|
||||||
|
@Override
|
||||||
|
public String toString(Language language) {
|
||||||
|
if(language != null) {
|
||||||
|
return LanguagesManager.getMessage("language." + language.getCode());
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Language fromString(String code) {
|
||||||
|
return Language.getFromCode(code);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Language configuredLanguage = Config.get().getLanguage();
|
||||||
|
if(configuredLanguage != null) {
|
||||||
|
languages.setValue(configuredLanguage);
|
||||||
|
} else {
|
||||||
|
languages.setValue(LanguagesManager.DEFAULT_LANGUAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
languages.valueProperty().addListener((observable, oldValue, newValue) -> {
|
||||||
|
if(Config.get().getLanguage() != newValue) {
|
||||||
|
Config.get().setLanguage(newValue);
|
||||||
|
LanguagesManager.loadLanguage(newValue.getCode());
|
||||||
|
|
||||||
|
EventManager.get().post(new LanguageChangedInWelcomeEvent(newValue));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
languages.setVisible(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean next() {
|
public boolean next() {
|
||||||
|
@ -69,7 +117,7 @@ public class WelcomeController {
|
||||||
PauseTransition wait = new PauseTransition(Duration.millis(200));
|
PauseTransition wait = new PauseTransition(Duration.millis(200));
|
||||||
wait.setOnFinished((e) -> {
|
wait.setOnFinished((e) -> {
|
||||||
serverToggle.setSelected(true);
|
serverToggle.setSelected(true);
|
||||||
serverStatus.setText("Connected to a Public Server (demonstration only)");
|
serverStatus.setText(LanguagesManager.getMessage("welcome.server-status.online.public-server"));
|
||||||
});
|
});
|
||||||
wait.play();
|
wait.play();
|
||||||
return true;
|
return true;
|
||||||
|
@ -81,7 +129,7 @@ public class WelcomeController {
|
||||||
welcomeBox.getStyleClass().clear();
|
welcomeBox.getStyleClass().clear();
|
||||||
welcomeBox.getStyleClass().add("bitcoin-core");
|
welcomeBox.getStyleClass().add("bitcoin-core");
|
||||||
serverToggle.setSelected(true);
|
serverToggle.setSelected(true);
|
||||||
serverStatus.setText("Connected to Bitcoin Core (demonstration only)");
|
serverStatus.setText(LanguagesManager.getMessage("welcome.server-status.online.bitcoin-core"));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +139,7 @@ public class WelcomeController {
|
||||||
welcomeBox.getStyleClass().clear();
|
welcomeBox.getStyleClass().clear();
|
||||||
welcomeBox.getStyleClass().add("private-electrum");
|
welcomeBox.getStyleClass().add("private-electrum");
|
||||||
serverToggle.setSelected(true);
|
serverToggle.setSelected(true);
|
||||||
serverStatus.setText("Connected to a Private Electrum Server (demonstration only)");
|
serverStatus.setText(LanguagesManager.getMessage("welcome.server-status.online.private-electrum"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -106,7 +154,7 @@ public class WelcomeController {
|
||||||
PauseTransition wait = new PauseTransition(Duration.millis(200));
|
PauseTransition wait = new PauseTransition(Duration.millis(200));
|
||||||
wait.setOnFinished((e) -> {
|
wait.setOnFinished((e) -> {
|
||||||
serverToggle.setSelected(false);
|
serverToggle.setSelected(false);
|
||||||
serverStatus.setText("Offline");
|
serverStatus.setText(LanguagesManager.getMessage("welcome.offline"));
|
||||||
});
|
});
|
||||||
wait.play();
|
wait.play();
|
||||||
return false;
|
return false;
|
||||||
|
@ -118,7 +166,7 @@ public class WelcomeController {
|
||||||
welcomeBox.getStyleClass().clear();
|
welcomeBox.getStyleClass().clear();
|
||||||
welcomeBox.getStyleClass().add("public-electrum");
|
welcomeBox.getStyleClass().add("public-electrum");
|
||||||
serverToggle.setSelected(true);
|
serverToggle.setSelected(true);
|
||||||
serverStatus.setText("Connected to a Public Server (demonstration only)");
|
serverStatus.setText(LanguagesManager.getMessage("welcome.server-status.online.public-server"));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,10 +176,15 @@ public class WelcomeController {
|
||||||
welcomeBox.getStyleClass().clear();
|
welcomeBox.getStyleClass().clear();
|
||||||
welcomeBox.getStyleClass().add("bitcoin-core");
|
welcomeBox.getStyleClass().add("bitcoin-core");
|
||||||
serverToggle.setSelected(true);
|
serverToggle.setSelected(true);
|
||||||
serverStatus.setText("Connected to Bitcoin Core (demonstration only)");
|
serverStatus.setText(LanguagesManager.getMessage("welcome.server-status.online.bitcoin-core"));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ObservableList<Language> getLanguagesList() {
|
||||||
|
List<Language> languages = Arrays.asList(Language.values());
|
||||||
|
return FXCollections.observableList(languages);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,8 @@
|
||||||
package com.sparrowwallet.sparrow;
|
package com.sparrowwallet.sparrow;
|
||||||
|
|
||||||
|
import com.google.common.eventbus.Subscribe;
|
||||||
|
import com.sparrowwallet.sparrow.event.LanguageChangedInWelcomeEvent;
|
||||||
|
import com.sparrowwallet.sparrow.i18n.LanguagesManager;
|
||||||
import javafx.event.ActionEvent;
|
import javafx.event.ActionEvent;
|
||||||
import javafx.fxml.FXMLLoader;
|
import javafx.fxml.FXMLLoader;
|
||||||
import javafx.scene.control.*;
|
import javafx.scene.control.*;
|
||||||
|
@ -9,16 +12,22 @@ import javafx.scene.image.ImageView;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class WelcomeDialog extends Dialog<Mode> {
|
public class WelcomeDialog extends Dialog<Mode> {
|
||||||
public WelcomeDialog() {
|
|
||||||
|
private WelcomeController welcomeController;
|
||||||
|
|
||||||
|
public WelcomeDialog(boolean isFirstExecution) {
|
||||||
|
super();
|
||||||
final DialogPane dialogPane = getDialogPane();
|
final DialogPane dialogPane = getDialogPane();
|
||||||
AppServices.setStageIcon(dialogPane.getScene().getWindow());
|
AppServices.setStageIcon(dialogPane.getScene().getWindow());
|
||||||
AppServices.onEscapePressed(dialogPane.getScene(), this::close);
|
AppServices.onEscapePressed(dialogPane.getScene(), this::close);
|
||||||
|
|
||||||
|
EventManager.get().register(this);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
FXMLLoader welcomeLoader = new FXMLLoader(AppServices.class.getResource("welcome.fxml"));
|
FXMLLoader welcomeLoader = new FXMLLoader(AppServices.class.getResource("welcome.fxml"), LanguagesManager.getResourceBundle());
|
||||||
dialogPane.setContent(welcomeLoader.load());
|
dialogPane.setContent(welcomeLoader.load());
|
||||||
WelcomeController welcomeController = welcomeLoader.getController();
|
welcomeController = welcomeLoader.getController();
|
||||||
welcomeController.initializeView();
|
welcomeController.initializeView(isFirstExecution);
|
||||||
|
|
||||||
dialogPane.setPrefWidth(600);
|
dialogPane.setPrefWidth(600);
|
||||||
dialogPane.setPrefHeight(520);
|
dialogPane.setPrefHeight(520);
|
||||||
|
@ -27,10 +36,10 @@ public class WelcomeDialog extends Dialog<Mode> {
|
||||||
|
|
||||||
dialogPane.getStylesheets().add(AppServices.class.getResource("welcome.css").toExternalForm());
|
dialogPane.getStylesheets().add(AppServices.class.getResource("welcome.css").toExternalForm());
|
||||||
|
|
||||||
final ButtonType nextButtonType = new javafx.scene.control.ButtonType("Next", ButtonBar.ButtonData.OK_DONE);
|
final ButtonType nextButtonType = new javafx.scene.control.ButtonType(LanguagesManager.getMessage("welcome.next"), ButtonBar.ButtonData.OK_DONE);
|
||||||
final ButtonType backButtonType = new javafx.scene.control.ButtonType("Back", ButtonBar.ButtonData.LEFT);
|
final ButtonType backButtonType = new javafx.scene.control.ButtonType(LanguagesManager.getMessage("welcome.back"), ButtonBar.ButtonData.LEFT);
|
||||||
final ButtonType onlineButtonType = new javafx.scene.control.ButtonType("Configure Server", ButtonBar.ButtonData.APPLY);
|
final ButtonType onlineButtonType = new javafx.scene.control.ButtonType(LanguagesManager.getMessage("welcome.configure-server"), ButtonBar.ButtonData.APPLY);
|
||||||
final ButtonType offlineButtonType = new javafx.scene.control.ButtonType(AppServices.isConnected() ? "Done" : "Later or Offline Mode", ButtonBar.ButtonData.CANCEL_CLOSE);
|
final ButtonType offlineButtonType = new javafx.scene.control.ButtonType(AppServices.isConnected() ? LanguagesManager.getMessage("welcome.done") : LanguagesManager.getMessage("welcome.configure-later"), ButtonBar.ButtonData.CANCEL_CLOSE);
|
||||||
dialogPane.getButtonTypes().addAll(nextButtonType, backButtonType, onlineButtonType, offlineButtonType);
|
dialogPane.getButtonTypes().addAll(nextButtonType, backButtonType, onlineButtonType, offlineButtonType);
|
||||||
|
|
||||||
Button nextButton = (Button)dialogPane.lookupButton(nextButtonType);
|
Button nextButton = (Button)dialogPane.lookupButton(nextButtonType);
|
||||||
|
@ -69,4 +78,18 @@ public class WelcomeDialog extends Dialog<Mode> {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void languageChanged(LanguageChangedInWelcomeEvent event) {
|
||||||
|
final DialogPane dialogPane = getDialogPane();
|
||||||
|
|
||||||
|
try {
|
||||||
|
FXMLLoader welcomeLoader = new FXMLLoader(AppServices.class.getResource("welcome.fxml"), LanguagesManager.getResourceBundle());
|
||||||
|
dialogPane.setContent(welcomeLoader.load());
|
||||||
|
welcomeController = welcomeLoader.getController();
|
||||||
|
welcomeController.initializeView(true);
|
||||||
|
} catch(IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import com.sparrowwallet.sparrow.EventManager;
|
||||||
import com.sparrowwallet.sparrow.event.WalletAddressesChangedEvent;
|
import com.sparrowwallet.sparrow.event.WalletAddressesChangedEvent;
|
||||||
import com.sparrowwallet.sparrow.event.WalletDataChangedEvent;
|
import com.sparrowwallet.sparrow.event.WalletDataChangedEvent;
|
||||||
import com.sparrowwallet.sparrow.event.WalletHistoryStatusEvent;
|
import com.sparrowwallet.sparrow.event.WalletHistoryStatusEvent;
|
||||||
|
import com.sparrowwallet.sparrow.i18n.LanguagesManager;
|
||||||
import com.sparrowwallet.sparrow.io.Config;
|
import com.sparrowwallet.sparrow.io.Config;
|
||||||
import com.sparrowwallet.sparrow.io.Storage;
|
import com.sparrowwallet.sparrow.io.Storage;
|
||||||
import com.sparrowwallet.sparrow.net.ServerType;
|
import com.sparrowwallet.sparrow.net.ServerType;
|
||||||
|
@ -86,12 +87,12 @@ public class CoinTreeTable extends TreeTableView<Entry> {
|
||||||
if(entry != null && event.getWallet() != null && entry.getWallet() == event.getWallet()) {
|
if(entry != null && event.getWallet() != null && entry.getWallet() == event.getWallet()) {
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
if(event.getErrorMessage() != null) {
|
if(event.getErrorMessage() != null) {
|
||||||
setPlaceholder(new Label("Error loading transactions: " + event.getErrorMessage()));
|
setPlaceholder(new Label(LanguagesManager.getMessage("wallet.transactions.table.loading.error")+ " " + event.getErrorMessage()));
|
||||||
} else if(event.isLoading()) {
|
} else if(event.isLoading()) {
|
||||||
if(event.getStatusMessage() != null) {
|
if(event.getStatusMessage() != null) {
|
||||||
setPlaceholder(new Label(event.getStatusMessage() + "..."));
|
setPlaceholder(new Label(event.getStatusMessage() + "..."));
|
||||||
} else {
|
} else {
|
||||||
setPlaceholder(new Label("Loading transactions..."));
|
setPlaceholder(new Label(LanguagesManager.getMessage("wallet.transactions.table.loading")));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setPlaceholder(getDefaultPlaceholder(event.getWallet()));
|
setPlaceholder(getDefaultPlaceholder(event.getWallet()));
|
||||||
|
@ -103,7 +104,7 @@ public class CoinTreeTable extends TreeTableView<Entry> {
|
||||||
|
|
||||||
protected Node getDefaultPlaceholder(Wallet wallet) {
|
protected Node getDefaultPlaceholder(Wallet wallet) {
|
||||||
StackPane stackPane = new StackPane();
|
StackPane stackPane = new StackPane();
|
||||||
stackPane.getChildren().add(AppServices.isConnecting() ? new Label("Loading transactions...") : new Label("No transactions"));
|
stackPane.getChildren().add(AppServices.isConnecting() ? new Label(LanguagesManager.getMessage("wallet.transactions.table.loading")) : new Label(LanguagesManager.getMessage("wallet.transactions.table.no-transactions")));
|
||||||
|
|
||||||
if(Config.get().getServerType() == ServerType.BITCOIN_CORE && !AppServices.isConnecting()) {
|
if(Config.get().getServerType() == ServerType.BITCOIN_CORE && !AppServices.isConnecting()) {
|
||||||
Hyperlink hyperlink = new Hyperlink();
|
Hyperlink hyperlink = new Hyperlink();
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.sparrowwallet.sparrow.control;
|
package com.sparrowwallet.sparrow.control;
|
||||||
|
|
||||||
|
import com.sparrowwallet.sparrow.i18n.LanguagesManager;
|
||||||
import com.sparrowwallet.sparrow.wallet.Entry;
|
import com.sparrowwallet.sparrow.wallet.Entry;
|
||||||
import com.sparrowwallet.sparrow.wallet.TransactionEntry;
|
import com.sparrowwallet.sparrow.wallet.TransactionEntry;
|
||||||
import com.sparrowwallet.sparrow.wallet.WalletTransactionsEntry;
|
import com.sparrowwallet.sparrow.wallet.WalletTransactionsEntry;
|
||||||
|
@ -15,7 +16,7 @@ public class TransactionsTreeTable extends CoinTreeTable {
|
||||||
updateAll(rootEntry);
|
updateAll(rootEntry);
|
||||||
setShowRoot(false);
|
setShowRoot(false);
|
||||||
|
|
||||||
TreeTableColumn<Entry, Entry> dateCol = new TreeTableColumn<>("Date");
|
TreeTableColumn<Entry, Entry> dateCol = new TreeTableColumn<>(LanguagesManager.getMessage("wallet.transactions.table.date"));
|
||||||
dateCol.setCellValueFactory((TreeTableColumn.CellDataFeatures<Entry, Entry> param) -> {
|
dateCol.setCellValueFactory((TreeTableColumn.CellDataFeatures<Entry, Entry> param) -> {
|
||||||
return new ReadOnlyObjectWrapper<>(param.getValue().getValue());
|
return new ReadOnlyObjectWrapper<>(param.getValue().getValue());
|
||||||
});
|
});
|
||||||
|
@ -23,7 +24,7 @@ public class TransactionsTreeTable extends CoinTreeTable {
|
||||||
dateCol.setSortable(true);
|
dateCol.setSortable(true);
|
||||||
getColumns().add(dateCol);
|
getColumns().add(dateCol);
|
||||||
|
|
||||||
TreeTableColumn<Entry, String> labelCol = new TreeTableColumn<>("Label");
|
TreeTableColumn<Entry, String> labelCol = new TreeTableColumn<>(LanguagesManager.getMessage("wallet.transactions.table.label"));
|
||||||
labelCol.setCellValueFactory((TreeTableColumn.CellDataFeatures<Entry, String> param) -> {
|
labelCol.setCellValueFactory((TreeTableColumn.CellDataFeatures<Entry, String> param) -> {
|
||||||
return param.getValue().getValue().labelProperty();
|
return param.getValue().getValue().labelProperty();
|
||||||
});
|
});
|
||||||
|
@ -31,7 +32,7 @@ public class TransactionsTreeTable extends CoinTreeTable {
|
||||||
labelCol.setSortable(true);
|
labelCol.setSortable(true);
|
||||||
getColumns().add(labelCol);
|
getColumns().add(labelCol);
|
||||||
|
|
||||||
TreeTableColumn<Entry, Number> amountCol = new TreeTableColumn<>("Value");
|
TreeTableColumn<Entry, Number> amountCol = new TreeTableColumn<>(LanguagesManager.getMessage("wallet.transactions.table.value"));
|
||||||
amountCol.setCellValueFactory((TreeTableColumn.CellDataFeatures<Entry, Number> param) -> {
|
amountCol.setCellValueFactory((TreeTableColumn.CellDataFeatures<Entry, Number> param) -> {
|
||||||
return new ReadOnlyObjectWrapper<>(param.getValue().getValue().getValue());
|
return new ReadOnlyObjectWrapper<>(param.getValue().getValue().getValue());
|
||||||
});
|
});
|
||||||
|
@ -39,7 +40,7 @@ public class TransactionsTreeTable extends CoinTreeTable {
|
||||||
amountCol.setSortable(true);
|
amountCol.setSortable(true);
|
||||||
getColumns().add(amountCol);
|
getColumns().add(amountCol);
|
||||||
|
|
||||||
TreeTableColumn<Entry, Number> balanceCol = new TreeTableColumn<>("Balance");
|
TreeTableColumn<Entry, Number> balanceCol = new TreeTableColumn<>(LanguagesManager.getMessage("wallet.transactions.table.balance"));
|
||||||
balanceCol.setCellValueFactory((TreeTableColumn.CellDataFeatures<Entry, Number> param) -> {
|
balanceCol.setCellValueFactory((TreeTableColumn.CellDataFeatures<Entry, Number> param) -> {
|
||||||
return param.getValue().getValue() instanceof TransactionEntry ? ((TransactionEntry)param.getValue().getValue()).balanceProperty() : new ReadOnlyObjectWrapper<>(null);
|
return param.getValue().getValue() instanceof TransactionEntry ? ((TransactionEntry)param.getValue().getValue()).balanceProperty() : new ReadOnlyObjectWrapper<>(null);
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.sparrowwallet.sparrow.event;
|
||||||
|
|
||||||
|
import com.sparrowwallet.sparrow.i18n.Language;
|
||||||
|
|
||||||
|
public class LanguageChangedInWelcomeEvent {
|
||||||
|
private final Language language;
|
||||||
|
|
||||||
|
public LanguageChangedInWelcomeEvent(Language language) {
|
||||||
|
this.language = language;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Language getLanguage() {
|
||||||
|
return language;
|
||||||
|
}
|
||||||
|
}
|
25
src/main/java/com/sparrowwallet/sparrow/i18n/Language.java
Normal file
25
src/main/java/com/sparrowwallet/sparrow/i18n/Language.java
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
package com.sparrowwallet.sparrow.i18n;
|
||||||
|
|
||||||
|
public enum Language {
|
||||||
|
ENGLISH("en"),
|
||||||
|
SPANISH("es");
|
||||||
|
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
Language(String code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Language getFromCode(String code) {
|
||||||
|
for (Language l : Language.values()) {
|
||||||
|
if (l.code.equals(code)) {
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package com.sparrowwallet.sparrow.i18n;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class LanguagesManager {
|
||||||
|
|
||||||
|
public static final Language DEFAULT_LANGUAGE = Language.ENGLISH;
|
||||||
|
|
||||||
|
private static ResourceBundle bundle;
|
||||||
|
|
||||||
|
public static ResourceBundle getResourceBundle() {
|
||||||
|
if(bundle == null) {
|
||||||
|
loadLanguage(DEFAULT_LANGUAGE.getCode());
|
||||||
|
}
|
||||||
|
return bundle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void loadLanguage(String language) {
|
||||||
|
Locale locale = new Locale(language);
|
||||||
|
|
||||||
|
if(bundle == null || !locale.equals(bundle.getLocale())) {
|
||||||
|
bundle = ResourceBundle.getBundle("i18n/messages", locale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getMessage(String key) { return bundle.getString(key); }
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ import com.sparrowwallet.sparrow.UnitFormat;
|
||||||
import com.sparrowwallet.sparrow.Mode;
|
import com.sparrowwallet.sparrow.Mode;
|
||||||
import com.sparrowwallet.sparrow.Theme;
|
import com.sparrowwallet.sparrow.Theme;
|
||||||
import com.sparrowwallet.sparrow.control.QRDensity;
|
import com.sparrowwallet.sparrow.control.QRDensity;
|
||||||
|
import com.sparrowwallet.sparrow.i18n.Language;
|
||||||
import com.sparrowwallet.sparrow.net.*;
|
import com.sparrowwallet.sparrow.net.*;
|
||||||
import com.sparrowwallet.sparrow.wallet.FeeRatesSelection;
|
import com.sparrowwallet.sparrow.wallet.FeeRatesSelection;
|
||||||
import com.sparrowwallet.sparrow.wallet.OptimizationStrategy;
|
import com.sparrowwallet.sparrow.wallet.OptimizationStrategy;
|
||||||
|
@ -43,6 +44,7 @@ public class Config {
|
||||||
private boolean notifyNewTransactions = true;
|
private boolean notifyNewTransactions = true;
|
||||||
private boolean checkNewVersions = true;
|
private boolean checkNewVersions = true;
|
||||||
private Theme theme;
|
private Theme theme;
|
||||||
|
private Language language;
|
||||||
private boolean openWalletsInNewWindows = false;
|
private boolean openWalletsInNewWindows = false;
|
||||||
private boolean hideEmptyUsedAddresses = false;
|
private boolean hideEmptyUsedAddresses = false;
|
||||||
private boolean showTransactionHex = true;
|
private boolean showTransactionHex = true;
|
||||||
|
@ -277,6 +279,15 @@ public class Config {
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Language getLanguage() {
|
||||||
|
return language;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLanguage(Language language) {
|
||||||
|
this.language = language;
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isOpenWalletsInNewWindows() {
|
public boolean isOpenWalletsInNewWindows() {
|
||||||
return openWalletsInNewWindows;
|
return openWalletsInNewWindows;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import com.sparrowwallet.drongo.protocol.Sha256Hash;
|
||||||
import com.sparrowwallet.drongo.wallet.Wallet;
|
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||||
import com.sparrowwallet.sparrow.EventManager;
|
import com.sparrowwallet.sparrow.EventManager;
|
||||||
import com.sparrowwallet.sparrow.event.WalletHistoryStatusEvent;
|
import com.sparrowwallet.sparrow.event.WalletHistoryStatusEvent;
|
||||||
|
import com.sparrowwallet.sparrow.i18n.LanguagesManager;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -82,7 +83,7 @@ public class BatchedElectrumServerRpc implements ElectrumServerRpc {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public Map<String, ScriptHashTx[]> getScriptHashHistory(Transport transport, Wallet wallet, Map<String, String> pathScriptHashes, boolean failOnError) {
|
public Map<String, ScriptHashTx[]> getScriptHashHistory(Transport transport, Wallet wallet, Map<String, String> pathScriptHashes, boolean failOnError) {
|
||||||
PagedBatchRequestBuilder<String, ScriptHashTx[]> batchRequest = PagedBatchRequestBuilder.create(transport, idCounter).keysType(String.class).returnType(ScriptHashTx[].class);
|
PagedBatchRequestBuilder<String, ScriptHashTx[]> batchRequest = PagedBatchRequestBuilder.create(transport, idCounter).keysType(String.class).returnType(ScriptHashTx[].class);
|
||||||
EventManager.get().post(new WalletHistoryStatusEvent(wallet, true, "Loading transactions for " + nodeRangesToString(pathScriptHashes.keySet())));
|
EventManager.get().post(new WalletHistoryStatusEvent(wallet, true, LanguagesManager.getMessage("wallet.transactions.loading-transactions") + " " + nodeRangesToString(pathScriptHashes.keySet())));
|
||||||
|
|
||||||
for(String path : pathScriptHashes.keySet()) {
|
for(String path : pathScriptHashes.keySet()) {
|
||||||
batchRequest.add(path, "blockchain.scripthash.get_history", pathScriptHashes.get(path));
|
batchRequest.add(path, "blockchain.scripthash.get_history", pathScriptHashes.get(path));
|
||||||
|
@ -137,7 +138,7 @@ public class BatchedElectrumServerRpc implements ElectrumServerRpc {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public Map<String, String> subscribeScriptHashes(Transport transport, Wallet wallet, Map<String, String> pathScriptHashes) {
|
public Map<String, String> subscribeScriptHashes(Transport transport, Wallet wallet, Map<String, String> pathScriptHashes) {
|
||||||
PagedBatchRequestBuilder<String, String> batchRequest = PagedBatchRequestBuilder.create(transport, idCounter).keysType(String.class).returnType(String.class);
|
PagedBatchRequestBuilder<String, String> batchRequest = PagedBatchRequestBuilder.create(transport, idCounter).keysType(String.class).returnType(String.class);
|
||||||
EventManager.get().post(new WalletHistoryStatusEvent(wallet, true, "Finding transactions for " + nodeRangesToString(pathScriptHashes.keySet())));
|
EventManager.get().post(new WalletHistoryStatusEvent(wallet, true, LanguagesManager.getMessage("wallet.transactions.finding-transactions") + " " + nodeRangesToString(pathScriptHashes.keySet())));
|
||||||
|
|
||||||
for(String path : pathScriptHashes.keySet()) {
|
for(String path : pathScriptHashes.keySet()) {
|
||||||
batchRequest.add(path, "blockchain.scripthash.subscribe", pathScriptHashes.get(path));
|
batchRequest.add(path, "blockchain.scripthash.subscribe", pathScriptHashes.get(path));
|
||||||
|
@ -157,7 +158,7 @@ public class BatchedElectrumServerRpc implements ElectrumServerRpc {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public Map<Integer, String> getBlockHeaders(Transport transport, Wallet wallet, Set<Integer> blockHeights) {
|
public Map<Integer, String> getBlockHeaders(Transport transport, Wallet wallet, Set<Integer> blockHeights) {
|
||||||
PagedBatchRequestBuilder<Integer, String> batchRequest = PagedBatchRequestBuilder.create(transport, idCounter).keysType(Integer.class).returnType(String.class);
|
PagedBatchRequestBuilder<Integer, String> batchRequest = PagedBatchRequestBuilder.create(transport, idCounter).keysType(Integer.class).returnType(String.class);
|
||||||
EventManager.get().post(new WalletHistoryStatusEvent(wallet, true, "Retrieving " + blockHeights.size() + " block headers"));
|
EventManager.get().post(new WalletHistoryStatusEvent(wallet, true, LanguagesManager.getMessage("wallet.transactions.retrieving") + " " + blockHeights.size() + " " + LanguagesManager.getMessage("wallet.transactions.retrieving-headers")));
|
||||||
|
|
||||||
for(Integer height : blockHeights) {
|
for(Integer height : blockHeights) {
|
||||||
batchRequest.add(height, "blockchain.block.header", height);
|
batchRequest.add(height, "blockchain.block.header", height);
|
||||||
|
@ -176,7 +177,7 @@ public class BatchedElectrumServerRpc implements ElectrumServerRpc {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public Map<String, String> getTransactions(Transport transport, Wallet wallet, Set<String> txids) {
|
public Map<String, String> getTransactions(Transport transport, Wallet wallet, Set<String> txids) {
|
||||||
PagedBatchRequestBuilder<String, String> batchRequest = PagedBatchRequestBuilder.create(transport, idCounter).keysType(String.class).returnType(String.class);
|
PagedBatchRequestBuilder<String, String> batchRequest = PagedBatchRequestBuilder.create(transport, idCounter).keysType(String.class).returnType(String.class);
|
||||||
EventManager.get().post(new WalletHistoryStatusEvent(wallet, true, "Retrieving " + txids.size() + " transactions"));
|
EventManager.get().post(new WalletHistoryStatusEvent(wallet, true, LanguagesManager.getMessage("wallet.transactions.retrieving") + " " + txids.size() + " " + LanguagesManager.getMessage("wallet.transactions.retrieving-transactions")));
|
||||||
|
|
||||||
for(String txid : txids) {
|
for(String txid : txids) {
|
||||||
batchRequest.add(txid, "blockchain.transaction.get", txid);
|
batchRequest.add(txid, "blockchain.transaction.get", txid);
|
||||||
|
|
|
@ -10,6 +10,7 @@ import com.sparrowwallet.drongo.wallet.Wallet;
|
||||||
import com.sparrowwallet.sparrow.AppServices;
|
import com.sparrowwallet.sparrow.AppServices;
|
||||||
import com.sparrowwallet.sparrow.EventManager;
|
import com.sparrowwallet.sparrow.EventManager;
|
||||||
import com.sparrowwallet.sparrow.event.WalletHistoryStatusEvent;
|
import com.sparrowwallet.sparrow.event.WalletHistoryStatusEvent;
|
||||||
|
import com.sparrowwallet.sparrow.i18n.LanguagesManager;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -76,7 +77,7 @@ public class SimpleElectrumServerRpc implements ElectrumServerRpc {
|
||||||
|
|
||||||
Map<String, ScriptHashTx[]> result = new LinkedHashMap<>();
|
Map<String, ScriptHashTx[]> result = new LinkedHashMap<>();
|
||||||
for(String path : pathScriptHashes.keySet()) {
|
for(String path : pathScriptHashes.keySet()) {
|
||||||
EventManager.get().post(new WalletHistoryStatusEvent(wallet, true, "Loading transactions for " + path));
|
EventManager.get().post(new WalletHistoryStatusEvent(wallet, true, LanguagesManager.getMessage("wallet.transactions.loading-transactions") + " " + path));
|
||||||
try {
|
try {
|
||||||
ScriptHashTx[] scriptHashTxes = new RetryLogic<ScriptHashTx[]>(MAX_RETRIES, RETRY_DELAY, List.of(IllegalStateException.class, IllegalArgumentException.class)).getResult(() ->
|
ScriptHashTx[] scriptHashTxes = new RetryLogic<ScriptHashTx[]>(MAX_RETRIES, RETRY_DELAY, List.of(IllegalStateException.class, IllegalArgumentException.class)).getResult(() ->
|
||||||
client.createRequest().returnAs(ScriptHashTx[].class).method("blockchain.scripthash.get_history").id(idCounter.incrementAndGet()).params(pathScriptHashes.get(path)).execute());
|
client.createRequest().returnAs(ScriptHashTx[].class).method("blockchain.scripthash.get_history").id(idCounter.incrementAndGet()).params(pathScriptHashes.get(path)).execute());
|
||||||
|
@ -121,7 +122,7 @@ public class SimpleElectrumServerRpc implements ElectrumServerRpc {
|
||||||
|
|
||||||
Map<String, String> result = new LinkedHashMap<>();
|
Map<String, String> result = new LinkedHashMap<>();
|
||||||
for(String path : pathScriptHashes.keySet()) {
|
for(String path : pathScriptHashes.keySet()) {
|
||||||
EventManager.get().post(new WalletHistoryStatusEvent(wallet, true, "Finding transactions for " + path));
|
EventManager.get().post(new WalletHistoryStatusEvent(wallet, true, LanguagesManager.getMessage("wallet.transactions.finding-transactions") + " " + path));
|
||||||
try {
|
try {
|
||||||
String scriptHash = new RetryLogic<String>(MAX_RETRIES, RETRY_DELAY, List.of(IllegalStateException.class, IllegalArgumentException.class)).getResult(() ->
|
String scriptHash = new RetryLogic<String>(MAX_RETRIES, RETRY_DELAY, List.of(IllegalStateException.class, IllegalArgumentException.class)).getResult(() ->
|
||||||
client.createRequest().returnAs(String.class).method("blockchain.scripthash.subscribe").id(idCounter.incrementAndGet()).params(pathScriptHashes.get(path)).executeNullable());
|
client.createRequest().returnAs(String.class).method("blockchain.scripthash.subscribe").id(idCounter.incrementAndGet()).params(pathScriptHashes.get(path)).executeNullable());
|
||||||
|
@ -141,7 +142,7 @@ public class SimpleElectrumServerRpc implements ElectrumServerRpc {
|
||||||
|
|
||||||
Map<Integer, String> result = new LinkedHashMap<>();
|
Map<Integer, String> result = new LinkedHashMap<>();
|
||||||
for(Integer blockHeight : blockHeights) {
|
for(Integer blockHeight : blockHeights) {
|
||||||
EventManager.get().post(new WalletHistoryStatusEvent(wallet, true, "Retrieving block at height " + blockHeight));
|
EventManager.get().post(new WalletHistoryStatusEvent(wallet, true, LanguagesManager.getMessage("wallet.transactions.retrieving-block-height") + " " + blockHeight));
|
||||||
try {
|
try {
|
||||||
String blockHeader = new RetryLogic<String>(MAX_RETRIES, RETRY_DELAY, List.of(IllegalStateException.class, IllegalArgumentException.class)).getResult(() ->
|
String blockHeader = new RetryLogic<String>(MAX_RETRIES, RETRY_DELAY, List.of(IllegalStateException.class, IllegalArgumentException.class)).getResult(() ->
|
||||||
client.createRequest().returnAs(String.class).method("blockchain.block.header").id(idCounter.incrementAndGet()).params(blockHeight).execute());
|
client.createRequest().returnAs(String.class).method("blockchain.block.header").id(idCounter.incrementAndGet()).params(blockHeight).execute());
|
||||||
|
@ -165,7 +166,7 @@ public class SimpleElectrumServerRpc implements ElectrumServerRpc {
|
||||||
|
|
||||||
Map<String, String> result = new LinkedHashMap<>();
|
Map<String, String> result = new LinkedHashMap<>();
|
||||||
for(String txid : txids) {
|
for(String txid : txids) {
|
||||||
EventManager.get().post(new WalletHistoryStatusEvent(wallet, true, "Retrieving transaction [" + txid.substring(0, 6) + "]"));
|
EventManager.get().post(new WalletHistoryStatusEvent(wallet, true, LanguagesManager.getMessage("wallet.transactions.retrieving-transaction") + " [" + txid.substring(0, 6) + "]"));
|
||||||
try {
|
try {
|
||||||
String rawTxHex = new RetryLogic<String>(MAX_RETRIES, RETRY_DELAY, List.of(IllegalStateException.class, IllegalArgumentException.class)).getResult(() ->
|
String rawTxHex = new RetryLogic<String>(MAX_RETRIES, RETRY_DELAY, List.of(IllegalStateException.class, IllegalArgumentException.class)).getResult(() ->
|
||||||
client.createRequest().returnAs(String.class).method("blockchain.transaction.get").id(idCounter.incrementAndGet()).params(txid).execute());
|
client.createRequest().returnAs(String.class).method("blockchain.transaction.get").id(idCounter.incrementAndGet()).params(txid).execute());
|
||||||
|
|
|
@ -5,6 +5,7 @@ import com.sparrowwallet.sparrow.AppServices;
|
||||||
import com.sparrowwallet.sparrow.EventManager;
|
import com.sparrowwallet.sparrow.EventManager;
|
||||||
import com.sparrowwallet.sparrow.control.*;
|
import com.sparrowwallet.sparrow.control.*;
|
||||||
import com.sparrowwallet.sparrow.event.*;
|
import com.sparrowwallet.sparrow.event.*;
|
||||||
|
import com.sparrowwallet.sparrow.i18n.LanguagesManager;
|
||||||
import com.sparrowwallet.sparrow.io.Config;
|
import com.sparrowwallet.sparrow.io.Config;
|
||||||
import com.sparrowwallet.sparrow.io.WalletTransactions;
|
import com.sparrowwallet.sparrow.io.WalletTransactions;
|
||||||
import com.sparrowwallet.sparrow.net.ExchangeSource;
|
import com.sparrowwallet.sparrow.net.ExchangeSource;
|
||||||
|
@ -96,7 +97,7 @@ public class TransactionsController extends WalletFormController implements Init
|
||||||
});
|
});
|
||||||
|
|
||||||
transactionsMasterDetail.setShowDetailNode(Config.get().isShowLoadingLog());
|
transactionsMasterDetail.setShowDetailNode(Config.get().isShowLoadingLog());
|
||||||
loadingLog.appendText("Wallet loading history for " + getWalletForm().getWallet().getFullDisplayName());
|
loadingLog.appendText(LanguagesManager.getMessage("wallet.transactions.loading-history") + " " + getWalletForm().getWallet().getFullDisplayName());
|
||||||
loadingLog.setEditable(false);
|
loadingLog.setEditable(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,7 +110,7 @@ public class TransactionsController extends WalletFormController implements Init
|
||||||
|
|
||||||
Stage window = new Stage();
|
Stage window = new Stage();
|
||||||
FileChooser fileChooser = new FileChooser();
|
FileChooser fileChooser = new FileChooser();
|
||||||
fileChooser.setTitle("Export Transactions as CSV");
|
fileChooser.setTitle(LanguagesManager.getMessage("wallet.transactions.csv-export"));
|
||||||
fileChooser.setInitialFileName(wallet.getFullName() + "-transactions.csv");
|
fileChooser.setInitialFileName(wallet.getFullName() + "-transactions.csv");
|
||||||
AppServices.moveToActiveWindowScreen(window, 800, 450);
|
AppServices.moveToActiveWindowScreen(window, 800, 450);
|
||||||
File file = fileChooser.showSaveDialog(window);
|
File file = fileChooser.showSaveDialog(window);
|
||||||
|
@ -118,7 +119,7 @@ public class TransactionsController extends WalletFormController implements Init
|
||||||
exportService.setOnFailed(failedEvent -> {
|
exportService.setOnFailed(failedEvent -> {
|
||||||
Throwable e = failedEvent.getSource().getException();
|
Throwable e = failedEvent.getSource().getException();
|
||||||
log.error("Error exporting transactions as CSV", e);
|
log.error("Error exporting transactions as CSV", e);
|
||||||
AppServices.showErrorDialog("Error exporting transactions as CSV", e.getMessage());
|
AppServices.showErrorDialog(LanguagesManager.getMessage("wallet.transactions.csv-export.error"), e.getMessage());
|
||||||
});
|
});
|
||||||
exportService.start();
|
exportService.start();
|
||||||
}
|
}
|
||||||
|
@ -212,7 +213,7 @@ public class TransactionsController extends WalletFormController implements Init
|
||||||
String logMessage = event.getStatusMessage();
|
String logMessage = event.getStatusMessage();
|
||||||
if(logMessage == null) {
|
if(logMessage == null) {
|
||||||
if(event instanceof WalletHistoryFinishedEvent) {
|
if(event instanceof WalletHistoryFinishedEvent) {
|
||||||
logMessage = "Finished loading.";
|
logMessage = LanguagesManager.getMessage("wallet.transactions.loading-finish");
|
||||||
} else if(event instanceof WalletHistoryFailedEvent) {
|
} else if(event instanceof WalletHistoryFailedEvent) {
|
||||||
logMessage = event.getErrorMessage();
|
logMessage = event.getErrorMessage();
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import com.sparrowwallet.sparrow.AppServices;
|
||||||
import com.sparrowwallet.sparrow.EventManager;
|
import com.sparrowwallet.sparrow.EventManager;
|
||||||
import com.sparrowwallet.sparrow.control.ViewPasswordField;
|
import com.sparrowwallet.sparrow.control.ViewPasswordField;
|
||||||
import com.sparrowwallet.sparrow.event.*;
|
import com.sparrowwallet.sparrow.event.*;
|
||||||
|
import com.sparrowwallet.sparrow.i18n.LanguagesManager;
|
||||||
import com.sparrowwallet.sparrow.io.Storage;
|
import com.sparrowwallet.sparrow.io.Storage;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.beans.property.BooleanProperty;
|
import javafx.beans.property.BooleanProperty;
|
||||||
|
@ -95,7 +96,7 @@ public class WalletController extends WalletFormController implements Initializa
|
||||||
throw new IllegalStateException("Cannot find wallet/" + function.toString().toLowerCase(Locale.ROOT) + ".fxml");
|
throw new IllegalStateException("Cannot find wallet/" + function.toString().toLowerCase(Locale.ROOT) + ".fxml");
|
||||||
}
|
}
|
||||||
|
|
||||||
FXMLLoader functionLoader = new FXMLLoader(url);
|
FXMLLoader functionLoader = new FXMLLoader(url, LanguagesManager.getResourceBundle());
|
||||||
Node walletFunction = functionLoader.load();
|
Node walletFunction = functionLoader.load();
|
||||||
walletFunction.setUserData(function);
|
walletFunction.setUserData(function);
|
||||||
WalletFormController controller = functionLoader.getController();
|
WalletFormController controller = functionLoader.getController();
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
<?import com.sparrowwallet.drongo.BitcoinUnit?>
|
<?import com.sparrowwallet.drongo.BitcoinUnit?>
|
||||||
<?import com.sparrowwallet.sparrow.UnitFormat?>
|
<?import com.sparrowwallet.sparrow.UnitFormat?>
|
||||||
<?import com.sparrowwallet.sparrow.Theme?>
|
<?import com.sparrowwallet.sparrow.Theme?>
|
||||||
|
<?import com.sparrowwallet.sparrow.i18n.Language?>
|
||||||
<?import impl.org.controlsfx.skin.DecorationPane?>
|
<?import impl.org.controlsfx.skin.DecorationPane?>
|
||||||
|
|
||||||
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="200" minWidth="350" prefHeight="770.0" prefWidth="1070.0" fx:controller="com.sparrowwallet.sparrow.AppController" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1">
|
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="200" minWidth="350" prefHeight="770.0" prefWidth="1070.0" fx:controller="com.sparrowwallet.sparrow.AppController" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1">
|
||||||
|
@ -64,6 +65,9 @@
|
||||||
<fx:define>
|
<fx:define>
|
||||||
<ToggleGroup fx:id="theme"/>
|
<ToggleGroup fx:id="theme"/>
|
||||||
</fx:define>
|
</fx:define>
|
||||||
|
<fx:define>
|
||||||
|
<ToggleGroup fx:id="language"/>
|
||||||
|
</fx:define>
|
||||||
<Menu fx:id="viewMenu" mnemonicParsing="false" text="View">
|
<Menu fx:id="viewMenu" mnemonicParsing="false" text="View">
|
||||||
<items>
|
<items>
|
||||||
<Menu mnemonicParsing="false" text="Bitcoin Unit">
|
<Menu mnemonicParsing="false" text="Bitcoin Unit">
|
||||||
|
@ -113,6 +117,20 @@
|
||||||
</RadioMenuItem>
|
</RadioMenuItem>
|
||||||
</items>
|
</items>
|
||||||
</Menu>
|
</Menu>
|
||||||
|
<Menu mnemonicParsing="false" text="%language">
|
||||||
|
<items>
|
||||||
|
<RadioMenuItem mnemonicParsing="false" text="%language.en" toggleGroup="$language" onAction="#setLanguage">
|
||||||
|
<userData>
|
||||||
|
<Language fx:constant="ENGLISH" />
|
||||||
|
</userData>
|
||||||
|
</RadioMenuItem>
|
||||||
|
<RadioMenuItem mnemonicParsing="false" text="%language.es" toggleGroup="$language" onAction="#setLanguage">
|
||||||
|
<userData>
|
||||||
|
<Language fx:constant="SPANISH" />
|
||||||
|
</userData>
|
||||||
|
</RadioMenuItem>
|
||||||
|
</items>
|
||||||
|
</Menu>
|
||||||
<SeparatorMenuItem />
|
<SeparatorMenuItem />
|
||||||
<CheckMenuItem fx:id="openWalletsInNewWindows" mnemonicParsing="false" text="Open Wallets In New Windows" onAction="#openWalletsInNewWindows"/>
|
<CheckMenuItem fx:id="openWalletsInNewWindows" mnemonicParsing="false" text="Open Wallets In New Windows" onAction="#openWalletsInNewWindows"/>
|
||||||
<CheckMenuItem fx:id="hideEmptyUsedAddresses" mnemonicParsing="false" text="Hide Empty Used Addresses" onAction="#hideEmptyUsedAddresses"/>
|
<CheckMenuItem fx:id="hideEmptyUsedAddresses" mnemonicParsing="false" text="Hide Empty Used Addresses" onAction="#hideEmptyUsedAddresses"/>
|
||||||
|
|
|
@ -33,21 +33,21 @@
|
||||||
<RowConstraints />
|
<RowConstraints />
|
||||||
</rowConstraints>
|
</rowConstraints>
|
||||||
<Form GridPane.columnIndex="0" GridPane.rowIndex="0">
|
<Form GridPane.columnIndex="0" GridPane.rowIndex="0">
|
||||||
<Fieldset inputGrow="SOMETIMES" text="Transactions" styleClass="header">
|
<Fieldset inputGrow="SOMETIMES" text="%wallet.transactions" styleClass="header">
|
||||||
<Field text="Balance:">
|
<Field text="%wallet.transactions.balance">
|
||||||
<CopyableCoinLabel fx:id="balance"/><Region HBox.hgrow="ALWAYS"/><FiatLabel fx:id="fiatBalance" minWidth="110" />
|
<CopyableCoinLabel fx:id="balance"/><Region HBox.hgrow="ALWAYS"/><FiatLabel fx:id="fiatBalance" minWidth="110" />
|
||||||
</Field>
|
</Field>
|
||||||
<Field text="Mempool:">
|
<Field text="Mempool:">
|
||||||
<CopyableCoinLabel fx:id="mempoolBalance" /><Region HBox.hgrow="ALWAYS"/><FiatLabel fx:id="fiatMempoolBalance" minWidth="110" />
|
<CopyableCoinLabel fx:id="mempoolBalance" /><Region HBox.hgrow="ALWAYS"/><FiatLabel fx:id="fiatMempoolBalance" minWidth="110" />
|
||||||
</Field>
|
</Field>
|
||||||
<Field text="Transactions:">
|
<Field text="%wallet.transactions.transactions">
|
||||||
<CopyableLabel fx:id="transactionCount" />
|
<CopyableLabel fx:id="transactionCount" />
|
||||||
<Button fx:id="exportCsv" maxHeight="25" onAction="#exportCSV" translateY="-1" styleClass="icon-button">
|
<Button fx:id="exportCsv" maxHeight="25" onAction="#exportCSV" translateY="-1" styleClass="icon-button">
|
||||||
<graphic>
|
<graphic>
|
||||||
<Glyph fontFamily="Font Awesome 5 Free Solid" icon="ARROW_CIRCLE_DOWN" fontSize="12" />
|
<Glyph fontFamily="Font Awesome 5 Free Solid" icon="ARROW_CIRCLE_DOWN" fontSize="12" />
|
||||||
</graphic>
|
</graphic>
|
||||||
<tooltip>
|
<tooltip>
|
||||||
<Tooltip text="Export transactions as CSV" />
|
<Tooltip text="%wallet.transactions.csv-export" />
|
||||||
</tooltip>
|
</tooltip>
|
||||||
</Button>
|
</Button>
|
||||||
</Field>
|
</Field>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<BorderPane stylesheets="@wallet.css, @../general.css" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" fx:controller="com.sparrowwallet.sparrow.wallet.WalletController">
|
<BorderPane stylesheets="@wallet.css, @../general.css" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" fx:controller="com.sparrowwallet.sparrow.wallet.WalletController">
|
||||||
<left>
|
<left>
|
||||||
<VBox fx:id="walletMenuBox" styleClass="list-menu">
|
<VBox fx:id="walletMenuBox" styleClass="list-menu">
|
||||||
<ToggleButton VBox.vgrow="ALWAYS" text="Transactions" contentDisplay="TOP" styleClass="list-item" maxHeight="Infinity">
|
<ToggleButton VBox.vgrow="ALWAYS" text="%wallet.transactions" contentDisplay="TOP" styleClass="list-item" maxHeight="Infinity">
|
||||||
<toggleGroup>
|
<toggleGroup>
|
||||||
<ToggleGroup fx:id="walletMenu" />
|
<ToggleGroup fx:id="walletMenu" />
|
||||||
</toggleGroup>
|
</toggleGroup>
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<VBox spacing="20">
|
<VBox spacing="20">
|
||||||
<HBox styleClass="title-area">
|
<HBox styleClass="title-area">
|
||||||
<HBox alignment="CENTER_LEFT">
|
<HBox alignment="CENTER_LEFT">
|
||||||
<Label fx:id="title" text="Welcome to Sparrow" styleClass="title-label" />
|
<Label fx:id="title" text="%welcome.title" styleClass="title-label" />
|
||||||
</HBox>
|
</HBox>
|
||||||
<Region HBox.hgrow="ALWAYS"/>
|
<Region HBox.hgrow="ALWAYS"/>
|
||||||
<ImageView AnchorPane.rightAnchor="0">
|
<ImageView AnchorPane.rightAnchor="0">
|
||||||
|
@ -24,44 +24,48 @@
|
||||||
</HBox>
|
</HBox>
|
||||||
<VBox fx:id="welcomeBox" styleClass="content-area" spacing="20" prefHeight="370">
|
<VBox fx:id="welcomeBox" styleClass="content-area" spacing="20" prefHeight="370">
|
||||||
<VBox fx:id="step1" spacing="15">
|
<VBox fx:id="step1" spacing="15">
|
||||||
<Label text="Introduction" styleClass="title-text">
|
<HBox>
|
||||||
<graphic>
|
<Label text="%welcome.step1.introduction" styleClass="title-text">
|
||||||
<Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="20" icon="TOGGLE_OFF" styleClass="title-icon" />
|
<graphic>
|
||||||
</graphic>
|
<Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="20" icon="TOGGLE_OFF" styleClass="title-icon" />
|
||||||
</Label>
|
</graphic>
|
||||||
<Label text="Sparrow is a Bitcoin wallet with a focus on security and usability." wrapText="true" styleClass="content-text" />
|
</Label>
|
||||||
<Label text="Sparrow can operate in both an online and offline mode. In the online mode it connects to a server to display transaction history. In the offline mode it is useful as a transaction editor and as an airgapped multisig coordinator." wrapText="true" styleClass="content-text" />
|
<Region HBox.hgrow="ALWAYS" />
|
||||||
<Label text="The status bar at the bottom displays the connection status, as demonstrated below:" wrapText="true" styleClass="content-text" />
|
<ComboBox fx:id="languages"/>
|
||||||
|
</HBox>
|
||||||
|
<Label text="%welcome.step1.label1" wrapText="true" styleClass="content-text" />
|
||||||
|
<Label text="%welcome.step1.label2" wrapText="true" styleClass="content-text" />
|
||||||
|
<Label text="%welcome.step1.label3" wrapText="true" styleClass="content-text" />
|
||||||
</VBox>
|
</VBox>
|
||||||
<VBox fx:id="step2" spacing="15">
|
<VBox fx:id="step2" spacing="15">
|
||||||
<Label text="Connecting to a Public Server" styleClass="title-text">
|
<Label text="%welcome.step2.introduction" styleClass="title-text">
|
||||||
<graphic>
|
<graphic>
|
||||||
<Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="20" icon="TOGGLE_ON" styleClass="title-icon" />
|
<Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="20" icon="TOGGLE_ON" styleClass="title-icon" />
|
||||||
</graphic>
|
</graphic>
|
||||||
</Label>
|
</Label>
|
||||||
<Label text="If you are beginning your journey in self custody, or just storing a small amount, the easiest way to connect Sparrow to the Bitcoin blockchain is via one of the preconfigured public Electrum servers. " wrapText="true" styleClass="content-text" />
|
<Label text="%welcome.step2.label1" wrapText="true" styleClass="content-text" />
|
||||||
<Label text="However, although Sparrow only connects to servers that have a record of respecting privacy, it is still not ideal as you are sharing your transaction history and balance with them." wrapText="true" styleClass="content-text" />
|
<Label text="%welcome.step2.label2" wrapText="true" styleClass="content-text" />
|
||||||
<Label text="A yellow toggle means you are connected to a public server." wrapText="true" styleClass="content-text" />
|
<Label text="%welcome.step2.label3" wrapText="true" styleClass="content-text" />
|
||||||
</VBox>
|
</VBox>
|
||||||
<VBox fx:id="step3" spacing="15">
|
<VBox fx:id="step3" spacing="15">
|
||||||
<Label text="Connecting to a Bitcoin Core node" styleClass="title-text">
|
<Label text="%welcome.step3.introduction" styleClass="title-text">
|
||||||
<graphic>
|
<graphic>
|
||||||
<Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="20" icon="TOGGLE_ON" styleClass="title-icon" />
|
<Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="20" icon="TOGGLE_ON" styleClass="title-icon" />
|
||||||
</graphic>
|
</graphic>
|
||||||
</Label>
|
</Label>
|
||||||
<Label text="If you are running your own Bitcoin Core node, you can configure Sparrow to connect to it directly. " wrapText="true" styleClass="content-text" />
|
<Label text="%welcome.step3.label1" wrapText="true" styleClass="content-text" />
|
||||||
<Label text="This means you are not sharing your transaction data, but be aware Bitcoin Core stores your balance, transactions and public keys unencrypted on that node, which is not ideal for true cold storage." wrapText="true" styleClass="content-text" />
|
<Label text="%welcome.step3.label2" wrapText="true" styleClass="content-text" />
|
||||||
<Label text="A green toggle means you are connected to a Bitcoin Core node." wrapText="true" styleClass="content-text" />
|
<Label text="%welcome.step3.label3" wrapText="true" styleClass="content-text" />
|
||||||
</VBox>
|
</VBox>
|
||||||
<VBox fx:id="step4" spacing="15">
|
<VBox fx:id="step4" spacing="15">
|
||||||
<Label text="Connecting to a Private Electrum Server" styleClass="title-text">
|
<Label text="%welcome.step4.introduction" styleClass="title-text">
|
||||||
<graphic>
|
<graphic>
|
||||||
<Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="20" icon="TOGGLE_ON" styleClass="title-icon" />
|
<Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="20" icon="TOGGLE_ON" styleClass="title-icon" />
|
||||||
</graphic>
|
</graphic>
|
||||||
</Label>
|
</Label>
|
||||||
<Label text="The most private way to connect is to your own Electrum server, which in turn connects to your Bitcoin Core node." wrapText="true" styleClass="content-text" />
|
<Label text="%welcome.step4.label1" wrapText="true" styleClass="content-text" />
|
||||||
<Label text="Because these servers index all Bitcoin transactions equally, your wallet transactions are never stored on the server in an identifiable way, and your server forgets your requests immediately after serving them." wrapText="true" styleClass="content-text" />
|
<Label text="%welcome.step4.label2" wrapText="true" styleClass="content-text" />
|
||||||
<Label text="A blue toggle means you are connected to a private Electrum server. You're now ready to configure a server and start using Sparrow!" wrapText="true" styleClass="content-text" />
|
<Label text="%welcome.step4.label3" wrapText="true" styleClass="content-text" />
|
||||||
</VBox>
|
</VBox>
|
||||||
<Region VBox.vgrow="ALWAYS" />
|
<Region VBox.vgrow="ALWAYS" />
|
||||||
<StatusBar fx:id="serverStatus">
|
<StatusBar fx:id="serverStatus">
|
||||||
|
|
57
src/main/resources/i18n/messages_en.properties
Normal file
57
src/main/resources/i18n/messages_en.properties
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
#welcome
|
||||||
|
welcome.title=Welcome to Sparrow
|
||||||
|
welcome.step1.introduction=Introduction
|
||||||
|
welcome.step1.label1=Sparrow is a Bitcoin wallet with a focus on security and usability.
|
||||||
|
welcome.step1.label2=Sparrow can operate in both an online and offline mode. In the online mode it connects to a server to display transaction history. In the offline mode it is useful as a transaction editor and as an airgapped multisig coordinator.
|
||||||
|
welcome.step1.label3=The status bar at the bottom displays the connection status, as demonstrated below:
|
||||||
|
welcome.step2.introduction=Connecting to a Public Server
|
||||||
|
welcome.step2.label1=If you are beginning your journey in self custody, or just storing a small amount, the easiest way to connect Sparrow to the Bitcoin blockchain is via one of the preconfigured public Electrum servers.
|
||||||
|
welcome.step2.label2=However, although Sparrow only connects to servers that have a record of respecting privacy, it is still not ideal as you are sharing your transaction history and balance with them.
|
||||||
|
welcome.step2.label3=A yellow toggle means you are connected to a public server.
|
||||||
|
welcome.step3.introduction=Connecting to a Bitcoin Core node
|
||||||
|
welcome.step3.label1=If you are running your own Bitcoin Core node, you can configure Sparrow to connect to it directly.
|
||||||
|
welcome.step3.label2=This means you are not sharing your transaction data, but be aware Bitcoin Core stores your balance, transactions and public keys unencrypted on that node, which is not ideal for true cold storage.
|
||||||
|
welcome.step3.label3=A green toggle means you are connected to a Bitcoin Core node.
|
||||||
|
welcome.step4.introduction=Connecting to a Private Electrum Server
|
||||||
|
welcome.step4.label1=The most private way to connect is to your own Electrum server, which in turn connects to your Bitcoin Core node.
|
||||||
|
welcome.step4.label2=Because these servers index all Bitcoin transactions equally, your wallet transactions are never stored on the server in an identifiable way, and your server forgets your requests immediately after serving them.
|
||||||
|
welcome.step4.label3=A blue toggle means you are connected to a private Electrum server. You're now ready to configure a server and start using Sparrow!
|
||||||
|
welcome.offline=Offline
|
||||||
|
welcome.offline.tooltip=Demonstration only - you are not connected!
|
||||||
|
welcome.server-status.online=Connected (demonstration only)
|
||||||
|
welcome.server-status.online.public-server=Connected to a Public Server (demonstration only)
|
||||||
|
welcome.server-status.online.bitcoin-core=Connected to Bitcoin Core (demonstration only)
|
||||||
|
welcome.server-status.online.private-electrum=Connected to a Private Electrum Server (demonstration only)
|
||||||
|
welcome.next=Next
|
||||||
|
welcome.back=Back
|
||||||
|
welcome.configure-server=Configure Server
|
||||||
|
welcome.done=Done
|
||||||
|
welcome.configure-later=Later or Offline Mode
|
||||||
|
|
||||||
|
# wallet transactions
|
||||||
|
wallet.transactions=Transactions
|
||||||
|
wallet.transactions.balance=Balance:
|
||||||
|
wallet.transactions.transactions=Transactions:
|
||||||
|
wallet.transactions.csv-export=Export transactions as CSV
|
||||||
|
wallet.transactions.csv-export.error=Error exporting transactions as CSV
|
||||||
|
wallet.transactions.loading-history=Wallet loading history for
|
||||||
|
wallet.transactions.loading-finish=Finished loading.
|
||||||
|
wallet.transactions.loading-transactions=Loading transactions for
|
||||||
|
wallet.transactions.finding-transactions=Finding transactions for
|
||||||
|
wallet.transactions.retrieving=Retrieving
|
||||||
|
wallet.transactions.retrieving-transactions=transactions
|
||||||
|
wallet.transactions.retrieving-headers=block headers
|
||||||
|
wallet.transactions.retrieving-block-height=Retrieving block at height
|
||||||
|
wallet.transactions.retrieving-transaction=Retrieving transaction
|
||||||
|
wallet.transactions.table.date=Date
|
||||||
|
wallet.transactions.table.label=Label
|
||||||
|
wallet.transactions.table.value=Value
|
||||||
|
wallet.transactions.table.balance=Balance
|
||||||
|
wallet.transactions.table.loading=Loading transactions...
|
||||||
|
wallet.transactions.table.loading.error=Error loading transactions:
|
||||||
|
wallet.transactions.table.no-transactions=No transactions
|
||||||
|
|
||||||
|
# settings
|
||||||
|
language=Language
|
||||||
|
language.en=English
|
||||||
|
language.es=Spanish
|
57
src/main/resources/i18n/messages_es.properties
Normal file
57
src/main/resources/i18n/messages_es.properties
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
#welcome
|
||||||
|
welcome.title=Bienvenido a Sparrow
|
||||||
|
welcome.step1.introduction=Introducción
|
||||||
|
welcome.step1.label1=Sparrow es una billetera de Bitcoin con un enfoque en la seguridad y la facilidad de uso.
|
||||||
|
welcome.step1.label2=Sparrow puede operar tanto en modo en línea como fuera de línea. En el modo en línea, se conecta a un servidor para mostrar el historial de transacciones. En el modo fuera de línea, es útil como editor de transacciones y como coordinador multisig desconectado.
|
||||||
|
welcome.step1.label3=La barra de estado en la parte inferior muestra el estado de la conexión, como se muestra a continuación:
|
||||||
|
welcome.step2.introduction=Conexión a un servidor público
|
||||||
|
welcome.step2.label1=Si estás comenzando tu camino en la auto custodia o solo almacenando una pequeña cantidad, la forma más fácil de conectar Sparrow a la blockchain de Bitcoin es a través de uno de los servidores públicos de Electrum preconfigurados.
|
||||||
|
welcome.step2.label2=Sin embargo, aunque Sparrow solo se conecta a servidores que tienen un historial de respetar la privacidad, aún no es lo ideal ya que estás compartiendo tu historial de transacciones y tu saldo con ellos.
|
||||||
|
welcome.step2.label3=Un interruptor amarillo significa que estás conectado a un servidor público.
|
||||||
|
welcome.step3.introduction=Conexión a un nodo de Bitcoin Core
|
||||||
|
welcome.step3.label1=Si estás ejecutando tu propio nodo de Bitcoin Core, puedes configurar Sparrow para que se conecte directamente a él.
|
||||||
|
welcome.step3.label2=Esto significa que no estás compartiendo tus datos de transacciones, pero ten en cuenta que Bitcoin Core almacena tu saldo, transacciones y claves públicas sin cifrar en ese nodo, lo cual no es ideal para un almacenamiento en frío verdadero.
|
||||||
|
welcome.step3.label3=Un interruptor verde significa que estás conectado a un nodo de Bitcoin Core.
|
||||||
|
welcome.step4.introduction=Conexión a un servidor privado de Electrum
|
||||||
|
welcome.step4.label1=La forma más privada de conectarse es a tu propio servidor de Electrum, que a su vez se conecta a tu nodo de Bitcoin Core.
|
||||||
|
welcome.step4.label2=Dado que estos servidores indexan todas las transacciones de Bitcoin por igual, las transacciones de tu billetera nunca se almacenan en el servidor de manera identificable, y tu servidor olvida tus solicitudes inmediatamente después de servirlas.
|
||||||
|
welcome.step4.label3=Un interruptor azul significa que estás conectado a un servidor privado de Electrum. ¡Ahora estás listo para configurar un servidor y empezar a usar Sparrow!
|
||||||
|
welcome.offline=Desconectado
|
||||||
|
welcome.offline.tooltip=Sólo demostración - ¡no estás conectado!
|
||||||
|
welcome.server-status.online=Conectado (sólo demostración)
|
||||||
|
welcome.server-status.online.public-server=Conectado a un Servidor Público (sólo demostración)
|
||||||
|
welcome.server-status.online.bitcoin-core=Conectado a Bitcoin Core (sólo demostración)
|
||||||
|
welcome.server-status.online.private-electrum=Conectado a un Servidor Privado Electrum (sólo demostración)
|
||||||
|
welcome.next=Siguiente
|
||||||
|
welcome.back=Anterior
|
||||||
|
welcome.configure-server=Configurar Servidor
|
||||||
|
welcome.done=Hecho
|
||||||
|
welcome.configure-later=Después o Modo Sin Conexción
|
||||||
|
|
||||||
|
# wallet transactions
|
||||||
|
wallet.transactions=Transacciones
|
||||||
|
wallet.transactions.balance=Saldo:
|
||||||
|
wallet.transactions.transactions=Transacciones:
|
||||||
|
wallet.transactions.csv-export=Exportar transacciones en CSV
|
||||||
|
wallet.transactions.csv-export.error=Error exportando transacciones a CSV
|
||||||
|
wallet.transactions.loading-history=Cargando historial de carga para la billetera
|
||||||
|
wallet.transactions.loading-finish=Carga terminada.
|
||||||
|
wallet.transactions.loading-transactions=Cargando transacciones para
|
||||||
|
wallet.transactions.finding-transactions=Encontrando transacciones para
|
||||||
|
wallet.transactions.retrieving=Recuperando
|
||||||
|
wallet.transactions.retrieving-transactions=transacciones
|
||||||
|
wallet.transactions.retrieving-headers=cabeceras de bloque
|
||||||
|
wallet.transactions.retrieving-block-height=Recuperando bloque en altura
|
||||||
|
wallet.transactions.retrieving-transaction=Recuperando transacción
|
||||||
|
wallet.transactions.table.date=Fecha
|
||||||
|
wallet.transactions.table.label=Etiqueta
|
||||||
|
wallet.transactions.table.value=Valor
|
||||||
|
wallet.transactions.table.balance=Saldo
|
||||||
|
wallet.transactions.table.loading=Cargando transacciones...
|
||||||
|
wallet.transactions.table.loading.error=Error cargando transacciones:
|
||||||
|
wallet.transactions.table.no-transactions=Sin transacciones
|
||||||
|
|
||||||
|
# settings
|
||||||
|
language=Idioma
|
||||||
|
language.en=Inglés
|
||||||
|
language.es=Español
|
Loading…
Reference in a new issue