From c6016ec7b23634df98ef03af1addd5f8e24b1728 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Sat, 16 Apr 2016 14:10:32 +0200 Subject: [PATCH 01/15] using constructor-injection, organized imports, code autoformatting [ci skip] --- .../controllers/ChangePasswordController.java | 23 +-- .../ui/controllers/InitializeController.java | 50 +++-- .../ui/util/PasswordStrengthUtil.java | 175 +++++++++--------- 3 files changed, 120 insertions(+), 128 deletions(-) diff --git a/main/ui/src/main/java/org/cryptomator/ui/controllers/ChangePasswordController.java b/main/ui/src/main/java/org/cryptomator/ui/controllers/ChangePasswordController.java index 2b5e644c9..aff40e587 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/controllers/ChangePasswordController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/controllers/ChangePasswordController.java @@ -12,21 +12,11 @@ package org.cryptomator.ui.controllers; import java.io.IOException; import java.io.UncheckedIOException; import java.net.URL; -import java.util.ArrayList; -import java.util.List; import java.util.Optional; import javax.inject.Inject; import javax.inject.Singleton; -import com.nulabinc.zxcvbn.Strength; -import com.nulabinc.zxcvbn.Zxcvbn; -import javafx.beans.property.IntegerProperty; -import javafx.beans.property.SimpleIntegerProperty; -import javafx.scene.control.Label; -import javafx.scene.paint.Color; -import javafx.scene.shape.Rectangle; -import org.apache.commons.lang3.StringUtils; import org.cryptomator.crypto.engine.InvalidPassphraseException; import org.cryptomator.crypto.engine.UnsupportedVaultFormatException; import org.cryptomator.ui.controls.SecPasswordField; @@ -40,12 +30,16 @@ import org.slf4j.LoggerFactory; import javafx.application.Application; import javafx.application.Platform; import javafx.beans.binding.BooleanBinding; +import javafx.beans.property.IntegerProperty; import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleIntegerProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.control.Button; import javafx.scene.control.Hyperlink; +import javafx.scene.control.Label; +import javafx.scene.shape.Rectangle; import javafx.scene.text.Text; @Singleton @@ -54,19 +48,18 @@ public class ChangePasswordController extends LocalizedFXMLViewController { private static final Logger LOG = LoggerFactory.getLogger(ChangePasswordController.class); private final Application app; + private final PasswordStrengthUtil strengthRater; final ObjectProperty vault = new SimpleObjectProperty<>(); private Optional listener = Optional.empty(); - final IntegerProperty passwordStrength = new SimpleIntegerProperty(); // 0-4 + private final IntegerProperty passwordStrength = new SimpleIntegerProperty(); // 0-4 @Inject - public ChangePasswordController(Application app, Localization localization) { + public ChangePasswordController(Application app, PasswordStrengthUtil strengthRater, Localization localization) { super(localization); this.app = app; + this.strengthRater = strengthRater; } - @Inject - PasswordStrengthUtil strengthRater; - @FXML private SecPasswordField oldPasswordField; diff --git a/main/ui/src/main/java/org/cryptomator/ui/controllers/InitializeController.java b/main/ui/src/main/java/org/cryptomator/ui/controllers/InitializeController.java index 0a87c4fd6..a0fb0baf9 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/controllers/InitializeController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/controllers/InitializeController.java @@ -9,16 +9,15 @@ ******************************************************************************/ package org.cryptomator.ui.controllers; -import javafx.application.Platform; -import javafx.beans.binding.BooleanBinding; -import javafx.beans.property.*; -import javafx.event.ActionEvent; -import javafx.fxml.FXML; -import javafx.scene.control.Button; -import javafx.scene.control.Label; -import javafx.scene.paint.Color; -import javafx.scene.shape.Rectangle; -import org.apache.commons.lang3.StringUtils; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.URL; +import java.nio.file.FileAlreadyExistsException; +import java.util.Optional; + +import javax.inject.Inject; +import javax.inject.Singleton; + import org.cryptomator.ui.controls.SecPasswordField; import org.cryptomator.ui.model.Vault; import org.cryptomator.ui.settings.Localization; @@ -27,35 +26,34 @@ import org.fxmisc.easybind.EasyBind; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.inject.Inject; -import javax.inject.Singleton; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.net.URL; -import java.nio.file.FileAlreadyExistsException; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -import com.nulabinc.zxcvbn.*; +import javafx.application.Platform; +import javafx.beans.binding.BooleanBinding; +import javafx.beans.property.IntegerProperty; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleIntegerProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.shape.Rectangle; @Singleton public class InitializeController extends LocalizedFXMLViewController { private static final Logger LOG = LoggerFactory.getLogger(InitializeController.class); + private final PasswordStrengthUtil strengthRater; final ObjectProperty vault = new SimpleObjectProperty<>(); private Optional listener = Optional.empty(); - final IntegerProperty passwordStrength = new SimpleIntegerProperty(); // 0-4 + private final IntegerProperty passwordStrength = new SimpleIntegerProperty(); // 0-4 @Inject - public InitializeController(Localization localization) { + public InitializeController(Localization localization, PasswordStrengthUtil strengthRater) { super(localization); + this.strengthRater = strengthRater; } - @Inject - PasswordStrengthUtil strengthRater; - @FXML private SecPasswordField passwordField; diff --git a/main/ui/src/main/java/org/cryptomator/ui/util/PasswordStrengthUtil.java b/main/ui/src/main/java/org/cryptomator/ui/util/PasswordStrengthUtil.java index fe6af2f61..bc24b415c 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/util/PasswordStrengthUtil.java +++ b/main/ui/src/main/java/org/cryptomator/ui/util/PasswordStrengthUtil.java @@ -8,105 +8,106 @@ *******************************************************************************/ package org.cryptomator.ui.util; -import com.nulabinc.zxcvbn.Zxcvbn; -import javafx.beans.property.IntegerProperty; -import javafx.scene.paint.Color; -import org.apache.commons.lang3.StringUtils; -import org.cryptomator.ui.settings.Localization; +import java.util.ArrayList; +import java.util.List; import javax.inject.Inject; import javax.inject.Singleton; -import java.util.ArrayList; -import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.cryptomator.ui.settings.Localization; + +import com.nulabinc.zxcvbn.Zxcvbn; + +import javafx.scene.paint.Color; @Singleton public class PasswordStrengthUtil { - private final Zxcvbn zxcvbn; - private final List sanitizedInputs; - private final Localization localization; + private final Zxcvbn zxcvbn; + private final List sanitizedInputs; + private final Localization localization; - @Inject - public PasswordStrengthUtil(Localization localization){ - this.localization = localization; - this.zxcvbn = new Zxcvbn(); - this.sanitizedInputs = new ArrayList<>(); - this.sanitizedInputs.add("cryptomator"); - } + @Inject + public PasswordStrengthUtil(Localization localization) { + this.localization = localization; + this.zxcvbn = new Zxcvbn(); + this.sanitizedInputs = new ArrayList<>(); + this.sanitizedInputs.add("cryptomator"); + } - public int computeRate(String password) { - if (StringUtils.isEmpty(password)) { - return -1; - } else { - return zxcvbn.measure(password, sanitizedInputs).getScore(); - } - } + public int computeRate(String password) { + if (StringUtils.isEmpty(password)) { + return -1; + } else { + return zxcvbn.measure(password, sanitizedInputs).getScore(); + } + } - public Color getStrengthColor(Number score) { - Color strengthColor = Color.web("#FF0000"); - switch (score.intValue()) { - case 0: - strengthColor = Color.web("#FF0000"); - break; - case 1: - strengthColor = Color.web("#FF8000"); - break; - case 2: - strengthColor = Color.web("#FFBF00"); - break; - case 3: - strengthColor = Color.web("#FFFF00"); - break; - case 4: - strengthColor = Color.web("#BFFF00"); - break; - default: - strengthColor = Color.web("#FF0000"); - break; - } - return strengthColor; - } + public Color getStrengthColor(Number score) { + Color strengthColor = Color.web("#FF0000"); + switch (score.intValue()) { + case 0: + strengthColor = Color.web("#FF0000"); + break; + case 1: + strengthColor = Color.web("#FF8000"); + break; + case 2: + strengthColor = Color.web("#FFBF00"); + break; + case 3: + strengthColor = Color.web("#FFFF00"); + break; + case 4: + strengthColor = Color.web("#BFFF00"); + break; + default: + strengthColor = Color.web("#FF0000"); + break; + } + return strengthColor; + } - public int getWidth(Number score) { - int width = 0; - switch (score.intValue()) { - case 0: - width += 5; - break; - case 1: - width += 25; - break; - case 2: - width += 50; - break; - case 3: - width += 75; - break; - case 4: - width = 100; - break; - default: - width = 0; - break; - } - return Math.round(width*2.23f); - } + public int getWidth(Number score) { + int width = 0; + switch (score.intValue()) { + case 0: + width += 5; + break; + case 1: + width += 25; + break; + case 2: + width += 50; + break; + case 3: + width += 75; + break; + case 4: + width = 100; + break; + default: + width = 0; + break; + } + return Math.round(width * 2.23f); + } - public float getStrokeWidth(Number score) { - if (score.intValue() >= 0) { - return 0.5f; - } else { - return 0; - } - } + public float getStrokeWidth(Number score) { + if (score.intValue() >= 0) { + return 0.5f; + } else { + return 0; + } + } - public String getStrengthDescription(Number score) { - if (score.intValue() >= 0) { - return String.format(localization.getString("initialize.messageLabel.passwordStrength"), - localization.getString("initialize.messageLabel.passwordStrength." + score.intValue())); - } else { - return ""; - } - } + public String getStrengthDescription(Number score) { + if (score.intValue() >= 0) { + return String.format(localization.getString("initialize.messageLabel.passwordStrength"), localization.getString("initialize.messageLabel.passwordStrength." + score.intValue())); + } else { + return ""; + } + } } From c02a63878ef366c0f82778dd1dac3e808099fcdc Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Wed, 27 Apr 2016 01:14:41 +0200 Subject: [PATCH 02/15] new method to calculate test coverage (across modules) --- main/commons/pom.xml | 9 ++++ main/jacoco-report/.gitignore | 1 + main/jacoco-report/pom.xml | 82 +++++++++++++++++++++++++++++++++++ main/pom.xml | 33 +++++++++++++- 4 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 main/jacoco-report/.gitignore create mode 100644 main/jacoco-report/pom.xml diff --git a/main/commons/pom.xml b/main/commons/pom.xml index 81ef3d6ef..5d7b53e9f 100644 --- a/main/commons/pom.xml +++ b/main/commons/pom.xml @@ -43,4 +43,13 @@ test + + + + + org.jacoco + jacoco-maven-plugin + + + diff --git a/main/jacoco-report/.gitignore b/main/jacoco-report/.gitignore new file mode 100644 index 000000000..b83d22266 --- /dev/null +++ b/main/jacoco-report/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/main/jacoco-report/pom.xml b/main/jacoco-report/pom.xml new file mode 100644 index 000000000..97a4411aa --- /dev/null +++ b/main/jacoco-report/pom.xml @@ -0,0 +1,82 @@ + + + + 4.0.0 + + org.cryptomator + main + 1.1.0-SNAPSHOT + + jacoco-report + Cryptomator Code Coverage Report + + + + + org.cryptomator + commons + + + org.cryptomator + commons-test + + + + + org.cryptomator + filesystem-api + + + org.cryptomator + filesystem-crypto + + + org.cryptomator + filesystem-crypto-integration-tests + + + org.cryptomator + filesystem-inmemory + + + org.cryptomator + filesystem-nameshortening + + + org.cryptomator + filesystem-nio + + + org.cryptomator + filesystem-stats + + + + + org.cryptomator + frontend-api + + + org.cryptomator + frontend-webdav + + + + + + + org.jacoco + jacoco-maven-plugin + + + report-aggregate + verify + + report-aggregate + + + + + + + \ No newline at end of file diff --git a/main/pom.xml b/main/pom.xml index abcdf6abc..12de27cb6 100644 --- a/main/pom.xml +++ b/main/pom.xml @@ -49,6 +49,16 @@ https://jitpack.io + + + + jacoco-snapshots + https://oss.sonatype.org/content/repositories/snapshots + + true + + + @@ -81,6 +91,12 @@ ${project.version} test + + org.cryptomator + filesystem-invariants-tests + ${project.version} + test + org.cryptomator filesystem-nameshortening @@ -280,6 +296,12 @@ ant-kit + + test-coverage + + jacoco-report + + @@ -304,7 +326,7 @@ org.jacoco jacoco-maven-plugin - 0.7.5.201505241946 + 0.7.7-SNAPSHOT prepare-agent @@ -313,6 +335,12 @@ + + + **/*_* + **/Dagger* + + @@ -331,6 +359,9 @@ coveralls-maven-plugin 4.0.0 + + jacoco-report/target/site/jacoco-aggregate/jacoco.xml + ${env.COVERALLS_REPO_TOKEN} From 833f2d85667544fa2bbc528669e3e1f150f267cc Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Wed, 27 Apr 2016 01:18:37 +0200 Subject: [PATCH 03/15] fixed travis test coverage configuration --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ff30b781b..611045f47 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,7 @@ before_install: "curl -L --cookie 'oraclelicense=accept-securebackup-cookie;' ht script: mvn -fmain/pom.xml clean test -after_success: mvn -fmain/pom.xml clean test jacoco:report coveralls:report +after_success: mvn -fmain/pom.xml -Ptest-coverage clean test jacoco:report-aggregate coveralls:report notifications: webhooks: From f16be84aa37d19419573a2b16f43c5e30a1f9a69 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Mon, 2 May 2016 11:11:42 +0200 Subject: [PATCH 04/15] restored bash-based webdav mounting for OS X before 10.10 (issue #211 - to be tested) --- main/commons/pom.xml | 19 +++- .../org/cryptomator/common/CommonsModule.java | 21 +++++ .../cryptomator/common}/SemVerComparator.java | 2 +- .../common}/SemVerComparatorTest.java | 3 +- .../frontend/webdav/WebDavComponent.java | 4 +- ...va => MacOsXAppleScriptWebDavMounter.java} | 11 ++- .../mount/MacOsXShellScriptWebDavMounter.java | 89 +++++++++++++++++++ .../webdav/mount/MountStrategies.java | 25 ++++-- .../webdav/mount/WindowsWebDavMounter.java | 13 ++- main/pom.xml | 4 +- .../org/cryptomator/ui/CryptomatorModule.java | 12 +-- 11 files changed, 171 insertions(+), 32 deletions(-) create mode 100644 main/commons/src/main/java/org/cryptomator/common/CommonsModule.java rename main/{ui/src/main/java/org/cryptomator/ui/util => commons/src/main/java/org/cryptomator/common}/SemVerComparator.java (97%) rename main/{ui/src/test/java/org/cryptomator/ui/util => commons/src/test/java/org/cryptomator/common}/SemVerComparatorTest.java (95%) rename main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/{MacOsXWebDavMounter.java => MacOsXAppleScriptWebDavMounter.java} (91%) create mode 100644 main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MacOsXShellScriptWebDavMounter.java diff --git a/main/commons/pom.xml b/main/commons/pom.xml index 5d7b53e9f..5603f36b5 100644 --- a/main/commons/pom.xml +++ b/main/commons/pom.xml @@ -17,11 +17,28 @@ Shared utilities + com.google.guava guava - + + org.apache.commons + commons-lang3 + + + + + com.google.dagger + dagger + + + com.google.dagger + dagger-compiler + provided + + + junit junit diff --git a/main/commons/src/main/java/org/cryptomator/common/CommonsModule.java b/main/commons/src/main/java/org/cryptomator/common/CommonsModule.java new file mode 100644 index 000000000..d56d22f80 --- /dev/null +++ b/main/commons/src/main/java/org/cryptomator/common/CommonsModule.java @@ -0,0 +1,21 @@ +package org.cryptomator.common; + +import java.util.Comparator; + +import javax.inject.Named; +import javax.inject.Singleton; + +import dagger.Module; +import dagger.Provides; + +@Module +public class CommonsModule { + + @Provides + @Singleton + @Named("SemVer") + Comparator providesSemVerComparator() { + return new SemVerComparator(); + } + +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/util/SemVerComparator.java b/main/commons/src/main/java/org/cryptomator/common/SemVerComparator.java similarity index 97% rename from main/ui/src/main/java/org/cryptomator/ui/util/SemVerComparator.java rename to main/commons/src/main/java/org/cryptomator/common/SemVerComparator.java index b9031b471..930e2e93d 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/util/SemVerComparator.java +++ b/main/commons/src/main/java/org/cryptomator/common/SemVerComparator.java @@ -6,7 +6,7 @@ * Contributors: * Sebastian Stenzel - initial API and implementation *******************************************************************************/ -package org.cryptomator.ui.util; +package org.cryptomator.common; import java.util.Comparator; diff --git a/main/ui/src/test/java/org/cryptomator/ui/util/SemVerComparatorTest.java b/main/commons/src/test/java/org/cryptomator/common/SemVerComparatorTest.java similarity index 95% rename from main/ui/src/test/java/org/cryptomator/ui/util/SemVerComparatorTest.java rename to main/commons/src/test/java/org/cryptomator/common/SemVerComparatorTest.java index a505d0af4..859eb9471 100644 --- a/main/ui/src/test/java/org/cryptomator/ui/util/SemVerComparatorTest.java +++ b/main/commons/src/test/java/org/cryptomator/common/SemVerComparatorTest.java @@ -6,10 +6,11 @@ * Contributors: * Sebastian Stenzel - initial API and implementation *******************************************************************************/ -package org.cryptomator.ui.util; +package org.cryptomator.common; import java.util.Comparator; +import org.cryptomator.common.SemVerComparator; import org.junit.Assert; import org.junit.Test; diff --git a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavComponent.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavComponent.java index 9f6c5dbff..68f1a43e7 100644 --- a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavComponent.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavComponent.java @@ -10,10 +10,12 @@ package org.cryptomator.frontend.webdav; import javax.inject.Singleton; +import org.cryptomator.common.CommonsModule; + import dagger.Component; @Singleton -@Component +@Component(modules = {CommonsModule.class}) public interface WebDavComponent { WebDavServer server(); diff --git a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MacOsXWebDavMounter.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MacOsXAppleScriptWebDavMounter.java similarity index 91% rename from main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MacOsXWebDavMounter.java rename to main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MacOsXAppleScriptWebDavMounter.java index 0acf2ddee..f381e2e6f 100644 --- a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MacOsXWebDavMounter.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MacOsXAppleScriptWebDavMounter.java @@ -12,11 +12,13 @@ package org.cryptomator.frontend.webdav.mount; import java.io.IOException; import java.net.URI; import java.nio.charset.StandardCharsets; +import java.util.Comparator; import java.util.Map; import java.util.Optional; import java.util.concurrent.TimeUnit; import javax.inject.Inject; +import javax.inject.Named; import javax.inject.Singleton; import org.apache.commons.io.IOUtils; @@ -26,15 +28,18 @@ import org.cryptomator.frontend.CommandFailedException; import org.cryptomator.frontend.Frontend.MountParam; @Singleton -final class MacOsXWebDavMounter implements WebDavMounterStrategy { +final class MacOsXAppleScriptWebDavMounter implements WebDavMounterStrategy { + + private final Comparator semVerComparator; @Inject - MacOsXWebDavMounter() { + MacOsXAppleScriptWebDavMounter(@Named("SemVer") Comparator semVerComparator) { + this.semVerComparator = semVerComparator; } @Override public boolean shouldWork() { - return SystemUtils.IS_OS_MAC_OSX; + return SystemUtils.IS_OS_MAC_OSX && semVerComparator.compare(SystemUtils.OS_VERSION, "10.10") >= 0; } @Override diff --git a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MacOsXShellScriptWebDavMounter.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MacOsXShellScriptWebDavMounter.java new file mode 100644 index 000000000..89e8a86a2 --- /dev/null +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MacOsXShellScriptWebDavMounter.java @@ -0,0 +1,89 @@ +/******************************************************************************* + * Copyright (c) 2014, 2016 Sebastian Stenzel, Markus Kreusch + * This file is licensed under the terms of the MIT license. + * See the LICENSE.txt file for more info. + * + * Contributors: + * Sebastian Stenzel - initial API and implementation, strategy fine tuning + * Markus Kreusch - Refactored WebDavMounter to use strategy pattern + ******************************************************************************/ +package org.cryptomator.frontend.webdav.mount; + +import java.net.URI; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.util.Comparator; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.apache.commons.lang3.SystemUtils; +import org.cryptomator.frontend.CommandFailedException; +import org.cryptomator.frontend.Frontend.MountParam; +import org.cryptomator.frontend.webdav.mount.command.Script; + +@Singleton +final class MacOsXShellScriptWebDavMounter implements WebDavMounterStrategy { + + private final Comparator semVerComparator; + + @Inject + MacOsXShellScriptWebDavMounter(@Named("SemVer") Comparator semVerComparator) { + this.semVerComparator = semVerComparator; + } + + @Override + public boolean shouldWork() { + return SystemUtils.IS_OS_MAC_OSX && semVerComparator.compare(SystemUtils.OS_VERSION, "10.10") < 0; + } + + @Override + public void warmUp(int serverPort) { + // no-op + } + + @Override + public WebDavMount mount(URI uri, Map> mountParams) throws CommandFailedException { + final String mountName = mountParams.getOrDefault(MountParam.MOUNT_NAME, Optional.empty()).orElseThrow(() -> { + return new IllegalArgumentException("Missing mount parameter MOUNT_NAME."); + }); + + // we don't use the uri to derive a path, as it *could* be longer than 255 chars. + final String path = "/Volumes/Cryptomator_" + UUID.randomUUID().toString(); + final Script mountScript = Script.fromLines("mkdir \"$MOUNT_PATH\"", "mount_webdav -S -v $MOUNT_NAME \"$DAV_AUTHORITY$DAV_PATH\" \"$MOUNT_PATH\"").addEnv("DAV_AUTHORITY", uri.getRawAuthority()) + .addEnv("DAV_PATH", uri.getRawPath()).addEnv("MOUNT_PATH", path).addEnv("MOUNT_NAME", mountName); + mountScript.execute(); + return new MacWebDavMount(path); + } + + private static class MacWebDavMount extends AbstractWebDavMount { + private final String mountPath; + private final Script revealScript; + private final Script unmountScript; + + private MacWebDavMount(String mountPath) { + this.mountPath = mountPath; + this.revealScript = Script.fromLines("open \"$MOUNT_PATH\"").addEnv("MOUNT_PATH", mountPath); + this.unmountScript = Script.fromLines("diskutil umount $MOUNT_PATH").addEnv("MOUNT_PATH", mountPath); + } + + @Override + public void unmount() throws CommandFailedException { + // only attempt unmount if user didn't unmount manually: + if (Files.exists(FileSystems.getDefault().getPath(mountPath))) { + unmountScript.execute(); + } + } + + @Override + public void reveal() throws CommandFailedException { + revealScript.execute(); + } + + } + +} diff --git a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MountStrategies.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MountStrategies.java index edb5645fa..3cd1b2a08 100644 --- a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MountStrategies.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MountStrategies.java @@ -19,74 +19,87 @@ import javax.inject.Singleton; @Singleton class MountStrategies implements Collection { - + private final Collection delegate; - + @Inject - MountStrategies(LinuxGvfsWebDavMounter linuxMounter, MacOsXWebDavMounter osxMounter, WindowsWebDavMounter winMounter) { - delegate = unmodifiableList(asList(linuxMounter, osxMounter, winMounter)); + MountStrategies(LinuxGvfsWebDavMounter linuxMounter, MacOsXAppleScriptWebDavMounter osxAppleScriptMounter, MacOsXShellScriptWebDavMounter osxShellScriptMounter, WindowsWebDavMounter winMounter) { + delegate = unmodifiableList(asList(linuxMounter, osxAppleScriptMounter, osxShellScriptMounter, winMounter)); } + @Override public int size() { return delegate.size(); } + @Override public boolean isEmpty() { return delegate.isEmpty(); } + @Override public boolean contains(Object o) { return delegate.contains(o); } + @Override public Iterator iterator() { return delegate.iterator(); } + @Override public Object[] toArray() { return delegate.toArray(); } + @Override public T[] toArray(T[] a) { return delegate.toArray(a); } + @Override public boolean add(WebDavMounterStrategy e) { return delegate.add(e); } + @Override public boolean remove(Object o) { return delegate.remove(o); } + @Override public boolean containsAll(Collection c) { return delegate.containsAll(c); } + @Override public boolean addAll(Collection c) { return delegate.addAll(c); } + @Override public boolean removeAll(Collection c) { return delegate.removeAll(c); } + @Override public boolean retainAll(Collection c) { return delegate.retainAll(c); } + @Override public void clear() { delegate.clear(); } + @Override public boolean equals(Object o) { return delegate.equals(o); } + @Override public int hashCode() { return delegate.hashCode(); } - - } diff --git a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WindowsWebDavMounter.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WindowsWebDavMounter.java index a2a257a61..4136fd2bf 100644 --- a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WindowsWebDavMounter.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WindowsWebDavMounter.java @@ -60,12 +60,12 @@ final class WindowsWebDavMounter implements WebDavMounterStrategy { @Override public WebDavMount mount(URI uri, Map> mountParams) throws CommandFailedException { - final String driveLetter = mountParams.getOrDefault(MountParam.WIN_DRIVE_LETTER, Optional.of(AUTO_ASSIGN_DRIVE_LETTER)).orElse(AUTO_ASSIGN_DRIVE_LETTER); + final String driveLetter = mountParams.getOrDefault(MountParam.WIN_DRIVE_LETTER, Optional.empty()).orElse(AUTO_ASSIGN_DRIVE_LETTER); if (driveLetters.getOccupiedDriveLetters().contains(CharUtils.toChar(driveLetter))) { throw new CommandFailedException("Drive letter occupied."); } - - final String hostname = mountParams.getOrDefault(MountParam.HOSTNAME, Optional.of(LOCALHOST)).orElse(LOCALHOST); + + final String hostname = mountParams.getOrDefault(MountParam.HOSTNAME, Optional.empty()).orElse(LOCALHOST); try { final URI adjustedUri = new URI(uri.getScheme(), uri.getUserInfo(), hostname, uri.getPort(), uri.getPath(), uri.getQuery(), uri.getFragment()); CommandResult mountResult = mount(adjustedUri, driveLetter); @@ -74,14 +74,13 @@ final class WindowsWebDavMounter implements WebDavMounterStrategy { throw new IllegalArgumentException("Invalid host: " + hostname); } } - + private CommandResult mount(URI uri, String driveLetter) throws CommandFailedException { - final Script proxyBypassScript = fromLines( - "reg add \"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\" /v \"ProxyOverride\" /d \";%DAV_HOST%;%DAV_HOST%:%DAV_PORT%\" /f"); + final Script proxyBypassScript = fromLines("reg add \"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\" /v \"ProxyOverride\" /d \";%DAV_HOST%;%DAV_HOST%:%DAV_PORT%\" /f"); proxyBypassScript.addEnv("DAV_HOST", uri.getHost()); proxyBypassScript.addEnv("DAV_PORT", String.valueOf(uri.getPort())); proxyBypassScript.execute(); - + final String driveLetterStr = AUTO_ASSIGN_DRIVE_LETTER.equals(driveLetter) ? AUTO_ASSIGN_DRIVE_LETTER : driveLetter + ":"; final Script mountScript = fromLines("net use %DRIVE_LETTER% \\\\%DAV_HOST%@%DAV_PORT%\\DavWWWRoot%DAV_UNC_PATH% /persistent:no"); mountScript.addEnv("DRIVE_LETTER", driveLetterStr); diff --git a/main/pom.xml b/main/pom.xml index 12de27cb6..1aac82079 100644 --- a/main/pom.xml +++ b/main/pom.xml @@ -35,12 +35,12 @@ 1.3 2.4 4.0 - 3.3.2 + 3.4 1.10 3.1 2.4.4 1.10.19 - 2.0.2 + 2.4 diff --git a/main/ui/src/main/java/org/cryptomator/ui/CryptomatorModule.java b/main/ui/src/main/java/org/cryptomator/ui/CryptomatorModule.java index fa432cc9d..3740b566d 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/CryptomatorModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/CryptomatorModule.java @@ -8,13 +8,13 @@ *******************************************************************************/ package org.cryptomator.ui; -import java.util.Comparator; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import javax.inject.Named; import javax.inject.Singleton; +import org.cryptomator.common.CommonsModule; import org.cryptomator.crypto.engine.impl.CryptoEngineModule; import org.cryptomator.frontend.FrontendFactory; import org.cryptomator.frontend.webdav.WebDavServer; @@ -24,7 +24,6 @@ import org.cryptomator.ui.model.VaultObjectMapperProvider; import org.cryptomator.ui.settings.Settings; import org.cryptomator.ui.settings.SettingsProvider; import org.cryptomator.ui.util.DeferredCloser; -import org.cryptomator.ui.util.SemVerComparator; import com.fasterxml.jackson.databind.ObjectMapper; @@ -33,7 +32,7 @@ import dagger.Provides; import javafx.application.Application; import javafx.stage.Stage; -@Module(includes = CryptoEngineModule.class) +@Module(includes = {CryptoEngineModule.class, CommonsModule.class}) class CryptomatorModule { private final Application application; @@ -65,13 +64,6 @@ class CryptomatorModule { return closer; } - @Provides - @Singleton - @Named("SemVer") - Comparator provideSemVerComparator() { - return new SemVerComparator(); - } - @Provides @Singleton @Named("VaultJsonMapper") From d4235174f76c37aabd955d7ac7d0be4a7f21dbc1 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Mon, 2 May 2016 11:37:40 +0200 Subject: [PATCH 05/15] imported localizations from POEditor fixes #231 and #234 (ci skip) --- .../main/resources/localization_de.properties | 59 +++---- .../main/resources/localization_es.properties | 84 +++++++++- .../main/resources/localization_fr.properties | 148 ++++++++---------- .../main/resources/localization_hu.properties | 84 ++++++++++ .../main/resources/localization_it.properties | 84 ++++++++++ .../main/resources/localization_pt.properties | 34 ++++ .../main/resources/localization_ru.properties | 55 +++++++ .../main/resources/localization_sk.properties | 85 ++++++++++ 8 files changed, 526 insertions(+), 107 deletions(-) create mode 100644 main/ui/src/main/resources/localization_hu.properties create mode 100644 main/ui/src/main/resources/localization_it.properties create mode 100644 main/ui/src/main/resources/localization_pt.properties create mode 100644 main/ui/src/main/resources/localization_ru.properties create mode 100644 main/ui/src/main/resources/localization_sk.properties diff --git a/main/ui/src/main/resources/localization_de.properties b/main/ui/src/main/resources/localization_de.properties index 12bee9c0f..a9b0ad58c 100644 --- a/main/ui/src/main/resources/localization_de.properties +++ b/main/ui/src/main/resources/localization_de.properties @@ -3,20 +3,24 @@ # See the LICENSE.txt file for more info. # # Contributors: -# Markus Kreusch - initial translation +# Markus Kreusch +# Michael Schmetter +# Sebastian Wiesendahl +# Tim Marius Wunderlich + app.name = Cryptomator # main.fxml -main.emptyListInstructions = Klicken Sie hier, um neue Tresore hinzuzufĂĽgen +main.emptyListInstructions = Klicken Sie hier, um neue Tresore hinzuzufügen main.directoryList.contextMenu.remove = Aus Liste entfernen -main.directoryList.contextMenu.changePassword = Passwort ändern +main.directoryList.contextMenu.changePassword = Passwort ändern main.addDirectory.contextMenu.new = Tresor erstellen -main.addDirectory.contextMenu.open = Tresor öffnen +main.addDirectory.contextMenu.open = Tresor öffnen # welcome.fxml -welcome.checkForUpdates.label.currentlyChecking = Auf Updates prĂĽfen... +welcome.checkForUpdates.label.currentlyChecking = Auf Updates prüfen... welcome.newVersionMessage = Version %s kann heruntergeladen werden. Aktuelle Version %s. # initialize.fxml initialize.label.password = Passwort -initialize.label.retypePassword = Passwort bestätigen +initialize.label.retypePassword = Passwort bestätigen initialize.button.ok = Tresor erstellen initialize.messageLabel.alreadyInitialized = Tresor bereits vorhanden initialize.messageLabel.initializationFailed = Fehler beim Initialisieren. Details in der Log-Datei. @@ -38,46 +42,47 @@ unlock.button.advancedOptions.hide = Weniger Optionen unlock.choicebox.winDriveLetter.auto = Automatisch ermitteln unlock.errorMessage.wrongPassword = Falsches Passwort unlock.errorMessage.mountingFailed = Verbindung fehlgeschlagen. Details in der Log-Datei. -unlock.errorMessage.unsupportedKeyLengthInstallJCE = EntschlĂĽsselung fehlgeschlagen. Bitte die Oracle JCE Unlimited Strength Policy installieren. -unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Tresor nicht unterstĂĽtzt. Der Tresor wurde mit einer älteren Version von Cryptomator erstellt. -unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = Tresor nicht unterstĂĽtzt. Der Tresor wurde mit einer neueren Version von Cryptomator erstellt. +unlock.errorMessage.unsupportedKeyLengthInstallJCE = Entschlüsselung fehlgeschlagen. Bitte die Oracle JCE Unlimited Strength Policy installieren. +unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Tresor nicht unterstützt. Der Tresor wurde mit einer älteren Version von Cryptomator erstellt. +unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = Tresor nicht unterstützt. Der Tresor wurde mit einer neueren Version von Cryptomator erstellt. unlock.messageLabel.startServerFailed = Starten des WebDAV-Servers fehlgeschlagen. # change_password.fxml changePassword.label.oldPassword = Altes Passwort changePassword.label.newPassword = Neues Passwort -changePassword.label.retypePassword = Passwort bestätigen +changePassword.label.retypePassword = Passwort bestätigen changePassword.label.downloadsPageLink = Alle Cryptomator Versionen -changePassword.button.change = Passwort ändern +changePassword.button.change = Passwort ändern changePassword.errorMessage.wrongPassword = Falsches Passwort -changePassword.errorMessage.decryptionFailed = EntschlĂĽsselung fehlgeschlagen -changePassword.errorMessage.unsupportedKeyLengthInstallJCE = EntschlĂĽsselung fehlgeschlagen. Bitte die Oracle JCE Unlimited Strength Policy installieren. -changePassword.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Tresor nicht unterstĂĽtzt. Der Tresor wurde mit einer älteren Version von Cryptomator erstellt. -changePassword.errorMessage.unsupportedVersion.softwareOlderThanVault = Tresor nicht unterstĂĽtzt. Der Tresor wurde mit einer neueren Version von Cryptomator erstellt. -changePassword.infoMessage.success = Passwort geändert +changePassword.errorMessage.decryptionFailed = Entschlüsselung fehlgeschlagen +changePassword.errorMessage.unsupportedKeyLengthInstallJCE = Entschlüsselung fehlgeschlagen. Bitte die Oracle JCE Unlimited Strength Policy installieren. +changePassword.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Tresor nicht unterstützt. Der Tresor wurde mit einer älteren Version von Cryptomator erstellt. +changePassword.errorMessage.unsupportedVersion.softwareOlderThanVault = Tresor nicht unterstützt. Der Tresor wurde mit einer neueren Version von Cryptomator erstellt. +changePassword.infoMessage.success = Passwort geändert # unlocked.fxml unlocked.button.lock = Tresor sperren unlocked.moreOptions.reveal = Laufwerk anzeigen unlocked.moreOptions.copyUrl = WebDAV-URL kopieren unlocked.label.revealFailed = Befehl fehlgeschlagen unlocked.label.unmountFailed = Trennen des Laufwerks fehlgeschlagen -unlocked.label.statsEncrypted = verschlĂĽsselt -unlocked.label.statsDecrypted = entschlĂĽsselt +unlocked.label.statsEncrypted = verschlüsselt +unlocked.label.statsDecrypted = entschlüsselt unlocked.ioGraph.yAxis.label = Durchsatz (MiB/s) # mac_warnings.fxml macWarnings.windowTitle = Achtung - Kompromittierte Datei in %s -macWarnings.message = Cryptomator hat möglicherweise unerlaubte Veränderungen in den folgenden Dateien erkannt\: +# "potentially detected" or "potentially malicious"? +macWarnings.message = Cryptomator hat möglicherweise unerlaubte Veränderungen in den folgenden Dateien erkannt\: macWarnings.moreInformationButton = Mehr erfahren -macWarnings.whitelistButton = Trotzdem entschlĂĽsseln +macWarnings.whitelistButton = Trotzdem entschlüsseln # settings.fxml settings.version.label = Version %s -settings.checkForUpdates.label = Auf Updates prĂĽfen +settings.checkForUpdates.label = Auf Updates prüfen settings.port.label = WebDAV Port * -settings.port.prompt = 0 \= Automatisch wählen +settings.port.prompt = 0 \= Automatisch wählen settings.useipv6.label = IPv6-Literal nutzen -settings.requiresRestartLabel = * benötigt Neustart von Cryptomator +settings.requiresRestartLabel = * benötigt Neustart von Cryptomator # tray icon -tray.menu.open = Ă–ffnen +tray.menu.open = Öffnen tray.menu.quit = Beenden -tray.infoMsg.title = Cryptomator läuft noch -tray.infoMsg.msg = Cryptomator läuft noch. Mit dem Tray-Icon beenden. -tray.infoMsg.msg.osx = Cryptomator läuft noch. Ăśber die MenĂĽleiste beenden. \ No newline at end of file +tray.infoMsg.title = Cryptomator läuft noch +tray.infoMsg.msg = Cryptomator läuft noch. Mit dem Tray-Icon beenden. +tray.infoMsg.msg.osx = Cryptomator läuft noch. Über die Menüleiste beenden. \ No newline at end of file diff --git a/main/ui/src/main/resources/localization_es.properties b/main/ui/src/main/resources/localization_es.properties index 64cdce6f1..18e960a30 100644 --- a/main/ui/src/main/resources/localization_es.properties +++ b/main/ui/src/main/resources/localization_es.properties @@ -1,5 +1,87 @@ # Copyright (c) 2016 The Cryptomator Contributors # This file is licensed under the terms of the MIT license. # See the LICENSE.txt file for more info. +# +# Contributos: +# Jay +# Sebastian Wiesendahl -app.name=Cryptomator +app.name = Cryptomator +# main.fxml +main.emptyListInstructions = Click aquí para ańadir una caja fuerte +# should it be imperative? +main.directoryList.contextMenu.remove = Eliminar de la lista +main.directoryList.contextMenu.changePassword = Cambiar la contraseńa +main.addDirectory.contextMenu.new = Crear una nueva caja fuerte +main.addDirectory.contextMenu.open = Abrir una caja fuerte existente +# welcome.fxml +welcome.checkForUpdates.label.currentlyChecking = Chequando por actualizaciónes... +welcome.newVersionMessage = Se puede bajar version %s. Este es %s. +# initialize.fxml +initialize.label.password = Contraseńa +initialize.label.retypePassword = Reintroduzca contraseńa +initialize.button.ok = Crear caja fuerte +initialize.messageLabel.alreadyInitialized = Caja fuerte ya está inicializado +initialize.messageLabel.initializationFailed = No se pudo inicializar la caja fuerte. Ver archivo de registro para detalles. +# notfound.fxml +notfound.label = No se pudo encontrar la caja fuerte. Se movió a otro lugar? +# upgrade.fxml +upgrade.button = Actualizar caja fuerte +upgrade.version3dropBundleExtension.msg = Este caja fuerte se debe actualizar a un nuevo formato.\n"%1$s" se renombra a "%2$s".\nPor favor aseguranse que la sincronización ya se terminó antes de continuar. +upgrade.version3dropBundleExtension.err.alreadyExists = Migración automática ha fallado.\n"%s" ya existe. +# unlock.fxml +unlock.label.password = Contraseńa +unlock.label.mountName = Nombre del disco +unlock.label.winDriveLetter = Letra del disco +unlock.label.downloadsPageLink = Todas las versiones de Cryptomator +unlock.label.advancedHeading = Opciones avanzadas +unlock.button.unlock = Abrir caja fuerte +unlock.button.advancedOptions.show = Más opciones +unlock.button.advancedOptions.hide = Menos opciones +unlock.choicebox.winDriveLetter.auto = Asignar automáticamente +unlock.errorMessage.wrongPassword = Contraseńa incorrecta +unlock.errorMessage.mountingFailed = Monteo ha fallado. Ver archivo del registro para detalles. +unlock.errorMessage.unsupportedKeyLengthInstallJCE = Decifración ha fallado. Por favor instala archivos de la Oracle JCE Unlimited Strength Policy. +unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Caja fuerte insupportado. Este caja se ha creado con una versión pasada de Cryptomator. +unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = Caja fuerte insupportado. Este caja se ha creado con una versión nueva de Cryptomator. +unlock.messageLabel.startServerFailed = Iniciación del servidor de WebDAV ha fallado. +# change_password.fxml +changePassword.label.oldPassword = Contraseńa anterior +# Can also use "current password" = "contraseńa actual" +changePassword.label.newPassword = Nueva contraseńa +changePassword.label.retypePassword = Reintroduzca contraseńa +changePassword.label.downloadsPageLink = Todas las versiones de Cryptomator +changePassword.button.change = Cambiar contraseńa +changePassword.errorMessage.wrongPassword = Contraseńa incorrecta +changePassword.errorMessage.decryptionFailed = Decifración ha fallado +changePassword.errorMessage.unsupportedKeyLengthInstallJCE = Decifración ha fallado. Por favor instala Oracle JCE Unlimited Strength Policy. +changePassword.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Caja fuerte insupportado. Este caja se ha creado con una versión pasada de Cryptomator. +changePassword.errorMessage.unsupportedVersion.softwareOlderThanVault = Caja fuerte insupportado. Este caja se ha creado con una versión nueva de Cryptomator. +changePassword.infoMessage.success = Contraseńa se ha cambiado +# unlocked.fxml +unlocked.button.lock = Encerrar caja fuerte +unlocked.moreOptions.reveal = Revelar disco +unlocked.moreOptions.copyUrl = Copiar URL de WebDAV +unlocked.label.revealFailed = Comando ha fallado +unlocked.label.unmountFailed = Expulsar el disco ha fallado +unlocked.label.statsEncrypted = cifrado +unlocked.label.statsDecrypted = decifrado +unlocked.ioGraph.yAxis.label = Procesamiento (MiB/s) +# mac_warnings.fxml +macWarnings.windowTitle = Peligro - archivo corrupto en %s +macWarnings.message = Cryptomator ha detectado corrupciones malciosas en los seguientes archivos\: +macWarnings.moreInformationButton = Aprende más +macWarnings.whitelistButton = Decifrar selecionado de todos modos +# settings.fxml +settings.version.label = Version %s +settings.checkForUpdates.label = Chequear por actualizaciones +settings.port.label = Puerta de WebDAV * +settings.port.prompt = 0 \= Elige automáticamente +settings.useipv6.label = Usa literal de IPv6 +settings.requiresRestartLabel = * Cryptomator se necesita reiniciar +# tray icon +tray.menu.open = Abrir +tray.menu.quit = Salir +tray.infoMsg.title = Todavía en ejecución +tray.infoMsg.msg = Cryptomator todavía esta en ejecución. Sale del icono del tray. +tray.infoMsg.msg.osx = Cryptomator todavía esta en ejecución. Sale del icono de la barra del menú. diff --git a/main/ui/src/main/resources/localization_fr.properties b/main/ui/src/main/resources/localization_fr.properties index 377f56331..8815f6d48 100644 --- a/main/ui/src/main/resources/localization_fr.properties +++ b/main/ui/src/main/resources/localization_fr.properties @@ -3,94 +3,84 @@ # See the LICENSE.txt file for more info. # # Contributors: -# Jean-Noël Charon - initial translation - -app.name=Cryptomator +# Jean-Noël Charon +# Olivier Thomasson +# vesparny +app.name = Cryptomator # main.fxml -main.emptyListInstructions=Cliquez ici pour ajouter un coffre -main.directoryList.contextMenu.remove=Retirer de la liste -main.directoryList.contextMenu.changePassword=Changer le mot de passe -main.addDirectory.contextMenu.new=Créer un nouveau coffre -main.addDirectory.contextMenu.open=Ouvrir un coffre existant - +main.emptyListInstructions = Cliquez ici pour ajouter un coffre +main.directoryList.contextMenu.remove = Retirer de la liste +main.directoryList.contextMenu.changePassword = Changer le mot de passe +main.addDirectory.contextMenu.new = Créer un nouveau coffre +main.addDirectory.contextMenu.open = Ouvrir un coffre existant # welcome.fxml -welcome.checkForUpdates.label.currentlyChecking=Recherche de mise ŕ jour... -welcome.newVersionMessage=La version %s peut-ętre téléchargée. Il s'agit de %s. - +welcome.checkForUpdates.label.currentlyChecking = Recherche de mise ŕ jour... +welcome.newVersionMessage = La version %s peut-ętre téléchargée. Il s'agit de %s. # initialize.fxml -initialize.label.password=Mot de passe -initialize.label.retypePassword=Confirmation -initialize.button.ok=Créer le coffre -initialize.messageLabel.alreadyInitialized=Coffre déjŕ initialisé -initialize.messageLabel.initializationFailed=Impossible d'initialiser le coffre. Voir le fichier de log pour plus de détails. - +initialize.label.password = Mot de passe +initialize.label.retypePassword = Confirmation +initialize.button.ok = Créer le coffre +initialize.messageLabel.alreadyInitialized = Coffre déjŕ initialisé +initialize.messageLabel.initializationFailed = Impossible d'initialiser le coffre. Voir le fichier de log pour plus de détails. # notfound.fxml -notfound.label=Coffre introuvable. A t'il été déplacé? - +notfound.label = Coffre introuvable. A t'il été déplacé? # upgrade.fxml -upgrade.button=Mettre ŕ niveau - -upgrade.version3dropBundleExtension.msg=This vault needs to be migrated to a newer format.\n"%1$s" will be renamed to "%2$s".\nPlease make sure synchronization has finished before proceeding. -upgrade.version3dropBundleExtension.err.alreadyExists=Automatic migration failed.\n"%s" already exists. - +upgrade.button = Mettre ŕ niveau +upgrade.version3dropBundleExtension.msg = Ce coffre doit ętre converti dans un format plus récent.\n"%1$s" sera renommé en "%2$s".\nAssurez-vous que la synchronisation est terminée avant de continuer. +upgrade.version3dropBundleExtension.err.alreadyExists = La conversion automatique a échoué.\n"%s" existe déjŕ. # unlock.fxml -unlock.label.password=Mot de passe -unlock.label.mountName=Nom du lecteur -unlock.label.winDriveLetter=Lettre du lecteur -unlock.label.downloadsPageLink=Toutes les versions de Cryptomator -unlock.label.advancedHeading=Options avancées -unlock.button.unlock=Déverrouiller le coffre -unlock.button.advancedOptions.show=Plus d'options -unlock.button.advancedOptions.hide=Moins d'options -unlock.choicebox.winDriveLetter.auto=Assigner automatiquement -unlock.errorMessage.wrongPassword=Mot de passe incorrect -unlock.errorMessage.mountingFailed=Echec du montage. Voir le fichier de log pour plus de détails. -unlock.errorMessage.unsupportedKeyLengthInstallJCE=Echec du décryptage. Veuillez installer la Policy Oracle "JCE Unlimited Strength Policy". -unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware=Coffre non supporté. Ce coffre a été créé avec une ancienne version de Cryptomator. -unlock.errorMessage.unsupportedVersion.softwareOlderThanVault=Coffre non supporté. Ce coffre a été créé avec une version de Cryptomator plus récente. -unlock.messageLabel.startServerFailed=Le serveur WebDAV n'a pas pu démarrer. - +unlock.label.password = Mot de passe +unlock.label.mountName = Nom du lecteur +unlock.label.winDriveLetter = Lettre du lecteur +unlock.label.downloadsPageLink = Toutes les versions de Cryptomator +unlock.label.advancedHeading = Options avancées +unlock.button.unlock = Déverrouiller le coffre +unlock.button.advancedOptions.show = Plus d'options +unlock.button.advancedOptions.hide = Moins d'options +unlock.choicebox.winDriveLetter.auto = Assigner automatiquement +unlock.errorMessage.wrongPassword = Mot de passe incorrect +unlock.errorMessage.mountingFailed = Echec du montage. Voir le fichier de log pour plus de détails. +unlock.errorMessage.unsupportedKeyLengthInstallJCE = Echec du décryptage. Veuillez installer la Policy Oracle "JCE Unlimited Strength Policy". +unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Coffre non supporté. Ce coffre a été créé avec une ancienne version de Cryptomator. +unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = Coffre non supporté. Ce coffre a été créé avec une version de Cryptomator plus récente. +unlock.messageLabel.startServerFailed = Le serveur WebDAV n'a pas pu démarrer. # change_password.fxml -changePassword.label.oldPassword=Ancien mot de passe -changePassword.label.newPassword=Nouveau mot de passe -changePassword.label.retypePassword=Resaisissez votre mot de passe -changePassword.label.downloadsPageLink=Toutes les versions de Cryptomator -changePassword.button.change=Modification du mot de masse -changePassword.errorMessage.wrongPassword=Mot de passe incorrect -changePassword.errorMessage.decryptionFailed=Echec du décryptage -changePassword.errorMessage.unsupportedKeyLengthInstallJCE=Echec du décryptage. Veuillez installer la Policy Oracle "JCE Unlimited Strength Policy". -changePassword.errorMessage.unsupportedVersion.vaultOlderThanSoftware=Coffre non supporté. Ce coffre a été créé avec une ancienne version de Cryptomator. -changePassword.errorMessage.unsupportedVersion.softwareOlderThanVault=Coffre non supporté. Ce coffre a été créé avec une version de Cryptomator plus récente. -changePassword.infoMessage.success=Password changed - +changePassword.label.oldPassword = Ancien mot de passe +changePassword.label.newPassword = Nouveau mot de passe +changePassword.label.retypePassword = Vérification +changePassword.label.downloadsPageLink = Toutes les versions de Cryptomator +changePassword.button.change = Modification du mot de masse +changePassword.errorMessage.wrongPassword = Mot de passe incorrect +changePassword.errorMessage.decryptionFailed = Echec du décryptage +changePassword.errorMessage.unsupportedKeyLengthInstallJCE = Echec du décryptage. Veuillez installer la Policy Oracle "JCE Unlimited Strength Policy". +changePassword.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Coffre non supporté. Ce coffre a été créé avec une ancienne version de Cryptomator. +changePassword.errorMessage.unsupportedVersion.softwareOlderThanVault = Coffre non supporté. Ce coffre a été créé avec une version de Cryptomator plus récente. +changePassword.infoMessage.success = Password changed # unlocked.fxml -unlocked.button.lock=Verrouiller le coffre -unlocked.moreOptions.reveal=Voir le lecteur -unlocked.moreOptions.copyUrl=Copier l'URL WebDAV -unlocked.label.revealFailed=Echec de la commande -unlocked.label.unmountFailed=Echec de l'éjection du lecteur -unlocked.label.statsEncrypted=cryptage -unlocked.label.statsDecrypted=décryptage -unlocked.ioGraph.yAxis.label=Débit (MiB/s) - +unlocked.button.lock = Verrouiller le coffre +unlocked.moreOptions.reveal = Voir le lecteur +unlocked.moreOptions.copyUrl = Copier l'URL WebDAV +unlocked.label.revealFailed = Echec de la commande +unlocked.label.unmountFailed = Echec de l'éjection du lecteur +unlocked.label.statsEncrypted = crypté +unlocked.label.statsDecrypted = décryptage +unlocked.ioGraph.yAxis.label = Débit (MiB/s) # mac_warnings.fxml -macWarnings.windowTitle=Attention - Fichier corrompu dans %s -macWarnings.message=Cryptomator a détecté des corruptions de données dans les fichiers suivants: -macWarnings.moreInformationButton=En savoir plus -macWarnings.whitelistButton=Décrypter tout de męme - +macWarnings.windowTitle = Attention - Fichier corrompu dans %s +macWarnings.message = Cryptomator a détecté des corruptions de données dans les fichiers suivants\: +macWarnings.moreInformationButton = En savoir plus +macWarnings.whitelistButton = Décrypter tout de męme # settings.fxml -settings.version.label=Version %s -settings.checkForUpdates.label=Vérif. des mises ŕ jour -settings.port.label=Port WebDAV * -settings.port.prompt=0 = Choix automatique -settings.useipv6.label=Utiliser un litéral IPv6 -settings.requiresRestartLabel=* Redémarrage requis - +settings.version.label = Version %s +settings.checkForUpdates.label = Vérif. des mises ŕ jour +settings.port.label = Port WebDAV * +settings.port.prompt = 0 \= Choix automatique +settings.useipv6.label = Utiliser un litéral IPv6 +settings.requiresRestartLabel = * Redémarrage requis # tray icon -tray.menu.open=Ouvrir -tray.menu.quit=Quitter -tray.infoMsg.title=Toujours en fonctionnement -tray.infoMsg.msg=Cryptomator est toujours en fonctionnement. Utiliser l'icône de la barre des tâches pour quitter. -tray.infoMsg.msg.osx=Cryptomator est toujours en fonctionnement. Utilisez la barre de menu pour quitter. +tray.menu.open = Ouvrir +tray.menu.quit = Quitter +tray.infoMsg.title = Toujours en fonctionnement +tray.infoMsg.msg = Cryptomator est toujours en fonctionnement. Utiliser l'icône de la barre des tâches pour quitter. +tray.infoMsg.msg.osx = Cryptomator est toujours en fonctionnement. Utilisez la barre de menu pour quitter. \ No newline at end of file diff --git a/main/ui/src/main/resources/localization_hu.properties b/main/ui/src/main/resources/localization_hu.properties new file mode 100644 index 000000000..8fdc27761 --- /dev/null +++ b/main/ui/src/main/resources/localization_hu.properties @@ -0,0 +1,84 @@ +# Copyright (c) 2016 The Cryptomator Contributors +# This file is licensed under the terms of the MIT license. +# See the LICENSE.txt file for more info. +# +# Contributors: +# Roland Burda + +app.name = Cryptomator +# main.fxml +main.emptyListInstructions = Kattints ide egy széf létrehozásához +main.directoryList.contextMenu.remove = Eltávolítás listából +main.directoryList.contextMenu.changePassword = Jelszó megváltoztatása +main.addDirectory.contextMenu.new = Új széf létrehozása +main.addDirectory.contextMenu.open = Létez\u0151 széf megnyitása +# welcome.fxml +welcome.checkForUpdates.label.currentlyChecking = Frissítések keresése... +welcome.newVersionMessage = Új verzió érhet\u0151 el\: %s. Jelenlegi verzió\: %s. +# initialize.fxml +initialize.label.password = Jelszó +initialize.label.retypePassword = Jelszó ismét +initialize.button.ok = Széf létrehozása +initialize.messageLabel.alreadyInitialized = A széf már meg van nyitva +initialize.messageLabel.initializationFailed = Nem sikerült megnyitni a széfet. További információ a naplófájlban. +# notfound.fxml +notfound.label = Széf nem található. Lehetséges, hogy áthelyezésre került? +# upgrade.fxml +upgrade.button = Széf frissítése +upgrade.version3dropBundleExtension.msg = A széf új verzióra történ\u0151 migrációja szükséges. "%1$s" a következ\u0151re lesz átnevezve\: "%2$s". Kérlek gy\u0151z\u0151dj meg a szinkronizáció befejeztér\u0151l, miel\u0151tt más m\u0171veletet végeznél. +upgrade.version3dropBundleExtension.err.alreadyExists = Automatikus migráció meghíusúlt. "%s" már létezik. +# unlock.fxml +unlock.label.password = Jelszó +unlock.label.mountName = Meghajtó neve +unlock.label.winDriveLetter = Meghajtó bet\u0171jele +unlock.label.downloadsPageLink = Összes Cryptomator verzió +unlock.label.advancedHeading = Haladó beállítások +unlock.button.unlock = Széf feloldása +unlock.button.advancedOptions.show = További beállítások +unlock.button.advancedOptions.hide = Alapbeállítások +unlock.choicebox.winDriveLetter.auto = Automatikus hozzárendelés +unlock.errorMessage.wrongPassword = Hibás jelszó +unlock.errorMessage.mountingFailed = Meghajtó felcsatolása sikertelen. További információk a naplófájlban. +unlock.errorMessage.unsupportedKeyLengthInstallJCE = A titkosítás feloldása sikertelen. Kérlek telepítsd a "Oracle JCE Unlimited Strength Policy Files"-t. +unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Nem támogatott széf. Ez a széf a Cryptomator egy korábbi verziójával került létrehozásra. +unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = Nem támogatott széf. Ez a széf a Cryptomator egy újabb verziójával került létrehozásra. +unlock.messageLabel.startServerFailed = WebDAV szerver indítása sikertelen. +# change_password.fxml +changePassword.label.oldPassword = Régi jelszó +changePassword.label.newPassword = Új jelszó +changePassword.label.retypePassword = Új jelszó ismét +changePassword.label.downloadsPageLink = Összes Cryptomator verzió +changePassword.button.change = Jelszó megváltoztatása +changePassword.errorMessage.wrongPassword = Hibás jelszó +changePassword.errorMessage.decryptionFailed = A titkosítás feloldása meghíusúlt +changePassword.errorMessage.unsupportedKeyLengthInstallJCE = A titkosítás feloldása sikertelen. Kérlek telepítsd a "Oracle JCE Unlimited Strength Policy"-t. +changePassword.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Nem támogatott széf. Ez a széf a Cryptomator egy korábbi verziójával került létrehozásra. +changePassword.errorMessage.unsupportedVersion.softwareOlderThanVault = Nem támogatott széf. Ez a széf a Cryptomator egy újabb verziójával került létrehozásra. +changePassword.infoMessage.success = Jelszó megváltoztatva +# unlocked.fxml +unlocked.button.lock = Széf lezárása +unlocked.moreOptions.reveal = Meghajtó felfedése +unlocked.moreOptions.copyUrl = WebDAV URL másolása +unlocked.label.revealFailed = Parancs meghíusúlt +unlocked.label.unmountFailed = Meghajtó leválasztása sikertelen +unlocked.label.statsEncrypted = titkosított +unlocked.label.statsDecrypted = titkosítás feloldva +unlocked.ioGraph.yAxis.label = Teljesítmény (MiB/s) +# mac_warnings.fxml +macWarnings.windowTitle = Veszély - Korrupt fájl a következ\u0151ben\: %s +macWarnings.message = Cryptomator potenciálisan rosszindulatú hibákat fedezett fel a következ\u0151 fájlokban\: +macWarnings.moreInformationButton = Tudj meg többet +macWarnings.whitelistButton = Kiválasztottak titkosításának feloldása mindenképp +# settings.fxml +settings.version.label = Verzió\: %s +settings.checkForUpdates.label = Frissítések keresése +settings.port.label = WebDAV Port * +settings.port.prompt = 0 \= Automatikus választás +settings.useipv6.label = Literális IPv6 használata +settings.requiresRestartLabel = * Cryptomator újraindítása szükséges +# tray icon +tray.menu.open = Megnyit +tray.menu.quit = Kilépés +tray.infoMsg.title = M\u0171velet folyamatban +tray.infoMsg.msg = Cryptomator még fut. A tálcán található ikon segítségével bezárhatod. +tray.infoMsg.msg.osx = Cryptomator még fut. A menüsávban található ikon segítségével bezárhatod. \ No newline at end of file diff --git a/main/ui/src/main/resources/localization_it.properties b/main/ui/src/main/resources/localization_it.properties new file mode 100644 index 000000000..06ac22ade --- /dev/null +++ b/main/ui/src/main/resources/localization_it.properties @@ -0,0 +1,84 @@ +# Copyright (c) 2016 The Cryptomator Contributors +# This file is licensed under the terms of the MIT license. +# See the LICENSE.txt file for more info. +# +# Contributors: +# vesparny + +app.name = Cryptomator +# main.fxml +main.emptyListInstructions = Clicca qui per aggiungere un vault +main.directoryList.contextMenu.remove = Rimuovi dalla lista +main.directoryList.contextMenu.changePassword = Cambia la password +main.addDirectory.contextMenu.new = Crea un nuovo vault +main.addDirectory.contextMenu.open = Apri un vault +# welcome.fxml +welcome.checkForUpdates.label.currentlyChecking = Verifica aggiornamenti... +welcome.newVersionMessage = La versione %s puň essere scaricata. Questa č %s +# initialize.fxml +initialize.label.password = Password +initialize.label.retypePassword = Conferma password +initialize.button.ok = Crea un vault +initialize.messageLabel.alreadyInitialized = Vault giŕ inizializzato +initialize.messageLabel.initializationFailed = Non č possibile inizializzare il vault. Controlla il file di log per dettagli. +# notfound.fxml +notfound.label = Il vault non puň essere trovato. E' stato rimosso? +# upgrade.fxml +upgrade.button = Aggiorna vault +upgrade.version3dropBundleExtension.msg = Questo vault deve essere migrato ad un nuovo formato.\n"%1$s" verrŕ rinominato in "%2$s".\nPer favore verifica che la sincronizzazione sia finita prima di procedere\n +upgrade.version3dropBundleExtension.err.alreadyExists = Migrazione automatica fallita.\n"%s" esiste giŕ. +# unlock.fxml +unlock.label.password = Password +unlock.label.mountName = nome del drive +unlock.label.winDriveLetter = lettera del drive +unlock.label.downloadsPageLink = Tutte le versioni di Cryptomator +unlock.label.advancedHeading = Opzioni avanzate +unlock.button.unlock = Sblocca vault +unlock.button.advancedOptions.show = Piů opzioni +unlock.button.advancedOptions.hide = Meno opzioni +unlock.choicebox.winDriveLetter.auto = Assegna automaticamente +unlock.errorMessage.wrongPassword = Password errata +unlock.errorMessage.mountingFailed = Montaggio fallito. Controlla il file di log per dettagli. +unlock.errorMessage.unsupportedKeyLengthInstallJCE = Decriptaggio fallito. +unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Vault non supportato. Questo vault č stato creato con una versione di Cryptomator piů vecchia. +unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = Vault non supportato. Questo vault č stato creato con una versione di Cryptomator piů recente. +unlock.messageLabel.startServerFailed = Avvio del server WebDAV fallito +# change_password.fxml +changePassword.label.oldPassword = Vecchia password +changePassword.label.newPassword = Nuova password +changePassword.label.retypePassword = Conferma password +changePassword.label.downloadsPageLink = Tutte le versioni di Cryptomator +changePassword.button.change = Cambia la password +changePassword.errorMessage.wrongPassword = Password errata +changePassword.errorMessage.decryptionFailed = Decriptaggio fallito +changePassword.errorMessage.unsupportedKeyLengthInstallJCE = Decriptaggio fallito. Per favore installa Oracle JCE Unlimited Strength Policy +changePassword.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Vault non supportato. Questo vault č stato creato con una versione di Cryptomator piů recente. +changePassword.errorMessage.unsupportedVersion.softwareOlderThanVault = Vault non supportato. Questo vault č stato creato con una versione di Cryptomator piů vecchia. +changePassword.infoMessage.success = Password cambiata +# unlocked.fxml +unlocked.button.lock = Blocca vault +unlocked.moreOptions.reveal = Apri il disco +unlocked.moreOptions.copyUrl = Copia url WebDAV +unlocked.label.revealFailed = Comando fallito +unlocked.label.unmountFailed = Espulsione disco fallita +unlocked.label.statsEncrypted = criptato +unlocked.label.statsDecrypted = decriptato +unlocked.ioGraph.yAxis.label = Volume dati (MiB/s) +# mac_warnings.fxml +macWarnings.windowTitle = Pericolo - File corroto in %s +macWarnings.message = Cryptomator ha individuato potenziali pericolose corruzioni nei seguenti file\: +macWarnings.moreInformationButton = Piů informazioni +macWarnings.whitelistButton = Decripta i selezionati comunque +# settings.fxml +settings.version.label = Versione %s +settings.checkForUpdates.label = Verifica aggiornamenti +settings.port.label = WebDAV Port * +settings.port.prompt = 0 \= Scegli automaticamente +settings.useipv6.label = Utilizza IPv6 literal +settings.requiresRestartLabel = * Cryptomator deve essere riavviato +# tray icon +tray.menu.open = Apri +tray.menu.quit = Chiudi +tray.infoMsg.title = Ancora in esecuzione +tray.infoMsg.msg = Cryptomator č ancora in esecuzione. Chiudilo utilizzando l'icona nel menů di stato. +tray.infoMsg.msg.osx = Cryptomator č ancora in esecuzione. Chiudilo utilizzando l'icona nella barra del menů. \ No newline at end of file diff --git a/main/ui/src/main/resources/localization_pt.properties b/main/ui/src/main/resources/localization_pt.properties new file mode 100644 index 000000000..c6dad850a --- /dev/null +++ b/main/ui/src/main/resources/localization_pt.properties @@ -0,0 +1,34 @@ +# Copyright (c) 2016 The Cryptomator Contributors +# This file is licensed under the terms of the MIT license. +# See the LICENSE.txt file for more info. +# +# Contributors: +# Will +# André Di Biasi + +app.name = Cryptomator +main.directoryList.contextMenu.remove = Remover da lista +main.directoryList.contextMenu.changePassword = Alterar senha +# welcome.fxml +welcome.checkForUpdates.label.currentlyChecking = Procurando atualizaçőes... +# initialize.fxml +initialize.label.password = Senha +initialize.label.retypePassword = Digite a senha novamente +# unlock.fxml +unlock.label.password = Senha +unlock.label.advancedHeading = Opçőes avançadas +unlock.button.advancedOptions.hide = Menos opçőes +unlock.choicebox.winDriveLetter.auto = Atribuir automaticamente +unlock.errorMessage.wrongPassword = Senha incorreta +unlock.errorMessage.mountingFailed = Montagem falhou. Veja o arquivo de log para detalhes +unlock.messageLabel.startServerFailed = Inicializaçăo do servidor WEBDAV falhou +# change_password.fxml +changePassword.label.oldPassword = Senha antiga +changePassword.label.newPassword = Nova senha +changePassword.label.retypePassword = Digite a senha novamente +changePassword.button.change = Alterar senha +changePassword.infoMessage.success = Senha alterada +unlocked.label.revealFailed = Falha no comando +unlocked.label.unmountFailed = Falha ao ejetar o drive +unlocked.label.statsEncrypted = encriptado +macWarnings.moreInformationButton = Saiba mais \ No newline at end of file diff --git a/main/ui/src/main/resources/localization_ru.properties b/main/ui/src/main/resources/localization_ru.properties new file mode 100644 index 000000000..52214c75a --- /dev/null +++ b/main/ui/src/main/resources/localization_ru.properties @@ -0,0 +1,55 @@ +# Copyright (c) 2016 The Cryptomator Contributors +# This file is licensed under the terms of the MIT license. +# See the LICENSE.txt file for more info. +# +# Contributors: +# Garik +# Konstantine + +app.name = Cryptomator +# main.fxml +main.emptyListInstructions = \u041D\u0430\u0436\u043C\u0438\u0442\u0435 \u0437\u0434\u0435\u0441\u044C \u0447\u0442\u043E \u0434\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435 +main.directoryList.contextMenu.remove = \u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0438\u0437 \u0441\u043F\u0438\u0441\u043A\u0430 +main.directoryList.contextMenu.changePassword = \u0421\u043C\u0435\u043D\u0438\u0442\u044C \u043F\u0430\u0440\u043E\u043B\u044C +main.addDirectory.contextMenu.new = \u0421\u043E\u0437\u0434\u0430\u0442\u044C \u043D\u043E\u0432\u043E\u0435 \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435 +main.addDirectory.contextMenu.open = \u041E\u0442\u043A\u0440\u044B\u0442\u044C \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044E\u0449\u0435\u0435 \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435 +# welcome.fxml +welcome.checkForUpdates.label.currentlyChecking = \u041F\u0440\u043E\u0432\u0435\u0440\u043A\u0430 \u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u0439... +welcome.newVersionMessage = \u0412\u0435\u0440\u0441\u0438\u044F \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u0441\u043A\u0430\u0447\u0435\u043D\u0430. \u042D\u0442\u043E. +# initialize.fxml +initialize.label.password = \u041F\u0430\u0440\u043E\u043B\u044C +initialize.label.retypePassword = \u041F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0435 \u043F\u0430\u0440\u043E\u043B\u044C +initialize.button.ok = \u0421\u043E\u0437\u0434\u0430\u0442\u044C \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435 +initialize.messageLabel.alreadyInitialized = \u0425\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435 \u0443\u0436\u0435 \u0438\u043D\u0438\u0446\u0438\u0430\u043B\u0438\u0437\u0438\u0440\u043E\u0432\u0430\u043D\u043E +initialize.messageLabel.initializationFailed = \u041D\u0435\u0432\u043E\u0437\u043C\u043E\u0436\u043D\u043E \u0438\u043D\u0438\u0446\u0438\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435. \u0421\u043C\u043E\u0442\u0440\u0438\u0442\u0435 \u043B\u043E\u0433 \u0434\u043B\u044F \u0434\u0435\u0442\u0430\u043B\u0435\u0439. +# notfound.fxml +notfound.label = \u0425\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435 \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u043E.\u041E\u043D\u043E \u0431\u044B\u043B\u043E \u0443\u0434\u0430\u043B\u0435\u043D\u043E? +# upgrade.fxml +upgrade.button = \u041E\u0431\u043D\u043E\u0432\u0438\u0442\u044C \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435 +upgrade.version3dropBundleExtension.msg = \u042D\u0442\u043E\u043C\u0443 \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0443 \u043D\u0443\u0436\u043D\u043E \u043C\u0438\u0433\u0440\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0432 \u043D\u043E\u0432\u044B\u0439 \u0444\u043E\u0440\u043C\u0430\u0442.\n"%1$s" will be renamed to "%2$s".\nPlease make sure synchronization has finished before proceeding. +upgrade.version3dropBundleExtension.err.alreadyExists = \u0410\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u0430\u044F \u043C\u0438\u0433\u0440\u0430\u0446\u0438\u044F \u043D\u0435 \u0443\u0434\u0430\u043B\u0430\u0441\u044C.\n"%" \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442. +# unlock.fxml +unlock.label.password = \u041F\u0430\u0440\u043E\u043B\u044C +unlock.label.mountName = \u0418\u043C\u044F \u043D\u043E\u0441\u0438\u0442\u0435\u043B\u044F +changePassword.errorMessage.wrongPassword = \u041D\u0435\u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u044B\u0439 \u043F\u0430\u0440\u043E\u043B\u044C +changePassword.errorMessage.decryptionFailed = \u0420\u0430\u0441\u0448\u0438\u0444\u0440\u043E\u0432\u043A\u0430 \u043F\u0440\u043E\u0432\u0430\u043B\u0438\u043B\u0430\u0441\u044C +changePassword.errorMessage.unsupportedKeyLengthInstallJCE = \u0420\u0430\u0441\u0448\u0438\u0444\u0440\u043E\u0432\u043A\u0430 \u043D\u0435 \u0443\u0434\u0430\u043B\u0430\u0441\u044C. \u041F\u043E\u0436\u0430\u043B\u0443\u0439\u0441\u0442\u0430 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u0435 Oracle JCE Unlimited Strength Policy. +changePassword.infoMessage.success = \u041F\u0430\u0440\u043E\u043B\u044C \u0438\u0437\u043C\u0435\u043D\u0438\u043B\u0441\u044F +# unlocked.fxml +unlocked.button.lock = \u0417\u0430\u0431\u043B\u043E\u043A\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435 +unlocked.moreOptions.copyUrl = \u0421\u043A\u043E\u043F\u0438\u0440\u043E\u0432\u0430\u0442\u044C WebDAV URL +unlocked.label.revealFailed = \u041A\u043E\u043C\u0430\u043D\u0434\u0430 \u043D\u0435 \u0443\u0434\u0430\u043B\u0430\u0441\u044C +unlocked.label.unmountFailed = \u0418\u0437\u0432\u043B\u0435\u0447\u0435\u043D\u0438\u0435 \u0434\u0438\u0441\u043A\u0430 \u043D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C +unlocked.label.statsEncrypted = \u0437\u0430\u0448\u0438\u0444\u0440\u043E\u0432\u0430\u043D\u043E +unlocked.label.statsDecrypted = \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043E\u0432\u0430\u043D\u043E +macWarnings.moreInformationButton = \u0418\u0437\u0443\u0447\u0438\u0442\u044C \u0431\u043E\u043B\u044C\u0448\u0435 +# settings.fxml +settings.version.label = \u0412\u0435\u0440\u0441\u0438\u044F %s +settings.checkForUpdates.label = \u041F\u0440\u043E\u0432\u0435\u0440\u043A\u0430 \u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u0439 +settings.requiresRestartLabel = * Cryptomator \u0434\u043E\u043B\u0436\u0435\u043D \u043F\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u0441\u044F +# tray icon +tray.menu.open = \u041E\u0442\u043A\u0440\u044B\u0442\u044C +tray.menu.quit = \u0412\u044B\u0439\u0442\u0438 +tray.infoMsg.title = \u0412\u0441\u0451 \u0435\u0449\u0451 \u0440\u0430\u0431\u043E\u0442\u0430\u0435\u0442 +tray.infoMsg.msg = Cryptomator \u0440\u0430\u0431\u043E\u0442\u0430\u0435\u0442. \u0412\u044B\u0439\u0434\u0438\u0442\u0435 c \u043F\u043E\u043C\u043E\u0449\u044C\u044E \u0438\u043A\u043E\u043D\u043A\u0438 \u0432 \u0442\u0440\u0435\u0435. +tray.infoMsg.msg.osx = Cryptomator \u0432\u0441\u0451 \u0435\u0449\u0451 \u0440\u0430\u0431\u043E\u0442\u0430\u0435\u0442.\u0412\u044B\u0439\u0434\u0438\u0442\u0435 \u0441 \u043F\u043E\u043C\u043E\u0449\u044C\u044E \u0438\u043A\u043E\u043D\u043A\u0438 \u0432 \u043C\u0435\u043D\u044E \u0431\u0430\u0440\u0435. \ No newline at end of file diff --git a/main/ui/src/main/resources/localization_sk.properties b/main/ui/src/main/resources/localization_sk.properties new file mode 100644 index 000000000..2bec55581 --- /dev/null +++ b/main/ui/src/main/resources/localization_sk.properties @@ -0,0 +1,85 @@ +# Copyright (c) 2016 The Cryptomator Contributors +# This file is licensed under the terms of the MIT license. +# See the LICENSE.txt file for more info. +# +# Contributors: +# Filip Havrlent +# Tatiana Chovancová + +app.name = Cryptomator +# main.fxml +main.emptyListInstructions = Prida\u0165 trezor +main.directoryList.contextMenu.remove = Odstráni\u0165 zo zoznamu +main.directoryList.contextMenu.changePassword = Zmeni\u0165 heslo +main.addDirectory.contextMenu.new = Vytvori\u0165 nový trezor +main.addDirectory.contextMenu.open = Otvori\u0165 existujúci trezor +# welcome.fxml +welcome.checkForUpdates.label.currentlyChecking = Kontrolujú sa aktualizácie... +welcome.newVersionMessage = Verzia %s je pripravená na stiahnutie. Toto je verzia %s. +# initialize.fxml +initialize.label.password = Heslo +initialize.label.retypePassword = Zadajte heslo znova +initialize.button.ok = Vytvori\u0165 trezor +initialize.messageLabel.alreadyInitialized = Trezor je u\u017E inicializovaný +initialize.messageLabel.initializationFailed = Nepodarilo sa inicializova\u0165 trezor. Pozrite súbor záznamov pre viac detailov. +# notfound.fxml +notfound.label = Trezor nemohol by\u0165 nenájdený. Bol presunutý? +# upgrade.fxml +upgrade.button = Upgradnú\u0165 trezor +upgrade.version3dropBundleExtension.msg = Tento trezor musí by\u0165 premigrovaný na nový formát. "%1$s" bude premenovaný na "%2$s". Prosím, uistite sa \u017Ee je dokon\u010Dená synchronizácia skôr ne\u017E budete pokra\u010Dova\u0165. +upgrade.version3dropBundleExtension.err.alreadyExists = Automatická migrácia zlyhala. "%s" u\u017E existuje. +# unlock.fxml +unlock.label.password = Heslo +unlock.label.mountName = Názov jednotky +unlock.label.winDriveLetter = Ozna\u010Denie jednotky +unlock.label.downloadsPageLink = V\u0161etky verzie Cryptomatoru +unlock.label.advancedHeading = Pokro\u010Dilé nastavenia +unlock.button.unlock = Odomknú\u0165 trezor +unlock.button.advancedOptions.show = Viac nastavení +unlock.button.advancedOptions.hide = Menej nastavení +unlock.choicebox.winDriveLetter.auto = Priradi\u0165 automaticky +unlock.errorMessage.wrongPassword = Nesprávne heslo +unlock.errorMessage.mountingFailed = Pripájanie zlyhalo. Viac informácii v logu. +unlock.errorMessage.unsupportedKeyLengthInstallJCE = De\u0161ifrovanie zlyhalo. Prosím nain\u0161talujte Oracle JCE Unlimited Strength Policy Files. +unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Nepodporovaný trezor. Tento trezor bol vytvorený star\u0161ou verziou Cryptromatoru. +unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = Nepodporovaný trezor. Bol vytvorený z nov\u0161ou verziou Cryptomatoru. +unlock.messageLabel.startServerFailed = Spustenie WebDAv servera zlyhalo. +# change_password.fxml +changePassword.label.oldPassword = Staré heslo +changePassword.label.newPassword = Nové heslo +changePassword.label.retypePassword = Znova zadajte heslo +changePassword.label.downloadsPageLink = V\u0161etky verzie Cryptomatoru. +changePassword.button.change = Zmeni\u0165 heslo +changePassword.errorMessage.wrongPassword = Nesprávne heslo +changePassword.errorMessage.decryptionFailed = De\u0161ifrovanie zlyhalo. +changePassword.errorMessage.unsupportedKeyLengthInstallJCE = De\u0161ifrovanie zlyhalo. Prosím nain\u0161talujte Oracle JCE Unlimited Strength Policy. +changePassword.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Nepodporovaný trezor. Bol vytvorený star\u0161ou verziou Cryptomatoru. +changePassword.errorMessage.unsupportedVersion.softwareOlderThanVault = Nepodporovaný trezor. Bol vytvorený nov\u0161ou verziou Cryptomatoru. +changePassword.infoMessage.success = Heslo zmenené +# unlocked.fxml +unlocked.button.lock = Zamknú\u0165 trezor +unlocked.moreOptions.reveal = Odhali\u0165 jednotku +unlocked.moreOptions.copyUrl = Kopírova\u0165 WebDAV URL +unlocked.label.revealFailed = Príkaz zlyhal +unlocked.label.unmountFailed = Odpájanie jednotky zlyhalo +unlocked.label.statsEncrypted = za\u0161ifrované +unlocked.label.statsDecrypted = de\u0161ifrované +unlocked.ioGraph.yAxis.label = Priepustnos\u0165 (MiB/s) +# mac_warnings.fxml +macWarnings.windowTitle = Upozornenie - Po\u0161kodený súbor v %s +macWarnings.message = Cryptomator odhalil potencionálne \u0161kodlivé po\u0161kodenie v nasledujúcich súboroch\: +macWarnings.moreInformationButton = Zisti\u0165 viac +macWarnings.whitelistButton = Napriek tomu de\u0161ifrova\u0165 vybrané +# settings.fxml +settings.version.label = Verzia %s +settings.checkForUpdates.label = Skontrolova\u0165 aktualizácie +settings.port.label = WebDAV Port * +settings.port.prompt = 0 \= Vybra\u0165 automaticky +settings.useipv6.label = Pou\u017Ei\u0165 IPv6 +settings.requiresRestartLabel = * Cryptomator vy\u017Eaduje re\u0161tart +# tray icon +tray.menu.open = Otvori\u0165 +tray.menu.quit = Vypnú\u0165 +tray.infoMsg.title = Stále be\u017Eí +tray.infoMsg.msg = Cryptomator je stále spustený. Vypnite ho pomocou ikony v systémovej li\u0161te. +tray.infoMsg.msg.osx = Cryptomator je stále sputený. Ukon\u010Dite ho pomocou ikony v menu. \ No newline at end of file From 0f20c7c3c9842e91e76f09a0938558f5e1cb7615 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Mon, 2 May 2016 12:36:31 +0200 Subject: [PATCH 06/15] fixes #209 --- .../java/org/cryptomator/ui/Cryptomator.java | 2 ++ .../org/cryptomator/ui/MainApplication.java | 1 + .../org/cryptomator/ui/settings/Settings.java | 29 ++++++++++++++++++- .../ui/settings/SettingsProvider.java | 14 ++++----- 4 files changed, 37 insertions(+), 9 deletions(-) diff --git a/main/ui/src/main/java/org/cryptomator/ui/Cryptomator.java b/main/ui/src/main/java/org/cryptomator/ui/Cryptomator.java index f4fbdb1a0..3150ddc4d 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/Cryptomator.java +++ b/main/ui/src/main/java/org/cryptomator/ui/Cryptomator.java @@ -36,6 +36,8 @@ public class Cryptomator { private static final CleanShutdownPerformer CLEAN_SHUTDOWN_PERFORMER = new CleanShutdownPerformer(); public static void main(String[] args) { + String cryptomatorVersion = Optional.ofNullable(Cryptomator.class.getPackage().getImplementationVersion()).orElse("SNAPSHOT"); + LOG.info("Starting Cryptomator {} on {} {} ({})", cryptomatorVersion, SystemUtils.OS_NAME, SystemUtils.OS_VERSION, SystemUtils.OS_ARCH); if (SystemUtils.IS_OS_MAC_OSX) { /* * On OSX we're in an awkward position. We need to register a handler in the main thread of this application. However, we can't diff --git a/main/ui/src/main/java/org/cryptomator/ui/MainApplication.java b/main/ui/src/main/java/org/cryptomator/ui/MainApplication.java index ed01184b3..86c16261b 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/MainApplication.java +++ b/main/ui/src/main/java/org/cryptomator/ui/MainApplication.java @@ -38,6 +38,7 @@ public class MainApplication extends Application { @Override public void start(Stage primaryStage) throws IOException { + LOG.info("JavaFX application started"); final CryptomatorComponent comp = DaggerCryptomatorComponent.builder().cryptomatorModule(new CryptomatorModule(this, primaryStage)).build(); final MainController mainCtrl = comp.mainController(); closer = comp.deferredCloser(); diff --git a/main/ui/src/main/java/org/cryptomator/ui/settings/Settings.java b/main/ui/src/main/java/org/cryptomator/ui/settings/Settings.java index 85c8fefdc..ca3800069 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/settings/Settings.java +++ b/main/ui/src/main/java/org/cryptomator/ui/settings/Settings.java @@ -11,6 +11,7 @@ package org.cryptomator.ui.settings; import java.io.Serializable; import java.util.ArrayList; import java.util.List; +import java.util.function.Consumer; import org.cryptomator.ui.model.Vault; @@ -27,6 +28,8 @@ public class Settings implements Serializable { public static final boolean DEFAULT_USE_IPV6 = false; public static final Integer DEFAULT_NUM_TRAY_NOTIFICATIONS = 3; + private final Consumer saveCmd; + @JsonProperty("directories") private List directories; @@ -35,7 +38,7 @@ public class Settings implements Serializable { @JsonProperty("port") private Integer port; - + @JsonProperty("useIpv6") private Boolean useIpv6; @@ -46,7 +49,26 @@ public class Settings implements Serializable { * Package-private constructor; use {@link SettingsProvider}. */ Settings() { + this.saveCmd = s -> { + }; + } + private Settings(Consumer saveCmd) { + this.saveCmd = saveCmd; + } + + Settings withSaveCmd(Consumer saveCmd) { + final Settings result = new Settings(saveCmd); + result.directories = this.directories; + result.checkForUpdatesEnabled = this.checkForUpdatesEnabled; + result.port = this.port; + result.useIpv6 = this.useIpv6; + result.numTrayNotifications = this.numTrayNotifications; + return result; + } + + private void save() { + saveCmd.accept(this); } /* Getter/Setter */ @@ -60,6 +82,7 @@ public class Settings implements Serializable { public void setDirectories(List directories) { this.directories = directories; + save(); } public boolean isCheckForUpdatesEnabled() { @@ -69,6 +92,7 @@ public class Settings implements Serializable { public void setCheckForUpdatesEnabled(boolean checkForUpdatesEnabled) { this.checkForUpdatesEnabled = checkForUpdatesEnabled; + save(); } public void setPort(int port) { @@ -76,6 +100,7 @@ public class Settings implements Serializable { throw new IllegalArgumentException("Invalid port"); } this.port = port; + save(); } public int getPort() { @@ -96,6 +121,7 @@ public class Settings implements Serializable { public void setUseIpv6(boolean useIpv6) { this.useIpv6 = useIpv6; + save(); } public Integer getNumTrayNotifications() { @@ -104,6 +130,7 @@ public class Settings implements Serializable { public void setNumTrayNotifications(Integer numTrayNotifications) { this.numTrayNotifications = numTrayNotifications; + save(); } } diff --git a/main/ui/src/main/java/org/cryptomator/ui/settings/SettingsProvider.java b/main/ui/src/main/java/org/cryptomator/ui/settings/SettingsProvider.java index 9d40ac09d..1bfddbddf 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/settings/SettingsProvider.java +++ b/main/ui/src/main/java/org/cryptomator/ui/settings/SettingsProvider.java @@ -23,7 +23,6 @@ import javax.inject.Provider; import javax.inject.Singleton; import org.apache.commons.lang3.SystemUtils; -import org.cryptomator.ui.util.DeferredCloser; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -32,7 +31,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; @Singleton public class SettingsProvider implements Provider { - private static final Logger LOG = LoggerFactory.getLogger(Settings.class); + private static final Logger LOG = LoggerFactory.getLogger(SettingsProvider.class); private static final Path SETTINGS_DIR; private static final String SETTINGS_FILE = "settings.json"; @@ -52,12 +51,10 @@ public class SettingsProvider implements Provider { } } - private final DeferredCloser deferredCloser; private final ObjectMapper objectMapper; @Inject - public SettingsProvider(DeferredCloser deferredCloser, @Named("VaultJsonMapper") ObjectMapper objectMapper) { - this.deferredCloser = deferredCloser; + public SettingsProvider(@Named("VaultJsonMapper") ObjectMapper objectMapper) { this.objectMapper = objectMapper; } @@ -77,12 +74,12 @@ public class SettingsProvider implements Provider { final Path settingsPath = getSettingsPath(); final InputStream in = Files.newInputStream(settingsPath, StandardOpenOption.READ); settings = objectMapper.readValue(in, Settings.class); + LOG.info("Settings loaded from " + settingsPath); } catch (IOException e) { - LOG.warn("Failed to load settings, creating new one."); + LOG.info("Failed to load settings, creating new one."); settings = new Settings(); } - deferredCloser.closeLater(settings, this::save); - return settings; + return settings.withSaveCmd(this::save); } private void save(Settings settings) { @@ -94,6 +91,7 @@ public class SettingsProvider implements Provider { Files.createDirectories(settingsPath.getParent()); final OutputStream out = Files.newOutputStream(settingsPath, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE); objectMapper.writeValue(out, settings); + LOG.info("Settings saved to " + settingsPath); } catch (IOException e) { LOG.error("Failed to save settings.", e); } From 78f11b4a5e0bed50ad47f2e4ab95a1cfcd14359a Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Mon, 2 May 2016 16:01:28 +0200 Subject: [PATCH 07/15] added korean localization [ci skip] --- .../main/resources/localization_kr.properties | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 main/ui/src/main/resources/localization_kr.properties diff --git a/main/ui/src/main/resources/localization_kr.properties b/main/ui/src/main/resources/localization_kr.properties new file mode 100644 index 000000000..ecdfcf9fd --- /dev/null +++ b/main/ui/src/main/resources/localization_kr.properties @@ -0,0 +1,84 @@ +# Copyright (c) 2016 The Cryptomator Contributors +# This file is licensed under the terms of the MIT license. +# See the LICENSE.txt file for more info. +# +# Contributors: +# ChangHwan Kim + +app.name = Cryptomator +# main.fxml +main.emptyListInstructions = \uC5EC\uAE30\uB97C \uD074\uB9AD\uD558\uC5EC \uBCF4\uAD00\uD568 \uCD94\uAC00\uD558\uAE30 +main.directoryList.contextMenu.remove = \uBAA9\uB85D\uC5D0\uC11C \uC0AD\uC81C +main.directoryList.contextMenu.changePassword = \uBE44\uBC00\uBC88\uD638 \uBCC0\uACBD +main.addDirectory.contextMenu.new = \uC0C8 \uBCF4\uAD00\uD568 \uB9CC\uB4E4\uAE30 +main.addDirectory.contextMenu.open = \uAE30\uC874 \uBCF4\uAD00\uD568 \uC5F4\uAE30 +# welcome.fxml +welcome.checkForUpdates.label.currentlyChecking = \uC5C5\uB370\uC774\uD2B8 \uD655\uC778 +welcome.newVersionMessage = %s \uBC84\uC804\uC774 \uC0C8\uB85C \uB2E4\uC6B4\uB85C\uB4DC \uAC00\uB2A5\uD569\uB2C8\uB2E4. \uC9C0\uAE08 \uBC84\uC804\uC740 %s \uC785\uB2C8\uB2E4. +# initialize.fxml +initialize.label.password = \uBE44\uBC00\uBC88\uD638 +initialize.label.retypePassword = \uBE44\uBC00\uBC88\uD638 \uC7AC\uC785\uB825 +initialize.button.ok = \uBCF4\uAD00\uD568 \uB9CC\uB4E4\uAE30 +initialize.messageLabel.alreadyInitialized = \uC774\uBBF8 \uBCF4\uAD00\uD568\uC774 \uCD08\uAE30\uD654\uB418\uC5C8\uC2B5\uB2C8\uB2E4. +initialize.messageLabel.initializationFailed = \uBCF4\uAD00\uD568\uC744 \uCD08\uAE30\uD654\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uC790\uC138\uD55C \uC0AC\uD56D\uC740 \uB85C\uADF8 \uD30C\uC77C\uC744 \uCC38\uC870\uD558\uC138\uC694. +# notfound.fxml +notfound.label = \uBCF4\uAD00\uD568\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uC62E\uACA8\uC9C4 \uAC83\uC740 \uC544\uB2CC\uAC00\uC694? +# upgrade.fxml +upgrade.button = \uBCF4\uAD00\uD568 \uC5C5\uADF8\uB808\uC774\uB4DC +upgrade.version3dropBundleExtension.msg = \uC774 \uBCF4\uAD00\uD568\uC740 \uC0C8\uB85C\uC6B4 \uD615\uC2DD\uC73C\uB85C \uB2E4\uC2DC \uBC14\uB014 \uD544\uC694\uAC00 \uC788\uC2B5\uB2C8\uB2E4. "%1$s"\uC758 \uC774\uB984\uC740 "%2$s"\uB85C \uBC14\uB014 \uAC83\uC785\uB2C8\uB2E4. \uC9C4\uD589\uD558\uAE30 \uC804\uC5D0 \uB3D9\uAE30\uD654\uAC00 \uC644\uB8CC\uB418\uC5C8\uB294\uC9C0 \uB2E4\uC2DC \uD55C \uBC88 \uD655\uC778\uD574\uC8FC\uC2DC\uAE30 \uBC14\uB78D\uB2C8\uB2E4. +upgrade.version3dropBundleExtension.err.alreadyExists = \uC790\uB3D9 \uB9C8\uC774\uADF8\uB808\uC774\uC158 \uC2E4\uD328. "%s"\uB294 \uC774\uBBF8 \uC874\uC7AC\uD569\uB2C8\uB2E4. +# unlock.fxml +unlock.label.password = \uBE44\uBC00\uBC88\uD638 +unlock.label.mountName = \uB4DC\uB77C\uC774\uBE0C \uC774\uB984 +unlock.label.winDriveLetter = \uB4DC\uB77C\uC774\uBE0C \uBB38\uC790 +unlock.label.downloadsPageLink = \uBAA8\uB4E0 Cryptomator \uBC84\uC804 +unlock.label.advancedHeading = \uACE0\uAE09 \uC635\uC158 +unlock.button.unlock = \uBCF4\uAD00\uD568 \uD574\uC81C +unlock.button.advancedOptions.show = \uB354 \uB9CE\uC740 \uC635\uC158 +unlock.button.advancedOptions.hide = \uAE30\uBCF8 \uC635\uC158 +unlock.choicebox.winDriveLetter.auto = \uC790\uB3D9\uC73C\uB85C \uD560\uB2F9 +unlock.errorMessage.wrongPassword = \uD2C0\uB9B0 \uBE44\uBC00\uBC88\uD638 +unlock.errorMessage.mountingFailed = \uB9C8\uC6B4\uD2B8 \uC2E4\uD328. \uC790\uC138\uD55C \uC0AC\uD56D\uC740 \uB85C\uADF8 \uD30C\uC77C\uC744 \uCC38\uC870\uD558\uC138\uC694. +unlock.errorMessage.unsupportedKeyLengthInstallJCE = \uBCF5\uD638\uD654 \uC2E4\uD328. Oracle JCE Unlimited Strength Policy Files\uC744 \uC124\uCE58\uD558\uC138\uC694. +unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = \uC9C0\uC6D0\uB418\uC9C0 \uC54A\uB294 \uBCF4\uAD00\uD568. \uC774 \uBCF4\uAD00\uD568\uC740 \uC774\uC804 \uBC84\uC804\uC758 Cryptomator\uC5D0\uC11C \uC0DD\uC131\uB418\uC5C8\uC2B5\uB2C8\uB2E4. +unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = \uC9C0\uC6D0\uB418\uC9C0 \uC54A\uB294 \uBCF4\uAD00\uD568. \uC774 \uBCF4\uAD00\uD568\uC740 \uCD5C\uC2E0 \uBC84\uC804\uC758 Cryptomator\uC5D0\uC11C \uC0DD\uC131\uB418\uC5C8\uC2B5\uB2C8\uB2E4. +unlock.messageLabel.startServerFailed = WedDAV \uC11C\uBC84 \uC2DC\uC791 \uC2E4\uD328 +# change_password.fxml +changePassword.label.oldPassword = \uC774\uC804 \uBE44\uBC00\uBC88\uD638 +changePassword.label.newPassword = \uC0C8\uB85C\uC6B4 \uBE44\uBC00\uBC88\uD638 +changePassword.label.retypePassword = \uBE44\uBC00\uBC88\uD638 \uC7AC\uC785\uB825 +changePassword.label.downloadsPageLink = \uBAA8\uB4E0 Cryptomator \uBC84\uC804 +changePassword.button.change = \uBE44\uBC00\uBC88\uD638 \uBCC0\uACBD +changePassword.errorMessage.wrongPassword = \uD2C0\uB9B0 \uBE44\uBC00\uBC88\uD638 +changePassword.errorMessage.decryptionFailed = \uBCF5\uD638\uD654 \uC2E4\uD328 +changePassword.errorMessage.unsupportedKeyLengthInstallJCE = \uBCF5\uD638\uD654 \uC2E4\uD328. Oracle JCE Unlimited Strength Policy Files\uC744 \uC124\uCE58\uD558\uC138\uC694. +changePassword.errorMessage.unsupportedVersion.vaultOlderThanSoftware = \uC9C0\uC6D0\uB418\uC9C0 \uC54A\uB294 \uBCF4\uAD00\uD568. \uC774 \uBCF4\uAD00\uD568\uC740 \uC774\uC804 \uBC84\uC804\uC758 Cryptomator\uC5D0\uC11C \uC0DD\uC131\uB418\uC5C8\uC2B5\uB2C8\uB2E4. +changePassword.errorMessage.unsupportedVersion.softwareOlderThanVault = \uC9C0\uC6D0\uB418\uC9C0 \uC54A\uB294 \uBCF4\uAD00\uD568. \uC774 \uBCF4\uAD00\uD568\uC740 \uCD5C\uC2E0 \uBC84\uC804\uC758 Cryptomator\uC5D0\uC11C \uC0DD\uC131\uB418\uC5C8\uC2B5\uB2C8\uB2E4. +changePassword.infoMessage.success = \uBE44\uBC00\uBC88\uD638 \uBCC0\uACBD +# unlocked.fxml +unlocked.button.lock = \uBCF4\uAD00\uD568 \uC7A0\uADF8\uAE30 +unlocked.moreOptions.reveal = \uB4DC\uB77C\uC774\uBE0C \uD45C\uC2DC +unlocked.moreOptions.copyUrl = WebDAV \uC8FC\uC18C \uBCF5\uC0AC +unlocked.label.revealFailed = \uBA85\uB839 \uC2E4\uD328 +unlocked.label.unmountFailed = \uB4DC\uB77C\uC774\uBE0C \uCD94\uCD9C \uC2E4\uD328 +unlocked.label.statsEncrypted = \uC554\uD638\uD654\uB428 +unlocked.label.statsDecrypted = \uBCF5\uD638\uD654\uB428 +unlocked.ioGraph.yAxis.label = \uCC98\uB9AC\uB7C9 (MiB/s) +# mac_warnings.fxml +macWarnings.windowTitle = \uC704\uD5D8 - %s\uC5D0 \uC190\uC0C1\uB41C \uD30C\uC77C +macWarnings.message = Cryptomator\uAC00 \uB2E4\uC74C \uD30C\uC77C\uB4E4\uC5D0\uC11C \uC7A0\uC7AC\uC801\uC778 \uC190\uC0C1 \uC704\uD5D8\uC744 \uAC10\uC9C0\uD588\uC2B5\uB2C8\uB2E4. +macWarnings.moreInformationButton = \uB354 \uC54C\uC544\uBCF4\uAE30 +macWarnings.whitelistButton = \uC120\uD0DD \uD56D\uBAA9 \uAC15\uC81C \uBCF5\uD638\uD654 +# settings.fxml +settings.version.label = \uBC84\uC804 %s +settings.checkForUpdates.label = \uC5C5\uB370\uC774\uD2B8 \uD655\uC778 +settings.port.label = WebDAV \uD3EC\uD2B8 * +settings.port.prompt = 0 \= \uC790\uB3D9\uC73C\uB85C \uC120\uD0DD +settings.useipv6.label = IPv6 \uC0AC\uC6A9 +settings.requiresRestartLabel = * Cryptomator \uC7AC\uC2DC\uC791 \uD544\uC694 +# tray icon +tray.menu.open = \uC5F4\uAE30 +tray.menu.quit = \uC885\uB8CC +tray.infoMsg.title = \uACC4\uC18D \uC2E4\uD589 \uC911\uC785\uB2C8\uB2E4. +tray.infoMsg.msg = Cryptomator\uAC00 \uACC4\uC18D \uC2E4\uD589 \uC911\uC785\uB2C8\uB2E4. \uC885\uB8CC\uD558\uC2E4\uB824\uBA74 \uD2B8\uB808\uC774 \uC544\uC774\uCF58\uC5D0\uC11C \uD574\uC8FC\uC138\uC694. +tray.infoMsg.msg.osx = Cryptomator\uAC00 \uACC4\uC18D \uC2E4\uD589\uC911\uC785\uB2C8\uB2E4. \uC885\uB8CC\uD558\uC2E4\uB824\uBA74 \uBA54\uB274 \uBC14 \uC544\uC774\uCF58\uC5D0\uC11C \uD574\uC8FC\uC138\uC694. \ No newline at end of file From be2b63ab2a13b6e8fafacf259b67edcaec090c9d Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Mon, 2 May 2016 22:28:49 +0200 Subject: [PATCH 08/15] support for UTF-8 localization files --- .../cryptomator/ui/settings/Localization.java | 49 ++++++++++- .../de.txt} | 54 ++++++------ .../en.txt} | 0 .../es.txt} | 68 +++++++------- .../fr.txt} | 70 +++++++-------- .../ui/src/main/resources/localization/hu.txt | 84 ++++++++++++++++++ .../it.txt} | 36 ++++---- .../ui/src/main/resources/localization/kr.txt | 84 ++++++++++++++++++ .../pt.txt} | 14 +-- .../ui/src/main/resources/localization/ru.txt | 55 ++++++++++++ .../ui/src/main/resources/localization/sk.txt | 88 +++++++++++++++++++ .../main/resources/localization_hu.properties | 84 ------------------ .../main/resources/localization_kr.properties | 84 ------------------ .../main/resources/localization_ru.properties | 55 ------------ .../main/resources/localization_sk.properties | 85 ------------------ 15 files changed, 478 insertions(+), 432 deletions(-) rename main/ui/src/main/resources/{localization_de.properties => localization/de.txt} (65%) rename main/ui/src/main/resources/{localization.properties => localization/en.txt} (100%) rename main/ui/src/main/resources/{localization_es.properties => localization/es.txt} (57%) rename main/ui/src/main/resources/{localization_fr.properties => localization/fr.txt} (56%) create mode 100644 main/ui/src/main/resources/localization/hu.txt rename main/ui/src/main/resources/{localization_it.properties => localization/it.txt} (71%) create mode 100644 main/ui/src/main/resources/localization/kr.txt rename main/ui/src/main/resources/{localization_pt.properties => localization/pt.txt} (81%) create mode 100644 main/ui/src/main/resources/localization/ru.txt create mode 100644 main/ui/src/main/resources/localization/sk.txt delete mode 100644 main/ui/src/main/resources/localization_hu.properties delete mode 100644 main/ui/src/main/resources/localization_kr.properties delete mode 100644 main/ui/src/main/resources/localization_ru.properties delete mode 100644 main/ui/src/main/resources/localization_sk.properties diff --git a/main/ui/src/main/java/org/cryptomator/ui/settings/Localization.java b/main/ui/src/main/java/org/cryptomator/ui/settings/Localization.java index d12082ef5..1c2fbf8d5 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/settings/Localization.java +++ b/main/ui/src/main/java/org/cryptomator/ui/settings/Localization.java @@ -1,27 +1,70 @@ package org.cryptomator.ui.settings; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.UncheckedIOException; +import java.nio.charset.StandardCharsets; +import java.util.Collection; +import java.util.Collections; import java.util.Enumeration; +import java.util.Locale; +import java.util.Objects; +import java.util.PropertyResourceBundle; import java.util.ResourceBundle; import javax.inject.Inject; import javax.inject.Singleton; +import org.apache.commons.collections4.CollectionUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + @Singleton public class Localization extends ResourceBundle { + private static final Logger LOG = LoggerFactory.getLogger(Localization.class); + + private static final String LOCALIZATION_DEFAULT_FILE = "/localization/en.txt"; + private static final String LOCALIZATION_FILENAME_FMT = "/localization/%s.txt"; + private static final String LOCALIZATION_FILE = String.format(LOCALIZATION_FILENAME_FMT, Locale.getDefault().getLanguage()); + + private final ResourceBundle fallback; + private final ResourceBundle localized; + @Inject public Localization() { - this.parent = ResourceBundle.getBundle("localization"); + try (InputStream in = getClass().getResourceAsStream(LOCALIZATION_DEFAULT_FILE)) { + Objects.requireNonNull(in); + Reader reader = new InputStreamReader(in, StandardCharsets.UTF_8); + this.fallback = new PropertyResourceBundle(reader); + LOG.info("Loaded localization from {}", LOCALIZATION_FILE); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + + try (InputStream in = getClass().getResourceAsStream(LOCALIZATION_FILE)) { + if (in != null) { + Reader reader = new InputStreamReader(in, StandardCharsets.UTF_8); + this.localized = new PropertyResourceBundle(reader); + } else { + this.localized = this.fallback; + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } } @Override protected Object handleGetObject(String key) { - return parent.getObject(key); + return localized.containsKey(key) ? localized.getObject(key) : fallback.getObject(key); } @Override public Enumeration getKeys() { - return parent.getKeys(); + Collection keys = CollectionUtils.union(localized.keySet(), fallback.keySet()); + return Collections.enumeration(keys); } } diff --git a/main/ui/src/main/resources/localization_de.properties b/main/ui/src/main/resources/localization/de.txt similarity index 65% rename from main/ui/src/main/resources/localization_de.properties rename to main/ui/src/main/resources/localization/de.txt index a9b0ad58c..d656e86c0 100644 --- a/main/ui/src/main/resources/localization_de.properties +++ b/main/ui/src/main/resources/localization/de.txt @@ -1,7 +1,7 @@ # Copyright (c) 2016 The Cryptomator Contributors # This file is licensed under the terms of the MIT license. # See the LICENSE.txt file for more info. -# +# # Contributors: # Markus Kreusch # Michael Schmetter @@ -10,17 +10,17 @@ app.name = Cryptomator # main.fxml -main.emptyListInstructions = Klicken Sie hier, um neue Tresore hinzuzufügen +main.emptyListInstructions = Klicken Sie hier, um neue Tresore hinzuzufĂĽgen main.directoryList.contextMenu.remove = Aus Liste entfernen -main.directoryList.contextMenu.changePassword = Passwort ändern +main.directoryList.contextMenu.changePassword = Passwort ändern main.addDirectory.contextMenu.new = Tresor erstellen -main.addDirectory.contextMenu.open = Tresor öffnen +main.addDirectory.contextMenu.open = Tresor öffnen # welcome.fxml -welcome.checkForUpdates.label.currentlyChecking = Auf Updates prüfen... +welcome.checkForUpdates.label.currentlyChecking = Auf Updates prĂĽfen... welcome.newVersionMessage = Version %s kann heruntergeladen werden. Aktuelle Version %s. # initialize.fxml initialize.label.password = Passwort -initialize.label.retypePassword = Passwort bestätigen +initialize.label.retypePassword = Passwort bestätigen initialize.button.ok = Tresor erstellen initialize.messageLabel.alreadyInitialized = Tresor bereits vorhanden initialize.messageLabel.initializationFailed = Fehler beim Initialisieren. Details in der Log-Datei. @@ -42,47 +42,47 @@ unlock.button.advancedOptions.hide = Weniger Optionen unlock.choicebox.winDriveLetter.auto = Automatisch ermitteln unlock.errorMessage.wrongPassword = Falsches Passwort unlock.errorMessage.mountingFailed = Verbindung fehlgeschlagen. Details in der Log-Datei. -unlock.errorMessage.unsupportedKeyLengthInstallJCE = Entschlüsselung fehlgeschlagen. Bitte die Oracle JCE Unlimited Strength Policy installieren. -unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Tresor nicht unterstützt. Der Tresor wurde mit einer älteren Version von Cryptomator erstellt. -unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = Tresor nicht unterstützt. Der Tresor wurde mit einer neueren Version von Cryptomator erstellt. +unlock.errorMessage.unsupportedKeyLengthInstallJCE = EntschlĂĽsselung fehlgeschlagen. Bitte die Oracle JCE Unlimited Strength Policy installieren. +unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Tresor nicht unterstĂĽtzt. Der Tresor wurde mit einer älteren Version von Cryptomator erstellt. +unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = Tresor nicht unterstĂĽtzt. Der Tresor wurde mit einer neueren Version von Cryptomator erstellt. unlock.messageLabel.startServerFailed = Starten des WebDAV-Servers fehlgeschlagen. # change_password.fxml changePassword.label.oldPassword = Altes Passwort changePassword.label.newPassword = Neues Passwort -changePassword.label.retypePassword = Passwort bestätigen +changePassword.label.retypePassword = Passwort bestätigen changePassword.label.downloadsPageLink = Alle Cryptomator Versionen -changePassword.button.change = Passwort ändern +changePassword.button.change = Passwort ändern changePassword.errorMessage.wrongPassword = Falsches Passwort -changePassword.errorMessage.decryptionFailed = Entschlüsselung fehlgeschlagen -changePassword.errorMessage.unsupportedKeyLengthInstallJCE = Entschlüsselung fehlgeschlagen. Bitte die Oracle JCE Unlimited Strength Policy installieren. -changePassword.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Tresor nicht unterstützt. Der Tresor wurde mit einer älteren Version von Cryptomator erstellt. -changePassword.errorMessage.unsupportedVersion.softwareOlderThanVault = Tresor nicht unterstützt. Der Tresor wurde mit einer neueren Version von Cryptomator erstellt. -changePassword.infoMessage.success = Passwort geändert +changePassword.errorMessage.decryptionFailed = EntschlĂĽsselung fehlgeschlagen +changePassword.errorMessage.unsupportedKeyLengthInstallJCE = EntschlĂĽsselung fehlgeschlagen. Bitte die Oracle JCE Unlimited Strength Policy installieren. +changePassword.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Tresor nicht unterstĂĽtzt. Der Tresor wurde mit einer älteren Version von Cryptomator erstellt. +changePassword.errorMessage.unsupportedVersion.softwareOlderThanVault = Tresor nicht unterstĂĽtzt. Der Tresor wurde mit einer neueren Version von Cryptomator erstellt. +changePassword.infoMessage.success = Passwort geändert # unlocked.fxml unlocked.button.lock = Tresor sperren unlocked.moreOptions.reveal = Laufwerk anzeigen unlocked.moreOptions.copyUrl = WebDAV-URL kopieren unlocked.label.revealFailed = Befehl fehlgeschlagen unlocked.label.unmountFailed = Trennen des Laufwerks fehlgeschlagen -unlocked.label.statsEncrypted = verschlüsselt -unlocked.label.statsDecrypted = entschlüsselt +unlocked.label.statsEncrypted = verschlĂĽsselt +unlocked.label.statsDecrypted = entschlĂĽsselt unlocked.ioGraph.yAxis.label = Durchsatz (MiB/s) # mac_warnings.fxml macWarnings.windowTitle = Achtung - Kompromittierte Datei in %s # "potentially detected" or "potentially malicious"? -macWarnings.message = Cryptomator hat möglicherweise unerlaubte Veränderungen in den folgenden Dateien erkannt\: +macWarnings.message = Cryptomator hat möglicherweise unerlaubte Veränderungen in den folgenden Dateien erkannt\: macWarnings.moreInformationButton = Mehr erfahren -macWarnings.whitelistButton = Trotzdem entschlüsseln +macWarnings.whitelistButton = Trotzdem entschlĂĽsseln # settings.fxml settings.version.label = Version %s -settings.checkForUpdates.label = Auf Updates prüfen +settings.checkForUpdates.label = Auf Updates prĂĽfen settings.port.label = WebDAV Port * -settings.port.prompt = 0 \= Automatisch wählen +settings.port.prompt = 0 \= Automatisch wählen settings.useipv6.label = IPv6-Literal nutzen -settings.requiresRestartLabel = * benötigt Neustart von Cryptomator +settings.requiresRestartLabel = * benötigt Neustart von Cryptomator # tray icon -tray.menu.open = Öffnen +tray.menu.open = Ă–ffnen tray.menu.quit = Beenden -tray.infoMsg.title = Cryptomator läuft noch -tray.infoMsg.msg = Cryptomator läuft noch. Mit dem Tray-Icon beenden. -tray.infoMsg.msg.osx = Cryptomator läuft noch. Über die Menüleiste beenden. \ No newline at end of file +tray.infoMsg.title = Cryptomator läuft noch +tray.infoMsg.msg = Cryptomator läuft noch. Mit dem Tray-Icon beenden. +tray.infoMsg.msg.osx = Cryptomator läuft noch. Ăśber die MenĂĽleiste beenden. diff --git a/main/ui/src/main/resources/localization.properties b/main/ui/src/main/resources/localization/en.txt similarity index 100% rename from main/ui/src/main/resources/localization.properties rename to main/ui/src/main/resources/localization/en.txt diff --git a/main/ui/src/main/resources/localization_es.properties b/main/ui/src/main/resources/localization/es.txt similarity index 57% rename from main/ui/src/main/resources/localization_es.properties rename to main/ui/src/main/resources/localization/es.txt index 18e960a30..4433abb62 100644 --- a/main/ui/src/main/resources/localization_es.properties +++ b/main/ui/src/main/resources/localization/es.txt @@ -8,56 +8,56 @@ app.name = Cryptomator # main.fxml -main.emptyListInstructions = Click aquí para ańadir una caja fuerte +main.emptyListInstructions = Click aquĂ­ para añadir una caja fuerte # should it be imperative? main.directoryList.contextMenu.remove = Eliminar de la lista -main.directoryList.contextMenu.changePassword = Cambiar la contraseńa +main.directoryList.contextMenu.changePassword = Cambiar la contraseña main.addDirectory.contextMenu.new = Crear una nueva caja fuerte main.addDirectory.contextMenu.open = Abrir una caja fuerte existente # welcome.fxml -welcome.checkForUpdates.label.currentlyChecking = Chequando por actualizaciónes... +welcome.checkForUpdates.label.currentlyChecking = Chequando por actualizaciĂłnes... welcome.newVersionMessage = Se puede bajar version %s. Este es %s. # initialize.fxml -initialize.label.password = Contraseńa -initialize.label.retypePassword = Reintroduzca contraseńa +initialize.label.password = Contraseña +initialize.label.retypePassword = Reintroduzca contraseña initialize.button.ok = Crear caja fuerte -initialize.messageLabel.alreadyInitialized = Caja fuerte ya está inicializado -initialize.messageLabel.initializationFailed = No se pudo inicializar la caja fuerte. Ver archivo de registro para detalles. +initialize.messageLabel.alreadyInitialized = Caja fuerte ya está inicializado +initialize.messageLabel.initializationFailed = No se pudo inicializar la caja fuerte. Ver archivo de registro para detalles. # notfound.fxml -notfound.label = No se pudo encontrar la caja fuerte. Se movió a otro lugar? +notfound.label = No se pudo encontrar la caja fuerte. Se moviĂł a otro lugar? # upgrade.fxml upgrade.button = Actualizar caja fuerte -upgrade.version3dropBundleExtension.msg = Este caja fuerte se debe actualizar a un nuevo formato.\n"%1$s" se renombra a "%2$s".\nPor favor aseguranse que la sincronización ya se terminó antes de continuar. -upgrade.version3dropBundleExtension.err.alreadyExists = Migración automática ha fallado.\n"%s" ya existe. +upgrade.version3dropBundleExtension.msg = Este caja fuerte se debe actualizar a un nuevo formato.\n"%1$s" se renombra a "%2$s".\nPor favor aseguranse que la sincronizaciĂłn ya se terminĂł antes de continuar. +upgrade.version3dropBundleExtension.err.alreadyExists = MigraciĂłn automática ha fallado.\n"%s" ya existe. # unlock.fxml -unlock.label.password = Contraseńa +unlock.label.password = Contraseña unlock.label.mountName = Nombre del disco unlock.label.winDriveLetter = Letra del disco unlock.label.downloadsPageLink = Todas las versiones de Cryptomator unlock.label.advancedHeading = Opciones avanzadas unlock.button.unlock = Abrir caja fuerte -unlock.button.advancedOptions.show = Más opciones +unlock.button.advancedOptions.show = Más opciones unlock.button.advancedOptions.hide = Menos opciones -unlock.choicebox.winDriveLetter.auto = Asignar automáticamente -unlock.errorMessage.wrongPassword = Contraseńa incorrecta +unlock.choicebox.winDriveLetter.auto = Asignar automáticamente +unlock.errorMessage.wrongPassword = Contraseña incorrecta unlock.errorMessage.mountingFailed = Monteo ha fallado. Ver archivo del registro para detalles. -unlock.errorMessage.unsupportedKeyLengthInstallJCE = Decifración ha fallado. Por favor instala archivos de la Oracle JCE Unlimited Strength Policy. -unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Caja fuerte insupportado. Este caja se ha creado con una versión pasada de Cryptomator. -unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = Caja fuerte insupportado. Este caja se ha creado con una versión nueva de Cryptomator. -unlock.messageLabel.startServerFailed = Iniciación del servidor de WebDAV ha fallado. +unlock.errorMessage.unsupportedKeyLengthInstallJCE = DecifraciĂłn ha fallado. Por favor instala archivos de la Oracle JCE Unlimited Strength Policy. +unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Caja fuerte insupportado. Este caja se ha creado con una versiĂłn pasada de Cryptomator. +unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = Caja fuerte insupportado. Este caja se ha creado con una versiĂłn nueva de Cryptomator. +unlock.messageLabel.startServerFailed = IniciaciĂłn del servidor de WebDAV ha fallado. # change_password.fxml -changePassword.label.oldPassword = Contraseńa anterior -# Can also use "current password" = "contraseńa actual" -changePassword.label.newPassword = Nueva contraseńa -changePassword.label.retypePassword = Reintroduzca contraseńa +changePassword.label.oldPassword = Contraseña anterior +# Can also use "current password" = "contraseña actual" +changePassword.label.newPassword = Nueva contraseña +changePassword.label.retypePassword = Reintroduzca contraseña changePassword.label.downloadsPageLink = Todas las versiones de Cryptomator -changePassword.button.change = Cambiar contraseńa -changePassword.errorMessage.wrongPassword = Contraseńa incorrecta -changePassword.errorMessage.decryptionFailed = Decifración ha fallado -changePassword.errorMessage.unsupportedKeyLengthInstallJCE = Decifración ha fallado. Por favor instala Oracle JCE Unlimited Strength Policy. -changePassword.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Caja fuerte insupportado. Este caja se ha creado con una versión pasada de Cryptomator. -changePassword.errorMessage.unsupportedVersion.softwareOlderThanVault = Caja fuerte insupportado. Este caja se ha creado con una versión nueva de Cryptomator. -changePassword.infoMessage.success = Contraseńa se ha cambiado +changePassword.button.change = Cambiar contraseña +changePassword.errorMessage.wrongPassword = Contraseña incorrecta +changePassword.errorMessage.decryptionFailed = DecifraciĂłn ha fallado +changePassword.errorMessage.unsupportedKeyLengthInstallJCE = DecifraciĂłn ha fallado. Por favor instala Oracle JCE Unlimited Strength Policy. +changePassword.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Caja fuerte insupportado. Este caja se ha creado con una versiĂłn pasada de Cryptomator. +changePassword.errorMessage.unsupportedVersion.softwareOlderThanVault = Caja fuerte insupportado. Este caja se ha creado con una versiĂłn nueva de Cryptomator. +changePassword.infoMessage.success = Contraseña se ha cambiado # unlocked.fxml unlocked.button.lock = Encerrar caja fuerte unlocked.moreOptions.reveal = Revelar disco @@ -70,18 +70,18 @@ unlocked.ioGraph.yAxis.label = Procesamiento (MiB/s) # mac_warnings.fxml macWarnings.windowTitle = Peligro - archivo corrupto en %s macWarnings.message = Cryptomator ha detectado corrupciones malciosas en los seguientes archivos\: -macWarnings.moreInformationButton = Aprende más +macWarnings.moreInformationButton = Aprende más macWarnings.whitelistButton = Decifrar selecionado de todos modos # settings.fxml settings.version.label = Version %s settings.checkForUpdates.label = Chequear por actualizaciones settings.port.label = Puerta de WebDAV * -settings.port.prompt = 0 \= Elige automáticamente +settings.port.prompt = 0 \= Elige automáticamente settings.useipv6.label = Usa literal de IPv6 settings.requiresRestartLabel = * Cryptomator se necesita reiniciar # tray icon tray.menu.open = Abrir tray.menu.quit = Salir -tray.infoMsg.title = Todavía en ejecución -tray.infoMsg.msg = Cryptomator todavía esta en ejecución. Sale del icono del tray. -tray.infoMsg.msg.osx = Cryptomator todavía esta en ejecución. Sale del icono de la barra del menú. +tray.infoMsg.title = TodavĂ­a en ejecuciĂłn +tray.infoMsg.msg = Cryptomator todavĂ­a esta en ejecuciĂłn. Sale del icono del tray. +tray.infoMsg.msg.osx = Cryptomator todavĂ­a esta en ejecuciĂłn. Sale del icono de la barra del menĂş. diff --git a/main/ui/src/main/resources/localization_fr.properties b/main/ui/src/main/resources/localization/fr.txt similarity index 56% rename from main/ui/src/main/resources/localization_fr.properties rename to main/ui/src/main/resources/localization/fr.txt index 8815f6d48..17aec69f4 100644 --- a/main/ui/src/main/resources/localization_fr.properties +++ b/main/ui/src/main/resources/localization/fr.txt @@ -1,9 +1,9 @@ # Copyright (c) 2016 The Cryptomator Contributors # This file is licensed under the terms of the MIT license. # See the LICENSE.txt file for more info. -# +# # Contributors: -# Jean-Noël Charon +# Jean-NoĂ«l Charon # Olivier Thomasson # vesparny @@ -12,75 +12,75 @@ app.name = Cryptomator main.emptyListInstructions = Cliquez ici pour ajouter un coffre main.directoryList.contextMenu.remove = Retirer de la liste main.directoryList.contextMenu.changePassword = Changer le mot de passe -main.addDirectory.contextMenu.new = Créer un nouveau coffre +main.addDirectory.contextMenu.new = CrĂ©er un nouveau coffre main.addDirectory.contextMenu.open = Ouvrir un coffre existant # welcome.fxml -welcome.checkForUpdates.label.currentlyChecking = Recherche de mise ŕ jour... -welcome.newVersionMessage = La version %s peut-ętre téléchargée. Il s'agit de %s. +welcome.checkForUpdates.label.currentlyChecking = Recherche de mise Ă  jour... +welcome.newVersionMessage = La version %s peut-ĂŞtre tĂ©lĂ©chargĂ©e. Il s'agit de %s. # initialize.fxml initialize.label.password = Mot de passe initialize.label.retypePassword = Confirmation -initialize.button.ok = Créer le coffre -initialize.messageLabel.alreadyInitialized = Coffre déjŕ initialisé -initialize.messageLabel.initializationFailed = Impossible d'initialiser le coffre. Voir le fichier de log pour plus de détails. +initialize.button.ok = CrĂ©er le coffre +initialize.messageLabel.alreadyInitialized = Coffre dĂ©jĂ  initialisĂ© +initialize.messageLabel.initializationFailed = Impossible d'initialiser le coffre. Voir le fichier de log pour plus de dĂ©tails. # notfound.fxml -notfound.label = Coffre introuvable. A t'il été déplacé? +notfound.label = Coffre introuvable. A t'il Ă©tĂ© dĂ©placĂ©? # upgrade.fxml -upgrade.button = Mettre ŕ niveau -upgrade.version3dropBundleExtension.msg = Ce coffre doit ętre converti dans un format plus récent.\n"%1$s" sera renommé en "%2$s".\nAssurez-vous que la synchronisation est terminée avant de continuer. -upgrade.version3dropBundleExtension.err.alreadyExists = La conversion automatique a échoué.\n"%s" existe déjŕ. +upgrade.button = Mettre Ă  niveau +upgrade.version3dropBundleExtension.msg = Ce coffre doit ĂŞtre converti dans un format plus rĂ©cent.\n"%1$s" sera renommĂ© en "%2$s".\nAssurez-vous que la synchronisation est terminĂ©e avant de continuer. +upgrade.version3dropBundleExtension.err.alreadyExists = La conversion automatique a Ă©chouĂ©.\n"%s" existe dĂ©jĂ . # unlock.fxml unlock.label.password = Mot de passe unlock.label.mountName = Nom du lecteur unlock.label.winDriveLetter = Lettre du lecteur unlock.label.downloadsPageLink = Toutes les versions de Cryptomator -unlock.label.advancedHeading = Options avancées -unlock.button.unlock = Déverrouiller le coffre +unlock.label.advancedHeading = Options avancĂ©es +unlock.button.unlock = DĂ©verrouiller le coffre unlock.button.advancedOptions.show = Plus d'options unlock.button.advancedOptions.hide = Moins d'options unlock.choicebox.winDriveLetter.auto = Assigner automatiquement unlock.errorMessage.wrongPassword = Mot de passe incorrect -unlock.errorMessage.mountingFailed = Echec du montage. Voir le fichier de log pour plus de détails. -unlock.errorMessage.unsupportedKeyLengthInstallJCE = Echec du décryptage. Veuillez installer la Policy Oracle "JCE Unlimited Strength Policy". -unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Coffre non supporté. Ce coffre a été créé avec une ancienne version de Cryptomator. -unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = Coffre non supporté. Ce coffre a été créé avec une version de Cryptomator plus récente. -unlock.messageLabel.startServerFailed = Le serveur WebDAV n'a pas pu démarrer. +unlock.errorMessage.mountingFailed = Echec du montage. Voir le fichier de log pour plus de dĂ©tails. +unlock.errorMessage.unsupportedKeyLengthInstallJCE = Echec du dĂ©cryptage. Veuillez installer la Policy Oracle "JCE Unlimited Strength Policy". +unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Coffre non supportĂ©. Ce coffre a Ă©tĂ© créé avec une ancienne version de Cryptomator. +unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = Coffre non supportĂ©. Ce coffre a Ă©tĂ© créé avec une version de Cryptomator plus rĂ©cente. +unlock.messageLabel.startServerFailed = Le serveur WebDAV n'a pas pu dĂ©marrer. # change_password.fxml changePassword.label.oldPassword = Ancien mot de passe changePassword.label.newPassword = Nouveau mot de passe -changePassword.label.retypePassword = Vérification +changePassword.label.retypePassword = VĂ©rification changePassword.label.downloadsPageLink = Toutes les versions de Cryptomator changePassword.button.change = Modification du mot de masse changePassword.errorMessage.wrongPassword = Mot de passe incorrect -changePassword.errorMessage.decryptionFailed = Echec du décryptage -changePassword.errorMessage.unsupportedKeyLengthInstallJCE = Echec du décryptage. Veuillez installer la Policy Oracle "JCE Unlimited Strength Policy". -changePassword.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Coffre non supporté. Ce coffre a été créé avec une ancienne version de Cryptomator. -changePassword.errorMessage.unsupportedVersion.softwareOlderThanVault = Coffre non supporté. Ce coffre a été créé avec une version de Cryptomator plus récente. +changePassword.errorMessage.decryptionFailed = Echec du dĂ©cryptage +changePassword.errorMessage.unsupportedKeyLengthInstallJCE = Echec du dĂ©cryptage. Veuillez installer la Policy Oracle "JCE Unlimited Strength Policy". +changePassword.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Coffre non supportĂ©. Ce coffre a Ă©tĂ© créé avec une ancienne version de Cryptomator. +changePassword.errorMessage.unsupportedVersion.softwareOlderThanVault = Coffre non supportĂ©. Ce coffre a Ă©tĂ© créé avec une version de Cryptomator plus rĂ©cente. changePassword.infoMessage.success = Password changed # unlocked.fxml unlocked.button.lock = Verrouiller le coffre unlocked.moreOptions.reveal = Voir le lecteur unlocked.moreOptions.copyUrl = Copier l'URL WebDAV unlocked.label.revealFailed = Echec de la commande -unlocked.label.unmountFailed = Echec de l'éjection du lecteur -unlocked.label.statsEncrypted = crypté -unlocked.label.statsDecrypted = décryptage -unlocked.ioGraph.yAxis.label = Débit (MiB/s) +unlocked.label.unmountFailed = Echec de l'Ă©jection du lecteur +unlocked.label.statsEncrypted = cryptĂ© +unlocked.label.statsDecrypted = dĂ©cryptage +unlocked.ioGraph.yAxis.label = DĂ©bit (MiB/s) # mac_warnings.fxml macWarnings.windowTitle = Attention - Fichier corrompu dans %s -macWarnings.message = Cryptomator a détecté des corruptions de données dans les fichiers suivants\: +macWarnings.message = Cryptomator a dĂ©tectĂ© des corruptions de donnĂ©es dans les fichiers suivants\: macWarnings.moreInformationButton = En savoir plus -macWarnings.whitelistButton = Décrypter tout de męme +macWarnings.whitelistButton = DĂ©crypter tout de mĂŞme # settings.fxml settings.version.label = Version %s -settings.checkForUpdates.label = Vérif. des mises ŕ jour +settings.checkForUpdates.label = VĂ©rif. des mises Ă  jour settings.port.label = Port WebDAV * settings.port.prompt = 0 \= Choix automatique -settings.useipv6.label = Utiliser un litéral IPv6 -settings.requiresRestartLabel = * Redémarrage requis +settings.useipv6.label = Utiliser un litĂ©ral IPv6 +settings.requiresRestartLabel = * RedĂ©marrage requis # tray icon tray.menu.open = Ouvrir tray.menu.quit = Quitter tray.infoMsg.title = Toujours en fonctionnement -tray.infoMsg.msg = Cryptomator est toujours en fonctionnement. Utiliser l'icône de la barre des tâches pour quitter. -tray.infoMsg.msg.osx = Cryptomator est toujours en fonctionnement. Utilisez la barre de menu pour quitter. \ No newline at end of file +tray.infoMsg.msg = Cryptomator est toujours en fonctionnement. Utiliser l'icĂ´ne de la barre des tâches pour quitter. +tray.infoMsg.msg.osx = Cryptomator est toujours en fonctionnement. Utilisez la barre de menu pour quitter. diff --git a/main/ui/src/main/resources/localization/hu.txt b/main/ui/src/main/resources/localization/hu.txt new file mode 100644 index 000000000..86deb76a0 --- /dev/null +++ b/main/ui/src/main/resources/localization/hu.txt @@ -0,0 +1,84 @@ +# Copyright (c) 2016 The Cryptomator Contributors +# This file is licensed under the terms of the MIT license. +# See the LICENSE.txt file for more info. +# +# Contributors: +# Roland Burda + +app.name = Cryptomator +# main.fxml +main.emptyListInstructions = Kattints ide egy szĂ©f lĂ©trehozásához +main.directoryList.contextMenu.remove = EltávolĂ­tás listábĂłl +main.directoryList.contextMenu.changePassword = JelszĂł megváltoztatása +main.addDirectory.contextMenu.new = Ăšj szĂ©f lĂ©trehozása +main.addDirectory.contextMenu.open = LĂ©tez\u0151 szĂ©f megnyitása +# welcome.fxml +welcome.checkForUpdates.label.currentlyChecking = FrissĂ­tĂ©sek keresĂ©se... +welcome.newVersionMessage = Ăšj verziĂł Ă©rhet\u0151 el\: %s. Jelenlegi verziĂł\: %s. +# initialize.fxml +initialize.label.password = JelszĂł +initialize.label.retypePassword = JelszĂł ismĂ©t +initialize.button.ok = SzĂ©f lĂ©trehozása +initialize.messageLabel.alreadyInitialized = A szĂ©f már meg van nyitva +initialize.messageLabel.initializationFailed = Nem sikerĂĽlt megnyitni a szĂ©fet. További informáciĂł a naplĂłfájlban. +# notfound.fxml +notfound.label = SzĂ©f nem találhatĂł. LehetsĂ©ges, hogy áthelyezĂ©sre kerĂĽlt? +# upgrade.fxml +upgrade.button = SzĂ©f frissĂ­tĂ©se +upgrade.version3dropBundleExtension.msg = A szĂ©f Ăşj verziĂłra törtĂ©n\u0151 migráciĂłja szĂĽksĂ©ges. "%1$s" a következ\u0151re lesz átnevezve\: "%2$s". KĂ©rlek gy\u0151z\u0151dj meg a szinkronizáciĂł befejeztĂ©r\u0151l, miel\u0151tt más m\u0171veletet vĂ©geznĂ©l. +upgrade.version3dropBundleExtension.err.alreadyExists = Automatikus migráciĂł meghĂ­usĂşlt. "%s" már lĂ©tezik. +# unlock.fxml +unlock.label.password = JelszĂł +unlock.label.mountName = MeghajtĂł neve +unlock.label.winDriveLetter = MeghajtĂł bet\u0171jele +unlock.label.downloadsPageLink = Ă–sszes Cryptomator verziĂł +unlock.label.advancedHeading = HaladĂł beállĂ­tások +unlock.button.unlock = SzĂ©f feloldása +unlock.button.advancedOptions.show = További beállĂ­tások +unlock.button.advancedOptions.hide = AlapbeállĂ­tások +unlock.choicebox.winDriveLetter.auto = Automatikus hozzárendelĂ©s +unlock.errorMessage.wrongPassword = Hibás jelszĂł +unlock.errorMessage.mountingFailed = MeghajtĂł felcsatolása sikertelen. További informáciĂłk a naplĂłfájlban. +unlock.errorMessage.unsupportedKeyLengthInstallJCE = A titkosĂ­tás feloldása sikertelen. KĂ©rlek telepĂ­tsd a "Oracle JCE Unlimited Strength Policy Files"-t. +unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Nem támogatott szĂ©f. Ez a szĂ©f a Cryptomator egy korábbi verziĂłjával kerĂĽlt lĂ©trehozásra. +unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = Nem támogatott szĂ©f. Ez a szĂ©f a Cryptomator egy Ăşjabb verziĂłjával kerĂĽlt lĂ©trehozásra. +unlock.messageLabel.startServerFailed = WebDAV szerver indĂ­tása sikertelen. +# change_password.fxml +changePassword.label.oldPassword = RĂ©gi jelszĂł +changePassword.label.newPassword = Ăšj jelszĂł +changePassword.label.retypePassword = Ăšj jelszĂł ismĂ©t +changePassword.label.downloadsPageLink = Ă–sszes Cryptomator verziĂł +changePassword.button.change = JelszĂł megváltoztatása +changePassword.errorMessage.wrongPassword = Hibás jelszĂł +changePassword.errorMessage.decryptionFailed = A titkosĂ­tás feloldása meghĂ­usĂşlt +changePassword.errorMessage.unsupportedKeyLengthInstallJCE = A titkosĂ­tás feloldása sikertelen. KĂ©rlek telepĂ­tsd a "Oracle JCE Unlimited Strength Policy"-t. +changePassword.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Nem támogatott szĂ©f. Ez a szĂ©f a Cryptomator egy korábbi verziĂłjával kerĂĽlt lĂ©trehozásra. +changePassword.errorMessage.unsupportedVersion.softwareOlderThanVault = Nem támogatott szĂ©f. Ez a szĂ©f a Cryptomator egy Ăşjabb verziĂłjával kerĂĽlt lĂ©trehozásra. +changePassword.infoMessage.success = JelszĂł megváltoztatva +# unlocked.fxml +unlocked.button.lock = SzĂ©f lezárása +unlocked.moreOptions.reveal = MeghajtĂł felfedĂ©se +unlocked.moreOptions.copyUrl = WebDAV URL másolása +unlocked.label.revealFailed = Parancs meghĂ­usĂşlt +unlocked.label.unmountFailed = MeghajtĂł leválasztása sikertelen +unlocked.label.statsEncrypted = titkosĂ­tott +unlocked.label.statsDecrypted = titkosĂ­tás feloldva +unlocked.ioGraph.yAxis.label = TeljesĂ­tmĂ©ny (MiB/s) +# mac_warnings.fxml +macWarnings.windowTitle = VeszĂ©ly - Korrupt fájl a következ\u0151ben\: %s +macWarnings.message = Cryptomator potenciálisan rosszindulatĂş hibákat fedezett fel a következ\u0151 fájlokban\: +macWarnings.moreInformationButton = Tudj meg többet +macWarnings.whitelistButton = Kiválasztottak titkosĂ­tásának feloldása mindenkĂ©pp +# settings.fxml +settings.version.label = VerziĂł\: %s +settings.checkForUpdates.label = FrissĂ­tĂ©sek keresĂ©se +settings.port.label = WebDAV Port * +settings.port.prompt = 0 \= Automatikus választás +settings.useipv6.label = Literális IPv6 használata +settings.requiresRestartLabel = * Cryptomator ĂşjraindĂ­tása szĂĽksĂ©ges +# tray icon +tray.menu.open = Megnyit +tray.menu.quit = KilĂ©pĂ©s +tray.infoMsg.title = M\u0171velet folyamatban +tray.infoMsg.msg = Cryptomator mĂ©g fut. A tálcán találhatĂł ikon segĂ­tsĂ©gĂ©vel bezárhatod. +tray.infoMsg.msg.osx = Cryptomator mĂ©g fut. A menĂĽsávban találhatĂł ikon segĂ­tsĂ©gĂ©vel bezárhatod. diff --git a/main/ui/src/main/resources/localization_it.properties b/main/ui/src/main/resources/localization/it.txt similarity index 71% rename from main/ui/src/main/resources/localization_it.properties rename to main/ui/src/main/resources/localization/it.txt index 06ac22ade..1448d8f56 100644 --- a/main/ui/src/main/resources/localization_it.properties +++ b/main/ui/src/main/resources/localization/it.txt @@ -1,7 +1,7 @@ # Copyright (c) 2016 The Cryptomator Contributors # This file is licensed under the terms of the MIT license. # See the LICENSE.txt file for more info. -# +# # Contributors: # vesparny @@ -14,19 +14,19 @@ main.addDirectory.contextMenu.new = Crea un nuovo vault main.addDirectory.contextMenu.open = Apri un vault # welcome.fxml welcome.checkForUpdates.label.currentlyChecking = Verifica aggiornamenti... -welcome.newVersionMessage = La versione %s puň essere scaricata. Questa č %s +welcome.newVersionMessage = La versione %s può essere scaricata. Questa è %s # initialize.fxml initialize.label.password = Password initialize.label.retypePassword = Conferma password initialize.button.ok = Crea un vault -initialize.messageLabel.alreadyInitialized = Vault giŕ inizializzato -initialize.messageLabel.initializationFailed = Non č possibile inizializzare il vault. Controlla il file di log per dettagli. +initialize.messageLabel.alreadyInitialized = Vault giĂ  inizializzato +initialize.messageLabel.initializationFailed = Non è possibile inizializzare il vault. Controlla il file di log per dettagli. # notfound.fxml -notfound.label = Il vault non puň essere trovato. E' stato rimosso? +notfound.label = Il vault non può essere trovato. E' stato rimosso? # upgrade.fxml upgrade.button = Aggiorna vault -upgrade.version3dropBundleExtension.msg = Questo vault deve essere migrato ad un nuovo formato.\n"%1$s" verrŕ rinominato in "%2$s".\nPer favore verifica che la sincronizzazione sia finita prima di procedere\n -upgrade.version3dropBundleExtension.err.alreadyExists = Migrazione automatica fallita.\n"%s" esiste giŕ. +upgrade.version3dropBundleExtension.msg = Questo vault deve essere migrato ad un nuovo formato.\n"%1$s" verrĂ  rinominato in "%2$s".\nPer favore verifica che la sincronizzazione sia finita prima di procedere\n +upgrade.version3dropBundleExtension.err.alreadyExists = Migrazione automatica fallita.\n"%s" esiste giĂ . # unlock.fxml unlock.label.password = Password unlock.label.mountName = nome del drive @@ -34,14 +34,14 @@ unlock.label.winDriveLetter = lettera del drive unlock.label.downloadsPageLink = Tutte le versioni di Cryptomator unlock.label.advancedHeading = Opzioni avanzate unlock.button.unlock = Sblocca vault -unlock.button.advancedOptions.show = Piů opzioni +unlock.button.advancedOptions.show = PiĂą opzioni unlock.button.advancedOptions.hide = Meno opzioni unlock.choicebox.winDriveLetter.auto = Assegna automaticamente unlock.errorMessage.wrongPassword = Password errata unlock.errorMessage.mountingFailed = Montaggio fallito. Controlla il file di log per dettagli. -unlock.errorMessage.unsupportedKeyLengthInstallJCE = Decriptaggio fallito. -unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Vault non supportato. Questo vault č stato creato con una versione di Cryptomator piů vecchia. -unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = Vault non supportato. Questo vault č stato creato con una versione di Cryptomator piů recente. +unlock.errorMessage.unsupportedKeyLengthInstallJCE = Decriptaggio fallito. +unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Vault non supportato. Questo vault è stato creato con una versione di Cryptomator piĂą vecchia. +unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = Vault non supportato. Questo vault è stato creato con una versione di Cryptomator piĂą recente. unlock.messageLabel.startServerFailed = Avvio del server WebDAV fallito # change_password.fxml changePassword.label.oldPassword = Vecchia password @@ -52,22 +52,22 @@ changePassword.button.change = Cambia la password changePassword.errorMessage.wrongPassword = Password errata changePassword.errorMessage.decryptionFailed = Decriptaggio fallito changePassword.errorMessage.unsupportedKeyLengthInstallJCE = Decriptaggio fallito. Per favore installa Oracle JCE Unlimited Strength Policy -changePassword.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Vault non supportato. Questo vault č stato creato con una versione di Cryptomator piů recente. -changePassword.errorMessage.unsupportedVersion.softwareOlderThanVault = Vault non supportato. Questo vault č stato creato con una versione di Cryptomator piů vecchia. +changePassword.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Vault non supportato. Questo vault è stato creato con una versione di Cryptomator piĂą recente. +changePassword.errorMessage.unsupportedVersion.softwareOlderThanVault = Vault non supportato. Questo vault è stato creato con una versione di Cryptomator piĂą vecchia. changePassword.infoMessage.success = Password cambiata # unlocked.fxml -unlocked.button.lock = Blocca vault +unlocked.button.lock = Blocca vault unlocked.moreOptions.reveal = Apri il disco unlocked.moreOptions.copyUrl = Copia url WebDAV unlocked.label.revealFailed = Comando fallito unlocked.label.unmountFailed = Espulsione disco fallita unlocked.label.statsEncrypted = criptato unlocked.label.statsDecrypted = decriptato -unlocked.ioGraph.yAxis.label = Volume dati (MiB/s) +unlocked.ioGraph.yAxis.label = Volume dati (MiB/s) # mac_warnings.fxml macWarnings.windowTitle = Pericolo - File corroto in %s macWarnings.message = Cryptomator ha individuato potenziali pericolose corruzioni nei seguenti file\: -macWarnings.moreInformationButton = Piů informazioni +macWarnings.moreInformationButton = PiĂą informazioni macWarnings.whitelistButton = Decripta i selezionati comunque # settings.fxml settings.version.label = Versione %s @@ -80,5 +80,5 @@ settings.requiresRestartLabel = * Cryptomator deve essere riavviato tray.menu.open = Apri tray.menu.quit = Chiudi tray.infoMsg.title = Ancora in esecuzione -tray.infoMsg.msg = Cryptomator č ancora in esecuzione. Chiudilo utilizzando l'icona nel menů di stato. -tray.infoMsg.msg.osx = Cryptomator č ancora in esecuzione. Chiudilo utilizzando l'icona nella barra del menů. \ No newline at end of file +tray.infoMsg.msg = Cryptomator è ancora in esecuzione. Chiudilo utilizzando l'icona nel menĂą di stato. +tray.infoMsg.msg.osx = Cryptomator è ancora in esecuzione. Chiudilo utilizzando l'icona nella barra del menĂą. diff --git a/main/ui/src/main/resources/localization/kr.txt b/main/ui/src/main/resources/localization/kr.txt new file mode 100644 index 000000000..1978f9093 --- /dev/null +++ b/main/ui/src/main/resources/localization/kr.txt @@ -0,0 +1,84 @@ +# Copyright (c) 2016 The Cryptomator Contributors +# This file is licensed under the terms of the MIT license. +# See the LICENSE.txt file for more info. +# +# Contributors: +# ChangHwan Kim + +app.name = Cryptomator +# main.fxml +main.emptyListInstructions = 여기를 í´ë¦­í•ě—¬ 보관함 추가í•기 +main.directoryList.contextMenu.remove = 목록ě—서 ě‚­ě ś +main.directoryList.contextMenu.changePassword = 비밀ë˛í¸ 변경 +main.addDirectory.contextMenu.new = ě 보관함 만들기 +main.addDirectory.contextMenu.open = 기존 보관함 열기 +# welcome.fxml +welcome.checkForUpdates.label.currentlyChecking = 업데이트 확인 +welcome.newVersionMessage = %s 버전이 ě로 다운로드 가능합ë‹ë‹¤. ě§€ę¸ ë˛„ě „ěť€ %s ěž…ë‹ë‹¤. +# initialize.fxml +initialize.label.password = 비밀ë˛í¸ +initialize.label.retypePassword = 비밀ë˛í¸ 재입력 +initialize.button.ok = 보관함 만들기 +initialize.messageLabel.alreadyInitialized = 이미 보관함이 ě´ę¸°í™”ëě—습ë‹ë‹¤. +initialize.messageLabel.initializationFailed = 보관함을 ě´ę¸°í™”í•  ě 없습ë‹ë‹¤. ěžě„¸í•ś 사항은 로그 파일을 참조í•세요. +# notfound.fxml +notfound.label = 보관함을 ě°ľěť„ ě 없습ë‹ë‹¤. ě®ę˛¨ě§„ ę˛ěť€ 아닌가요? +# upgrade.fxml +upgrade.button = 보관함 ě—…ę·¸ë ěť´ë“ś +upgrade.version3dropBundleExtension.msg = ěť´ 보관함은 ě로운 í•식으로 다시 바뀔 필요가 ěžěеë‹ë‹¤. "%1$s"ěť ěť´ë¦„ěť€ "%2$s"로 바뀔 ę˛ěž…ë‹ë‹¤. ě§„í–‰í•기 ě „ě— ëŹ™ę¸°í™”ę°€ 완료ëě—는지 다시 한 ë˛ í™•ěť¸í•´ěŁĽě‹śę¸° 바랍ë‹ë‹¤. +upgrade.version3dropBundleExtension.err.alreadyExists = ěžëŹ™ ë§ěť´ę·¸ë ěť´ě… 실패. "%s"ę°€ 이미 존재합ë‹ë‹¤. +# unlock.fxml +unlock.label.password = 비밀ë˛í¸ +unlock.label.mountName = 드라이브 이름 +unlock.label.winDriveLetter = 드라이브 ë¬¸ěž +unlock.label.downloadsPageLink = 모든 Cryptomator 버전 +unlock.label.advancedHeading = 고급 ěµě… +unlock.button.unlock = 보관함 í•´ě ś +unlock.button.advancedOptions.show = 더 많은 ěµě… +unlock.button.advancedOptions.hide = 기본 ěµě… +unlock.choicebox.winDriveLetter.auto = ěžëŹ™ěśĽëˇś 할당 +unlock.errorMessage.wrongPassword = 틀린 비밀ë˛í¸ +unlock.errorMessage.mountingFailed = ë§ěš´íЏ 실패. ěžě„¸í•ś 사항은 로그 파일을 참조í•세요. +unlock.errorMessage.unsupportedKeyLengthInstallJCE = ëłµí¸í™” 실패. Oracle JCE Unlimited Strength Policy Filesěť„ 설ěąí•세요. +unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = ě§€ě›ëě§€ 않는 보관함. ěť´ 보관함은 ěť´ě „ ë˛„ě „ěť Cryptomatorě—서 ěťě„±ëě—습ë‹ë‹¤. +unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = ě§€ě›ëě§€ 않는 보관함. ěť´ 보관함은 최신 ë˛„ě „ěť Cryptomatorě—서 ěťě„±ëě—습ë‹ë‹¤. +unlock.messageLabel.startServerFailed = WedDAV 서버 시작 실패 +# change_password.fxml +changePassword.label.oldPassword = ěť´ě „ 비밀ë˛í¸ +changePassword.label.newPassword = ě로운 비밀ë˛í¸ +changePassword.label.retypePassword = 비밀ë˛í¸ 재입력 +changePassword.label.downloadsPageLink = 모든 Cryptomator 버전 +changePassword.button.change = 비밀ë˛í¸ 변경 +changePassword.errorMessage.wrongPassword = 틀린 비밀ë˛í¸ +changePassword.errorMessage.decryptionFailed = ëłµí¸í™” 실패 +changePassword.errorMessage.unsupportedKeyLengthInstallJCE = ëłµí¸í™” 실패. Oracle JCE Unlimited Strength Policy Filesěť„ 설ěąí•세요. +changePassword.errorMessage.unsupportedVersion.vaultOlderThanSoftware = ě§€ě›ëě§€ 않는 보관함. ěť´ 보관함은 ěť´ě „ ë˛„ě „ěť Cryptomatorě—서 ěťě„±ëě—습ë‹ë‹¤. +changePassword.errorMessage.unsupportedVersion.softwareOlderThanVault = ě§€ě›ëě§€ 않는 보관함. ěť´ 보관함은 최신 ë˛„ě „ěť Cryptomatorě—서 ěťě„±ëě—습ë‹ë‹¤. +changePassword.infoMessage.success = 비밀ë˛í¸ 변경 +# unlocked.fxml +unlocked.button.lock = 보관함 잠그기 +unlocked.moreOptions.reveal = 드라이브 표시 +unlocked.moreOptions.copyUrl = WebDAV 주소 복사 +unlocked.label.revealFailed = 명령 실패 +unlocked.label.unmountFailed = 드라이브 추출 실패 +unlocked.label.statsEncrypted = ě•”í¸í™” +unlocked.label.statsDecrypted = ëłµí¸í™” +unlocked.ioGraph.yAxis.label = ě˛ë¦¬ëź‰ (MiB/s) +# mac_warnings.fxml +macWarnings.windowTitle = ěś„í— - %sě— ě†ěëś íŚŚěťĽ +macWarnings.message = Cryptomatorę°€ 다음 파일들ě—서 잠재ě ěť¸ ě†ě ěś„í—ěť„ ę°ě§€í–습ë‹ë‹¤. +macWarnings.moreInformationButton = 더 알아보기 +macWarnings.whitelistButton = ě„ íť í•­ëŞ© ę°•ě ś ëłµí¸í™” +# settings.fxml +settings.version.label = 버전 %s +settings.checkForUpdates.label = 업데이트 확인 +settings.port.label = WebDAV 포트 * +settings.port.prompt = 0 \= ěžëŹ™ěśĽëˇś ě„ íť +settings.useipv6.label = IPv6 사용 +settings.requiresRestartLabel = * Cryptomator 재시작 í•„ěš” +# tray icon +tray.menu.open = 열기 +tray.menu.quit = 종료 +tray.infoMsg.title = 계속 실행 중입ë‹ë‹¤. +tray.infoMsg.msg = Cryptomatorę°€ 계속 실행 중입ë‹ë‹¤. 종료í•실려면 트ë ěť´ ě•„ěť´ě˝ě—서 해주세요. +tray.infoMsg.msg.osx = Cryptomatorę°€ 계속 실행중입ë‹ë‹¤. 종료í•실려면 메뉴 ë°” ě•„ěť´ě˝ě—서 해주세요. diff --git a/main/ui/src/main/resources/localization_pt.properties b/main/ui/src/main/resources/localization/pt.txt similarity index 81% rename from main/ui/src/main/resources/localization_pt.properties rename to main/ui/src/main/resources/localization/pt.txt index c6dad850a..ef8cdfbe3 100644 --- a/main/ui/src/main/resources/localization_pt.properties +++ b/main/ui/src/main/resources/localization/pt.txt @@ -1,27 +1,27 @@ # Copyright (c) 2016 The Cryptomator Contributors # This file is licensed under the terms of the MIT license. # See the LICENSE.txt file for more info. -# +# # Contributors: # Will -# André Di Biasi +# AndrĂ© Di Biasi app.name = Cryptomator main.directoryList.contextMenu.remove = Remover da lista main.directoryList.contextMenu.changePassword = Alterar senha # welcome.fxml -welcome.checkForUpdates.label.currentlyChecking = Procurando atualizaçőes... +welcome.checkForUpdates.label.currentlyChecking = Procurando atualizações... # initialize.fxml initialize.label.password = Senha initialize.label.retypePassword = Digite a senha novamente # unlock.fxml unlock.label.password = Senha -unlock.label.advancedHeading = Opçőes avançadas -unlock.button.advancedOptions.hide = Menos opçőes +unlock.label.advancedHeading = Opções avançadas +unlock.button.advancedOptions.hide = Menos opções unlock.choicebox.winDriveLetter.auto = Atribuir automaticamente unlock.errorMessage.wrongPassword = Senha incorreta unlock.errorMessage.mountingFailed = Montagem falhou. Veja o arquivo de log para detalhes -unlock.messageLabel.startServerFailed = Inicializaçăo do servidor WEBDAV falhou +unlock.messageLabel.startServerFailed = Inicialização do servidor WEBDAV falhou # change_password.fxml changePassword.label.oldPassword = Senha antiga changePassword.label.newPassword = Nova senha @@ -31,4 +31,4 @@ changePassword.infoMessage.success = Senha alterada unlocked.label.revealFailed = Falha no comando unlocked.label.unmountFailed = Falha ao ejetar o drive unlocked.label.statsEncrypted = encriptado -macWarnings.moreInformationButton = Saiba mais \ No newline at end of file +macWarnings.moreInformationButton = Saiba mais diff --git a/main/ui/src/main/resources/localization/ru.txt b/main/ui/src/main/resources/localization/ru.txt new file mode 100644 index 000000000..31241b6ea --- /dev/null +++ b/main/ui/src/main/resources/localization/ru.txt @@ -0,0 +1,55 @@ +# Copyright (c) 2016 The Cryptomator Contributors +# This file is licensed under the terms of the MIT license. +# See the LICENSE.txt file for more info. +# +# Contributors: +# Garik +# Konstantine + +app.name = Cryptomator +# main.fxml +main.emptyListInstructions = Нажмите здеŃŃŚ что добавить хранилище +main.directoryList.contextMenu.remove = Удалить из ŃпиŃка +main.directoryList.contextMenu.changePassword = Сменить пароль +main.addDirectory.contextMenu.new = Создать новое хранилище +main.addDirectory.contextMenu.open = Открыть ŃŃщеŃтвŃющее хранилище +# welcome.fxml +welcome.checkForUpdates.label.currentlyChecking = Проверка обновлений... +welcome.newVersionMessage = ВерŃия может быть Ńкачена. Это. +# initialize.fxml +initialize.label.password = Пароль +initialize.label.retypePassword = Повторите пароль +initialize.button.ok = Создать хранилище +initialize.messageLabel.alreadyInitialized = Хранилище Ńже инициализировано +initialize.messageLabel.initializationFailed = Невозможно инициировать хранилище. Смотрите лог для деталей. +# notfound.fxml +notfound.label = Хранилище не найдено.Оно было Ńдалено? +# upgrade.fxml +upgrade.button = Обновить хранилище +upgrade.version3dropBundleExtension.msg = Đ­Ń‚ĐľĐĽŃ Ń…Ń€Đ°Đ˝Đ¸Đ»Đ¸Ń‰Ń Đ˝Ńжно мигрировать в новый формат.\n"%1$s" will be renamed to "%2$s".\nPlease make sure synchronization has finished before proceeding. +upgrade.version3dropBundleExtension.err.alreadyExists = ĐвтоматичеŃкая миграция не ŃдалаŃŃŚ.\n"%" Ńже ŃŃщеŃтвŃет. +# unlock.fxml +unlock.label.password = Пароль +unlock.label.mountName = ĐĐĽŃŹ ноŃителя +changePassword.errorMessage.wrongPassword = Неправильный пароль +changePassword.errorMessage.decryptionFailed = РаŃŃифровка провалилаŃŃŚ +changePassword.errorMessage.unsupportedKeyLengthInstallJCE = РаŃŃифровка не ŃдалаŃŃŚ. ПожалŃĐąŃта ŃŃтановите Oracle JCE Unlimited Strength Policy. +changePassword.infoMessage.success = Пароль изменилŃŃŹ +# unlocked.fxml +unlocked.button.lock = Заблокировать хранилище +unlocked.moreOptions.copyUrl = Скопировать WebDAV URL +unlocked.label.revealFailed = Команда не ŃдалаŃŃŚ +unlocked.label.unmountFailed = Đзвлечение диŃка не ŃдалоŃŃŚ +unlocked.label.statsEncrypted = заŃифровано +unlocked.label.statsDecrypted = раŃŃифровано +macWarnings.moreInformationButton = ĐĐ·Ńчить больŃе +# settings.fxml +settings.version.label = ВерŃия %s +settings.checkForUpdates.label = Проверка обновлений +settings.requiresRestartLabel = * Cryptomator должен перезагрŃзитŃŃŹ +# tray icon +tray.menu.open = Открыть +tray.menu.quit = Выйти +tray.infoMsg.title = Đ’ŃŃ‘ ещё работает +tray.infoMsg.msg = Cryptomator работает. Выйдите c помощью иконки в трее. +tray.infoMsg.msg.osx = Cryptomator вŃŃ‘ ещё работает.Выйдите Ń ĐżĐľĐĽĐľŃ‰ŃŚŃŽ иконки в меню баре. diff --git a/main/ui/src/main/resources/localization/sk.txt b/main/ui/src/main/resources/localization/sk.txt new file mode 100644 index 000000000..74ef6bf14 --- /dev/null +++ b/main/ui/src/main/resources/localization/sk.txt @@ -0,0 +1,88 @@ +# Copyright (c) 2016 The Cryptomator Contributors +# This file is licensed under the terms of the MIT license. +# See the LICENSE.txt file for more info. +# +# Contributors: +# Filip Havrlent +# Tatiana Chovancová + +# Copyright (c) 2016 The Cryptomator Contributors +# This file is licensed under the terms of the MIT license. +# See the LICENSE.txt file for more info. +app.name = Cryptomator +# main.fxml +main.emptyListInstructions = PridaĹĄ trezor +main.directoryList.contextMenu.remove = OdstrániĹĄ zo zoznamu +main.directoryList.contextMenu.changePassword = ZmeniĹĄ heslo +main.addDirectory.contextMenu.new = VytvoriĹĄ novĂ˝ trezor +main.addDirectory.contextMenu.open = OtvoriĹĄ existujĂşci trezor +# welcome.fxml +welcome.checkForUpdates.label.currentlyChecking = KontrolujĂş sa aktualizácie... +welcome.newVersionMessage = Verzia %s je pripravená na stiahnutie. Toto je verzia %s. +# initialize.fxml +initialize.label.password = Heslo +initialize.label.retypePassword = Zadajte heslo znova +initialize.button.ok = VytvoriĹĄ trezor +initialize.messageLabel.alreadyInitialized = Trezor je uĹľ inicializovanĂ˝ +initialize.messageLabel.initializationFailed = Nepodarilo sa inicializovaĹĄ trezor. Pozrite sĂşbor záznamov pre viac detailov. +# notfound.fxml +notfound.label = Trezor nemohol byĹĄ nenájdenĂ˝. Bol presunutĂ˝? +# upgrade.fxml +upgrade.button = Upgradnúť trezor +upgrade.version3dropBundleExtension.msg = Tento trezor musĂ­ byĹĄ premigrovanĂ˝ na novĂ˝ formát. "%1$s" bude premenovanĂ˝ na "%2$s". ProsĂ­m, uistite sa Ĺľe je dokonÄŤená synchronizácia skĂ´r neĹľ budete pokraÄŤovaĹĄ. +upgrade.version3dropBundleExtension.err.alreadyExists = Automatická migrácia zlyhala. "%s" uĹľ existuje. +# unlock.fxml +unlock.label.password = Heslo +unlock.label.mountName = Názov jednotky +unlock.label.winDriveLetter = OznaÄŤenie jednotky +unlock.label.downloadsPageLink = Všetky verzie Cryptomatoru +unlock.label.advancedHeading = PokroÄŤilĂ© nastavenia +unlock.button.unlock = Odomknúť trezor +unlock.button.advancedOptions.show = Viac nastavenĂ­ +unlock.button.advancedOptions.hide = Menej nastavenĂ­ +unlock.choicebox.winDriveLetter.auto = PriradiĹĄ automaticky +unlock.errorMessage.wrongPassword = Nesprávne heslo +unlock.errorMessage.mountingFailed = Pripájanie zlyhalo. Viac informácii v logu. +unlock.errorMessage.unsupportedKeyLengthInstallJCE = Dešifrovanie zlyhalo. ProsĂ­m nainštalujte Oracle JCE Unlimited Strength Policy Files. +unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = NepodporovanĂ˝ trezor. Tento trezor bol vytvorenĂ˝ staršou verziou Cryptromatoru. +unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = NepodporovanĂ˝ trezor. Bol vytvorenĂ˝ z novšou verziou Cryptomatoru. +unlock.messageLabel.startServerFailed = Spustenie WebDAv servera zlyhalo. +# change_password.fxml +changePassword.label.oldPassword = StarĂ© heslo +changePassword.label.newPassword = NovĂ© heslo +changePassword.label.retypePassword = Znova zadajte heslo +changePassword.label.downloadsPageLink = Všetky verzie Cryptomatoru. +changePassword.button.change = ZmeniĹĄ heslo +changePassword.errorMessage.wrongPassword = Nesprávne heslo +changePassword.errorMessage.decryptionFailed = Dešifrovanie zlyhalo. +changePassword.errorMessage.unsupportedKeyLengthInstallJCE = Dešifrovanie zlyhalo. ProsĂ­m nainštalujte Oracle JCE Unlimited Strength Policy. +changePassword.errorMessage.unsupportedVersion.vaultOlderThanSoftware = NepodporovanĂ˝ trezor. Bol vytvorenĂ˝ staršou verziou Cryptomatoru. +changePassword.errorMessage.unsupportedVersion.softwareOlderThanVault = NepodporovanĂ˝ trezor. Bol vytvorenĂ˝ novšou verziou Cryptomatoru. +changePassword.infoMessage.success = Heslo zmenenĂ© +# unlocked.fxml +unlocked.button.lock = Zamknúť trezor +unlocked.moreOptions.reveal = OdhaliĹĄ jednotku +unlocked.moreOptions.copyUrl = KopĂ­rovaĹĄ WebDAV URL +unlocked.label.revealFailed = PrĂ­kaz zlyhal +unlocked.label.unmountFailed = Odpájanie jednotky zlyhalo +unlocked.label.statsEncrypted = zašifrovanĂ© +unlocked.label.statsDecrypted = dešifrovanĂ© +unlocked.ioGraph.yAxis.label = PriepustnosĹĄ (MiB/s) +# mac_warnings.fxml +macWarnings.windowTitle = Upozornenie - PoškodenĂ˝ sĂşbor v %s +macWarnings.message = Cryptomator odhalil potencionálne škodlivĂ© poškodenie v nasledujĂşcich sĂşboroch\: +macWarnings.moreInformationButton = ZistiĹĄ viac +macWarnings.whitelistButton = Napriek tomu dešifrovaĹĄ vybranĂ© +# settings.fxml +settings.version.label = Verzia %s +settings.checkForUpdates.label = SkontrolovaĹĄ aktualizácie +settings.port.label = WebDAV Port * +settings.port.prompt = 0 \= VybraĹĄ automaticky +settings.useipv6.label = PouĹľiĹĄ IPv6 +settings.requiresRestartLabel = * Cryptomator vyĹľaduje reštart +# tray icon +tray.menu.open = OtvoriĹĄ +tray.menu.quit = Vypnúť +tray.infoMsg.title = Stále beží +tray.infoMsg.msg = Cryptomator je stále spustenĂ˝. Vypnite ho pomocou ikony v systĂ©movej lište. +tray.infoMsg.msg.osx = Cryptomator je stále sputenĂ˝. UkonÄŤite ho pomocou ikony v menu. diff --git a/main/ui/src/main/resources/localization_hu.properties b/main/ui/src/main/resources/localization_hu.properties deleted file mode 100644 index 8fdc27761..000000000 --- a/main/ui/src/main/resources/localization_hu.properties +++ /dev/null @@ -1,84 +0,0 @@ -# Copyright (c) 2016 The Cryptomator Contributors -# This file is licensed under the terms of the MIT license. -# See the LICENSE.txt file for more info. -# -# Contributors: -# Roland Burda - -app.name = Cryptomator -# main.fxml -main.emptyListInstructions = Kattints ide egy széf létrehozásához -main.directoryList.contextMenu.remove = Eltávolítás listából -main.directoryList.contextMenu.changePassword = Jelszó megváltoztatása -main.addDirectory.contextMenu.new = Új széf létrehozása -main.addDirectory.contextMenu.open = Létez\u0151 széf megnyitása -# welcome.fxml -welcome.checkForUpdates.label.currentlyChecking = Frissítések keresése... -welcome.newVersionMessage = Új verzió érhet\u0151 el\: %s. Jelenlegi verzió\: %s. -# initialize.fxml -initialize.label.password = Jelszó -initialize.label.retypePassword = Jelszó ismét -initialize.button.ok = Széf létrehozása -initialize.messageLabel.alreadyInitialized = A széf már meg van nyitva -initialize.messageLabel.initializationFailed = Nem sikerült megnyitni a széfet. További információ a naplófájlban. -# notfound.fxml -notfound.label = Széf nem található. Lehetséges, hogy áthelyezésre került? -# upgrade.fxml -upgrade.button = Széf frissítése -upgrade.version3dropBundleExtension.msg = A széf új verzióra történ\u0151 migrációja szükséges. "%1$s" a következ\u0151re lesz átnevezve\: "%2$s". Kérlek gy\u0151z\u0151dj meg a szinkronizáció befejeztér\u0151l, miel\u0151tt más m\u0171veletet végeznél. -upgrade.version3dropBundleExtension.err.alreadyExists = Automatikus migráció meghíusúlt. "%s" már létezik. -# unlock.fxml -unlock.label.password = Jelszó -unlock.label.mountName = Meghajtó neve -unlock.label.winDriveLetter = Meghajtó bet\u0171jele -unlock.label.downloadsPageLink = Összes Cryptomator verzió -unlock.label.advancedHeading = Haladó beállítások -unlock.button.unlock = Széf feloldása -unlock.button.advancedOptions.show = További beállítások -unlock.button.advancedOptions.hide = Alapbeállítások -unlock.choicebox.winDriveLetter.auto = Automatikus hozzárendelés -unlock.errorMessage.wrongPassword = Hibás jelszó -unlock.errorMessage.mountingFailed = Meghajtó felcsatolása sikertelen. További információk a naplófájlban. -unlock.errorMessage.unsupportedKeyLengthInstallJCE = A titkosítás feloldása sikertelen. Kérlek telepítsd a "Oracle JCE Unlimited Strength Policy Files"-t. -unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Nem támogatott széf. Ez a széf a Cryptomator egy korábbi verziójával került létrehozásra. -unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = Nem támogatott széf. Ez a széf a Cryptomator egy újabb verziójával került létrehozásra. -unlock.messageLabel.startServerFailed = WebDAV szerver indítása sikertelen. -# change_password.fxml -changePassword.label.oldPassword = Régi jelszó -changePassword.label.newPassword = Új jelszó -changePassword.label.retypePassword = Új jelszó ismét -changePassword.label.downloadsPageLink = Összes Cryptomator verzió -changePassword.button.change = Jelszó megváltoztatása -changePassword.errorMessage.wrongPassword = Hibás jelszó -changePassword.errorMessage.decryptionFailed = A titkosítás feloldása meghíusúlt -changePassword.errorMessage.unsupportedKeyLengthInstallJCE = A titkosítás feloldása sikertelen. Kérlek telepítsd a "Oracle JCE Unlimited Strength Policy"-t. -changePassword.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Nem támogatott széf. Ez a széf a Cryptomator egy korábbi verziójával került létrehozásra. -changePassword.errorMessage.unsupportedVersion.softwareOlderThanVault = Nem támogatott széf. Ez a széf a Cryptomator egy újabb verziójával került létrehozásra. -changePassword.infoMessage.success = Jelszó megváltoztatva -# unlocked.fxml -unlocked.button.lock = Széf lezárása -unlocked.moreOptions.reveal = Meghajtó felfedése -unlocked.moreOptions.copyUrl = WebDAV URL másolása -unlocked.label.revealFailed = Parancs meghíusúlt -unlocked.label.unmountFailed = Meghajtó leválasztása sikertelen -unlocked.label.statsEncrypted = titkosított -unlocked.label.statsDecrypted = titkosítás feloldva -unlocked.ioGraph.yAxis.label = Teljesítmény (MiB/s) -# mac_warnings.fxml -macWarnings.windowTitle = Veszély - Korrupt fájl a következ\u0151ben\: %s -macWarnings.message = Cryptomator potenciálisan rosszindulatú hibákat fedezett fel a következ\u0151 fájlokban\: -macWarnings.moreInformationButton = Tudj meg többet -macWarnings.whitelistButton = Kiválasztottak titkosításának feloldása mindenképp -# settings.fxml -settings.version.label = Verzió\: %s -settings.checkForUpdates.label = Frissítések keresése -settings.port.label = WebDAV Port * -settings.port.prompt = 0 \= Automatikus választás -settings.useipv6.label = Literális IPv6 használata -settings.requiresRestartLabel = * Cryptomator újraindítása szükséges -# tray icon -tray.menu.open = Megnyit -tray.menu.quit = Kilépés -tray.infoMsg.title = M\u0171velet folyamatban -tray.infoMsg.msg = Cryptomator még fut. A tálcán található ikon segítségével bezárhatod. -tray.infoMsg.msg.osx = Cryptomator még fut. A menüsávban található ikon segítségével bezárhatod. \ No newline at end of file diff --git a/main/ui/src/main/resources/localization_kr.properties b/main/ui/src/main/resources/localization_kr.properties deleted file mode 100644 index ecdfcf9fd..000000000 --- a/main/ui/src/main/resources/localization_kr.properties +++ /dev/null @@ -1,84 +0,0 @@ -# Copyright (c) 2016 The Cryptomator Contributors -# This file is licensed under the terms of the MIT license. -# See the LICENSE.txt file for more info. -# -# Contributors: -# ChangHwan Kim - -app.name = Cryptomator -# main.fxml -main.emptyListInstructions = \uC5EC\uAE30\uB97C \uD074\uB9AD\uD558\uC5EC \uBCF4\uAD00\uD568 \uCD94\uAC00\uD558\uAE30 -main.directoryList.contextMenu.remove = \uBAA9\uB85D\uC5D0\uC11C \uC0AD\uC81C -main.directoryList.contextMenu.changePassword = \uBE44\uBC00\uBC88\uD638 \uBCC0\uACBD -main.addDirectory.contextMenu.new = \uC0C8 \uBCF4\uAD00\uD568 \uB9CC\uB4E4\uAE30 -main.addDirectory.contextMenu.open = \uAE30\uC874 \uBCF4\uAD00\uD568 \uC5F4\uAE30 -# welcome.fxml -welcome.checkForUpdates.label.currentlyChecking = \uC5C5\uB370\uC774\uD2B8 \uD655\uC778 -welcome.newVersionMessage = %s \uBC84\uC804\uC774 \uC0C8\uB85C \uB2E4\uC6B4\uB85C\uB4DC \uAC00\uB2A5\uD569\uB2C8\uB2E4. \uC9C0\uAE08 \uBC84\uC804\uC740 %s \uC785\uB2C8\uB2E4. -# initialize.fxml -initialize.label.password = \uBE44\uBC00\uBC88\uD638 -initialize.label.retypePassword = \uBE44\uBC00\uBC88\uD638 \uC7AC\uC785\uB825 -initialize.button.ok = \uBCF4\uAD00\uD568 \uB9CC\uB4E4\uAE30 -initialize.messageLabel.alreadyInitialized = \uC774\uBBF8 \uBCF4\uAD00\uD568\uC774 \uCD08\uAE30\uD654\uB418\uC5C8\uC2B5\uB2C8\uB2E4. -initialize.messageLabel.initializationFailed = \uBCF4\uAD00\uD568\uC744 \uCD08\uAE30\uD654\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uC790\uC138\uD55C \uC0AC\uD56D\uC740 \uB85C\uADF8 \uD30C\uC77C\uC744 \uCC38\uC870\uD558\uC138\uC694. -# notfound.fxml -notfound.label = \uBCF4\uAD00\uD568\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uC62E\uACA8\uC9C4 \uAC83\uC740 \uC544\uB2CC\uAC00\uC694? -# upgrade.fxml -upgrade.button = \uBCF4\uAD00\uD568 \uC5C5\uADF8\uB808\uC774\uB4DC -upgrade.version3dropBundleExtension.msg = \uC774 \uBCF4\uAD00\uD568\uC740 \uC0C8\uB85C\uC6B4 \uD615\uC2DD\uC73C\uB85C \uB2E4\uC2DC \uBC14\uB014 \uD544\uC694\uAC00 \uC788\uC2B5\uB2C8\uB2E4. "%1$s"\uC758 \uC774\uB984\uC740 "%2$s"\uB85C \uBC14\uB014 \uAC83\uC785\uB2C8\uB2E4. \uC9C4\uD589\uD558\uAE30 \uC804\uC5D0 \uB3D9\uAE30\uD654\uAC00 \uC644\uB8CC\uB418\uC5C8\uB294\uC9C0 \uB2E4\uC2DC \uD55C \uBC88 \uD655\uC778\uD574\uC8FC\uC2DC\uAE30 \uBC14\uB78D\uB2C8\uB2E4. -upgrade.version3dropBundleExtension.err.alreadyExists = \uC790\uB3D9 \uB9C8\uC774\uADF8\uB808\uC774\uC158 \uC2E4\uD328. "%s"\uB294 \uC774\uBBF8 \uC874\uC7AC\uD569\uB2C8\uB2E4. -# unlock.fxml -unlock.label.password = \uBE44\uBC00\uBC88\uD638 -unlock.label.mountName = \uB4DC\uB77C\uC774\uBE0C \uC774\uB984 -unlock.label.winDriveLetter = \uB4DC\uB77C\uC774\uBE0C \uBB38\uC790 -unlock.label.downloadsPageLink = \uBAA8\uB4E0 Cryptomator \uBC84\uC804 -unlock.label.advancedHeading = \uACE0\uAE09 \uC635\uC158 -unlock.button.unlock = \uBCF4\uAD00\uD568 \uD574\uC81C -unlock.button.advancedOptions.show = \uB354 \uB9CE\uC740 \uC635\uC158 -unlock.button.advancedOptions.hide = \uAE30\uBCF8 \uC635\uC158 -unlock.choicebox.winDriveLetter.auto = \uC790\uB3D9\uC73C\uB85C \uD560\uB2F9 -unlock.errorMessage.wrongPassword = \uD2C0\uB9B0 \uBE44\uBC00\uBC88\uD638 -unlock.errorMessage.mountingFailed = \uB9C8\uC6B4\uD2B8 \uC2E4\uD328. \uC790\uC138\uD55C \uC0AC\uD56D\uC740 \uB85C\uADF8 \uD30C\uC77C\uC744 \uCC38\uC870\uD558\uC138\uC694. -unlock.errorMessage.unsupportedKeyLengthInstallJCE = \uBCF5\uD638\uD654 \uC2E4\uD328. Oracle JCE Unlimited Strength Policy Files\uC744 \uC124\uCE58\uD558\uC138\uC694. -unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = \uC9C0\uC6D0\uB418\uC9C0 \uC54A\uB294 \uBCF4\uAD00\uD568. \uC774 \uBCF4\uAD00\uD568\uC740 \uC774\uC804 \uBC84\uC804\uC758 Cryptomator\uC5D0\uC11C \uC0DD\uC131\uB418\uC5C8\uC2B5\uB2C8\uB2E4. -unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = \uC9C0\uC6D0\uB418\uC9C0 \uC54A\uB294 \uBCF4\uAD00\uD568. \uC774 \uBCF4\uAD00\uD568\uC740 \uCD5C\uC2E0 \uBC84\uC804\uC758 Cryptomator\uC5D0\uC11C \uC0DD\uC131\uB418\uC5C8\uC2B5\uB2C8\uB2E4. -unlock.messageLabel.startServerFailed = WedDAV \uC11C\uBC84 \uC2DC\uC791 \uC2E4\uD328 -# change_password.fxml -changePassword.label.oldPassword = \uC774\uC804 \uBE44\uBC00\uBC88\uD638 -changePassword.label.newPassword = \uC0C8\uB85C\uC6B4 \uBE44\uBC00\uBC88\uD638 -changePassword.label.retypePassword = \uBE44\uBC00\uBC88\uD638 \uC7AC\uC785\uB825 -changePassword.label.downloadsPageLink = \uBAA8\uB4E0 Cryptomator \uBC84\uC804 -changePassword.button.change = \uBE44\uBC00\uBC88\uD638 \uBCC0\uACBD -changePassword.errorMessage.wrongPassword = \uD2C0\uB9B0 \uBE44\uBC00\uBC88\uD638 -changePassword.errorMessage.decryptionFailed = \uBCF5\uD638\uD654 \uC2E4\uD328 -changePassword.errorMessage.unsupportedKeyLengthInstallJCE = \uBCF5\uD638\uD654 \uC2E4\uD328. Oracle JCE Unlimited Strength Policy Files\uC744 \uC124\uCE58\uD558\uC138\uC694. -changePassword.errorMessage.unsupportedVersion.vaultOlderThanSoftware = \uC9C0\uC6D0\uB418\uC9C0 \uC54A\uB294 \uBCF4\uAD00\uD568. \uC774 \uBCF4\uAD00\uD568\uC740 \uC774\uC804 \uBC84\uC804\uC758 Cryptomator\uC5D0\uC11C \uC0DD\uC131\uB418\uC5C8\uC2B5\uB2C8\uB2E4. -changePassword.errorMessage.unsupportedVersion.softwareOlderThanVault = \uC9C0\uC6D0\uB418\uC9C0 \uC54A\uB294 \uBCF4\uAD00\uD568. \uC774 \uBCF4\uAD00\uD568\uC740 \uCD5C\uC2E0 \uBC84\uC804\uC758 Cryptomator\uC5D0\uC11C \uC0DD\uC131\uB418\uC5C8\uC2B5\uB2C8\uB2E4. -changePassword.infoMessage.success = \uBE44\uBC00\uBC88\uD638 \uBCC0\uACBD -# unlocked.fxml -unlocked.button.lock = \uBCF4\uAD00\uD568 \uC7A0\uADF8\uAE30 -unlocked.moreOptions.reveal = \uB4DC\uB77C\uC774\uBE0C \uD45C\uC2DC -unlocked.moreOptions.copyUrl = WebDAV \uC8FC\uC18C \uBCF5\uC0AC -unlocked.label.revealFailed = \uBA85\uB839 \uC2E4\uD328 -unlocked.label.unmountFailed = \uB4DC\uB77C\uC774\uBE0C \uCD94\uCD9C \uC2E4\uD328 -unlocked.label.statsEncrypted = \uC554\uD638\uD654\uB428 -unlocked.label.statsDecrypted = \uBCF5\uD638\uD654\uB428 -unlocked.ioGraph.yAxis.label = \uCC98\uB9AC\uB7C9 (MiB/s) -# mac_warnings.fxml -macWarnings.windowTitle = \uC704\uD5D8 - %s\uC5D0 \uC190\uC0C1\uB41C \uD30C\uC77C -macWarnings.message = Cryptomator\uAC00 \uB2E4\uC74C \uD30C\uC77C\uB4E4\uC5D0\uC11C \uC7A0\uC7AC\uC801\uC778 \uC190\uC0C1 \uC704\uD5D8\uC744 \uAC10\uC9C0\uD588\uC2B5\uB2C8\uB2E4. -macWarnings.moreInformationButton = \uB354 \uC54C\uC544\uBCF4\uAE30 -macWarnings.whitelistButton = \uC120\uD0DD \uD56D\uBAA9 \uAC15\uC81C \uBCF5\uD638\uD654 -# settings.fxml -settings.version.label = \uBC84\uC804 %s -settings.checkForUpdates.label = \uC5C5\uB370\uC774\uD2B8 \uD655\uC778 -settings.port.label = WebDAV \uD3EC\uD2B8 * -settings.port.prompt = 0 \= \uC790\uB3D9\uC73C\uB85C \uC120\uD0DD -settings.useipv6.label = IPv6 \uC0AC\uC6A9 -settings.requiresRestartLabel = * Cryptomator \uC7AC\uC2DC\uC791 \uD544\uC694 -# tray icon -tray.menu.open = \uC5F4\uAE30 -tray.menu.quit = \uC885\uB8CC -tray.infoMsg.title = \uACC4\uC18D \uC2E4\uD589 \uC911\uC785\uB2C8\uB2E4. -tray.infoMsg.msg = Cryptomator\uAC00 \uACC4\uC18D \uC2E4\uD589 \uC911\uC785\uB2C8\uB2E4. \uC885\uB8CC\uD558\uC2E4\uB824\uBA74 \uD2B8\uB808\uC774 \uC544\uC774\uCF58\uC5D0\uC11C \uD574\uC8FC\uC138\uC694. -tray.infoMsg.msg.osx = Cryptomator\uAC00 \uACC4\uC18D \uC2E4\uD589\uC911\uC785\uB2C8\uB2E4. \uC885\uB8CC\uD558\uC2E4\uB824\uBA74 \uBA54\uB274 \uBC14 \uC544\uC774\uCF58\uC5D0\uC11C \uD574\uC8FC\uC138\uC694. \ No newline at end of file diff --git a/main/ui/src/main/resources/localization_ru.properties b/main/ui/src/main/resources/localization_ru.properties deleted file mode 100644 index 52214c75a..000000000 --- a/main/ui/src/main/resources/localization_ru.properties +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright (c) 2016 The Cryptomator Contributors -# This file is licensed under the terms of the MIT license. -# See the LICENSE.txt file for more info. -# -# Contributors: -# Garik -# Konstantine - -app.name = Cryptomator -# main.fxml -main.emptyListInstructions = \u041D\u0430\u0436\u043C\u0438\u0442\u0435 \u0437\u0434\u0435\u0441\u044C \u0447\u0442\u043E \u0434\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435 -main.directoryList.contextMenu.remove = \u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0438\u0437 \u0441\u043F\u0438\u0441\u043A\u0430 -main.directoryList.contextMenu.changePassword = \u0421\u043C\u0435\u043D\u0438\u0442\u044C \u043F\u0430\u0440\u043E\u043B\u044C -main.addDirectory.contextMenu.new = \u0421\u043E\u0437\u0434\u0430\u0442\u044C \u043D\u043E\u0432\u043E\u0435 \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435 -main.addDirectory.contextMenu.open = \u041E\u0442\u043A\u0440\u044B\u0442\u044C \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044E\u0449\u0435\u0435 \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435 -# welcome.fxml -welcome.checkForUpdates.label.currentlyChecking = \u041F\u0440\u043E\u0432\u0435\u0440\u043A\u0430 \u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u0439... -welcome.newVersionMessage = \u0412\u0435\u0440\u0441\u0438\u044F \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u0441\u043A\u0430\u0447\u0435\u043D\u0430. \u042D\u0442\u043E. -# initialize.fxml -initialize.label.password = \u041F\u0430\u0440\u043E\u043B\u044C -initialize.label.retypePassword = \u041F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0435 \u043F\u0430\u0440\u043E\u043B\u044C -initialize.button.ok = \u0421\u043E\u0437\u0434\u0430\u0442\u044C \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435 -initialize.messageLabel.alreadyInitialized = \u0425\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435 \u0443\u0436\u0435 \u0438\u043D\u0438\u0446\u0438\u0430\u043B\u0438\u0437\u0438\u0440\u043E\u0432\u0430\u043D\u043E -initialize.messageLabel.initializationFailed = \u041D\u0435\u0432\u043E\u0437\u043C\u043E\u0436\u043D\u043E \u0438\u043D\u0438\u0446\u0438\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435. \u0421\u043C\u043E\u0442\u0440\u0438\u0442\u0435 \u043B\u043E\u0433 \u0434\u043B\u044F \u0434\u0435\u0442\u0430\u043B\u0435\u0439. -# notfound.fxml -notfound.label = \u0425\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435 \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u043E.\u041E\u043D\u043E \u0431\u044B\u043B\u043E \u0443\u0434\u0430\u043B\u0435\u043D\u043E? -# upgrade.fxml -upgrade.button = \u041E\u0431\u043D\u043E\u0432\u0438\u0442\u044C \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435 -upgrade.version3dropBundleExtension.msg = \u042D\u0442\u043E\u043C\u0443 \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0443 \u043D\u0443\u0436\u043D\u043E \u043C\u0438\u0433\u0440\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0432 \u043D\u043E\u0432\u044B\u0439 \u0444\u043E\u0440\u043C\u0430\u0442.\n"%1$s" will be renamed to "%2$s".\nPlease make sure synchronization has finished before proceeding. -upgrade.version3dropBundleExtension.err.alreadyExists = \u0410\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u0430\u044F \u043C\u0438\u0433\u0440\u0430\u0446\u0438\u044F \u043D\u0435 \u0443\u0434\u0430\u043B\u0430\u0441\u044C.\n"%" \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442. -# unlock.fxml -unlock.label.password = \u041F\u0430\u0440\u043E\u043B\u044C -unlock.label.mountName = \u0418\u043C\u044F \u043D\u043E\u0441\u0438\u0442\u0435\u043B\u044F -changePassword.errorMessage.wrongPassword = \u041D\u0435\u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u044B\u0439 \u043F\u0430\u0440\u043E\u043B\u044C -changePassword.errorMessage.decryptionFailed = \u0420\u0430\u0441\u0448\u0438\u0444\u0440\u043E\u0432\u043A\u0430 \u043F\u0440\u043E\u0432\u0430\u043B\u0438\u043B\u0430\u0441\u044C -changePassword.errorMessage.unsupportedKeyLengthInstallJCE = \u0420\u0430\u0441\u0448\u0438\u0444\u0440\u043E\u0432\u043A\u0430 \u043D\u0435 \u0443\u0434\u0430\u043B\u0430\u0441\u044C. \u041F\u043E\u0436\u0430\u043B\u0443\u0439\u0441\u0442\u0430 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u0435 Oracle JCE Unlimited Strength Policy. -changePassword.infoMessage.success = \u041F\u0430\u0440\u043E\u043B\u044C \u0438\u0437\u043C\u0435\u043D\u0438\u043B\u0441\u044F -# unlocked.fxml -unlocked.button.lock = \u0417\u0430\u0431\u043B\u043E\u043A\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435 -unlocked.moreOptions.copyUrl = \u0421\u043A\u043E\u043F\u0438\u0440\u043E\u0432\u0430\u0442\u044C WebDAV URL -unlocked.label.revealFailed = \u041A\u043E\u043C\u0430\u043D\u0434\u0430 \u043D\u0435 \u0443\u0434\u0430\u043B\u0430\u0441\u044C -unlocked.label.unmountFailed = \u0418\u0437\u0432\u043B\u0435\u0447\u0435\u043D\u0438\u0435 \u0434\u0438\u0441\u043A\u0430 \u043D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C -unlocked.label.statsEncrypted = \u0437\u0430\u0448\u0438\u0444\u0440\u043E\u0432\u0430\u043D\u043E -unlocked.label.statsDecrypted = \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043E\u0432\u0430\u043D\u043E -macWarnings.moreInformationButton = \u0418\u0437\u0443\u0447\u0438\u0442\u044C \u0431\u043E\u043B\u044C\u0448\u0435 -# settings.fxml -settings.version.label = \u0412\u0435\u0440\u0441\u0438\u044F %s -settings.checkForUpdates.label = \u041F\u0440\u043E\u0432\u0435\u0440\u043A\u0430 \u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u0439 -settings.requiresRestartLabel = * Cryptomator \u0434\u043E\u043B\u0436\u0435\u043D \u043F\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u0441\u044F -# tray icon -tray.menu.open = \u041E\u0442\u043A\u0440\u044B\u0442\u044C -tray.menu.quit = \u0412\u044B\u0439\u0442\u0438 -tray.infoMsg.title = \u0412\u0441\u0451 \u0435\u0449\u0451 \u0440\u0430\u0431\u043E\u0442\u0430\u0435\u0442 -tray.infoMsg.msg = Cryptomator \u0440\u0430\u0431\u043E\u0442\u0430\u0435\u0442. \u0412\u044B\u0439\u0434\u0438\u0442\u0435 c \u043F\u043E\u043C\u043E\u0449\u044C\u044E \u0438\u043A\u043E\u043D\u043A\u0438 \u0432 \u0442\u0440\u0435\u0435. -tray.infoMsg.msg.osx = Cryptomator \u0432\u0441\u0451 \u0435\u0449\u0451 \u0440\u0430\u0431\u043E\u0442\u0430\u0435\u0442.\u0412\u044B\u0439\u0434\u0438\u0442\u0435 \u0441 \u043F\u043E\u043C\u043E\u0449\u044C\u044E \u0438\u043A\u043E\u043D\u043A\u0438 \u0432 \u043C\u0435\u043D\u044E \u0431\u0430\u0440\u0435. \ No newline at end of file diff --git a/main/ui/src/main/resources/localization_sk.properties b/main/ui/src/main/resources/localization_sk.properties deleted file mode 100644 index 2bec55581..000000000 --- a/main/ui/src/main/resources/localization_sk.properties +++ /dev/null @@ -1,85 +0,0 @@ -# Copyright (c) 2016 The Cryptomator Contributors -# This file is licensed under the terms of the MIT license. -# See the LICENSE.txt file for more info. -# -# Contributors: -# Filip Havrlent -# Tatiana Chovancová - -app.name = Cryptomator -# main.fxml -main.emptyListInstructions = Prida\u0165 trezor -main.directoryList.contextMenu.remove = Odstráni\u0165 zo zoznamu -main.directoryList.contextMenu.changePassword = Zmeni\u0165 heslo -main.addDirectory.contextMenu.new = Vytvori\u0165 nový trezor -main.addDirectory.contextMenu.open = Otvori\u0165 existujúci trezor -# welcome.fxml -welcome.checkForUpdates.label.currentlyChecking = Kontrolujú sa aktualizácie... -welcome.newVersionMessage = Verzia %s je pripravená na stiahnutie. Toto je verzia %s. -# initialize.fxml -initialize.label.password = Heslo -initialize.label.retypePassword = Zadajte heslo znova -initialize.button.ok = Vytvori\u0165 trezor -initialize.messageLabel.alreadyInitialized = Trezor je u\u017E inicializovaný -initialize.messageLabel.initializationFailed = Nepodarilo sa inicializova\u0165 trezor. Pozrite súbor záznamov pre viac detailov. -# notfound.fxml -notfound.label = Trezor nemohol by\u0165 nenájdený. Bol presunutý? -# upgrade.fxml -upgrade.button = Upgradnú\u0165 trezor -upgrade.version3dropBundleExtension.msg = Tento trezor musí by\u0165 premigrovaný na nový formát. "%1$s" bude premenovaný na "%2$s". Prosím, uistite sa \u017Ee je dokon\u010Dená synchronizácia skôr ne\u017E budete pokra\u010Dova\u0165. -upgrade.version3dropBundleExtension.err.alreadyExists = Automatická migrácia zlyhala. "%s" u\u017E existuje. -# unlock.fxml -unlock.label.password = Heslo -unlock.label.mountName = Názov jednotky -unlock.label.winDriveLetter = Ozna\u010Denie jednotky -unlock.label.downloadsPageLink = V\u0161etky verzie Cryptomatoru -unlock.label.advancedHeading = Pokro\u010Dilé nastavenia -unlock.button.unlock = Odomknú\u0165 trezor -unlock.button.advancedOptions.show = Viac nastavení -unlock.button.advancedOptions.hide = Menej nastavení -unlock.choicebox.winDriveLetter.auto = Priradi\u0165 automaticky -unlock.errorMessage.wrongPassword = Nesprávne heslo -unlock.errorMessage.mountingFailed = Pripájanie zlyhalo. Viac informácii v logu. -unlock.errorMessage.unsupportedKeyLengthInstallJCE = De\u0161ifrovanie zlyhalo. Prosím nain\u0161talujte Oracle JCE Unlimited Strength Policy Files. -unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Nepodporovaný trezor. Tento trezor bol vytvorený star\u0161ou verziou Cryptromatoru. -unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = Nepodporovaný trezor. Bol vytvorený z nov\u0161ou verziou Cryptomatoru. -unlock.messageLabel.startServerFailed = Spustenie WebDAv servera zlyhalo. -# change_password.fxml -changePassword.label.oldPassword = Staré heslo -changePassword.label.newPassword = Nové heslo -changePassword.label.retypePassword = Znova zadajte heslo -changePassword.label.downloadsPageLink = V\u0161etky verzie Cryptomatoru. -changePassword.button.change = Zmeni\u0165 heslo -changePassword.errorMessage.wrongPassword = Nesprávne heslo -changePassword.errorMessage.decryptionFailed = De\u0161ifrovanie zlyhalo. -changePassword.errorMessage.unsupportedKeyLengthInstallJCE = De\u0161ifrovanie zlyhalo. Prosím nain\u0161talujte Oracle JCE Unlimited Strength Policy. -changePassword.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Nepodporovaný trezor. Bol vytvorený star\u0161ou verziou Cryptomatoru. -changePassword.errorMessage.unsupportedVersion.softwareOlderThanVault = Nepodporovaný trezor. Bol vytvorený nov\u0161ou verziou Cryptomatoru. -changePassword.infoMessage.success = Heslo zmenené -# unlocked.fxml -unlocked.button.lock = Zamknú\u0165 trezor -unlocked.moreOptions.reveal = Odhali\u0165 jednotku -unlocked.moreOptions.copyUrl = Kopírova\u0165 WebDAV URL -unlocked.label.revealFailed = Príkaz zlyhal -unlocked.label.unmountFailed = Odpájanie jednotky zlyhalo -unlocked.label.statsEncrypted = za\u0161ifrované -unlocked.label.statsDecrypted = de\u0161ifrované -unlocked.ioGraph.yAxis.label = Priepustnos\u0165 (MiB/s) -# mac_warnings.fxml -macWarnings.windowTitle = Upozornenie - Po\u0161kodený súbor v %s -macWarnings.message = Cryptomator odhalil potencionálne \u0161kodlivé po\u0161kodenie v nasledujúcich súboroch\: -macWarnings.moreInformationButton = Zisti\u0165 viac -macWarnings.whitelistButton = Napriek tomu de\u0161ifrova\u0165 vybrané -# settings.fxml -settings.version.label = Verzia %s -settings.checkForUpdates.label = Skontrolova\u0165 aktualizácie -settings.port.label = WebDAV Port * -settings.port.prompt = 0 \= Vybra\u0165 automaticky -settings.useipv6.label = Pou\u017Ei\u0165 IPv6 -settings.requiresRestartLabel = * Cryptomator vy\u017Eaduje re\u0161tart -# tray icon -tray.menu.open = Otvori\u0165 -tray.menu.quit = Vypnú\u0165 -tray.infoMsg.title = Stále be\u017Eí -tray.infoMsg.msg = Cryptomator je stále spustený. Vypnite ho pomocou ikony v systémovej li\u0161te. -tray.infoMsg.msg.osx = Cryptomator je stále sputený. Ukon\u010Dite ho pomocou ikony v menu. \ No newline at end of file From a6cefe67c43c193bb40ed69a58ad28bb8a0777b0 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Tue, 3 May 2016 10:48:24 +0200 Subject: [PATCH 09/15] setting default port to 42427 [ci skip] --- main/ui/src/main/java/org/cryptomator/ui/settings/Settings.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/ui/src/main/java/org/cryptomator/ui/settings/Settings.java b/main/ui/src/main/java/org/cryptomator/ui/settings/Settings.java index ca3800069..a2540e003 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/settings/Settings.java +++ b/main/ui/src/main/java/org/cryptomator/ui/settings/Settings.java @@ -24,7 +24,7 @@ public class Settings implements Serializable { private static final long serialVersionUID = 7609959894417878744L; public static final int MIN_PORT = 1024; public static final int MAX_PORT = 65535; - public static final int DEFAULT_PORT = 0; + public static final int DEFAULT_PORT = 42427; public static final boolean DEFAULT_USE_IPV6 = false; public static final Integer DEFAULT_NUM_TRAY_NOTIFICATIONS = 3; From a0ef02b95c5e04ad347a61dac88a5756e41ebebe Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Tue, 3 May 2016 13:17:45 +0200 Subject: [PATCH 10/15] fixes #237 --- .../webdav/mount/WindowsWebDavMounter.java | 59 +++++++++++++++++-- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WindowsWebDavMounter.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WindowsWebDavMounter.java index 4136fd2bf..ee8fd5b96 100644 --- a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WindowsWebDavMounter.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WindowsWebDavMounter.java @@ -11,10 +11,16 @@ package org.cryptomator.frontend.webdav.mount; import static org.cryptomator.frontend.webdav.mount.command.Script.fromLines; +import java.io.IOException; +import java.io.InterruptedIOException; import java.net.URI; import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.HashSet; import java.util.Map; import java.util.Optional; +import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -22,12 +28,16 @@ import java.util.regex.Pattern; import javax.inject.Inject; import javax.inject.Singleton; +import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.CharUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.SystemUtils; import org.cryptomator.frontend.CommandFailedException; import org.cryptomator.frontend.Frontend.MountParam; import org.cryptomator.frontend.webdav.mount.command.CommandResult; import org.cryptomator.frontend.webdav.mount.command.Script; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * A {@link WebDavMounterStrategy} utilizing the "net use" command. @@ -37,7 +47,9 @@ import org.cryptomator.frontend.webdav.mount.command.Script; @Singleton final class WindowsWebDavMounter implements WebDavMounterStrategy { + private static final Logger LOG = LoggerFactory.getLogger(WindowsWebDavMounter.class); private static final Pattern WIN_MOUNT_DRIVELETTER_PATTERN = Pattern.compile("\\s*([A-Z]):\\s*"); + private static final Pattern REG_QUERY_PROXY_OVERRIDES_PATTERN = Pattern.compile("\\s*ProxyOverride\\s+REG_SZ\\s+(.*)\\s*"); private static final String AUTO_ASSIGN_DRIVE_LETTER = "*"; private static final String LOCALHOST = "localhost"; private static final int MOUNT_TIMEOUT_SECONDS = 60; @@ -76,10 +88,11 @@ final class WindowsWebDavMounter implements WebDavMounterStrategy { } private CommandResult mount(URI uri, String driveLetter) throws CommandFailedException { - final Script proxyBypassScript = fromLines("reg add \"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\" /v \"ProxyOverride\" /d \";%DAV_HOST%;%DAV_HOST%:%DAV_PORT%\" /f"); - proxyBypassScript.addEnv("DAV_HOST", uri.getHost()); - proxyBypassScript.addEnv("DAV_PORT", String.valueOf(uri.getPort())); - proxyBypassScript.execute(); + try { + addProxyOverrides(uri); + } catch (IOException e) { + throw new CommandFailedException(e); + } final String driveLetterStr = AUTO_ASSIGN_DRIVE_LETTER.equals(driveLetter) ? AUTO_ASSIGN_DRIVE_LETTER : driveLetter + ":"; final Script mountScript = fromLines("net use %DRIVE_LETTER% \\\\%DAV_HOST%@%DAV_PORT%\\DavWWWRoot%DAV_UNC_PATH% /persistent:no"); @@ -89,6 +102,44 @@ final class WindowsWebDavMounter implements WebDavMounterStrategy { mountScript.addEnv("DAV_UNC_PATH", uri.getRawPath().replace('/', '\\')); return mountScript.execute(MOUNT_TIMEOUT_SECONDS, TimeUnit.SECONDS); } + + private void addProxyOverrides(URI uri) throws IOException, CommandFailedException { + try { + // get existing value for ProxyOverride key from reqistry: + ProcessBuilder query = new ProcessBuilder("reg", "query", "\"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\"", "/v", "ProxyOverride"); + Process queryCmd = query.start(); + String queryStdOut = IOUtils.toString(queryCmd.getInputStream(), StandardCharsets.UTF_8); + int queryResult = queryCmd.waitFor(); + + // determine new value for ProxyOverride key: + Set overrides = new HashSet<>(); + Matcher matcher = REG_QUERY_PROXY_OVERRIDES_PATTERN.matcher(queryStdOut); + if (queryResult == 0 && matcher.find()) { + String[] existingOverrides = StringUtils.split(matcher.group(1), ';'); + overrides.addAll(Arrays.asList(existingOverrides)); + } + overrides.removeIf(s -> s.startsWith(uri.getHost() + ":")); + overrides.add(""); + overrides.add(uri.getHost()); + overrides.add(uri.getHost() + ":" + uri.getPort()); + + // set new value: + String overridesStr = StringUtils.join(overrides, ';'); + ProcessBuilder add = new ProcessBuilder("reg", "add", "\"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\"", "/v", "ProxyOverride", "/d", "\"" + overridesStr + "\"", "/f"); + LOG.debug("Invoking command: " + StringUtils.join(add.command(), ' ')); + Process addCmd = add.start(); + int addResult = addCmd.waitFor(); + if (addResult != 0) { + String addStdErr = IOUtils.toString(addCmd.getErrorStream(), StandardCharsets.UTF_8); + throw new CommandFailedException(addStdErr); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + InterruptedIOException ioException = new InterruptedIOException(); + ioException.initCause(e); + throw ioException; + } + } private String getDriveLetter(String result) throws CommandFailedException { final Matcher matcher = WIN_MOUNT_DRIVELETTER_PATTERN.matcher(result); From b6d1d1dc22865243a09824eca38ffa73128a74f1 Mon Sep 17 00:00:00 2001 From: Tobias Hagemann Date: Tue, 3 May 2016 16:07:30 +0200 Subject: [PATCH 11/15] updated linux app icon [ci skip] --- .../resources/package/linux/Cryptomator.png | Bin 46608 -> 45179 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/main/ant-kit/src/main/resources/package/linux/Cryptomator.png b/main/ant-kit/src/main/resources/package/linux/Cryptomator.png index 99d9fb876c869b5adbb453af105d973974c99723..1e0832c42af7992f5882357da9673672d9f0d776 100644 GIT binary patch literal 45179 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 From 08f664e3df6ae46641ed602cb7f0cb2efa005d85 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Tue, 3 May 2016 16:44:22 +0200 Subject: [PATCH 12/15] Throttle calls to Settings.save() --- .../java/org/cryptomator/ui/ExitUtil.java | 1 + .../ui/controllers/MainController.java | 4 +++ .../ui/controllers/SettingsController.java | 21 ++++++++++---- .../org/cryptomator/ui/settings/Settings.java | 24 ++------------- .../ui/settings/SettingsProvider.java | 29 +++++++++++++++---- 5 files changed, 46 insertions(+), 33 deletions(-) diff --git a/main/ui/src/main/java/org/cryptomator/ui/ExitUtil.java b/main/ui/src/main/java/org/cryptomator/ui/ExitUtil.java index 39cb090e3..3c4976cf4 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/ExitUtil.java +++ b/main/ui/src/main/java/org/cryptomator/ui/ExitUtil.java @@ -136,6 +136,7 @@ class ExitUtil { return; } else { settings.setNumTrayNotifications(settings.getNumTrayNotifications() - 1); + settings.save(); } final Runnable notificationCmd; if (SystemUtils.IS_OS_MAC_OSX) { diff --git a/main/ui/src/main/java/org/cryptomator/ui/controllers/MainController.java b/main/ui/src/main/java/org/cryptomator/ui/controllers/MainController.java index 5c262f6de..f316fe2c2 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/controllers/MainController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/controllers/MainController.java @@ -40,6 +40,7 @@ import javafx.beans.binding.BooleanBinding; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.collections.FXCollections; +import javafx.collections.ListChangeListener.Change; import javafx.collections.ObservableList; import javafx.event.ActionEvent; import javafx.fxml.FXML; @@ -94,6 +95,9 @@ public class MainController extends LocalizedFXMLViewController { this.changePasswordController = changePasswordController; this.settingsController = settingsController; this.vaults = FXCollections.observableList(settings.getDirectories()); + this.vaults.addListener((Change c) -> { + settings.save(); + }); // derived bindings: this.isShowingSettings = activeController.isEqualTo(settingsController.get()); diff --git a/main/ui/src/main/java/org/cryptomator/ui/controllers/SettingsController.java b/main/ui/src/main/java/org/cryptomator/ui/controllers/SettingsController.java index 7af0e8269..80cd60cab 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/controllers/SettingsController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/controllers/SettingsController.java @@ -59,9 +59,9 @@ public class SettingsController extends LocalizedFXMLViewController { useIpv6Checkbox.setSelected(SystemUtils.IS_OS_WINDOWS && settings.shouldUseIpv6()); versionLabel.setText(String.format(localization.getString("settings.version.label"), applicationVersion().orElse("SNAPSHOT"))); - EasyBind.subscribe(checkForUpdatesCheckbox.selectedProperty(), settings::setCheckForUpdatesEnabled); + EasyBind.subscribe(checkForUpdatesCheckbox.selectedProperty(), this::checkForUpdateDidChange); EasyBind.subscribe(portField.textProperty(), this::portDidChange); - EasyBind.subscribe(useIpv6Checkbox.selectedProperty(), settings::setUseIpv6); + EasyBind.subscribe(useIpv6Checkbox.selectedProperty(), this::useIpv6DidChange); } @Override @@ -73,21 +73,30 @@ public class SettingsController extends LocalizedFXMLViewController { return Optional.ofNullable(getClass().getPackage().getImplementationVersion()); } + private void checkForUpdateDidChange(Boolean newValue) { + settings.setCheckForUpdatesEnabled(newValue); + settings.save(); + } + private void portDidChange(String newValue) { try { int port = Integer.parseInt(newValue); - if (port < Settings.MIN_PORT) { + if (port < Settings.MIN_PORT || port > Settings.MAX_PORT) { settings.setPort(Settings.DEFAULT_PORT); - } else if (port < Settings.MAX_PORT) { - settings.setPort(port); } else { - portField.setText(String.valueOf(Settings.MAX_PORT)); + settings.setPort(port); + settings.save(); } } catch (NumberFormatException e) { portField.setText(String.valueOf(Settings.DEFAULT_PORT)); } } + private void useIpv6DidChange(Boolean newValue) { + settings.setUseIpv6(newValue); + settings.save(); + } + private void filterNumericKeyEvents(KeyEvent t) { if (t.getCharacter() == null || t.getCharacter().length() == 0) { return; diff --git a/main/ui/src/main/java/org/cryptomator/ui/settings/Settings.java b/main/ui/src/main/java/org/cryptomator/ui/settings/Settings.java index a2540e003..17f7c5b25 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/settings/Settings.java +++ b/main/ui/src/main/java/org/cryptomator/ui/settings/Settings.java @@ -48,26 +48,11 @@ public class Settings implements Serializable { /** * Package-private constructor; use {@link SettingsProvider}. */ - Settings() { - this.saveCmd = s -> { - }; - } - - private Settings(Consumer saveCmd) { + Settings(Consumer saveCmd) { this.saveCmd = saveCmd; } - Settings withSaveCmd(Consumer saveCmd) { - final Settings result = new Settings(saveCmd); - result.directories = this.directories; - result.checkForUpdatesEnabled = this.checkForUpdatesEnabled; - result.port = this.port; - result.useIpv6 = this.useIpv6; - result.numTrayNotifications = this.numTrayNotifications; - return result; - } - - private void save() { + public void save() { saveCmd.accept(this); } @@ -82,7 +67,6 @@ public class Settings implements Serializable { public void setDirectories(List directories) { this.directories = directories; - save(); } public boolean isCheckForUpdatesEnabled() { @@ -92,7 +76,6 @@ public class Settings implements Serializable { public void setCheckForUpdatesEnabled(boolean checkForUpdatesEnabled) { this.checkForUpdatesEnabled = checkForUpdatesEnabled; - save(); } public void setPort(int port) { @@ -100,7 +83,6 @@ public class Settings implements Serializable { throw new IllegalArgumentException("Invalid port"); } this.port = port; - save(); } public int getPort() { @@ -121,7 +103,6 @@ public class Settings implements Serializable { public void setUseIpv6(boolean useIpv6) { this.useIpv6 = useIpv6; - save(); } public Integer getNumTrayNotifications() { @@ -130,7 +111,6 @@ public class Settings implements Serializable { public void setNumTrayNotifications(Integer numTrayNotifications) { this.numTrayNotifications = numTrayNotifications; - save(); } } diff --git a/main/ui/src/main/java/org/cryptomator/ui/settings/SettingsProvider.java b/main/ui/src/main/java/org/cryptomator/ui/settings/SettingsProvider.java index 1bfddbddf..417b6c369 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/settings/SettingsProvider.java +++ b/main/ui/src/main/java/org/cryptomator/ui/settings/SettingsProvider.java @@ -16,6 +16,12 @@ import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; +import java.util.Objects; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; import javax.inject.Inject; import javax.inject.Named; @@ -34,6 +40,7 @@ public class SettingsProvider implements Provider { private static final Logger LOG = LoggerFactory.getLogger(SettingsProvider.class); private static final Path SETTINGS_DIR; private static final String SETTINGS_FILE = "settings.json"; + private static final long SAVE_DELAY_MS = 1000; static { final String appdata = System.getenv("APPDATA"); @@ -52,6 +59,8 @@ public class SettingsProvider implements Provider { } private final ObjectMapper objectMapper; + private final ScheduledExecutorService saveScheduler = Executors.newSingleThreadScheduledExecutor(); + private final AtomicReference> scheduledSaveCmd = new AtomicReference<>(); @Inject public SettingsProvider(@Named("VaultJsonMapper") ObjectMapper objectMapper) { @@ -69,23 +78,33 @@ public class SettingsProvider implements Provider { @Override public Settings get() { - Settings settings = null; + final Settings settings = new Settings(this::scheduleSave); try { final Path settingsPath = getSettingsPath(); final InputStream in = Files.newInputStream(settingsPath, StandardOpenOption.READ); - settings = objectMapper.readValue(in, Settings.class); + objectMapper.readerForUpdating(settings).readValue(in); LOG.info("Settings loaded from " + settingsPath); } catch (IOException e) { LOG.info("Failed to load settings, creating new one."); - settings = new Settings(); } - return settings.withSaveCmd(this::save); + return settings; } - private void save(Settings settings) { + private void scheduleSave(Settings settings) { if (settings == null) { return; } + ScheduledFuture saveCmd = saveScheduler.schedule(() -> { + this.save(settings); + } , SAVE_DELAY_MS, TimeUnit.MILLISECONDS); + ScheduledFuture previousSaveCmd = scheduledSaveCmd.getAndSet(saveCmd); + if (previousSaveCmd != null) { + previousSaveCmd.cancel(false); + } + } + + private void save(Settings settings) { + Objects.requireNonNull(settings); try { final Path settingsPath = getSettingsPath(); Files.createDirectories(settingsPath.getParent()); From 68ee89af989ac2a262e7a6acfb503d9ab33ecfb4 Mon Sep 17 00:00:00 2001 From: Tobias Hagemann Date: Tue, 3 May 2016 19:12:21 +0200 Subject: [PATCH 13/15] updated bot welcome asset [ci skip] --- main/ui/src/main/resources/bot_welcome.png | Bin 16299 -> 15759 bytes main/ui/src/main/resources/bot_welcome@2x.png | Bin 35492 -> 34271 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/main/ui/src/main/resources/bot_welcome.png b/main/ui/src/main/resources/bot_welcome.png index 5daf92fd6733eac839f21a2127fdd12c30572e95..a429621d919a0a9d34375d0d1b7c7f2c17ef5be6 100644 GIT binary patch literal 15759 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�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 diff --git a/main/ui/src/main/resources/bot_welcome@2x.png b/main/ui/src/main/resources/bot_welcome@2x.png index 8c25a5e21a9d99904802b5726c91ea23ea134f84..d6e201c2094a2b6f2f03bed82a58e51e8385199a 100644 GIT binary patch literal 34271 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 literal 35492 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

|1fg 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 FV1nm)>TUo4 From 78645ecdf66ae7f195d7d954624d96cb99c362f6 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Sat, 7 May 2016 14:40:44 +0200 Subject: [PATCH 14/15] fixes #264 --- main/filesystem-charsets/pom.xml | 45 ++++++ .../charsets/NormalizedNameFile.java | 32 ++++ .../charsets/NormalizedNameFileSystem.java | 27 ++++ .../charsets/NormalizedNameFolder.java | 76 +++++++++ .../filesystem/charsets/package-info.java | 16 ++ .../NormalizedNameFileSystemTest.java | 90 +++++++++++ .../charsets/NormalizedNameFileTest.java | 48 ++++++ .../charsets/NormalizedNameFolderTest.java | 149 ++++++++++++++++++ .../src/test/resources/log4j2.xml | 22 +++ main/filesystem-invariants-tests/pom.xml | 4 + .../invariants/FileSystemFactories.java | 22 ++- main/pom.xml | 6 + main/ui/pom.xml | 4 + .../java/org/cryptomator/ui/model/Vault.java | 4 +- 14 files changed, 541 insertions(+), 4 deletions(-) create mode 100644 main/filesystem-charsets/pom.xml create mode 100644 main/filesystem-charsets/src/main/java/org/cryptomator/filesystem/charsets/NormalizedNameFile.java create mode 100644 main/filesystem-charsets/src/main/java/org/cryptomator/filesystem/charsets/NormalizedNameFileSystem.java create mode 100644 main/filesystem-charsets/src/main/java/org/cryptomator/filesystem/charsets/NormalizedNameFolder.java create mode 100644 main/filesystem-charsets/src/main/java/org/cryptomator/filesystem/charsets/package-info.java create mode 100644 main/filesystem-charsets/src/test/java/org/cryptomator/filesystem/charsets/NormalizedNameFileSystemTest.java create mode 100644 main/filesystem-charsets/src/test/java/org/cryptomator/filesystem/charsets/NormalizedNameFileTest.java create mode 100644 main/filesystem-charsets/src/test/java/org/cryptomator/filesystem/charsets/NormalizedNameFolderTest.java create mode 100644 main/filesystem-charsets/src/test/resources/log4j2.xml diff --git a/main/filesystem-charsets/pom.xml b/main/filesystem-charsets/pom.xml new file mode 100644 index 000000000..b5eba0555 --- /dev/null +++ b/main/filesystem-charsets/pom.xml @@ -0,0 +1,45 @@ + + + + 4.0.0 + + org.cryptomator + main + 1.1.0-SNAPSHOT + + filesystem-charsets + Cryptomator filesystem: Filename charset compatibility layer + + + + org.cryptomator + filesystem-api + + + + + org.cryptomator + commons-test + + + org.cryptomator + filesystem-inmemory + + + + + + + org.jacoco + jacoco-maven-plugin + + + + \ No newline at end of file diff --git a/main/filesystem-charsets/src/main/java/org/cryptomator/filesystem/charsets/NormalizedNameFile.java b/main/filesystem-charsets/src/main/java/org/cryptomator/filesystem/charsets/NormalizedNameFile.java new file mode 100644 index 000000000..af73d59c1 --- /dev/null +++ b/main/filesystem-charsets/src/main/java/org/cryptomator/filesystem/charsets/NormalizedNameFile.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2016 Sebastian Stenzel and others. + * This file is licensed under the terms of the MIT license. + * See the LICENSE.txt file for more info. + * + * Contributors: + * Sebastian Stenzel - initial API and implementation + *******************************************************************************/ +package org.cryptomator.filesystem.charsets; + +import java.io.UncheckedIOException; +import java.text.Normalizer; +import java.text.Normalizer.Form; + +import org.cryptomator.filesystem.File; +import org.cryptomator.filesystem.delegating.DelegatingFile; + +class NormalizedNameFile extends DelegatingFile { + + private final Form displayForm; + + public NormalizedNameFile(NormalizedNameFolder parent, File delegate, Form displayForm) { + super(parent, delegate); + this.displayForm = displayForm; + } + + @Override + public String name() throws UncheckedIOException { + return Normalizer.normalize(super.name(), displayForm); + } + +} diff --git a/main/filesystem-charsets/src/main/java/org/cryptomator/filesystem/charsets/NormalizedNameFileSystem.java b/main/filesystem-charsets/src/main/java/org/cryptomator/filesystem/charsets/NormalizedNameFileSystem.java new file mode 100644 index 000000000..a69c572d6 --- /dev/null +++ b/main/filesystem-charsets/src/main/java/org/cryptomator/filesystem/charsets/NormalizedNameFileSystem.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2016 Sebastian Stenzel and others. + * This file is licensed under the terms of the MIT license. + * See the LICENSE.txt file for more info. + * + * Contributors: + * Sebastian Stenzel - initial API and implementation + *******************************************************************************/ +package org.cryptomator.filesystem.charsets; + +import java.text.Normalizer.Form; + +import org.cryptomator.filesystem.Folder; +import org.cryptomator.filesystem.delegating.DelegatingFileSystem; + +public class NormalizedNameFileSystem extends NormalizedNameFolder implements DelegatingFileSystem { + + public NormalizedNameFileSystem(Folder delegate, Form displayForm) { + super(null, delegate, displayForm); + } + + @Override + public Folder getDelegate() { + return delegate; + } + +} diff --git a/main/filesystem-charsets/src/main/java/org/cryptomator/filesystem/charsets/NormalizedNameFolder.java b/main/filesystem-charsets/src/main/java/org/cryptomator/filesystem/charsets/NormalizedNameFolder.java new file mode 100644 index 000000000..e2762059b --- /dev/null +++ b/main/filesystem-charsets/src/main/java/org/cryptomator/filesystem/charsets/NormalizedNameFolder.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (c) 2016 Sebastian Stenzel and others. + * This file is licensed under the terms of the MIT license. + * See the LICENSE.txt file for more info. + * + * Contributors: + * Sebastian Stenzel - initial API and implementation + *******************************************************************************/ +package org.cryptomator.filesystem.charsets; + +import java.io.UncheckedIOException; +import java.text.Normalizer; +import java.text.Normalizer.Form; + +import org.cryptomator.filesystem.File; +import org.cryptomator.filesystem.Folder; +import org.cryptomator.filesystem.delegating.DelegatingFolder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +class NormalizedNameFolder extends DelegatingFolder { + + private static final Logger LOG = LoggerFactory.getLogger(NormalizedNameFolder.class); + private final Form displayForm; + + public NormalizedNameFolder(NormalizedNameFolder parent, Folder delegate, Form displayForm) { + super(parent, delegate); + this.displayForm = displayForm; + } + + @Override + public String name() throws UncheckedIOException { + return Normalizer.normalize(super.name(), displayForm); + } + + @Override + public NormalizedNameFile file(String name) throws UncheckedIOException { + String nfcName = Normalizer.normalize(name, Form.NFC); + String nfdName = Normalizer.normalize(name, Form.NFD); + NormalizedNameFile nfcFile = super.file(nfcName); + NormalizedNameFile nfdFile = super.file(nfdName); + if (!nfcName.equals(nfdName) && nfcFile.exists() && nfdFile.exists()) { + LOG.warn("Ambiguous file names \"" + nfcName + "\" (NFC) vs. \"" + nfdName + "\" (NFD). Both files exist. Using \"" + nfcName + "\" (NFC)."); + } else if (!nfcName.equals(nfdName) && !nfcFile.exists() && nfdFile.exists()) { + LOG.info("Moving file from \"" + nfcName + "\" (NFD) to \"" + nfdName + "\" (NFC)."); + nfdFile.moveTo(nfcFile); + } + return nfcFile; + } + + @Override + protected NormalizedNameFile newFile(File delegate) { + return new NormalizedNameFile(this, delegate, displayForm); + } + + @Override + public NormalizedNameFolder folder(String name) throws UncheckedIOException { + String nfcName = Normalizer.normalize(name, Form.NFC); + String nfdName = Normalizer.normalize(name, Form.NFD); + NormalizedNameFolder nfcFolder = super.folder(nfcName); + NormalizedNameFolder nfdFolder = super.folder(nfdName); + if (!nfcName.equals(nfdName) && nfcFolder.exists() && nfdFolder.exists()) { + LOG.warn("Ambiguous folder names \"" + nfcName + "\" (NFC) vs. \"" + nfdName + "\" (NFD). Both files exist. Using \"" + nfcName + "\" (NFC)."); + } else if (!nfcName.equals(nfdName) && !nfcFolder.exists() && nfdFolder.exists()) { + LOG.info("Moving folder from \"" + nfcName + "\" (NFD) to \"" + nfdName + "\" (NFC)."); + nfdFolder.moveTo(nfcFolder); + } + return nfcFolder; + } + + @Override + protected NormalizedNameFolder newFolder(Folder delegate) { + return new NormalizedNameFolder(this, delegate, displayForm); + } + +} diff --git a/main/filesystem-charsets/src/main/java/org/cryptomator/filesystem/charsets/package-info.java b/main/filesystem-charsets/src/main/java/org/cryptomator/filesystem/charsets/package-info.java new file mode 100644 index 000000000..3ee4f6a17 --- /dev/null +++ b/main/filesystem-charsets/src/main/java/org/cryptomator/filesystem/charsets/package-info.java @@ -0,0 +1,16 @@ +/******************************************************************************* + * Copyright (c) 2016 Sebastian Stenzel and others. + * This file is licensed under the terms of the MIT license. + * See the LICENSE.txt file for more info. + * + * Contributors: + * Sebastian Stenzel - initial API and implementation + *******************************************************************************/ +/** + * Makes sure, the filesystems wrapped by this filesystem work only on UTF-8 encoded file paths using Normalization Form C. + * Filesystems wrapping this file system, on the other hand, will get filenames reported in a specified Normalization Form. + * It is recommended to use NFD for OS X and NFC for other operating systems. + * When looking for a file or folder with a name given in either form, both possibilities are considered + * and files/folders stored in NFD are automatically migrated to NFC. + */ +package org.cryptomator.filesystem.charsets; \ No newline at end of file diff --git a/main/filesystem-charsets/src/test/java/org/cryptomator/filesystem/charsets/NormalizedNameFileSystemTest.java b/main/filesystem-charsets/src/test/java/org/cryptomator/filesystem/charsets/NormalizedNameFileSystemTest.java new file mode 100644 index 000000000..e662838a8 --- /dev/null +++ b/main/filesystem-charsets/src/test/java/org/cryptomator/filesystem/charsets/NormalizedNameFileSystemTest.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * Copyright (c) 2016 Sebastian Stenzel and others. + * This file is licensed under the terms of the MIT license. + * See the LICENSE.txt file for more info. + * + * Contributors: + * Sebastian Stenzel - initial API and implementation + *******************************************************************************/ +package org.cryptomator.filesystem.charsets; + +import java.nio.ByteBuffer; +import java.text.Normalizer.Form; + +import org.cryptomator.filesystem.FileSystem; +import org.cryptomator.filesystem.WritableFile; +import org.cryptomator.filesystem.inmem.InMemoryFileSystem; +import org.junit.Assert; +import org.junit.Test; + +public class NormalizedNameFileSystemTest { + + @Test + public void testFileMigration() { + FileSystem inMemoryFs = new InMemoryFileSystem(); + try (WritableFile writable = inMemoryFs.file("\u006F\u0302").openWritable()) { + writable.write(ByteBuffer.allocate(0)); + } + FileSystem normalizationFs = new NormalizedNameFileSystem(inMemoryFs, Form.NFC); + Assert.assertTrue(normalizationFs.file("\u00F4").exists()); + Assert.assertTrue(normalizationFs.file("\u006F\u0302").exists()); + Assert.assertFalse(inMemoryFs.file("\u006F\u0302").exists()); + Assert.assertTrue(inMemoryFs.file("\u00F4").exists()); + } + + @Test + public void testNoFileMigration() { + FileSystem inMemoryFs = new InMemoryFileSystem(); + try (WritableFile writable = inMemoryFs.file("\u00F4").openWritable()) { + writable.write(ByteBuffer.allocate(0)); + } + FileSystem normalizationFs = new NormalizedNameFileSystem(inMemoryFs, Form.NFC); + Assert.assertTrue(normalizationFs.file("\u00F4").exists()); + Assert.assertTrue(normalizationFs.file("\u006F\u0302").exists()); + Assert.assertFalse(inMemoryFs.file("\u006F\u0302").exists()); + Assert.assertTrue(inMemoryFs.file("\u00F4").exists()); + } + + @Test + public void testFolderMigration() { + FileSystem inMemoryFs = new InMemoryFileSystem(); + inMemoryFs.folder("\u006F\u0302").create(); + FileSystem normalizationFs = new NormalizedNameFileSystem(inMemoryFs, Form.NFC); + Assert.assertTrue(normalizationFs.folder("\u00F4").exists()); + Assert.assertTrue(normalizationFs.folder("\u006F\u0302").exists()); + Assert.assertFalse(inMemoryFs.folder("\u006F\u0302").exists()); + Assert.assertTrue(inMemoryFs.folder("\u00F4").exists()); + } + + @Test + public void testNoFolderMigration() { + FileSystem inMemoryFs = new InMemoryFileSystem(); + inMemoryFs.folder("\u00F4").create(); + FileSystem normalizationFs = new NormalizedNameFileSystem(inMemoryFs, Form.NFC); + Assert.assertTrue(normalizationFs.folder("\u00F4").exists()); + Assert.assertTrue(normalizationFs.folder("\u006F\u0302").exists()); + Assert.assertFalse(inMemoryFs.folder("\u006F\u0302").exists()); + Assert.assertTrue(inMemoryFs.folder("\u00F4").exists()); + } + + @Test + public void testNfcDisplayNames() { + FileSystem inMemoryFs = new InMemoryFileSystem(); + inMemoryFs.folder("a\u00F4").create(); + inMemoryFs.folder("b\u006F\u0302").create(); + FileSystem normalizationFs = new NormalizedNameFileSystem(inMemoryFs, Form.NFC); + Assert.assertEquals("a\u00F4", normalizationFs.folder("a\u00F4").name()); + Assert.assertEquals("b\u00F4", normalizationFs.folder("b\u006F\u0302").name()); + } + + @Test + public void testNfdDisplayNames() { + FileSystem inMemoryFs = new InMemoryFileSystem(); + inMemoryFs.folder("a\u00F4").create(); + inMemoryFs.folder("b\u006F\u0302").create(); + FileSystem normalizationFs = new NormalizedNameFileSystem(inMemoryFs, Form.NFD); + Assert.assertEquals("a\u006F\u0302", normalizationFs.folder("a\u00F4").name()); + Assert.assertEquals("b\u006F\u0302", normalizationFs.folder("b\u006F\u0302").name()); + } + +} diff --git a/main/filesystem-charsets/src/test/java/org/cryptomator/filesystem/charsets/NormalizedNameFileTest.java b/main/filesystem-charsets/src/test/java/org/cryptomator/filesystem/charsets/NormalizedNameFileTest.java new file mode 100644 index 000000000..3a3f1fe64 --- /dev/null +++ b/main/filesystem-charsets/src/test/java/org/cryptomator/filesystem/charsets/NormalizedNameFileTest.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2016 Sebastian Stenzel and others. + * This file is licensed under the terms of the MIT license. + * See the LICENSE.txt file for more info. + * + * Contributors: + * Sebastian Stenzel - initial API and implementation + *******************************************************************************/ +package org.cryptomator.filesystem.charsets; + +import java.text.Normalizer.Form; + +import org.cryptomator.filesystem.File; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; + +public class NormalizedNameFileTest { + + private File delegateNfc; + private File delegateNfd; + + @Before + public void setup() { + delegateNfc = Mockito.mock(File.class); + delegateNfd = Mockito.mock(File.class); + Mockito.when(delegateNfc.name()).thenReturn("\u00C5"); + Mockito.when(delegateNfd.name()).thenReturn("\u0041\u030A"); + } + + @Test + public void testDisplayNameInNfc() { + File file1 = new NormalizedNameFile(null, delegateNfc, Form.NFC); + File file2 = new NormalizedNameFile(null, delegateNfd, Form.NFC); + Assert.assertEquals("\u00C5", file1.name()); + Assert.assertEquals("\u00C5", file2.name()); + } + + @Test + public void testDisplayNameInNfd() { + File file1 = new NormalizedNameFile(null, delegateNfc, Form.NFD); + File file2 = new NormalizedNameFile(null, delegateNfd, Form.NFD); + Assert.assertEquals("\u0041\u030A", file1.name()); + Assert.assertEquals("\u0041\u030A", file2.name()); + } + +} diff --git a/main/filesystem-charsets/src/test/java/org/cryptomator/filesystem/charsets/NormalizedNameFolderTest.java b/main/filesystem-charsets/src/test/java/org/cryptomator/filesystem/charsets/NormalizedNameFolderTest.java new file mode 100644 index 000000000..7bf017652 --- /dev/null +++ b/main/filesystem-charsets/src/test/java/org/cryptomator/filesystem/charsets/NormalizedNameFolderTest.java @@ -0,0 +1,149 @@ +/******************************************************************************* + * Copyright (c) 2016 Sebastian Stenzel and others. + * This file is licensed under the terms of the MIT license. + * See the LICENSE.txt file for more info. + * + * Contributors: + * Sebastian Stenzel - initial API and implementation + *******************************************************************************/ +package org.cryptomator.filesystem.charsets; + +import java.text.Normalizer.Form; + +import org.cryptomator.filesystem.File; +import org.cryptomator.filesystem.Folder; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; + +public class NormalizedNameFolderTest { + + private Folder delegate; + private File delegateSubFileNfc; + private File delegateSubFileNfd; + private Folder delegateSubFolderNfc; + private Folder delegateSubFolderNfd; + + @Before + public void setup() { + delegate = Mockito.mock(Folder.class); + delegateSubFileNfc = Mockito.mock(File.class); + delegateSubFileNfd = Mockito.mock(File.class); + Mockito.when(delegate.file("\u00C5")).thenReturn(delegateSubFileNfc); + Mockito.when(delegateSubFileNfc.name()).thenReturn("\u00C5"); + Mockito.when(delegate.file("\u0041\u030A")).thenReturn(delegateSubFileNfd); + Mockito.when(delegateSubFileNfd.name()).thenReturn("\u0041\u030A"); + delegateSubFolderNfc = Mockito.mock(Folder.class); + delegateSubFolderNfd = Mockito.mock(Folder.class); + Mockito.when(delegate.folder("\u00F4")).thenReturn(delegateSubFolderNfc); + Mockito.when(delegateSubFolderNfc.name()).thenReturn("\u00F4"); + Mockito.when(delegate.folder("\u006F\u0302")).thenReturn(delegateSubFolderNfd); + Mockito.when(delegateSubFolderNfd.name()).thenReturn("\u006F\u0302"); + } + + @Test + public void testDisplayNameInNfc() { + Folder folder1 = new NormalizedNameFolder(null, delegateSubFolderNfc, Form.NFC); + Folder folder2 = new NormalizedNameFolder(null, delegateSubFolderNfd, Form.NFC); + Assert.assertEquals("\u00F4", folder1.name()); + Assert.assertEquals("\u00F4", folder2.name()); + } + + @Test + public void testDisplayNameInNfd() { + Folder folder1 = new NormalizedNameFolder(null, delegateSubFolderNfc, Form.NFD); + Folder folder2 = new NormalizedNameFolder(null, delegateSubFolderNfd, Form.NFD); + Assert.assertEquals("\u006F\u0302", folder1.name()); + Assert.assertEquals("\u006F\u0302", folder2.name()); + } + + @Test + public void testNoFolderMigration1() { + Mockito.when(delegateSubFolderNfc.exists()).thenReturn(true); + Mockito.when(delegateSubFolderNfd.exists()).thenReturn(false); + Folder folder = new NormalizedNameFolder(null, delegate, Form.NFC); + Folder sub1 = folder.folder("\u00F4"); + Folder sub2 = folder.folder("\u006F\u0302"); + Mockito.verify(delegateSubFolderNfd, Mockito.never()).moveTo(Mockito.any()); + Assert.assertSame(sub1, sub2); + } + + @Test + public void testNoFolderMigration2() { + Mockito.when(delegateSubFolderNfc.exists()).thenReturn(true); + Mockito.when(delegateSubFolderNfd.exists()).thenReturn(true); + Folder folder = new NormalizedNameFolder(null, delegate, Form.NFC); + Folder sub1 = folder.folder("\u00F4"); + Folder sub2 = folder.folder("\u006F\u0302"); + Mockito.verify(delegateSubFolderNfd, Mockito.never()).moveTo(Mockito.any()); + Assert.assertSame(sub1, sub2); + } + + @Test + public void testNoFolderMigration3() { + Mockito.when(delegateSubFolderNfc.exists()).thenReturn(false); + Mockito.when(delegateSubFolderNfd.exists()).thenReturn(false); + Folder folder = new NormalizedNameFolder(null, delegate, Form.NFC); + Folder sub1 = folder.folder("\u00F4"); + Folder sub2 = folder.folder("\u006F\u0302"); + Mockito.verify(delegateSubFolderNfd, Mockito.never()).moveTo(Mockito.any()); + Assert.assertSame(sub1, sub2); + } + + @Test + public void testFolderMigration() { + Mockito.when(delegateSubFolderNfc.exists()).thenReturn(false); + Mockito.when(delegateSubFolderNfd.exists()).thenReturn(true); + Folder folder = new NormalizedNameFolder(null, delegate, Form.NFC); + Folder sub1 = folder.folder("\u00F4"); + Mockito.verify(delegateSubFolderNfd).moveTo(delegateSubFolderNfc); + Folder sub2 = folder.folder("\u006F\u0302"); + Assert.assertSame(sub1, sub2); + } + + @Test + public void testNoFileMigration1() { + Mockito.when(delegateSubFileNfc.exists()).thenReturn(true); + Mockito.when(delegateSubFileNfd.exists()).thenReturn(false); + Folder folder = new NormalizedNameFolder(null, delegate, Form.NFC); + File sub1 = folder.file("\u00C5"); + File sub2 = folder.file("\u0041\u030A"); + Mockito.verify(delegateSubFileNfd, Mockito.never()).moveTo(Mockito.any()); + Assert.assertSame(sub1, sub2); + } + + @Test + public void testNoFileMigration2() { + Mockito.when(delegateSubFileNfc.exists()).thenReturn(true); + Mockito.when(delegateSubFileNfd.exists()).thenReturn(true); + Folder folder = new NormalizedNameFolder(null, delegate, Form.NFC); + File sub1 = folder.file("\u00C5"); + File sub2 = folder.file("\u0041\u030A"); + Mockito.verify(delegateSubFileNfd, Mockito.never()).moveTo(Mockito.any()); + Assert.assertSame(sub1, sub2); + } + + @Test + public void testNoFileMigration3() { + Mockito.when(delegateSubFileNfc.exists()).thenReturn(false); + Mockito.when(delegateSubFileNfd.exists()).thenReturn(false); + Folder folder = new NormalizedNameFolder(null, delegate, Form.NFC); + File sub1 = folder.file("\u00C5"); + File sub2 = folder.file("\u0041\u030A"); + Mockito.verify(delegateSubFileNfd, Mockito.never()).moveTo(Mockito.any()); + Assert.assertSame(sub1, sub2); + } + + @Test + public void testFileMigration() { + Mockito.when(delegateSubFileNfc.exists()).thenReturn(false); + Mockito.when(delegateSubFileNfd.exists()).thenReturn(true); + Folder folder = new NormalizedNameFolder(null, delegate, Form.NFC); + File sub1 = folder.file("\u00C5"); + Mockito.verify(delegateSubFileNfd).moveTo(delegateSubFileNfc); + File sub2 = folder.file("\u0041\u030A"); + Assert.assertSame(sub1, sub2); + } + +} diff --git a/main/filesystem-charsets/src/test/resources/log4j2.xml b/main/filesystem-charsets/src/test/resources/log4j2.xml new file mode 100644 index 000000000..9b4889392 --- /dev/null +++ b/main/filesystem-charsets/src/test/resources/log4j2.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/main/filesystem-invariants-tests/pom.xml b/main/filesystem-invariants-tests/pom.xml index aa13917ee..054464338 100644 --- a/main/filesystem-invariants-tests/pom.xml +++ b/main/filesystem-invariants-tests/pom.xml @@ -20,6 +20,10 @@ org.cryptomator filesystem-api + + org.cryptomator + filesystem-charsets + org.cryptomator filesystem-crypto diff --git a/main/filesystem-invariants-tests/src/test/java/org/cryptomator/filesystem/invariants/FileSystemFactories.java b/main/filesystem-invariants-tests/src/test/java/org/cryptomator/filesystem/invariants/FileSystemFactories.java index 5f9a423f5..8f1eed8ca 100644 --- a/main/filesystem-invariants-tests/src/test/java/org/cryptomator/filesystem/invariants/FileSystemFactories.java +++ b/main/filesystem-invariants-tests/src/test/java/org/cryptomator/filesystem/invariants/FileSystemFactories.java @@ -4,11 +4,13 @@ import static org.cryptomator.common.test.TempFilesRemovedOnShutdown.createTempD import java.io.IOException; import java.io.UncheckedIOException; +import java.text.Normalizer.Form; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.cryptomator.filesystem.FileSystem; +import org.cryptomator.filesystem.charsets.NormalizedNameFileSystem; import org.cryptomator.filesystem.crypto.CryptoEngineTestModule; import org.cryptomator.filesystem.crypto.CryptoFileSystemDelegate; import org.cryptomator.filesystem.crypto.CryptoFileSystemTestComponent; @@ -35,8 +37,10 @@ class FileSystemFactories implements Iterable { add("ShorteningFileSystem > InMemoryFileSystem", this::createShorteningFileSystemInMemory); add("StatsFileSystem > NioFileSystem", this::createStatsFileSystemNio); add("StatsFileSystem > InMemoryFileSystem", this::createStatsFileSystemInMemory); - add("StatsFileSystem > CryptoFileSystem > ShorteningFileSystem > InMemoryFileSystem", this::createCompoundFileSystemInMemory); - add("StatsFileSystem > CryptoFileSystem > ShorteningFileSystem > NioFileSystem", this::createCompoundFileSystemNio); + add("NormalizingFileSystem > NioFileSystem", this::createNormalizingFileSystemNio); + add("NormalizingFileSystem > InMemoryFileSystem", this::createNormalizingFileSystemInMemory); + add("StatsFileSystem > NormalizingFileSystem > CryptoFileSystem > ShorteningFileSystem > InMemoryFileSystem", this::createCompoundFileSystemInMemory); + add("StatsFileSystem > NormalizingFileSystem > CryptoFileSystem > ShorteningFileSystem > NioFileSystem", this::createCompoundFileSystemNio); } private FileSystem createCryptoFileSystemInMemory() { @@ -63,6 +67,14 @@ class FileSystemFactories implements Iterable { return createStatsFileSystem(createInMemoryFileSystem()); } + private FileSystem createNormalizingFileSystemNio() { + return createNormalizingFileSystem(createInMemoryFileSystem()); + } + + private FileSystem createNormalizingFileSystemInMemory() { + return createNormalizingFileSystem(createInMemoryFileSystem()); + } + private FileSystem createCompoundFileSystemNio() { return createCompoundFileSystem(createNioFileSystem()); } @@ -84,13 +96,17 @@ class FileSystemFactories implements Iterable { } private FileSystem createCompoundFileSystem(FileSystem delegate) { - return createStatsFileSystem(createCryptoFileSystem(createShorteningFileSystem(delegate))); + return createStatsFileSystem(createNormalizingFileSystem(createCryptoFileSystem(createShorteningFileSystem(delegate)))); } private FileSystem createStatsFileSystem(FileSystem delegate) { return new StatsFileSystem(delegate); } + private FileSystem createNormalizingFileSystem(FileSystem delegate) { + return new NormalizedNameFileSystem(delegate, Form.NFC); + } + private FileSystem createCryptoFileSystem(FileSystem delegate) { CRYPTO_FS_COMP.cryptoFileSystemFactory().initializeNew(delegate, "aPassphrase"); return CRYPTO_FS_COMP.cryptoFileSystemFactory().unlockExisting(delegate, "aPassphrase", Mockito.mock(CryptoFileSystemDelegate.class)); diff --git a/main/pom.xml b/main/pom.xml index 1aac82079..75ba59663 100644 --- a/main/pom.xml +++ b/main/pom.xml @@ -80,6 +80,11 @@ filesystem-api ${project.version} + + org.cryptomator + filesystem-charsets + ${project.version} + org.cryptomator filesystem-nio @@ -286,6 +291,7 @@ frontend-api frontend-webdav ui + filesystem-charsets diff --git a/main/ui/pom.xml b/main/ui/pom.xml index 6808f3887..873c1af38 100644 --- a/main/ui/pom.xml +++ b/main/ui/pom.xml @@ -38,6 +38,10 @@ org.cryptomator filesystem-crypto + + org.cryptomator + filesystem-charsets + org.cryptomator filesystem-stats diff --git a/main/ui/src/main/java/org/cryptomator/ui/model/Vault.java b/main/ui/src/main/java/org/cryptomator/ui/model/Vault.java index 376e56d09..3cbc4bbc1 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/model/Vault.java +++ b/main/ui/src/main/java/org/cryptomator/ui/model/Vault.java @@ -30,6 +30,7 @@ import org.cryptomator.common.LazyInitializer; import org.cryptomator.common.Optionals; import org.cryptomator.crypto.engine.InvalidPassphraseException; import org.cryptomator.filesystem.FileSystem; +import org.cryptomator.filesystem.charsets.NormalizedNameFileSystem; import org.cryptomator.filesystem.crypto.CryptoFileSystemDelegate; import org.cryptomator.filesystem.crypto.CryptoFileSystemFactory; import org.cryptomator.filesystem.nio.NioFileSystem; @@ -126,7 +127,8 @@ public class Vault implements CryptoFileSystemDelegate { FileSystem fs = getNioFileSystem(); FileSystem shorteningFs = shorteningFileSystemFactory.get(fs); FileSystem cryptoFs = cryptoFileSystemFactory.unlockExisting(shorteningFs, passphrase, this); - StatsFileSystem statsFs = new StatsFileSystem(cryptoFs); + FileSystem normalizingFs = new NormalizedNameFileSystem(cryptoFs, SystemUtils.IS_OS_MAC_OSX ? Form.NFD : Form.NFC); + StatsFileSystem statsFs = new StatsFileSystem(normalizingFs); statsFileSystem = Optional.of(statsFs); String contextPath = StringUtils.prependIfMissing(mountName, "/"); Frontend frontend = frontendFactory.create(statsFs, contextPath); From dcea9e21f0b04c274422e8d63deb818a72acbfbb Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Sat, 7 May 2016 15:00:20 +0200 Subject: [PATCH 15/15] added module to code coverage report --- main/jacoco-report/pom.xml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/main/jacoco-report/pom.xml b/main/jacoco-report/pom.xml index 97a4411aa..20de8d2bf 100644 --- a/main/jacoco-report/pom.xml +++ b/main/jacoco-report/pom.xml @@ -26,6 +26,10 @@ org.cryptomator filesystem-api + + org.cryptomator + filesystem-charsets + org.cryptomator filesystem-crypto @@ -79,4 +83,4 @@ - \ No newline at end of file +