diff --git a/.github/workflows/win-exe.yml b/.github/workflows/win-exe.yml
index 245aa570e..48e9e61ff 100644
--- a/.github/workflows/win-exe.yml
+++ b/.github/workflows/win-exe.yml
@@ -198,7 +198,7 @@ jobs:
name: Publish on winget repo
runs-on: windows-latest
needs: [build-msi]
- if: github.event.action == 'release' || inputs.winget-release
+ if: github.event.action == 'published' || inputs.winget-release
steps:
- name: Submit package to Windows Package Manager Community Repository
run: |
diff --git a/.idea/runConfigurations/Cryptomator_macOS.xml b/.idea/runConfigurations/Cryptomator_macOS.xml
index bf8c97166..c5e8fd815 100644
--- a/.idea/runConfigurations/Cryptomator_macOS.xml
+++ b/.idea/runConfigurations/Cryptomator_macOS.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/.idea/runConfigurations/Cryptomator_macOS_Dev.xml b/.idea/runConfigurations/Cryptomator_macOS_Dev.xml
index 3f7ce8c3a..01ee81f60 100644
--- a/.idea/runConfigurations/Cryptomator_macOS_Dev.xml
+++ b/.idea/runConfigurations/Cryptomator_macOS_Dev.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/README.md b/README.md
index 66644f1a5..bfc5db571 100644
--- a/README.md
+++ b/README.md
@@ -32,6 +32,7 @@ Cryptomator is provided free of charge as an open-source project despite the hig
+
diff --git a/dist/linux/appimage/resources/AppDir/bin/cryptomator.sh b/dist/linux/appimage/resources/AppDir/bin/cryptomator.sh
index 39579a122..7aba42a18 100755
--- a/dist/linux/appimage/resources/AppDir/bin/cryptomator.sh
+++ b/dist/linux/appimage/resources/AppDir/bin/cryptomator.sh
@@ -19,7 +19,7 @@ fi
export LD_PRELOAD=lib/app/libjffi.so
if [ "$GTK2_PRESENT" -eq 0 ] && [ "$GTK3_PRESENT" -ne 0 ]; then
- bin/Cryptomator-gtk2
+ bin/Cryptomator-gtk2 $@
else
- bin/Cryptomator
+ bin/Cryptomator $@
fi
\ No newline at end of file
diff --git a/dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml b/dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml
index ff33e1d38..3e74a00a0 100644
--- a/dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml
+++ b/dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml
@@ -66,6 +66,7 @@
+
diff --git a/dist/linux/debian/cryptomator.sh b/dist/linux/debian/cryptomator.sh
index b8cea3cfe..0d6453962 100644
--- a/dist/linux/debian/cryptomator.sh
+++ b/dist/linux/debian/cryptomator.sh
@@ -3,4 +3,4 @@
# fix for https://github.com/cryptomator/cryptomator/issues/1370
export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/jni/libjffi-1.2.so
-/usr/lib/cryptomator/bin/cryptomator
\ No newline at end of file
+/usr/lib/cryptomator/bin/cryptomator $@
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 7755ed3de..151d7de69 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
4.0.0org.cryptomatorcryptomator
- 1.6.13
+ 1.6.14Cryptomator Desktop App
@@ -46,8 +46,8 @@
18.0.14.0.09.23
- 1.2.11
- 1.7.36
+ 1.4.0
+ 2.0.00.5.11.7.0
diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java
index de9647138..a4a71a2cc 100644
--- a/src/main/java/module-info.java
+++ b/src/main/java/module-info.java
@@ -1,11 +1,12 @@
+import ch.qos.logback.classic.spi.Configurator;
import org.cryptomator.integrations.tray.TrayMenuController;
+import org.cryptomator.logging.LogbackConfiguratorFactory;
import org.cryptomator.ui.traymenu.AwtTrayMenuController;
-module org.cryptomator.desktop {
+open module org.cryptomator.desktop {
requires static org.jetbrains.annotations;
requires org.cryptomator.cryptolib;
-
requires org.cryptomator.cryptofs;
requires org.cryptomator.frontend.dokany;
requires org.cryptomator.frontend.fuse;
@@ -20,9 +21,12 @@ module org.cryptomator.desktop {
requires javafx.fxml;
requires jdk.crypto.ec;
// 3rd party:
+ requires ch.qos.logback.classic;
+ requires ch.qos.logback.core;
requires com.auth0.jwt;
requires com.google.common;
requires com.google.gson;
+ requires com.nimbusds.jose.jwt;
requires com.nulabinc.zxcvbn;
requires com.tobiasdiez.easybind;
requires dagger;
@@ -32,39 +36,7 @@ module org.cryptomator.desktop {
/* TODO: filename-based modules: */
requires static javax.inject; /* ugly dagger/guava crap */
- requires logback.classic;
- requires logback.core;
- requires com.nimbusds.jose.jwt;
- exports org.cryptomator.ui.traymenu to org.cryptomator.integrations.api;
provides TrayMenuController with AwtTrayMenuController;
-
- exports org.cryptomator.ui.keyloading.hub to com.fasterxml.jackson.databind;
-
- opens org.cryptomator.common.settings to com.google.gson;
- opens org.cryptomator.ui.keyloading.hub to com.google.gson, javafx.fxml;
-
- opens org.cryptomator.launcher to javafx.graphics;
-
- opens org.cryptomator.common to javafx.fxml;
- opens org.cryptomator.common.vaults to javafx.fxml;
- opens org.cryptomator.ui.addvaultwizard to javafx.fxml;
- opens org.cryptomator.ui.changepassword to javafx.fxml;
- opens org.cryptomator.ui.common to javafx.fxml;
- opens org.cryptomator.ui.controls to javafx.fxml;
- opens org.cryptomator.ui.forgetPassword to javafx.fxml;
- opens org.cryptomator.ui.fxapp to javafx.fxml;
- opens org.cryptomator.ui.health to javafx.fxml;
- opens org.cryptomator.ui.keyloading.masterkeyfile to javafx.fxml;
- opens org.cryptomator.ui.lock to javafx.fxml;
- opens org.cryptomator.ui.mainwindow to javafx.fxml;
- opens org.cryptomator.ui.migration to javafx.fxml;
- opens org.cryptomator.ui.preferences to javafx.fxml;
- opens org.cryptomator.ui.quit to javafx.fxml;
- opens org.cryptomator.ui.recoverykey to javafx.fxml;
- opens org.cryptomator.ui.removevault to javafx.fxml;
- opens org.cryptomator.ui.stats to javafx.fxml;
- opens org.cryptomator.ui.unlock to javafx.fxml;
- opens org.cryptomator.ui.vaultoptions to javafx.fxml;
- opens org.cryptomator.ui.wrongfilealert to javafx.fxml;
+ provides Configurator with LogbackConfiguratorFactory;
}
\ No newline at end of file
diff --git a/src/main/java/org/cryptomator/common/CatchingExecutors.java b/src/main/java/org/cryptomator/common/CatchingExecutors.java
index d212b2c31..e3dedca87 100644
--- a/src/main/java/org/cryptomator/common/CatchingExecutors.java
+++ b/src/main/java/org/cryptomator/common/CatchingExecutors.java
@@ -10,6 +10,7 @@ import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
+import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
@@ -28,6 +29,18 @@ public final class CatchingExecutors {
super(corePoolSize, threadFactory);
}
+ @Override
+ public ScheduledFuture> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
+ Runnable oneShot = () -> this.execute(command);
+ return super.scheduleAtFixedRate(oneShot, initialDelay, period, unit);
+ }
+
+ @Override
+ public ScheduledFuture> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
+ Runnable oneShot = () -> this.execute(command);
+ return super.scheduleWithFixedDelay(oneShot, initialDelay, delay, unit);
+ }
+
@Override
protected void afterExecute(Runnable runnable, Throwable throwable) {
super.afterExecute(runnable, throwable);
@@ -77,6 +90,12 @@ public final class CatchingExecutors {
}
private static void afterExecuteFuture(Future> future) {
+ if (future instanceof ScheduledFuture> && !future.isDone()) {
+ //we assume that this must be a repeated ScheduledFutureTask, where the done-status is only set when not executed anymore
+ //see also https://github.com/cryptomator/cryptomator/pull/2422
+ return;
+ }
+
try {
future.get();
} catch (CancellationException ce) {
diff --git a/src/main/java/org/cryptomator/common/CommonsModule.java b/src/main/java/org/cryptomator/common/CommonsModule.java
index edb4f063b..101dc1e28 100644
--- a/src/main/java/org/cryptomator/common/CommonsModule.java
+++ b/src/main/java/org/cryptomator/common/CommonsModule.java
@@ -41,6 +41,12 @@ public abstract class CommonsModule {
private static final int NUM_CORE_BG_THREADS = 6;
private static final long BG_THREAD_KEEPALIVE_SECONDS = 60l;
+ @Provides
+ @Singleton
+ static Environment provideEnvironment() {
+ return Environment.getInstance();
+ }
+
@SuppressWarnings("SpellCheckingInspection")
@Provides
@Singleton
diff --git a/src/main/java/org/cryptomator/common/Environment.java b/src/main/java/org/cryptomator/common/Environment.java
index e45c29a29..261750ad1 100644
--- a/src/main/java/org/cryptomator/common/Environment.java
+++ b/src/main/java/org/cryptomator/common/Environment.java
@@ -5,8 +5,6 @@ import com.google.common.base.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.inject.Inject;
-import javax.inject.Singleton;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -17,7 +15,6 @@ import java.util.function.Predicate;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
-@Singleton
public class Environment {
private static final Logger LOG = LoggerFactory.getLogger(Environment.class);
@@ -36,24 +33,37 @@ public class Environment {
private static final String PLUGIN_DIR_PROP_NAME = "cryptomator.pluginDir";
private static final String TRAY_ICON_PROP_NAME = "cryptomator.showTrayIcon";
- @Inject
- public Environment() {
- LOG.debug("user.home: {}", System.getProperty("user.home"));
- LOG.debug("java.library.path: {}", System.getProperty("java.library.path"));
- LOG.debug("user.language: {}", System.getProperty("user.language"));
- LOG.debug("user.region: {}", System.getProperty("user.region"));
- LOG.debug("logback.configurationFile: {}", System.getProperty("logback.configurationFile"));
- LOG.debug("{}: {}", SETTINGS_PATH_PROP_NAME, System.getProperty(SETTINGS_PATH_PROP_NAME));
- LOG.debug("{}: {}", IPC_SOCKET_PATH_PROP_NAME, System.getProperty(IPC_SOCKET_PATH_PROP_NAME));
- LOG.debug("{}: {}", KEYCHAIN_PATHS_PROP_NAME, System.getProperty(KEYCHAIN_PATHS_PROP_NAME));
- LOG.debug("{}: {}", LOG_DIR_PROP_NAME, System.getProperty(LOG_DIR_PROP_NAME));
- LOG.debug("{}: {}", PLUGIN_DIR_PROP_NAME, System.getProperty(PLUGIN_DIR_PROP_NAME));
- LOG.debug("{}: {}", MOUNTPOINT_DIR_PROP_NAME, System.getProperty(MOUNTPOINT_DIR_PROP_NAME));
- LOG.debug("{}: {}", MIN_PW_LENGTH_PROP_NAME, System.getProperty(MIN_PW_LENGTH_PROP_NAME));
- LOG.debug("{}: {}", APP_VERSION_PROP_NAME, System.getProperty(APP_VERSION_PROP_NAME));
- LOG.debug("{}: {}", BUILD_NUMBER_PROP_NAME, System.getProperty(BUILD_NUMBER_PROP_NAME));
- LOG.debug("{}: {}", TRAY_ICON_PROP_NAME, System.getProperty(TRAY_ICON_PROP_NAME));
- LOG.debug("{}: {}", P12_PATH_PROP_NAME, System.getProperty(P12_PATH_PROP_NAME));
+ private Environment() {}
+
+ public void log() {
+ LOG.info("user.home: {}", System.getProperty("user.home"));
+ LOG.info("java.library.path: {}", System.getProperty("java.library.path"));
+ LOG.info("user.language: {}", System.getProperty("user.language"));
+ LOG.info("user.region: {}", System.getProperty("user.region"));
+ LOG.info("logback.configurationFile: {}", System.getProperty("logback.configurationFile"));
+ logCryptomatorSystemProperty(SETTINGS_PATH_PROP_NAME);
+ logCryptomatorSystemProperty(IPC_SOCKET_PATH_PROP_NAME);
+ logCryptomatorSystemProperty(KEYCHAIN_PATHS_PROP_NAME);
+ logCryptomatorSystemProperty(LOG_DIR_PROP_NAME);
+ logCryptomatorSystemProperty(PLUGIN_DIR_PROP_NAME);
+ logCryptomatorSystemProperty(MOUNTPOINT_DIR_PROP_NAME);
+ logCryptomatorSystemProperty(MIN_PW_LENGTH_PROP_NAME);
+ logCryptomatorSystemProperty(APP_VERSION_PROP_NAME);
+ logCryptomatorSystemProperty(BUILD_NUMBER_PROP_NAME);
+ logCryptomatorSystemProperty(TRAY_ICON_PROP_NAME);
+ logCryptomatorSystemProperty(P12_PATH_PROP_NAME);
+ }
+
+ public static Environment getInstance() {
+ final class Holder {
+
+ private static final Environment INSTANCE = new Environment();
+ }
+ return Holder.INSTANCE;
+ }
+
+ private void logCryptomatorSystemProperty(String propertyName) {
+ LOG.info("{}: {}", propertyName, System.getProperty(propertyName));
}
public boolean useCustomLogbackConfig() {
@@ -88,8 +98,13 @@ public class Environment {
return getPath(MOUNTPOINT_DIR_PROP_NAME).map(this::replaceHomeDir);
}
- public Optional getAppVersion() {
- return Optional.ofNullable(System.getProperty(APP_VERSION_PROP_NAME));
+ /**
+ * Returns the app version defined in the {@value APP_VERSION_PROP_NAME} property or returns "SNAPSHOT".
+ *
+ * @return App version or "SNAPSHOT", if undefined
+ */
+ public String getAppVersion() {
+ return System.getProperty(APP_VERSION_PROP_NAME, "SNAPSHOT");
}
public Optional getBuildNumber() {
diff --git a/src/main/java/org/cryptomator/common/settings/DeviceKey.java b/src/main/java/org/cryptomator/common/settings/DeviceKey.java
index aba0bb849..04e9ebd0f 100644
--- a/src/main/java/org/cryptomator/common/settings/DeviceKey.java
+++ b/src/main/java/org/cryptomator/common/settings/DeviceKey.java
@@ -2,7 +2,6 @@ package org.cryptomator.common.settings;
import com.google.common.base.Preconditions;
import com.google.common.base.Suppliers;
-import com.google.common.io.BaseEncoding;
import org.cryptomator.common.Environment;
import org.cryptomator.common.keychain.KeychainManager;
import org.cryptomator.cryptolib.common.P384KeyPair;
@@ -16,6 +15,7 @@ import javax.inject.Singleton;
import java.io.IOException;
import java.nio.CharBuffer;
import java.nio.file.Files;
+import java.nio.file.Path;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.UUID;
@@ -26,6 +26,7 @@ public class DeviceKey {
private static final Logger LOG = LoggerFactory.getLogger(DeviceKey.class);
private static final String KEYCHAIN_KEY = "cryptomator-device-p12";
+ private static final String KEYCHAIN_DISPLAY_NAME = "Cryptomator Device Keypair .p12 Passphrase";
private final KeychainManager keychainManager;
private final Environment env;
@@ -46,15 +47,16 @@ public class DeviceKey {
}
private P384KeyPair loadOrCreate() throws DeviceKeyRetrievalException {
+ Path p12File = env.getP12Path().findFirst().orElseThrow(() -> new DeviceKeyRetrievalException("No path for .p12 file configured"));
char[] passphrase = null;
try {
passphrase = keychainManager.loadPassphrase(KEYCHAIN_KEY);
- if (passphrase != null) {
- return loadExistingKeyPair(passphrase);
- } else {
+ if (passphrase != null && Files.isRegularFile(p12File)) {
+ return loadExistingKeyPair(passphrase, p12File);
+ } else { // (re)generate new key pair if either file or password got lost
passphrase = randomPassword();
- keychainManager.storePassphrase(KEYCHAIN_KEY, CharBuffer.wrap(passphrase));
- return createAndStoreNewKeyPair(passphrase);
+ keychainManager.storePassphrase(KEYCHAIN_KEY, KEYCHAIN_DISPLAY_NAME, CharBuffer.wrap(passphrase));
+ return createAndStoreNewKeyPair(passphrase, p12File);
}
} catch (KeychainAccessException e) {
throw new DeviceKeyRetrievalException("Failed to access system keychain", e);
@@ -67,19 +69,12 @@ public class DeviceKey {
}
}
- private P384KeyPair loadExistingKeyPair(char[] passphrase) throws IOException {
- var p12File = env.getP12Path() //
- .filter(Files::isRegularFile) //
- .findFirst() //
- .orElseThrow(() -> new DeviceKeyRetrievalException("Missing .p12 file"));
+ private P384KeyPair loadExistingKeyPair(char[] passphrase, Path p12File) throws IOException {
LOG.debug("Loading existing device key from {}", p12File);
return P384KeyPair.load(p12File, passphrase);
}
- private P384KeyPair createAndStoreNewKeyPair(char[] passphrase) throws IOException {
- var p12File = env.getP12Path() //
- .findFirst() //
- .orElseThrow(() -> new DeviceKeyRetrievalException("No path for .p12 file configured"));
+ private P384KeyPair createAndStoreNewKeyPair(char[] passphrase, Path p12File) throws IOException {
var keyPair = P384KeyPair.generate();
LOG.debug("Store new device key to {}", p12File);
keyPair.store(p12File, passphrase);
diff --git a/src/main/java/org/cryptomator/common/settings/SettingsJsonAdapter.java b/src/main/java/org/cryptomator/common/settings/SettingsJsonAdapter.java
index 3f4614604..ff62672bd 100644
--- a/src/main/java/org/cryptomator/common/settings/SettingsJsonAdapter.java
+++ b/src/main/java/org/cryptomator/common/settings/SettingsJsonAdapter.java
@@ -103,7 +103,7 @@ public class SettingsJsonAdapter extends TypeAdapter {
case "language" -> settings.languageProperty().set(in.nextString());
default -> {
- LOG.warn("Unsupported vault setting found in JSON: " + name);
+ LOG.warn("Unsupported vault setting found in JSON: {}", name);
in.skipValue();
}
}
diff --git a/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java b/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java
index 15a081f0d..a3a3118dc 100644
--- a/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java
+++ b/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java
@@ -73,7 +73,7 @@ class VaultSettingsJsonAdapter {
case "autoLockWhenIdle" -> autoLockWhenIdle = in.nextBoolean();
case "autoLockIdleSeconds" -> autoLockIdleSeconds = in.nextInt();
default -> {
- LOG.warn("Unsupported vault setting found in JSON: " + name);
+ LOG.warn("Unsupported vault setting found in JSON: {}", name);
in.skipValue();
}
}
diff --git a/src/main/java/org/cryptomator/common/vaults/AutoLocker.java b/src/main/java/org/cryptomator/common/vaults/AutoLocker.java
index da584086d..d113f4177 100644
--- a/src/main/java/org/cryptomator/common/vaults/AutoLocker.java
+++ b/src/main/java/org/cryptomator/common/vaults/AutoLocker.java
@@ -46,7 +46,6 @@ public class AutoLocker {
private boolean exceedsIdleTime(Vault vault) {
assert vault.isUnlocked();
- // TODO: shouldn't we read these properties from within FX Application Thread?
if (vault.getVaultSettings().autoLockWhenIdle().get()) {
int maxIdleSeconds = vault.getVaultSettings().autoLockIdleSeconds().get();
var deadline = vault.getStats().getLastActivity().plusSeconds(maxIdleSeconds);
diff --git a/src/main/java/org/cryptomator/common/vaults/FuseVolume.java b/src/main/java/org/cryptomator/common/vaults/FuseVolume.java
index 0321cfa0f..3bc869592 100644
--- a/src/main/java/org/cryptomator/common/vaults/FuseVolume.java
+++ b/src/main/java/org/cryptomator/common/vaults/FuseVolume.java
@@ -13,8 +13,6 @@ import org.cryptomator.frontend.fuse.mount.FuseMountFactory;
import org.cryptomator.frontend.fuse.mount.FuseNotSupportedException;
import org.cryptomator.frontend.fuse.mount.Mount;
import org.cryptomator.frontend.fuse.mount.Mounter;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Named;
@@ -26,7 +24,6 @@ import java.util.regex.Pattern;
public class FuseVolume extends AbstractVolume {
- private static final Logger LOG = LoggerFactory.getLogger(FuseVolume.class);
private static final Pattern NON_WHITESPACE_OR_QUOTED = Pattern.compile("[^\\s\"']+|\"([^\"]*)\"|'([^']*)'"); // Thanks to https://stackoverflow.com/a/366532
private final VaultSettings vaultSettings;
diff --git a/src/main/java/org/cryptomator/launcher/Cryptomator.java b/src/main/java/org/cryptomator/launcher/Cryptomator.java
index 3cd5ec727..2b066c730 100644
--- a/src/main/java/org/cryptomator/launcher/Cryptomator.java
+++ b/src/main/java/org/cryptomator/launcher/Cryptomator.java
@@ -12,7 +12,6 @@ import org.cryptomator.common.Environment;
import org.cryptomator.common.ShutdownHook;
import org.cryptomator.ipc.IpcCommunicator;
import org.cryptomator.logging.DebugMode;
-import org.cryptomator.logging.LoggerConfiguration;
import org.cryptomator.ui.fxapp.FxApplicationComponent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -35,7 +34,6 @@ public class Cryptomator {
private static final CryptomatorComponent CRYPTOMATOR_COMPONENT = DaggerCryptomatorComponent.factory().create(STARTUP_TIME);
private static final Logger LOG = LoggerFactory.getLogger(Cryptomator.class);
- private final LoggerConfiguration logConfig;
private final DebugMode debugMode;
private final SupportedLanguages supportedLanguages;
private final Environment env;
@@ -43,8 +41,7 @@ public class Cryptomator {
private final ShutdownHook shutdownHook;
@Inject
- Cryptomator(LoggerConfiguration logConfig, DebugMode debugMode, SupportedLanguages supportedLanguages, Environment env, Lazy ipcMessageHandler, ShutdownHook shutdownHook) {
- this.logConfig = logConfig;
+ Cryptomator(DebugMode debugMode, SupportedLanguages supportedLanguages, Environment env, Lazy ipcMessageHandler, ShutdownHook shutdownHook) {
this.debugMode = debugMode;
this.supportedLanguages = supportedLanguages;
this.env = env;
@@ -79,9 +76,9 @@ public class Cryptomator {
* @return Nonzero exit code in case of an error.
*/
private int run(String[] args) {
- logConfig.init();
+ env.log();
LOG.debug("Dagger graph initialized after {}ms", System.currentTimeMillis() - STARTUP_TIME);
- LOG.info("Starting Cryptomator {} on {} {} ({})", env.getAppVersion().orElse("SNAPSHOT"), SystemUtils.OS_NAME, SystemUtils.OS_VERSION, SystemUtils.OS_ARCH);
+ LOG.info("Starting Cryptomator {} on {} {} ({})", env.getAppVersion(), SystemUtils.OS_NAME, SystemUtils.OS_VERSION, SystemUtils.OS_ARCH);
debugMode.initialize();
supportedLanguages.applyPreferred();
diff --git a/src/main/java/org/cryptomator/launcher/CryptomatorComponent.java b/src/main/java/org/cryptomator/launcher/CryptomatorComponent.java
index 8c6443717..72b8af80c 100644
--- a/src/main/java/org/cryptomator/launcher/CryptomatorComponent.java
+++ b/src/main/java/org/cryptomator/launcher/CryptomatorComponent.java
@@ -3,14 +3,13 @@ package org.cryptomator.launcher;
import dagger.BindsInstance;
import dagger.Component;
import org.cryptomator.common.CommonsModule;
-import org.cryptomator.logging.LoggerModule;
import org.cryptomator.ui.fxapp.FxApplicationComponent;
import javax.inject.Named;
import javax.inject.Singleton;
@Singleton
-@Component(modules = {CryptomatorModule.class, CommonsModule.class, LoggerModule.class})
+@Component(modules = {CryptomatorModule.class, CommonsModule.class})
public interface CryptomatorComponent {
Cryptomator application();
diff --git a/src/main/java/org/cryptomator/logging/DebugMode.java b/src/main/java/org/cryptomator/logging/DebugMode.java
index c15fb466b..386b0fd43 100644
--- a/src/main/java/org/cryptomator/logging/DebugMode.java
+++ b/src/main/java/org/cryptomator/logging/DebugMode.java
@@ -5,29 +5,24 @@
*******************************************************************************/
package org.cryptomator.logging;
-import ch.qos.logback.classic.Level;
-import ch.qos.logback.classic.Logger;
-import ch.qos.logback.classic.LoggerContext;
import org.cryptomator.common.settings.Settings;
+import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Singleton;
import javafx.beans.value.ObservableValue;
-import java.util.Map;
@Singleton
public class DebugMode {
- private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(DebugMode.class);
+ private static final Logger LOG = LoggerFactory.getLogger(DebugMode.class);
private final Settings settings;
- private final LoggerContext context;
@Inject
- public DebugMode(Settings settings, LoggerContext context) {
+ public DebugMode(Settings settings) {
this.settings = settings;
- this.context = context;
}
public void initialize() {
@@ -40,19 +35,13 @@ public class DebugMode {
}
private void setLogLevels(boolean debugMode) {
+ var configurator = LogbackConfiguratorFactory.provider();
if (debugMode) {
- setLogLevels(LoggerModule.DEBUG_LOG_LEVELS);
+ configurator.setLogLevels(LogbackConfigurator.DEBUG_LOG_LEVELS);
LOG.debug("Debug mode enabled");
} else {
LOG.debug("Debug mode disabled");
- setLogLevels(LoggerModule.DEFAULT_LOG_LEVELS);
- }
- }
-
- private void setLogLevels(Map logLevels) {
- for (Map.Entry loglevel : logLevels.entrySet()) {
- Logger logger = context.getLogger(loglevel.getKey());
- logger.setLevel(loglevel.getValue());
+ configurator.setLogLevels(LogbackConfigurator.DEFAULT_LOG_LEVELS);
}
}
diff --git a/src/main/java/org/cryptomator/logging/LogbackConfigurator.java b/src/main/java/org/cryptomator/logging/LogbackConfigurator.java
new file mode 100644
index 000000000..5162369e8
--- /dev/null
+++ b/src/main/java/org/cryptomator/logging/LogbackConfigurator.java
@@ -0,0 +1,145 @@
+package org.cryptomator.logging;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
+import ch.qos.logback.classic.spi.Configurator;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.Appender;
+import ch.qos.logback.core.ConsoleAppender;
+import ch.qos.logback.core.FileAppender;
+import ch.qos.logback.core.helpers.NOPAppender;
+import ch.qos.logback.core.rolling.FixedWindowRollingPolicy;
+import ch.qos.logback.core.rolling.RollingFileAppender;
+import ch.qos.logback.core.spi.ContextAwareBase;
+import ch.qos.logback.core.util.FileSize;
+import org.cryptomator.common.Environment;
+
+import java.nio.file.Path;
+import java.util.Map;
+
+public class LogbackConfigurator extends ContextAwareBase implements Configurator {
+
+ private static final String LOG_PATTERN = "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n";
+ private static final String UPGRADE_FILENAME = "upgrade.log";
+ private static final String LOGFILE_NAME = "cryptomator0.log";
+ private static final String LOGFILE_ROLLING_PATTERN = "cryptomator%i.log";
+ private static final int LOGFILE_ROLLING_MIN = 1;
+ private static final int LOGFILE_ROLLING_MAX = 9;
+ private static final String LOG_MAX_SIZE = "100mb";
+
+ static final Map DEFAULT_LOG_LEVELS = Map.of( //
+ Logger.ROOT_LOGGER_NAME, Level.INFO, //
+ "org.cryptomator", Level.INFO //
+ );
+ static final Map DEBUG_LOG_LEVELS = Map.of( //
+ Logger.ROOT_LOGGER_NAME, Level.INFO, //
+ "org.cryptomator", Level.TRACE //
+ );
+
+ LogbackConfigurator() {}
+
+ /**
+ * Adjust the log levels
+ *
+ * @param logLevels new log levels to use
+ */
+ void setLogLevels(Map logLevels) {
+ if (context instanceof LoggerContext lc) {
+ for (var loglevel : logLevels.entrySet()) {
+ Logger logger = lc.getLogger(loglevel.getKey());
+ logger.setLevel(loglevel.getValue());
+ }
+ }
+ }
+
+ @Override
+ public ExecutionStatus configure(LoggerContext context) {
+ var useCustomCfg = Environment.getInstance().useCustomLogbackConfig();
+ var logDir = Environment.getInstance().getLogDir().orElse(null);
+
+ if (useCustomCfg) {
+ addInfo("Using external logback configuration file.");
+ } else {
+ // configure appenders:
+ var stdout = stdOutAppender(context);
+ var noop = noopAppender(context);
+ var file = logDir == null ? noop : fileAppender(context, logDir);
+ var upgrade = logDir == null ? noop : upgradeAppender(context, logDir);
+
+ // configure loggers:
+ for (var loglevel : DEFAULT_LOG_LEVELS.entrySet()) {
+ Logger logger = context.getLogger(loglevel.getKey());
+ logger.setLevel(loglevel.getValue());
+ logger.setAdditive(false);
+ logger.addAppender(stdout);
+ logger.addAppender(file);
+ }
+
+ // configure upgrade logger:
+ Logger upgrades = context.getLogger("org.cryptomator.cryptofs.migration");
+ upgrades.setLevel(Level.DEBUG);
+ upgrades.addAppender(stdout);
+ upgrades.addAppender(upgrade);
+ upgrades.addAppender(file);
+ upgrades.setAdditive(false);
+ }
+ return ExecutionStatus.DO_NOT_INVOKE_NEXT_IF_ANY;
+ }
+
+ private Appender noopAppender(LoggerContext context) {
+ var appender = new NOPAppender();
+ appender.setContext(context);
+ return appender;
+ }
+
+ private Appender stdOutAppender(LoggerContext context) {
+ var appender = new ConsoleAppender();
+ appender.setContext(context);
+ appender.setName("STDOUT");
+ appender.setEncoder(encoder(context));
+ appender.start();
+ return appender;
+ }
+
+ private Appender upgradeAppender(LoggerContext context, Path logDir) {
+ var appender = new FileAppender();
+ appender.setContext(context);
+ appender.setName("UPGRADE");
+ appender.setFile(logDir.resolve(UPGRADE_FILENAME).toString());
+ appender.setEncoder(encoder(context));
+ appender.start();
+ return appender;
+ }
+
+ private Appender fileAppender(LoggerContext context, Path logDir) {
+ var appender = new RollingFileAppender();
+ appender.setContext(context);
+ appender.setName("FILE");
+ appender.setFile(logDir.resolve(LOGFILE_NAME).toString());
+ appender.setEncoder(encoder(context));
+ var triggeringPolicy = new LaunchAndSizeBasedTriggeringPolicy(FileSize.valueOf(LOG_MAX_SIZE));
+ triggeringPolicy.setContext(context);
+ triggeringPolicy.start();
+ appender.setTriggeringPolicy(triggeringPolicy);
+ var rollingPolicy = new FixedWindowRollingPolicy();
+ rollingPolicy.setContext(context);
+ rollingPolicy.setFileNamePattern(logDir.resolve(LOGFILE_ROLLING_PATTERN).toString());
+ rollingPolicy.setMinIndex(LOGFILE_ROLLING_MIN);
+ rollingPolicy.setMaxIndex(LOGFILE_ROLLING_MAX);
+ rollingPolicy.setParent(appender);
+ rollingPolicy.start();
+ appender.setRollingPolicy(rollingPolicy);
+ appender.start();
+ return appender;
+ }
+
+ private PatternLayoutEncoder encoder(LoggerContext context) {
+ var encoder = new PatternLayoutEncoder();
+ encoder.setContext(context);
+ encoder.setPattern(LOG_PATTERN);
+ encoder.start();
+ return encoder;
+ }
+}
diff --git a/src/main/java/org/cryptomator/logging/LogbackConfiguratorFactory.java b/src/main/java/org/cryptomator/logging/LogbackConfiguratorFactory.java
new file mode 100644
index 000000000..1d796891f
--- /dev/null
+++ b/src/main/java/org/cryptomator/logging/LogbackConfiguratorFactory.java
@@ -0,0 +1,12 @@
+package org.cryptomator.logging;
+
+public class LogbackConfiguratorFactory {
+
+ public static LogbackConfigurator provider() {
+ final class Holder {
+ private static final LogbackConfigurator INSTANCE = new LogbackConfigurator();
+ }
+ return Holder.INSTANCE;
+ }
+
+}
diff --git a/src/main/java/org/cryptomator/logging/LoggerConfiguration.java b/src/main/java/org/cryptomator/logging/LoggerConfiguration.java
deleted file mode 100644
index 3d8cc9216..000000000
--- a/src/main/java/org/cryptomator/logging/LoggerConfiguration.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package org.cryptomator.logging;
-
-import ch.qos.logback.classic.Level;
-import ch.qos.logback.classic.Logger;
-import ch.qos.logback.classic.LoggerContext;
-import ch.qos.logback.classic.spi.ILoggingEvent;
-import ch.qos.logback.core.Appender;
-import org.cryptomator.common.Environment;
-import org.cryptomator.common.ShutdownHook;
-
-import javax.inject.Inject;
-import javax.inject.Named;
-import javax.inject.Singleton;
-import java.util.Map;
-
-@Singleton
-public class LoggerConfiguration {
-
- private final LoggerContext context;
- private final Environment environment;
- private final Appender stdout;
- private final Appender upgrade;
- private final Appender file;
- private final ShutdownHook shutdownHook;
-
- @Inject
- LoggerConfiguration(LoggerContext context, //
- Environment environment, //
- @Named("stdoutAppender") Appender stdout, //
- @Named("upgradeAppender") Appender upgrade, //
- @Named("fileAppender") Appender file, //
- ShutdownHook shutdownHook) {
- this.context = context;
- this.environment = environment;
- this.stdout = stdout;
- this.upgrade = upgrade;
- this.file = file;
- this.shutdownHook = shutdownHook;
- }
-
- public void init() {
- if (environment.useCustomLogbackConfig()) {
- Logger root = context.getLogger(Logger.ROOT_LOGGER_NAME);
- root.info("Using external logback configuration file.");
- } else {
- context.reset();
-
- // configure loggers:
- for (Map.Entry loglevel : LoggerModule.DEFAULT_LOG_LEVELS.entrySet()) {
- Logger logger = context.getLogger(loglevel.getKey());
- logger.setLevel(loglevel.getValue());
- logger.setAdditive(false);
- logger.addAppender(stdout);
- logger.addAppender(file);
- }
-
- // configure upgrade logger:
- Logger upgrades = context.getLogger("org.cryptomator.cryptofs.migration");
- upgrades.setLevel(Level.DEBUG);
- upgrades.addAppender(stdout);
- upgrades.addAppender(upgrade);
- upgrades.addAppender(file);
- upgrades.setAdditive(false);
-
- // add shutdown hook
- shutdownHook.runOnShutdown(ShutdownHook.PRIO_LAST, context::stop);
- }
- }
-
-}
diff --git a/src/main/java/org/cryptomator/logging/LoggerModule.java b/src/main/java/org/cryptomator/logging/LoggerModule.java
deleted file mode 100644
index 5031fe3be..000000000
--- a/src/main/java/org/cryptomator/logging/LoggerModule.java
+++ /dev/null
@@ -1,130 +0,0 @@
-package org.cryptomator.logging;
-
-import ch.qos.logback.classic.Level;
-import ch.qos.logback.classic.Logger;
-import ch.qos.logback.classic.LoggerContext;
-import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
-import ch.qos.logback.classic.spi.ILoggingEvent;
-import ch.qos.logback.core.Appender;
-import ch.qos.logback.core.ConsoleAppender;
-import ch.qos.logback.core.FileAppender;
-import ch.qos.logback.core.helpers.NOPAppender;
-import ch.qos.logback.core.rolling.FixedWindowRollingPolicy;
-import ch.qos.logback.core.rolling.RollingFileAppender;
-import ch.qos.logback.core.util.FileSize;
-import dagger.Module;
-import dagger.Provides;
-import org.cryptomator.common.Environment;
-import org.slf4j.ILoggerFactory;
-import org.slf4j.LoggerFactory;
-
-import javax.inject.Named;
-import javax.inject.Singleton;
-import java.nio.file.Path;
-import java.util.Map;
-
-@Module
-public class LoggerModule {
-
- private static final String UPGRADE_FILENAME = "upgrade.log";
- private static final String LOGFILE_NAME = "cryptomator0.log";
- private static final String LOGFILE_ROLLING_PATTERN = "cryptomator%i.log";
- private static final int LOGFILE_ROLLING_MIN = 1;
- private static final int LOGFILE_ROLLING_MAX = 9;
- private static final String LOG_PATTERN = "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n";
- private static final String LOG_MAX_SIZE = "100mb";
-
- static final Map DEFAULT_LOG_LEVELS = Map.of( //
- Logger.ROOT_LOGGER_NAME, Level.INFO, //
- "org.cryptomator", Level.INFO //
- );
- static final Map DEBUG_LOG_LEVELS = Map.of( //
- Logger.ROOT_LOGGER_NAME, Level.INFO, //
- "org.cryptomator", Level.TRACE //
- );
-
- @Provides
- @Singleton
- static LoggerContext provideLoggerContext() {
- ILoggerFactory loggerFactory = LoggerFactory.getILoggerFactory();
- if (loggerFactory instanceof LoggerContext context) {
- return context;
- } else {
- throw new IllegalStateException("SLF4J not bound to Logback.");
- }
- }
-
- @Provides
- @Singleton
- static PatternLayoutEncoder provideLayoutEncoder(LoggerContext context) {
- PatternLayoutEncoder ple = new PatternLayoutEncoder();
- ple.setPattern(LOG_PATTERN);
- ple.setContext(context);
- ple.start();
- return ple;
- }
-
- @Provides
- @Singleton
- @Named("stdoutAppender")
- static Appender provideStdoutAppender(LoggerContext context, PatternLayoutEncoder encoder) {
- ConsoleAppender appender = new ConsoleAppender<>();
- appender.setContext(context);
- appender.setEncoder(encoder);
- appender.start();
- return appender;
- }
-
- @Provides
- @Singleton
- @Named("fileAppender")
- static Appender provideFileAppender(LoggerContext context, PatternLayoutEncoder encoder, Environment environment) {
- var optionalLogDir = environment.getLogDir();
- if (optionalLogDir.isPresent()) {
- Path logDir = optionalLogDir.get();
- RollingFileAppender appender = new RollingFileAppender<>();
- appender.setContext(context);
- appender.setFile(logDir.resolve(LOGFILE_NAME).toString());
- appender.setEncoder(encoder);
- LaunchAndSizeBasedTriggeringPolicy triggeringPolicy = new LaunchAndSizeBasedTriggeringPolicy(FileSize.valueOf(LOG_MAX_SIZE));
- triggeringPolicy.setContext(context);
- triggeringPolicy.start();
- appender.setTriggeringPolicy(triggeringPolicy);
- FixedWindowRollingPolicy rollingPolicy = new FixedWindowRollingPolicy();
- rollingPolicy.setContext(context);
- rollingPolicy.setFileNamePattern(logDir.resolve(LOGFILE_ROLLING_PATTERN).toString());
- rollingPolicy.setMinIndex(LOGFILE_ROLLING_MIN);
- rollingPolicy.setMaxIndex(LOGFILE_ROLLING_MAX);
- rollingPolicy.setParent(appender);
- rollingPolicy.start();
- appender.setRollingPolicy(rollingPolicy);
- appender.start();
- return appender;
- } else {
- NOPAppender appender = new NOPAppender<>();
- appender.setContext(context);
- return appender;
- }
- }
-
- @Provides
- @Singleton
- @Named("upgradeAppender")
- static Appender provideUpgradeAppender(LoggerContext context, PatternLayoutEncoder encoder, Environment environment) {
- var optionalLogDir = environment.getLogDir();
- if (optionalLogDir.isPresent()) {
- FileAppender appender = new FileAppender<>();
- appender.setFile(optionalLogDir.get().resolve(UPGRADE_FILENAME).toString());
- appender.setContext(context);
- appender.setEncoder(encoder);
- appender.start();
- return appender;
- } else {
- NOPAppender appender = new NOPAppender<>();
- appender.setContext(context);
- return appender;
- }
- }
-
-
-}
diff --git a/src/main/java/org/cryptomator/ui/common/AutoAnimator.java b/src/main/java/org/cryptomator/ui/common/AutoAnimator.java
index b5398339c..9b53dc318 100644
--- a/src/main/java/org/cryptomator/ui/common/AutoAnimator.java
+++ b/src/main/java/org/cryptomator/ui/common/AutoAnimator.java
@@ -12,15 +12,15 @@ import javafx.beans.value.ObservableValue;
*
* During creation the consumer can optionally define actions to be executed everytime before the animation starts and after it stops.
*/
-public class AutoAnimator {
+public class AutoAnimator {
- private final T animation;
+ private final Animation animation;
private final ObservableValue condition;
private final Runnable beforeStart;
private final Runnable afterStop;
private final Subscription sub;
- AutoAnimator(T animation, ObservableValue condition, Runnable beforeStart, Runnable afterStop) {
+ AutoAnimator(Animation animation, ObservableValue condition, Runnable beforeStart, Runnable afterStop) {
this.animation = animation;
this.condition = condition;
this.beforeStart = beforeStart;
@@ -52,7 +52,7 @@ public class AutoAnimator {
public static class Builder {
- private Animation animation;
+ private final Animation animation;
private ObservableValue condition = new SimpleBooleanProperty(true);
private Runnable beforeStart = () -> {};
private Runnable afterStop = () -> {};
diff --git a/src/main/java/org/cryptomator/ui/common/ErrorController.java b/src/main/java/org/cryptomator/ui/common/ErrorController.java
index a2204fae3..3b5e08ffb 100644
--- a/src/main/java/org/cryptomator/ui/common/ErrorController.java
+++ b/src/main/java/org/cryptomator/ui/common/ErrorController.java
@@ -77,7 +77,7 @@ public class ErrorController implements FxController {
var enhancedTemplate = String.format(REPORT_BODY_TEMPLATE, //
System.getProperty("os.name"), //
System.getProperty("os.version"), //
- environment.getAppVersion().orElse("undefined"), //
+ environment.getAppVersion(), //
environment.getBuildNumber().orElse("undefined"));
var body = URLEncoder.encode(enhancedTemplate, StandardCharsets.UTF_8);
application.getHostServices().showDocument(REPORT_URL_FORMAT.formatted(title, body));
diff --git a/src/main/java/org/cryptomator/ui/common/FxmlFile.java b/src/main/java/org/cryptomator/ui/common/FxmlFile.java
index aa345dca9..73e805273 100644
--- a/src/main/java/org/cryptomator/ui/common/FxmlFile.java
+++ b/src/main/java/org/cryptomator/ui/common/FxmlFile.java
@@ -14,6 +14,7 @@ public enum FxmlFile {
HEALTH_START("/fxml/health_start.fxml"), //
HEALTH_CHECK_LIST("/fxml/health_check_list.fxml"), //
HUB_AUTH_FLOW("/fxml/hub_auth_flow.fxml"), //
+ HUB_LICENSE_EXCEEDED("/fxml/hub_license_exceeded.fxml"), //
HUB_RECEIVE_KEY("/fxml/hub_receive_key.fxml"), //
HUB_REGISTER_DEVICE("/fxml/hub_register_device.fxml"), //
HUB_REGISTER_SUCCESS("/fxml/hub_register_success.fxml"), //
diff --git a/src/main/java/org/cryptomator/ui/controls/SecurePasswordField.java b/src/main/java/org/cryptomator/ui/controls/SecurePasswordField.java
index 66df79394..a7ec9df6a 100644
--- a/src/main/java/org/cryptomator/ui/controls/SecurePasswordField.java
+++ b/src/main/java/org/cryptomator/ui/controls/SecurePasswordField.java
@@ -71,9 +71,11 @@ public class SecurePasswordField extends TextField {
}
public void cut() {
+ //not implemented by design
}
public void copy() {
+ //not implemented by design
}
public Object queryAccessibleAttribute(AccessibleAttribute attribute, Object... parameters) {
diff --git a/src/main/java/org/cryptomator/ui/fxapp/UpdateChecker.java b/src/main/java/org/cryptomator/ui/fxapp/UpdateChecker.java
index 729791356..b83fe8515 100644
--- a/src/main/java/org/cryptomator/ui/fxapp/UpdateChecker.java
+++ b/src/main/java/org/cryptomator/ui/fxapp/UpdateChecker.java
@@ -9,14 +9,12 @@ import javax.inject.Inject;
import javax.inject.Named;
import javafx.beans.binding.BooleanBinding;
import javafx.beans.property.ReadOnlyStringProperty;
-import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.concurrent.ScheduledService;
import javafx.concurrent.Worker;
import javafx.concurrent.WorkerStateEvent;
import javafx.util.Duration;
import java.util.Comparator;
-import java.util.Optional;
@FxApplicationScoped
public class UpdateChecker {
@@ -25,8 +23,7 @@ public class UpdateChecker {
private static final Duration AUTOCHECK_DELAY = Duration.seconds(5);
private final Settings settings;
- private final Optional applicationVersion;
- private final StringProperty currentVersionProperty;
+ private final String currentVersion;
private final StringProperty latestVersionProperty;
private final Comparator semVerComparator;
private final ScheduledService updateCheckerService;
@@ -34,11 +31,10 @@ public class UpdateChecker {
@Inject
UpdateChecker(Settings settings, Environment env, @Named("latestVersion") StringProperty latestVersionProperty, @Named("SemVer") Comparator semVerComparator, ScheduledService updateCheckerService) {
this.settings = settings;
- this.applicationVersion = env.getAppVersion();
this.latestVersionProperty = latestVersionProperty;
this.semVerComparator = semVerComparator;
this.updateCheckerService = updateCheckerService;
- this.currentVersionProperty = new SimpleStringProperty(applicationVersion.orElse("SNAPSHOT"));
+ this.currentVersion = env.getAppVersion();
}
public void automaticallyCheckForUpdatesIfEnabled() {
@@ -66,11 +62,10 @@ public class UpdateChecker {
}
private void checkSucceeded(WorkerStateEvent event) {
- String currentVersion = applicationVersion.orElse(null);
String latestVersion = updateCheckerService.getValue();
LOG.info("Current version: {}, lastest version: {}", currentVersion, latestVersion);
- if (currentVersion == null || semVerComparator.compare(currentVersion, latestVersion) < 0) {
+ if (semVerComparator.compare(currentVersion, latestVersion) < 0) {
// update is available
latestVersionProperty.set(latestVersion);
} else {
@@ -92,8 +87,8 @@ public class UpdateChecker {
return latestVersionProperty;
}
- public ReadOnlyStringProperty currentVersionProperty() {
- return currentVersionProperty;
+ public String getCurrentVersion() {
+ return currentVersion;
}
}
diff --git a/src/main/java/org/cryptomator/ui/fxapp/UpdateCheckerModule.java b/src/main/java/org/cryptomator/ui/fxapp/UpdateCheckerModule.java
index 58b8653da..dd7c5bf77 100644
--- a/src/main/java/org/cryptomator/ui/fxapp/UpdateCheckerModule.java
+++ b/src/main/java/org/cryptomator/ui/fxapp/UpdateCheckerModule.java
@@ -56,7 +56,7 @@ public abstract class UpdateCheckerModule {
@FxApplicationScoped
static HttpRequest provideCheckForUpdatesRequest(Environment env) {
String userAgent = String.format("Cryptomator VersionChecker/%s %s %s (%s)", //
- env.getAppVersion().orElse("SNAPSHOT"), //
+ env.getAppVersion(), //
SystemUtils.OS_NAME, //
SystemUtils.OS_VERSION, //
SystemUtils.OS_ARCH); //
diff --git a/src/main/java/org/cryptomator/ui/keyloading/hub/HubKeyLoadingModule.java b/src/main/java/org/cryptomator/ui/keyloading/hub/HubKeyLoadingModule.java
index 587810021..6e28b8796 100644
--- a/src/main/java/org/cryptomator/ui/keyloading/hub/HubKeyLoadingModule.java
+++ b/src/main/java/org/cryptomator/ui/keyloading/hub/HubKeyLoadingModule.java
@@ -92,6 +92,13 @@ public abstract class HubKeyLoadingModule {
return fxmlLoaders.createScene(FxmlFile.HUB_AUTH_FLOW);
}
+ @Provides
+ @FxmlScene(FxmlFile.HUB_LICENSE_EXCEEDED)
+ @KeyLoadingScoped
+ static Scene provideLicenseExceededScene(@KeyLoading FxmlLoaderFactory fxmlLoaders) {
+ return fxmlLoaders.createScene(FxmlFile.HUB_LICENSE_EXCEEDED);
+ }
+
@Provides
@FxmlScene(FxmlFile.HUB_RECEIVE_KEY)
@KeyLoadingScoped
@@ -139,6 +146,11 @@ public abstract class HubKeyLoadingModule {
return new NewPasswordController(resourceBundle, strengthRater);
}
+ @Binds
+ @IntoMap
+ @FxControllerKey(LicenseExceededController.class)
+ abstract FxController bindLicenseExceededController(LicenseExceededController controller);
+
@Binds
@IntoMap
@FxControllerKey(ReceiveKeyController.class)
diff --git a/src/main/java/org/cryptomator/ui/keyloading/hub/LicenseExceededController.java b/src/main/java/org/cryptomator/ui/keyloading/hub/LicenseExceededController.java
new file mode 100644
index 000000000..115ba16b4
--- /dev/null
+++ b/src/main/java/org/cryptomator/ui/keyloading/hub/LicenseExceededController.java
@@ -0,0 +1,23 @@
+package org.cryptomator.ui.keyloading.hub;
+
+import org.cryptomator.ui.common.FxController;
+import org.cryptomator.ui.keyloading.KeyLoading;
+
+import javax.inject.Inject;
+import javafx.fxml.FXML;
+import javafx.stage.Stage;
+
+public class LicenseExceededController implements FxController {
+
+ private final Stage window;
+
+ @Inject
+ public LicenseExceededController(@KeyLoading Stage window) {
+ this.window = window;
+ }
+
+ @FXML
+ public void close() {
+ window.close();
+ }
+}
diff --git a/src/main/java/org/cryptomator/ui/keyloading/hub/ReceiveKeyController.java b/src/main/java/org/cryptomator/ui/keyloading/hub/ReceiveKeyController.java
index 85af2c66d..07dc1e215 100644
--- a/src/main/java/org/cryptomator/ui/keyloading/hub/ReceiveKeyController.java
+++ b/src/main/java/org/cryptomator/ui/keyloading/hub/ReceiveKeyController.java
@@ -8,8 +8,6 @@ import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
import org.cryptomator.ui.keyloading.KeyLoading;
import org.cryptomator.ui.keyloading.KeyLoadingScoped;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Named;
@@ -44,10 +42,11 @@ public class ReceiveKeyController implements FxController {
private final Lazy registerDeviceScene;
private final Lazy unauthorizedScene;
private final URI vaultBaseUri;
+ private final Lazy licenseExceededScene;
private final HttpClient httpClient;
@Inject
- public ReceiveKeyController(@KeyLoading Vault vault, ExecutorService executor, @KeyLoading Stage window, @Named("deviceId") String deviceId, @Named("bearerToken") AtomicReference tokenRef, CompletableFuture result, @FxmlScene(FxmlFile.HUB_REGISTER_DEVICE) Lazy registerDeviceScene, @FxmlScene(FxmlFile.HUB_UNAUTHORIZED_DEVICE) Lazy unauthorizedScene) {
+ public ReceiveKeyController(@KeyLoading Vault vault, ExecutorService executor, @KeyLoading Stage window, @Named("deviceId") String deviceId, @Named("bearerToken") AtomicReference tokenRef, CompletableFuture result, @FxmlScene(FxmlFile.HUB_REGISTER_DEVICE) Lazy registerDeviceScene, @FxmlScene(FxmlFile.HUB_UNAUTHORIZED_DEVICE) Lazy unauthorizedScene, @FxmlScene(FxmlFile.HUB_LICENSE_EXCEEDED) Lazy licenseExceededScene) {
this.window = window;
this.deviceId = deviceId;
this.bearerToken = Objects.requireNonNull(tokenRef.get());
@@ -55,6 +54,7 @@ public class ReceiveKeyController implements FxController {
this.registerDeviceScene = registerDeviceScene;
this.unauthorizedScene = unauthorizedScene;
this.vaultBaseUri = getVaultBaseUri(vault);
+ this.licenseExceededScene = licenseExceededScene;
this.window.addEventHandler(WindowEvent.WINDOW_HIDING, this::windowClosed);
this.httpClient = HttpClient.newBuilder().executor(executor).build();
}
@@ -75,6 +75,7 @@ public class ReceiveKeyController implements FxController {
try {
switch (response.statusCode()) {
case 200 -> retrievalSucceeded(response);
+ case 402 -> licenseExceeded();
case 403 -> accessNotGranted();
case 404 -> needsDeviceRegistration();
default -> throw new IOException("Unexpected response " + response.statusCode());
@@ -94,6 +95,10 @@ public class ReceiveKeyController implements FxController {
}
}
+ private void licenseExceeded() {
+ window.setScene(licenseExceededScene.get());
+ }
+
private void needsDeviceRegistration() {
window.setScene(registerDeviceScene.get());
}
diff --git a/src/main/java/org/cryptomator/ui/mainwindow/VaultListController.java b/src/main/java/org/cryptomator/ui/mainwindow/VaultListController.java
index dbe858a55..adb9a961b 100644
--- a/src/main/java/org/cryptomator/ui/mainwindow/VaultListController.java
+++ b/src/main/java/org/cryptomator/ui/mainwindow/VaultListController.java
@@ -69,11 +69,15 @@ public class VaultListController implements FxController {
}
});
vaultList.addEventFilter(MouseEvent.MOUSE_RELEASED, this::deselect);
+
+ //don't show context menu when no vault selected
vaultList.addEventFilter(ContextMenuEvent.CONTEXT_MENU_REQUESTED, request -> {
if (selectedVault.get() == null) {
request.consume();
}
});
+
+ //show removeVaultDialog on certain key press
vaultList.addEventFilter(KeyEvent.KEY_PRESSED, keyEvent -> {
if (keyEvent.getCode() == KeyCode.DELETE) {
pressedShortcutToRemoveVault();
diff --git a/src/main/java/org/cryptomator/ui/migration/MigrationStartController.java b/src/main/java/org/cryptomator/ui/migration/MigrationStartController.java
index 27ad96d26..00d9364f7 100644
--- a/src/main/java/org/cryptomator/ui/migration/MigrationStartController.java
+++ b/src/main/java/org/cryptomator/ui/migration/MigrationStartController.java
@@ -25,9 +25,6 @@ public class MigrationStartController implements FxController {
this.runMigrationScene = runMigrationScene;
}
- public void initialize() {
- }
-
@FXML
public void cancel() {
window.close();
diff --git a/src/main/java/org/cryptomator/ui/preferences/AboutController.java b/src/main/java/org/cryptomator/ui/preferences/AboutController.java
index f418843ee..1f1b1864b 100644
--- a/src/main/java/org/cryptomator/ui/preferences/AboutController.java
+++ b/src/main/java/org/cryptomator/ui/preferences/AboutController.java
@@ -18,14 +18,14 @@ public class AboutController implements FxController {
private static final Logger LOG = LoggerFactory.getLogger(AboutController.class);
private final String thirdPartyLicenseText;
- private final String applicationVersion;
+ private final String fullApplicationVersion;
@Inject
AboutController(UpdateChecker updateChecker, Environment environment) {
this.thirdPartyLicenseText = loadThirdPartyLicenseFile();
- StringBuilder sb = new StringBuilder(updateChecker.currentVersionProperty().get());
+ StringBuilder sb = new StringBuilder(environment.getAppVersion());
environment.getBuildNumber().ifPresent(s -> sb.append(" (").append(s).append(')'));
- this.applicationVersion = sb.toString();
+ this.fullApplicationVersion = sb.toString();
}
private static String loadThirdPartyLicenseFile() {
@@ -43,7 +43,7 @@ public class AboutController implements FxController {
return thirdPartyLicenseText;
}
- public String getApplicationVersion() {
- return applicationVersion;
+ public String getFullApplicationVersion() {
+ return fullApplicationVersion;
}
}
diff --git a/src/main/java/org/cryptomator/ui/preferences/UpdatesPreferencesController.java b/src/main/java/org/cryptomator/ui/preferences/UpdatesPreferencesController.java
index 1714d00a6..6a47b992d 100644
--- a/src/main/java/org/cryptomator/ui/preferences/UpdatesPreferencesController.java
+++ b/src/main/java/org/cryptomator/ui/preferences/UpdatesPreferencesController.java
@@ -24,7 +24,7 @@ public class UpdatesPreferencesController implements FxController {
private final UpdateChecker updateChecker;
private final ObjectBinding checkForUpdatesButtonState;
private final ReadOnlyStringProperty latestVersion;
- private final ReadOnlyStringProperty currentVersion;
+ private final String currentVersion;
private final BooleanBinding updateAvailable;
/* FXML */
@@ -38,7 +38,7 @@ public class UpdatesPreferencesController implements FxController {
this.checkForUpdatesButtonState = Bindings.when(updateChecker.checkingForUpdatesProperty()).then(ContentDisplay.LEFT).otherwise(ContentDisplay.TEXT_ONLY);
this.latestVersion = updateChecker.latestVersionProperty();
this.updateAvailable = latestVersion.isNotNull();
- this.currentVersion = updateChecker.currentVersionProperty();
+ this.currentVersion = updateChecker.getCurrentVersion();
}
public void initialize() {
@@ -73,12 +73,8 @@ public class UpdatesPreferencesController implements FxController {
return latestVersion.get();
}
- public ReadOnlyStringProperty currentVersionProperty() {
- return currentVersion;
- }
-
public String getCurrentVersion() {
- return currentVersion.get();
+ return currentVersion;
}
public BooleanBinding updateAvailableProperty() {
diff --git a/src/main/resources/fxml/hub_license_exceeded.fxml b/src/main/resources/fxml/hub_license_exceeded.fxml
new file mode 100644
index 000000000..10be37307
--- /dev/null
+++ b/src/main/resources/fxml/hub_license_exceeded.fxml
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/fxml/preferences_about.fxml b/src/main/resources/fxml/preferences_about.fxml
index d08a5e43a..b6940b0ed 100644
--- a/src/main/resources/fxml/preferences_about.fxml
+++ b/src/main/resources/fxml/preferences_about.fxml
@@ -21,7 +21,7 @@
-
+
diff --git a/src/main/resources/i18n/strings.properties b/src/main/resources/i18n/strings.properties
index 80158d313..460b56476 100644
--- a/src/main/resources/i18n/strings.properties
+++ b/src/main/resources/i18n/strings.properties
@@ -152,6 +152,9 @@ hub.registerFailed.description=An error was thrown in the naming process. For mo
### Unauthorized
hub.unauthorized.message=Access denied
hub.unauthorized.description=Your device has not yet been authorized to access this vault. Ask the vault owner to authorize it.
+### License Exceeded
+hub.licenseExceeded.message=License exceeded
+hub.licenseExceeded.description=Cryptomator Hub has given access to more users than its license permits. Please contact your Hub admin to upgrade the license or a vault admin to remove users from vaults.
# Lock
diff --git a/src/main/resources/i18n/strings_ar.properties b/src/main/resources/i18n/strings_ar.properties
index e2fe4c9a0..d285db76d 100644
--- a/src/main/resources/i18n/strings_ar.properties
+++ b/src/main/resources/i18n/strings_ar.properties
@@ -107,6 +107,16 @@ unlock.error.message=غير قادر على فتح الخزنة
### Invalid Mount Point
unlock.error.invalidMountPoint.notExisting=نقطة التحميل ليست مجلد فارغ أو غير موجودة: %s
unlock.error.invalidMountPoint.existing=نقطة/مجلد التحميل موجود بالفعل أو المجلد الأصل مفقود: %s
+## Hub
+### Waiting
+### Receive Key
+### Register Device
+hub.register.registerBtn=تأكيد
+### Registration Success
+### Registration Failed
+### Unauthorized
+### License Exceeded
+
# Lock
## Force
diff --git a/src/main/resources/i18n/strings_be.properties b/src/main/resources/i18n/strings_be.properties
index b75d9eeda..f2a8d81a8 100644
--- a/src/main/resources/i18n/strings_be.properties
+++ b/src/main/resources/i18n/strings_be.properties
@@ -113,6 +113,15 @@ unlock.success.revealBtn=Паказаць дыск
## Failure
unlock.error.message=Немагчыма разамкнуць скарбніцу
### Invalid Mount Point
+## Hub
+### Waiting
+### Receive Key
+### Register Device
+### Registration Success
+### Registration Failed
+### Unauthorized
+### License Exceeded
+
# Lock
## Force
diff --git a/src/main/resources/i18n/strings_bn.properties b/src/main/resources/i18n/strings_bn.properties
index 10843d0f7..d9fbab722 100644
--- a/src/main/resources/i18n/strings_bn.properties
+++ b/src/main/resources/i18n/strings_bn.properties
@@ -80,6 +80,16 @@ unlock.unlockBtn=আনলক করুন
## Success
## Failure
### Invalid Mount Point
+## Hub
+### Waiting
+### Receive Key
+### Register Device
+hub.register.registerBtn=নিশ্চিত করুন
+### Registration Success
+### Registration Failed
+### Unauthorized
+### License Exceeded
+
# Lock
## Force
diff --git a/src/main/resources/i18n/strings_bs.properties b/src/main/resources/i18n/strings_bs.properties
index 63ddef343..3cfc2a387 100644
--- a/src/main/resources/i18n/strings_bs.properties
+++ b/src/main/resources/i18n/strings_bs.properties
@@ -107,6 +107,16 @@ unlock.error.message=Sef nije moguće otključati
### Invalid Mount Point
unlock.error.invalidMountPoint.notExisting=Tačka postavljanja "%s" nije direktorij, nije prazna ili ne postoji.
unlock.error.invalidMountPoint.existing=Tačka povezivanja "%s" već postoji ili nadređeni folder nedostaje.
+## Hub
+### Waiting
+### Receive Key
+### Register Device
+hub.register.registerBtn=Potvrdi
+### Registration Success
+### Registration Failed
+### Unauthorized
+### License Exceeded
+
# Lock
## Force
diff --git a/src/main/resources/i18n/strings_ca.properties b/src/main/resources/i18n/strings_ca.properties
index 083483587..3e6f33a34 100644
--- a/src/main/resources/i18n/strings_ca.properties
+++ b/src/main/resources/i18n/strings_ca.properties
@@ -53,6 +53,12 @@ addvaultwizard.new.fileAlreadyExists=Ja existeix un fitxer o un directori amb el
addvaultwizard.new.locationDoesNotExist=Un directori de la ruta especificada no existeix o no s'hi pot accedir
addvaultwizard.new.locationIsNotWritable=No teniu permís d'escriptura en la ruta especificada
addvaultwizard.new.locationIsOk=Localització per a la vostra caixa forta
+addvaultwizard.new.invalidName=Nom de caixa forta no vàlid
+addvaultwizard.new.validName=Nom de caixa forta vàlid
+addvaultwizard.new.validCharacters.message=El nom de la caixa forta només pot contenir els caràcters següents:
+addvaultwizard.new.validCharacters.chars=Caràcters que formen paraules (ex.: a, ж or 수)
+addvaultwizard.new.validCharacters.numbers=Nombres
+addvaultwizard.new.validCharacters.dashes=Guionet (%s) o guió baix (%s)
### Password
addvaultwizard.new.createVaultBtn=Crea la caixa forta
addvaultwizard.new.generateRecoveryKeyChoice=No podreu accedir a les vostres dades sense la contrasenya. Voleu crear una clau de recuperació en cas perdre la vostra contrasenya?
@@ -79,12 +85,14 @@ addvault.new.readme.accessLocation.4=Pots esborrar aquest fitxer si vols.
addvaultwizard.existing.instruction=Selecciona el fitxer "vault.cryptomator" de la teva caixa forta. Si només existeix un fitxer anomenat "masterkey.cryptomator", selecciona aquest.
addvaultwizard.existing.chooseBtn=Trieu…
addvaultwizard.existing.filePickerTitle=Selecciona el fitxer de la Caixa forta
+addvaultwizard.existing.filePickerMimeDesc=Caixa forta de Cryptomator
## Success
addvaultwizard.success.nextStepsInstructions=S'ha afegit la caixa forta "%s".\nHeu de desbloquejar-la si voleu accedir-hi o afegir nou contingut. També podeu desbloquejar-la en qualsevol altre moment.
addvaultwizard.success.unlockNow=Desbloqueja ara
# Remove Vault
removeVault.title=Elimina la caixa forta
+removeVault.message=Voleu eliminar la caixa forta?
removeVault.description=Cryptomator simplement deixarà de mostrar la caixa forta. Podeu tornar a afegir-la més endavant. Cap fitxer xifrat serà eliminat del disc dur.
removeVault.confirmBtn=Elimina la caixa forta
@@ -119,6 +127,26 @@ unlock.error.message=No ha estat possible desblocar la caixa forta
unlock.error.invalidMountPoint.notExisting=El punt de muntatge no és un directori buit, o no existeix: %s
unlock.error.invalidMountPoint.existing=El punt de muntatge o la carpeta ja existeix, o no es pot accedir al directori superior: %s
unlock.error.invalidMountPoint.driveLetterOccupied=La unitat o arxiu "%s" ja està en ús.
+## Hub
+### Waiting
+hub.auth.message=S’està esperant l’autenticació…
+hub.auth.description=Hauríeu de ser redirigits a la pàgina d'accés.
+hub.auth.loginLink=No heu estat redirigit? Feu clic aquí per a obrir-la.
+### Receive Key
+hub.receive.message=S'està processant la resposta…
+### Register Device
+hub.register.message=Cal un nom de dispositiu
+hub.register.nameLabel=Nom del dispositiu
+hub.register.occupiedMsg=El nom ja està en ús
+hub.register.registerBtn=Confirma
+### Registration Success
+hub.registerSuccess.description=Per a accedir a la caixa forta, el vostre dispositiu ha de ser autoritzat pel propietari de la caixa.
+### Registration Failed
+### Unauthorized
+hub.unauthorized.message=Accés denegat
+hub.unauthorized.description=El vostre dispositiu no ha estat encara autoritzat a accedir a aquesta caixa forta. Demaneu autorització al propietari.
+### License Exceeded
+
# Lock
## Force
@@ -211,6 +239,7 @@ preferences.interface.interfaceOrientation=Orientació de la interfície
preferences.interface.interfaceOrientation.ltr=Esquerra a dreta
preferences.interface.interfaceOrientation.rtl=Dreta a esquerra
preferences.interface.showMinimizeButton=Mostra el botó 'minimitzar'
+preferences.interface.showTrayIcon=Mostra la icona en la barra (cal reiniciar)
## Volume
preferences.volume=Unitat virtual
preferences.volume.type=Tipus de volum
@@ -371,6 +400,7 @@ recoveryKey.recover.prompt=Introduïu la vostra clau de recuperació de "%s":
recoveryKey.recover.validKey=La clau de recuperació és vàlida
recoveryKey.printout.heading=Clau de recuperació de Cryptomator\n"%s"\n
### Reset Password
+recoveryKey.recover.resetBtn=Reinicia
### Recovery Key Password Reset Success
recoveryKey.recover.resetSuccess.message=S'ha modificat la contrasenya correctament
recoveryKey.recover.resetSuccess.description=Pots desbloquejar la caixa forta amb la nova contrasenya.
diff --git a/src/main/resources/i18n/strings_cs.properties b/src/main/resources/i18n/strings_cs.properties
index ecd23f085..16097e8d2 100644
--- a/src/main/resources/i18n/strings_cs.properties
+++ b/src/main/resources/i18n/strings_cs.properties
@@ -118,6 +118,16 @@ unlock.error.message=Nelze odemknout trezor
unlock.error.invalidMountPoint.notExisting=Připojovací bod %s není složkou, není prázdný nebo neexistuje.
unlock.error.invalidMountPoint.existing=Připojovací bod %s již existuje nebo nadřazená složka chybí.
unlock.error.invalidMountPoint.driveLetterOccupied=Písmeno „%s“ už je používáno pro jiný disk.
+## Hub
+### Waiting
+### Receive Key
+### Register Device
+hub.register.registerBtn=Potvrdit
+### Registration Success
+### Registration Failed
+### Unauthorized
+### License Exceeded
+
# Lock
## Force
diff --git a/src/main/resources/i18n/strings_da.properties b/src/main/resources/i18n/strings_da.properties
new file mode 100644
index 000000000..408dcbd2a
--- /dev/null
+++ b/src/main/resources/i18n/strings_da.properties
@@ -0,0 +1,437 @@
+# Locale Specific CSS files such as CJK, RTL,...
+
+# Generics
+## Button
+generic.button.apply=Anvend
+generic.button.back=Tilbage
+generic.button.cancel=Annullér
+generic.button.change=Skift
+generic.button.choose=Vælg…
+generic.button.close=Luk
+generic.button.copy=Kopiér
+generic.button.copied=Kopieret!
+generic.button.done=Færdig
+generic.button.next=Næste
+generic.button.print=Print
+
+# Error
+error.message=Der opstod en fejl
+error.description=Cryptomator forventede ikke at dette skete. Du kan gennemse eksisterende løsninger for denne fejl - eller hvis denne fejl ikke er blevet rapporteret før, er du meget velkommen til at rapportere den.
+error.hyperlink.lookup=Slå denne fejl op
+error.hyperlink.report=Rapportér denne fejl
+error.technicalDetails=Detaljer:
+
+# Defaults
+defaults.vault.vaultName=Boks
+
+# Tray Menu
+traymenu.showMainWindow=Vis
+traymenu.showPreferencesWindow=Præferencer
+traymenu.lockAllVaults=Lås alle
+traymenu.quitApplication=Afslut
+traymenu.vault.unlock=Lås op
+traymenu.vault.lock=Lås
+traymenu.vault.reveal=Vis
+
+# Add Vault Wizard
+addvaultwizard.title=Tilføj boks
+## Welcome
+addvaultwizard.welcome.newButton=Opret ny boks
+addvaultwizard.welcome.existingButton=Open eksisterende boks
+## New
+### Name
+addvaultwizard.new.nameInstruction=Vælg et navn til boksen
+addvaultwizard.new.namePrompt=Boks-navn
+### Location
+addvaultwizard.new.locationInstruction=Hvor skal Cryptomator gemme de krypterede filer af din boks?
+addvaultwizard.new.locationLabel=Dataplacering
+addvaultwizard.new.locationPrompt=…
+addvaultwizard.new.directoryPickerLabel=Vælg placering
+addvaultwizard.new.directoryPickerButton=Vælg…
+addvaultwizard.new.directoryPickerTitle=Vælg mappe
+addvaultwizard.new.fileAlreadyExists=En fil eller mappe med samme navn findes allerede
+addvaultwizard.new.locationDoesNotExist=En mappe i den valgte sti findes ikke, eller kan ikke tilgås
+addvaultwizard.new.locationIsNotWritable=Ingen redigeringsadgang til den valgte sti
+addvaultwizard.new.locationIsOk=Egnet placering til din boks
+addvaultwizard.new.invalidName=Ugyldigt boks-navn
+addvaultwizard.new.validName=Gyldigt boks-navn
+addvaultwizard.new.validCharacters.message=Boks-navnet må indeholde de følgende tegn:
+addvaultwizard.new.validCharacters.chars=Bogstaver (fx a, ж eller 수)
+addvaultwizard.new.validCharacters.numbers=Tal
+addvaultwizard.new.validCharacters.dashes=Bindestreg (%s) eller understregning (%s)
+### Password
+addvaultwizard.new.createVaultBtn=Opret boks
+addvaultwizard.new.generateRecoveryKeyChoice=Du kan ikke tilgå dine data uden din adgangskode. Vil du oprette en gendannelses-nøgle i tilfælde af, at du mister din adgangskode?
+addvaultwizard.new.generateRecoveryKeyChoice.yes=Ja tak - for en sikkerheds skyld
+addvaultwizard.new.generateRecoveryKeyChoice.no=Nej tak. Jeg mister ikke min adgangskode
+### Information
+addvault.new.readme.storageLocation.fileName=VIGTIGT.rtf
+addvault.new.readme.storageLocation.1=⚠️ BOKS-FILER ⚠️
+addvault.new.readme.storageLocation.2=Det er her er lokationen for din boks' data.
+addvault.new.readme.storageLocation.3=SØRG FOR ALDRIG AT
+addvault.new.readme.storageLocation.4=• ændre filer i denne mappe eller
+addvault.new.readme.storageLocation.5=• indsæt nogen filer som skal krypteres i denne mappe.
+addvault.new.readme.storageLocation.6=Hvis du ønsker at kryptere filer eller se indholdet af boksen, skal du gøre følgende:
+addvault.new.readme.storageLocation.7=1. Tilføj denne boks til Cryptomator.
+addvault.new.readme.storageLocation.8=2. Lås boksen op i Cryptomator.
+addvault.new.readme.storageLocation.9=3. Åbn placeringen ved at klikke på knappen "Vis boks".
+addvault.new.readme.storageLocation.10=Hvis du har brug for hjælp, så kig i dokumentationen: %s
+addvault.new.readme.accessLocation.fileName=VELKOMMEN.rtf
+addvault.new.readme.accessLocation.1=🔐️ KRYPTERET DREV 🔐️
+addvault.new.readme.accessLocation.2=Det er her indholdet af din boks tilgås.
+addvault.new.readme.accessLocation.3=Filer du tilføjer til dette drev vil blive krypteret af Cryptomator. Du har arbejde med filerne ligesom enhver anden fil/mappe. Dette er blot en dekrypteret visning af indholdet. Dine filer er stadig krypterede på din harddisk hele tiden.
+addvault.new.readme.accessLocation.4=Fjern denne fil hvis du har lyst.
+## Existing
+addvaultwizard.existing.instruction=Vælgt filen "vault.cryptomator" i mappen med dine boks-filer. Hvis der kun findes en fil med navnet "masterkey.cryptomator", skal du vælge den i stedet.
+addvaultwizard.existing.chooseBtn=Vælg…
+addvaultwizard.existing.filePickerTitle=Vælg boks-fil
+addvaultwizard.existing.filePickerMimeDesc=Cryptomator boks
+## Success
+addvaultwizard.success.nextStepsInstructions=Tilføjede boks "%s".\nDu skal låse op for denne boks for at tilgå indholdet. Alternativt kan du låse den op på et senere tidspunkt.
+addvaultwizard.success.unlockNow=Lås op nu
+
+# Remove Vault
+removeVault.title=Fjern "%s"
+removeVault.message=Fjern boks?
+removeVault.description=Dette får blot Cryptomator til at glemme boksen. Du kan tilføje den igen senere. Ingen krypterede filer bliver slettet fra harddisken.
+removeVault.confirmBtn=Fjern boks
+
+# Change Password
+changepassword.title=Skift adgangskode
+changepassword.enterOldPassword=Angiv den nuværende adgangskode for "%s"
+changepassword.finalConfirmation=Jeg er indforstået med at jeg ikke kan få adgang til mine data, hvis jeg glemmer min adgangskode
+
+# Forget Password
+forgetPassword.title=Glemt adgangskode
+forgetPassword.message=Skal systemet holde op med at huske adgangskoden?
+forgetPassword.description=Dette vil slette den gemte adgangskode, til denne boks, fra dit system.
+forgetPassword.confirmBtn=Glem adgangskode
+
+# Unlock
+unlock.title=Lås op for "%s"
+unlock.passwordPrompt=Indtast adgangskoden for "%s":
+unlock.savePassword=Husk adgangskode
+unlock.unlockBtn=Lås op
+## Select
+unlock.chooseMasterkey.message=Hovednøgle-fil ikke fundet
+unlock.chooseMasterkey.description=Cryptomator kunne ikke finde hovednøgle-filen for boksen "%s". Vælg venligst filen manuelt.
+unlock.chooseMasterkey.filePickerTitle=Vælg hovednøgle-fil
+unlock.chooseMasterkey.filePickerMimeDesc=Cryptomator hovednøgle
+## Success
+unlock.success.message=Låst op
+unlock.success.description=Indholdet i boksen "%s" er nu tilgængeligt der hvor den er monteret.
+unlock.success.rememberChoice=Husk mit valg. Spørg ikke igen
+unlock.success.revealBtn=Vis drev
+## Failure
+unlock.error.message=Kan ikke låse boksen op
+### Invalid Mount Point
+unlock.error.invalidMountPoint.notExisting=Placeringen "%s" er ikke en mappe, er ikke tom, eller findes ikke.
+unlock.error.invalidMountPoint.existing=Placeringen "%s" findes allerede, eller den overordnede mappe mangler.
+unlock.error.invalidMountPoint.driveLetterOccupied=Drevbogstavet "%s" er allerede i brug.
+## Hub
+### Waiting
+hub.auth.message=Afventer godkendelse…
+hub.auth.description=Du burde automatisk blive omdirigeret til login-siden.
+hub.auth.loginLink=Ingen omdirigering? Klik her for at åbne den.
+### Receive Key
+hub.receive.message=Behandler svar…
+hub.receive.description=Cryptomator modtager og behandler svaret fra hubben. Vent venligst.
+### Register Device
+hub.register.message=Enheds-navn krævet
+hub.register.description=Det ser ud til at dette er første gang denne enhed tilgår hubben. For at identificere denne enhed, skal du navngive den.
+hub.register.nameLabel=Enheds-navn
+hub.register.occupiedMsg=Navnet er allerede i brug
+hub.register.registerBtn=Bekræft
+### Registration Success
+hub.registerSuccess.message=Enhed navngivet
+hub.registerSuccess.description=For at tilgå boksen, skal din enhed godkendes af boks-ejeren.
+### Registration Failed
+hub.registerFailed.message=Navngivning af enhed mislykkedes
+hub.registerFailed.description=Der opstod en fejl i navngivnings-processen. Kig i applikations-loggen for flere detaljer.
+### Unauthorized
+hub.unauthorized.message=Adgang nægtet
+hub.unauthorized.description=Din enhed er endnu ikke blevet godkendt til at få adgang til denne boks. Spørg boks-ejeren om godkendelse.
+### License Exceeded
+hub.licenseExceeded.message=Licens overskredet
+hub.licenseExceeded.description=Cryptomator Hub har givet adgang til flere brugere end licensen tillader. Kontakt venligst din Hub administrator for at opgradere din licens eller en boks administrator for at fjerne brugere fra bokse.
+
+
+# Lock
+## Force
+lock.forced.message=Låsning mislykkedes
+lock.forced.description=Låsning af "%s" blev blokeret fordi der er igangværende operationer eller åbne filer. Du kan gennemtvinge låsningen - men en afbrydelse af igangværende I/O operationer kan resultere i tab af data som endnu ikke er gemt.
+lock.forced.retryBtn=Forsøg igen
+lock.forced.forceBtn=Gennemtving låsning
+## Failure
+lock.fail.message=Låsning af boks mislykkedes
+lock.fail.description=Boksen "%s" kunne ikke låses. Sørg for, at ikke-gemt arbejde gemmes andre steder, og at vigtige læse/skriveoperationer er færdige. For at lukke boksen, afslut Cryptomator-processen.
+
+# Migration
+migration.title=Opgradér boks
+## Start
+migration.start.prompt=Din boks "%s" skal opdateres til et nyere format. Før du fortsætter, skal du sørge for, at der ikke er nogen afventende eller igangværende synkronisering.
+migration.start.confirm=Ja. Min boks er fuldt synkroniseret
+## Run
+migration.run.enterPassword=Indtast adgangskoden for "%s"
+migration.run.startMigrationBtn=Migrér boks
+migration.run.progressHint=Dette kan tage noget tid…
+## Success
+migration.success.nextStepsInstructions=Migrerede "%s" uden fejl.\nDu kan nu låse din boks op.
+migration.success.unlockNow=Lås op nu
+## Missing file system capabilities
+migration.error.missingFileSystemCapabilities.title=Filsystem ikke understøttet
+migration.error.missingFileSystemCapabilities.description=Migreringen er ikke gået i gang, fordi din boks er placeret på et utilstrækkeligt filsystem.
+migration.error.missingFileSystemCapabilities.reason.LONG_FILENAMES=Filsystemet understøtter ikke lange filnavne.
+migration.error.missingFileSystemCapabilities.reason.LONG_PATHS=Filsystemet understøtter ikke lange stier.
+migration.error.missingFileSystemCapabilities.reason.READ_ACCESS=Filsystemet tillader ikke læsning.
+migration.error.missingFileSystemCapabilities.reason.WRITE_ACCESS=Filsystemet tillader ikke at blive skrevet til.
+## Impossible
+migration.impossible.heading=Kan ikke migrere boks
+migration.impossible.reason=Boksen kan ikke automatisk migreres, fordi dens lagerplacering eller adgangspunkt ikke er kompatibel.
+migration.impossible.moreInfo=Boksen kan stadig åbnes med en ældre version. For instruktioner om hvordan du manuelt migrerer en boks, besøg
+
+# Health Check
+## Start
+health.title=Sundhedstjek af "%s"
+health.intro.header=Sundhedstjek
+health.intro.text=Sundhedstjek afvikler en række procedurer for at opdage og muligvis løse problemer, i den interne struktur i bin boks. Vær opmærksom på:
+health.intro.remarkSync=Sørg for, at alle enheder er synkroniseret fuldstændig, dette løser de fleste problemer.
+health.intro.remarkFix=Ikke alle problemer kan løses.
+health.intro.remarkBackup=Hvis data er beskadiget, kan kun en sikkerhedskopi hjælpe.
+health.intro.affirmation=Jeg har læst og forstået ovenstående oplysninger
+## Start Failure
+health.fail.header=Fejl ved indlæsning af boks konfiguration
+health.fail.ioError=Der opstod en fejl ved forsøg på læsning af konfigurationsfilen.
+health.fail.parseError=Der opstod en fejl under tolkning af boksens konfigurationen.
+health.fail.moreInfo=Yderligere oplysninger
+## Check Selection
+health.checkList.description=Vælg kontrolprocedurer i listen til venstre, eller brug knapperne nederst.
+health.checkList.selectAllButton=Vælg alle kontrolprocedurer
+health.checkList.deselectAllButton=Fravælg alle kontrolprocedurer
+health.check.runBatchBtn=Kør valgte kontrolprocedurer
+## Detail view
+health.check.detail.noSelectedCheck=Vælg en afsluttet kontrolprocedure i listen til venstre, for at at resultatet.
+health.check.detail.checkScheduled=Kontrolproceduren er planlagt.
+health.check.detail.checkRunning=Kontrolproceduren kører…
+health.check.detail.checkSkipped=Kontrolproceduren var ikke valgt til at køre.
+health.check.detail.checkFinished=Kontrolproceduren er afsluttet.
+health.check.detail.checkFinishedAndFound=Kontrolproceduren er kørt færdig. Gennemse venligst resultatet.
+health.check.detail.checkFailed=Kontrolproceduren blev afbrudt af en fejl.
+health.check.detail.checkCancelled=Kontrolproceduren blev annulleret.
+health.check.exportBtn=Eksportér rapport
+## Fix Application
+health.fix.fixBtn=Reparér
+health.fix.successTip=Repareret
+health.fix.failTip=Reparation fejlet. Se loggen for detaljer
+
+# Preferences
+preferences.title=Præferencer
+## General
+preferences.general=Generelt
+preferences.general.startHidden=Skjul vinduet når Cryptomator starter
+preferences.general.autoCloseVaults=Lås åbne bokse automatisk, når programmet afsluttes
+preferences.general.debugLogging=Aktiver fejllogning
+preferences.general.debugDirectory=Vis logfiler
+preferences.general.autoStart=Start Cryptomator automatisk ved opstart
+preferences.general.keychainBackend=Gem adgangskoder med
+## Interface
+preferences.interface=Brugerflade
+preferences.interface.theme=Udseende
+preferences.interface.theme.automatic=Automatisk
+preferences.interface.theme.dark=Mørk
+preferences.interface.theme.light=Lys
+preferences.interface.unlockThemes=Lås op for mørk tilstand
+preferences.interface.language=Sprog (kræver genstart)
+preferences.interface.language.auto=System standard
+preferences.interface.interfaceOrientation=Brugerflade retning
+preferences.interface.interfaceOrientation.ltr=Venstre til højre
+preferences.interface.interfaceOrientation.rtl=Højre til venstre
+preferences.interface.showMinimizeButton=Vis knap til minimering
+preferences.interface.showTrayIcon=Vis ikon i system-bakken (kræver genstart)
+## Volume
+preferences.volume=Virtuelt drev
+preferences.volume.type=Drev-type
+preferences.volume.webdav.port=WebDAV port
+preferences.volume.webdav.scheme=WebDAV skema
+## Updates
+preferences.updates=Opdateringer
+preferences.updates.currentVersion=Nuværende version: %s
+preferences.updates.autoUpdateCheck=Søg automatisk efter opdateringer
+preferences.updates.checkNowBtn=Kontrollér nu
+preferences.updates.updateAvailable=Opdatering til version %s er tilgængelig.
+## Contribution
+preferences.contribute=Støt os
+preferences.contribute.registeredFor=Registreret supporter-certifikat for %s
+preferences.contribute.noCertificate=Hjælp Cryptomator, og modtag et supporter-certifikat. Det er ligesom en license-nøgle, men til fantastiske mennesker som bruger fri software. ;-)
+preferences.contribute.getCertificate=Har du ikke et allerede? Se her hvordan du kan få et.
+preferences.contribute.promptText=Indsæt koden for supporter-certifikatet her
+#<-- Add entries for donations and code/translation/documentation contribution -->
+
+## About
+preferences.about=Om
+
+# Vault Statistics
+stats.title=Statistik for %s
+stats.cacheHitRate=Cache effektivitet
+## Read
+stats.read.throughput.idle=Læser: afventer
+stats.read.throughput.kibs=Læser: %.2f kiB/s
+stats.read.throughput.mibs=Læser: %.2f MiB/s
+stats.read.total.data.none=Data læst: -
+stats.read.total.data.kib=Data læst: %.1f kiB
+stats.read.total.data.mib=Data læst: %.1f MiB
+stats.read.total.data.gib=Data læst: %.1f GiB
+stats.decr.total.data.none=Data dekrypteret: -
+stats.decr.total.data.kib=Data dekrypteret: %.1f kiB
+stats.decr.total.data.mib=Data dekrypteret: %.1f MiB
+stats.decr.total.data.gib=Data dekrypteret: %.1f GiB
+stats.read.accessCount=Totalt antal læsninger: %d
+## Write
+stats.write.throughput.idle=Skriver: afventer
+stats.write.throughput.kibs=Skriver: %.2f kiB/s
+stats.write.throughput.mibs=Skriver: %.2f MiB/s
+stats.write.total.data.none=Data skrevet: -
+stats.write.total.data.kib=Data skrevet: %.1f kiB
+stats.write.total.data.mib=Data skrevet: %.1f MiB
+stats.write.total.data.gib=Data skrevet: %.1f GiB
+stats.encr.total.data.none=Data krypteret: -
+stats.encr.total.data.kib=Data krypteret: %.1f kiB
+stats.encr.total.data.mib=Data krypteret: %.1f MiB
+stats.encr.total.data.gib=Data krypteret: %.1f GiB
+stats.write.accessCount=Totalt antal skrivninger: %d
+
+# Main Window
+main.closeBtn.tooltip=Luk
+main.minimizeBtn.tooltip=Minimér
+main.preferencesBtn.tooltip=Præferencer
+main.debugModeEnabled.tooltip=Fejlfindingstilstand er aktiveret
+main.supporterCertificateMissing.tooltip=Overvej venligst at donere
+## Drag 'n' Drop
+main.dropZone.dropVault=Tilføj denne boks
+main.dropZone.unknownDragboardContent=Hvis du vil tilføje en boks, så træk den til dette vindue
+## Vault List
+main.vaultlist.emptyList.onboardingInstruction=Klik her for at tilføje en boks
+main.vaultlist.contextMenu.remove=Fjern…
+main.vaultlist.contextMenu.lock=Lås
+main.vaultlist.contextMenu.unlock=Lås op…
+main.vaultlist.contextMenu.unlockNow=Lås op nu
+main.vaultlist.contextMenu.vaultoptions=Vis boksindstillinger
+main.vaultlist.contextMenu.reveal=Vis drev
+main.vaultlist.addVaultBtn=Tilføj boks
+## Vault Detail
+### Welcome
+main.vaultDetail.welcomeOnboarding=Tak fordi du valgte Cryptomator til at beskytte dine filer. Hvis du har brug for hjælp, så tjek vores guider for at komme i gang:
+### Locked
+main.vaultDetail.lockedStatus=LÅST
+main.vaultDetail.unlockBtn=Lås op…
+main.vaultDetail.unlockNowBtn=Lås op nu
+main.vaultDetail.optionsBtn=Boksindstillinger
+main.vaultDetail.passwordSavedInKeychain=Adgangskode gemt
+### Unlocked
+main.vaultDetail.unlockedStatus=LÅST OP
+main.vaultDetail.accessLocation=Boksens indhold er tilgængeligt her:
+main.vaultDetail.revealBtn=Vis drev
+main.vaultDetail.lockBtn=Lås
+main.vaultDetail.bytesPerSecondRead=Læser:
+main.vaultDetail.bytesPerSecondWritten=Skriver:
+main.vaultDetail.throughput.idle=afventer
+main.vaultDetail.throughput.kbps=%.1f kiB/s
+main.vaultDetail.throughput.mbps=%.1f MiB/s
+main.vaultDetail.stats=Boks statistik
+### Missing
+main.vaultDetail.missing.info=Cryptomator kunne ikke finde en boks på denne sti.
+main.vaultDetail.missing.recheck=Kontrollér igen
+main.vaultDetail.missing.remove=Fjern fra listen over bokse…
+main.vaultDetail.missing.changeLocation=Skift placering for boks…
+### Needs Migration
+main.vaultDetail.migrateButton=Opgradér boks
+main.vaultDetail.migratePrompt=Din boks skal opgraderes til et nyt format, før du kan tilgå den
+### Error
+main.vaultDetail.error.info=Der opstod en fejl under læsning af din boks.
+main.vaultDetail.error.reload=Genindlæs
+main.vaultDetail.error.windowTitle=Fejl ved indlæsning af boks
+
+# Wrong File Alert
+wrongFileAlert.title=Sådan krypteres filer
+wrongFileAlert.message=Forsøgte du at kryptere disse filer?
+wrongFileAlert.description=For kryptering af filer, skal du bruge det drev som Cryptomator har lavet i din stifinder.
+wrongFileAlert.instruction.0=For at kryptere filer, gør følgende:
+wrongFileAlert.instruction.1=1. Lås din boks op.
+wrongFileAlert.instruction.2=2. Klik på "Vis drev" for at åbne drevet i din stifinder.
+wrongFileAlert.instruction.3=3. Tilføj filer til drevet.
+wrongFileAlert.link=For yderligere assistance, besøg
+
+# Vault Options
+## General
+vaultOptions.general=Generelt
+vaultOptions.general.vaultName=Boks-navn
+vaultOptions.general.autoLock.lockAfterTimePart1=Lås efter inaktivitet i
+vaultOptions.general.autoLock.lockAfterTimePart2=minutter
+vaultOptions.general.unlockAfterStartup=Lås boksen op når Cryptomator starter
+vaultOptions.general.actionAfterUnlock=Efter oplåsning af boks
+vaultOptions.general.actionAfterUnlock.ignore=Gør intet
+vaultOptions.general.actionAfterUnlock.reveal=Vis drev
+vaultOptions.general.actionAfterUnlock.ask=Spørg
+vaultOptions.general.startHealthCheckBtn=Start sunhedstjek
+
+## Mount
+vaultOptions.mount=Montering
+vaultOptions.mount.readonly=Skrivebeskyttet
+vaultOptions.mount.customMountFlags=Brugerdefinerede monterings-flag
+vaultOptions.mount.winDriveLetterOccupied=optaget
+vaultOptions.mount.mountPoint=Monterings-sted
+vaultOptions.mount.mountPoint.auto=Vælg automatisk en passende placering
+vaultOptions.mount.mountPoint.driveLetter=Brug et ledigt drevbogstav
+vaultOptions.mount.mountPoint.custom=Brugerdefineret sti
+vaultOptions.mount.mountPoint.directoryPickerButton=Vælg…
+vaultOptions.mount.mountPoint.directoryPickerTitle=Vælg en tom mappe
+## Master Key
+vaultOptions.masterkey=Adgangskode
+vaultOptions.masterkey.changePasswordBtn=Skift adgangskode
+vaultOptions.masterkey.forgetSavedPasswordBtn=Glem gemt adgangskode
+vaultOptions.masterkey.recoveryKeyExplanation=En gendannelsesnøgle er den eneste måde du kan få adgang til din boks på, hvis du har glemt dit password.
+vaultOptions.masterkey.showRecoveryKeyBtn=Vis gendannelsesnøgle
+vaultOptions.masterkey.recoverPasswordBtn=Nulstil adgangskode
+
+
+# Recovery Key
+## Display Recovery Key
+recoveryKey.display.title=Vis gendannelsesnøgle
+recoveryKey.create.message=Adgangskode krævet
+recoveryKey.create.description=Indtast adgangskoden for "%s", for at vise gendannelsesnøglen.
+recoveryKey.display.description=Den følgende gendannelsesnøgle kan bruges til at genskabe adgang til "%s":
+recoveryKey.display.StorageHints=Opbevar den et meget sikkert sted, som fx:\n • Gem den i din adgangskode-manager\n • Gem den på et USB-drev\n • Print den ud på papir
+## Reset Password
+### Enter Recovery Key
+recoveryKey.recover.title=Nulstil adgangskode
+recoveryKey.recover.prompt=Indtast din gendannelsesnøgle for "%s":
+recoveryKey.recover.validKey=Dette er en gyldig gendannelsesnøgle
+recoveryKey.printout.heading=Cryptomator gendannelsesnøgle\n"%s"\n
+### Reset Password
+recoveryKey.recover.resetBtn=Nulstil
+### Recovery Key Password Reset Success
+recoveryKey.recover.resetSuccess.message=Adgangskod nulstillet
+recoveryKey.recover.resetSuccess.description=Du kan nu låse din boks op med den nye adgangskode.
+
+# New Password
+newPassword.promptText=Skriv en ny adgangskode
+newPassword.reenterPassword=Bekræft ny adgangskode
+newPassword.passwordsMatch=Adgangskoderne er ens!
+newPassword.passwordsDoNotMatch=Adgangskoder stemmer ikke overens
+passwordStrength.messageLabel.tooShort=Angiv mindst %d tegn
+passwordStrength.messageLabel.0=Meget dårlig
+passwordStrength.messageLabel.1=Dårlig
+passwordStrength.messageLabel.2=Rimelig
+passwordStrength.messageLabel.3=God
+passwordStrength.messageLabel.4=Meget god
+
+# Quit
+quit.title=Afslut program
+quit.message=Der er ulåste bokse
+quit.description=Bekræft venligst, at du vil afslutte. Cryptomator låser alle ulåste bokse for at forhindre tab af data.
+quit.lockAndQuitBtn=Lås og afslut
+
+# Forced Quit
+quit.forced.message=Nogle bokse kunne ikke låses
+quit.forced.description=Låsning af "%s" blev blokeret fordi der er igangværende operationer eller åbne filer. Du kan gennemtvinge låsningen - men en afbrydelse af igangværende I/O operationer kan resultere i tab af data som endnu ikke er gemt.
+quit.forced.forceAndQuitBtn=Tving og afslut
\ No newline at end of file
diff --git a/src/main/resources/i18n/strings_de.properties b/src/main/resources/i18n/strings_de.properties
index 20ea485cf..620e5cac5 100644
--- a/src/main/resources/i18n/strings_de.properties
+++ b/src/main/resources/i18n/strings_de.properties
@@ -56,7 +56,7 @@ addvaultwizard.new.locationIsOk=Geeigneter Ort für deinen Tresor
addvaultwizard.new.invalidName=Ungültiger Tresorname
addvaultwizard.new.validName=Gültiger Tresorname
addvaultwizard.new.validCharacters.message=Der Tresorname darf folgende Zeichen enthalten:
-addvaultwizard.new.validCharacters.chars=Wortzeichen (z.B. a, ж oder 수)
+addvaultwizard.new.validCharacters.chars=Wortzeichen (z. B. a, ж oder 수)
addvaultwizard.new.validCharacters.numbers=Zahlen
addvaultwizard.new.validCharacters.dashes=Bindestrich (%s) oder Unterstrich (%s)
### Password
@@ -103,7 +103,7 @@ changepassword.finalConfirmation=Mir ist bewusst, dass ich bei Verlust meines Pa
# Forget Password
forgetPassword.title=Passwort vergessen
-forgetPassword.message=Gespeichertes Kennwort löschen?
+forgetPassword.message=Gespeichertes Passwort löschen?
forgetPassword.description=Dies löscht das gespeicherte Passwort dieses Tresors aus dem Schlüsselbund deines Betriebssystems.
forgetPassword.confirmBtn=Passwort vergessen
@@ -128,6 +128,33 @@ unlock.error.message=Tresor konnte nicht entsperrt werden
unlock.error.invalidMountPoint.notExisting=Einhängepunkt „%s“ ist kein leeres Verzeichnis oder existiert nicht.
unlock.error.invalidMountPoint.existing=Einhängepunkt „%s“ besteht bereits oder übergeordneter Ordner fehlt.
unlock.error.invalidMountPoint.driveLetterOccupied=Laufwerksbuchstabe „%s“ wird bereits verwendet.
+## Hub
+### Waiting
+hub.auth.message=Warten auf Authentifizierung …
+hub.auth.description=Du solltest automatisch zur Anmeldeseite weitergeleitet werden.
+hub.auth.loginLink=Keine Weiterleitung? Zum Öffnen hier anklicken.
+### Receive Key
+hub.receive.message=Antwort wird verarbeitet …
+hub.receive.description=Cryptomator empfängt und verarbeitet gerade die Antwort vom Hub. Bitte warten.
+### Register Device
+hub.register.message=Gerätename erforderlich
+hub.register.description=Dies scheint der erste Hub-Zugriff von diesem Gerät zu sein. Um es für die Zugriffsberechtigung zu identifizieren, mussst du diesem Gerät einen Namen geben.
+hub.register.nameLabel=Gerätename
+hub.register.occupiedMsg=Name bereits in Verwendung
+hub.register.registerBtn=Bestätigen
+### Registration Success
+hub.registerSuccess.message=Gerät wurde benannt
+hub.registerSuccess.description=Für Zugriff auf den Tresor muss dein Gerät vom Tresorbesitzer autorisiert werden.
+### Registration Failed
+hub.registerFailed.message=Gerät konnte kein Name gegeben werden
+hub.registerFailed.description=Während der Namensvergabe wurde ein Fehler ausgelöst. Weitere Details findest du im Anwendungsprotokoll.
+### Unauthorized
+hub.unauthorized.message=Zugriff verweigert
+hub.unauthorized.description=Dein Gerät wurde noch nicht für den Zugriff auf diesen Tresor autorisiert. Bitte den Tresorbesitzer, dein Gerät zu autorisieren.
+### License Exceeded
+hub.licenseExceeded.message=Lizenz überschritten
+hub.licenseExceeded.description=Im Cryptomator Hub wurden mehr Benutzern ein Zugriff gewährt, als die Lizenz erlaubt. Bitte kontaktieren Sie Ihren Hub-Administrator, um die Lizenz zu erweitern oder einen Tresoradministrator, um Benutzer aus dem Tresor zu entfernen.
+
# Lock
## Force
@@ -202,7 +229,7 @@ preferences.title=Einstellungen
## General
preferences.general=Allgemein
preferences.general.startHidden=Cryptomator im Hintergrund starten
-preferences.general.autoCloseVaults=Geöffnete Tresore automatisch beim Schließen sperren
+preferences.general.autoCloseVaults=Geöffnete Tresore beim Schließen automatisch sperren
preferences.general.debugLogging=Diagnoseprotokoll aktivieren
preferences.general.debugDirectory=Protokolldateien anzeigen
preferences.general.autoStart=Cryptomator beim Systemstart starten
@@ -237,7 +264,7 @@ preferences.contribute=Unterstütze uns
preferences.contribute.registeredFor=Supporter-Zertifikat registriert für %s
preferences.contribute.noCertificate=Unterstütze Cryptomator und erhalte ein Supporter-Zertifikat. Es ist eine Art Lizenzschlüssel, aber für großartige Menschen, die freie Software verwenden. ;-)
preferences.contribute.getCertificate=Du hast noch keines? Erfahre, wie du es erhalten kannst.
-preferences.contribute.promptText=Füge den Code des Supporter-Zertifikats hier ein
+preferences.contribute.promptText=Füge hier den Code des Supporter-Zertifikats ein
#<-- Add entries for donations and code/translation/documentation contribution -->
## About
@@ -384,7 +411,7 @@ recoveryKey.printout.heading=Cryptomator-Wiederherstellungsschlüssel\n„%s“\
recoveryKey.recover.resetBtn=Zurücksetzen
### Recovery Key Password Reset Success
recoveryKey.recover.resetSuccess.message=Passwort erfolgreich zurückgesetzt
-recoveryKey.recover.resetSuccess.description=Der Tresor kann mit dem neuen Passwort entsperrt werden.
+recoveryKey.recover.resetSuccess.description=Du kannst deinen Tresor mit dem neuen Passwort entsperren.
# New Password
newPassword.promptText=Gib ein neues Passwort ein
@@ -406,5 +433,5 @@ quit.lockAndQuitBtn=Sperren und beenden
# Forced Quit
quit.forced.message=Einige Tresore konnten nicht gesperrt werden
-quit.forced.description=Ausstehende Operationen oder geöffnete Dateien verhindern das Sperren von Tresoren. Das Schließen der verbleibenden Tresore kann erzwungen werden, wobei die Unterbrechung von I/O-Vorgängen zum Verlust ungespeicherter Daten führen kann.
+quit.forced.description=Das Sperren von Tresoren wurde durch ausstehende Operationen oder geöffnete Dateien verhindert. Du kannst das Sperren der verbleibenden Tresore erzwingen, jedoch kann das Unterbrechen von E/A-Vorgängen zum Verlust ungespeicherter Daten führen.
quit.forced.forceAndQuitBtn=Erzwingen und beenden
\ No newline at end of file
diff --git a/src/main/resources/i18n/strings_el.properties b/src/main/resources/i18n/strings_el.properties
index 470e85d2f..2dba9e476 100644
--- a/src/main/resources/i18n/strings_el.properties
+++ b/src/main/resources/i18n/strings_el.properties
@@ -128,6 +128,33 @@ unlock.error.message=Αδυναμία ξεκλειδώματος κρύπτης
unlock.error.invalidMountPoint.notExisting=Το σημείο προσάρτησης δεν είναι κενός φάκελος ή δεν υπάρχει: %s
unlock.error.invalidMountPoint.existing=Το σημείο/φάκελος προσάρτησης υπάρχει ήδη ή ο γονικός φάκελος λείπει: %s
unlock.error.invalidMountPoint.driveLetterOccupied=Το Γράμμα Δίσκου "%s" χρησιμοποιείται ήδη.
+## Hub
+### Waiting
+hub.auth.message=Αναμονή για επαλήθευση…
+hub.auth.description=Θα πρέπει να ανακατευθυνθείτε αυτόματα στη σελίδα σύνδεσης.
+hub.auth.loginLink=Δεν έγινε ανακατεύθυνση; Κάντε κλικ εδώ για να το ανοίξετε.
+### Receive Key
+hub.receive.message=Επεξεργασία απάντησης…
+hub.receive.description=Το Cryptomator λαμβάνει και επεξεργάζεται την απάντηση από το Hub. Παρακαλώ περιμένετε.
+### Register Device
+hub.register.message=Απαιτείται όνομα συσκευής
+hub.register.description=Αυτή φαίνεται να είναι η πρώτη πρόσβαση στο Hub από αυτήν τη συσκευή. Για να την αναγνωρίσετε για εξουσιοδότηση πρόσβασης, πρέπει να ονομάσετε αυτήν τη συσκευή.
+hub.register.nameLabel=Όνομα Συσκευής
+hub.register.occupiedMsg=Το όνομα χρησιμοποιείται ήδη
+hub.register.registerBtn=Επιβεβαίωση
+### Registration Success
+hub.registerSuccess.message=Η συσκευή ονομάστηκε
+hub.registerSuccess.description=Για να αποκτήσετε πρόσβαση στην κρύπτη, η συσκευή σας πρέπει να είναι εξουσιοδοτημένη από τον κάτοχο της κρύπτης.
+### Registration Failed
+hub.registerFailed.message=Η ονομασία της συσκευής απέτυχε
+hub.registerFailed.description=Παρουσιάστηκε σφάλμα στη διαδικασία ονομασίας. Για περισσότερες λεπτομέρειες, ανατρέξτε στο αρχείο καταγραφής της εφαρμογής.
+### Unauthorized
+hub.unauthorized.message=Δεν επιτρέπεται η πρόσβαση
+hub.unauthorized.description=Η συσκευή σας δεν έχει ακόμη εξουσιοδοτηθεί να έχει πρόσβαση σε αυτή την κρύπτη. Ζητήστε από τον κάτοχο της κρύπτης να την εξουσιοδοτήσει.
+### License Exceeded
+hub.licenseExceeded.message=Υπέρβαση άδειας
+hub.licenseExceeded.description=Το Cryptomator Hub έχει δώσει πρόσβαση σε περισσότερους χρήστες από ότι επιτρέπει η άδειά του. Παρακαλούμε επικοινωνήστε με το Hub admin για να αναβαθμίσετε την άδεια ή έναν διαχειριστή κρύπτης για να αφαιρέσετε τους χρήστες από τις κρύπτες.
+
# Lock
## Force
diff --git a/src/main/resources/i18n/strings_es.properties b/src/main/resources/i18n/strings_es.properties
index 192525c70..7abba0429 100644
--- a/src/main/resources/i18n/strings_es.properties
+++ b/src/main/resources/i18n/strings_es.properties
@@ -53,6 +53,12 @@ addvaultwizard.new.fileAlreadyExists=Ya existe un archivo o directorio con el no
addvaultwizard.new.locationDoesNotExist=No existe un directorio en la ruta especificada o no se puede acceder
addvaultwizard.new.locationIsNotWritable=Sin acceso de escritura en la ruta especificada
addvaultwizard.new.locationIsOk=Ubicación adecuada para la bóveda
+addvaultwizard.new.invalidName=Nombre de bóveda no válido
+addvaultwizard.new.validName=Nombre de bóveda válido
+addvaultwizard.new.validCharacters.message=El nombre de la bóveda puede contener los siguientes caracteres:
+addvaultwizard.new.validCharacters.chars=Caracteres de la palabra (por ejemplo, a, o o)
+addvaultwizard.new.validCharacters.numbers=Números
+addvaultwizard.new.validCharacters.dashes=Separación (%s) o subrayado (%s)
### Password
addvaultwizard.new.createVaultBtn=Crear bóveda
addvaultwizard.new.generateRecoveryKeyChoice=No podrá acceder a sus datos sin su contraseña. ¿Desea una clave de recuperación en caso de que pierda su contraseña?
@@ -122,6 +128,33 @@ unlock.error.message=No se puede desbloquear la bóveda
unlock.error.invalidMountPoint.notExisting=El punto de montaje "%s"no es un directorio, no está vacío o no existe.
unlock.error.invalidMountPoint.existing=El punto de montaje "%s" ya existe o falta la carpeta padre.
unlock.error.invalidMountPoint.driveLetterOccupied=La letra de unidad "%s" ya está en uso.
+## Hub
+### Waiting
+hub.auth.message=Esperando la autenticación…
+hub.auth.description=Debe ser redirigido automáticamente a la página de inicio de sesión.
+hub.auth.loginLink=¿No se ha redireccionado? Haga clic aquí para abrirla.
+### Receive Key
+hub.receive.message=Procesando la respuesta…
+hub.receive.description=Cryptomator está recibiendo y procesando la respuesta del Hub, espere.
+### Register Device
+hub.register.message=Nombre del dispositivo requerido
+hub.register.description=Este parece ser el primer acceso al Hub desde este dispositivo. Para identificarlo y autorizar el acceso, necesita nombrar este dispositivo.
+hub.register.nameLabel=Nombre del dispositivo
+hub.register.occupiedMsg=Nombre ya en uso
+hub.register.registerBtn=Confirmar
+### Registration Success
+hub.registerSuccess.message=Dispositivo nombrado
+hub.registerSuccess.description=Para acceder a la bóveda, su dispositivo debe ser autorizado por el propietario de la bóveda.
+### Registration Failed
+hub.registerFailed.message=Error al nombrar el dispositivo
+hub.registerFailed.description=Ocurrió un error en el nombramiento. Para más detalles consulte el registro de la aplicación.
+### Unauthorized
+hub.unauthorized.message=Acceso denegado
+hub.unauthorized.description=Su dispositivo aún no ha sido autorizado para acceder a esta bóveda. Pídale al propietario de la bóveda que lo autorice.
+### License Exceeded
+hub.licenseExceeded.message=Licencia excedida
+hub.licenseExceeded.description=Cryptomator Hub ha dado acceso a más usuarios de los que permite su licencia. Póngase en contacto con su administrador de Hub para actualizar la licencia o un administrador de la bóveda para eliminar usuarios de la misma.
+
# Lock
## Force
@@ -375,6 +408,7 @@ recoveryKey.recover.prompt=Ingresar la clave de recuperación para "%s":
recoveryKey.recover.validKey=Esta es una clave de recuperación válida
recoveryKey.printout.heading=Clave de recuperación de Cryptomator\n"%s"\n
### Reset Password
+recoveryKey.recover.resetBtn=## Reiniciar contraseña\nrecoveryKey.recover.resetBtn
### Recovery Key Password Reset Success
recoveryKey.recover.resetSuccess.message=Contraseña restablecida con éxito
recoveryKey.recover.resetSuccess.description=Puede desbloquear su bóveda con la contraseña nueva.
diff --git a/src/main/resources/i18n/strings_fa.properties b/src/main/resources/i18n/strings_fa.properties
index 8f7de851e..1cda0ec25 100644
--- a/src/main/resources/i18n/strings_fa.properties
+++ b/src/main/resources/i18n/strings_fa.properties
@@ -43,6 +43,15 @@ unlock.unlockBtn=بازکردن قفل
## Success
## Failure
### Invalid Mount Point
+## Hub
+### Waiting
+### Receive Key
+### Register Device
+### Registration Success
+### Registration Failed
+### Unauthorized
+### License Exceeded
+
# Lock
## Force
diff --git a/src/main/resources/i18n/strings_fil.properties b/src/main/resources/i18n/strings_fil.properties
index 7013660f6..7ab485d66 100644
--- a/src/main/resources/i18n/strings_fil.properties
+++ b/src/main/resources/i18n/strings_fil.properties
@@ -67,6 +67,15 @@ unlock.unlockBtn=I-unlock
## Success
## Failure
### Invalid Mount Point
+## Hub
+### Waiting
+### Receive Key
+### Register Device
+### Registration Success
+### Registration Failed
+### Unauthorized
+### License Exceeded
+
# Lock
## Force
diff --git a/src/main/resources/i18n/strings_fr.properties b/src/main/resources/i18n/strings_fr.properties
index 6d981168c..553820895 100644
--- a/src/main/resources/i18n/strings_fr.properties
+++ b/src/main/resources/i18n/strings_fr.properties
@@ -128,6 +128,33 @@ unlock.error.message=Impossible de déverrouiller l'espace chiffré
unlock.error.invalidMountPoint.notExisting=Le point de montage «%s» n'est pas un répertoire, n'est pas vide ou n'existe pas.
unlock.error.invalidMountPoint.existing=Le point de montage/le répertoire existe déjà ou le répertoire parent est manquant: %s
unlock.error.invalidMountPoint.driveLetterOccupied=Le lecteur "%s" est déjà utilisé.
+## Hub
+### Waiting
+hub.auth.message=Authentification en cours…
+hub.auth.description=Vous devriez automatiquement être redirigé vers la page de connexion.
+hub.auth.loginLink=Vous n'avez pas été redirigé(e) ? Cliquez ici pour l'ouvrir.
+### Receive Key
+hub.receive.message=Traitement de la réponse…
+hub.receive.description=Cryptomator est en train de recevoir et de traiter la réponse de Hub. Veuillez patienter.
+### Register Device
+hub.register.message=Le nom de l'appareil est requis
+hub.register.description=Il semble que ce soit le premier accès à Hub depuis cet appareil. Afin de l'identifier pour l'autorisation d'accès, vous devez nommer cet appareil.
+hub.register.nameLabel=Nom de l'appareil
+hub.register.occupiedMsg=Nom déjà utilisé
+hub.register.registerBtn=Confirmer
+### Registration Success
+hub.registerSuccess.message=Appareil nommé
+hub.registerSuccess.description=Pour accéder au coffre, votre appareil doit être autorisé par le propriétaire du coffre.
+### Registration Failed
+hub.registerFailed.message=Échec du nommage de l'appareil
+hub.registerFailed.description=Le processus de nommage a retourné une erreur. Pour plus de détails, regardez dans le journal de l'application.
+### Unauthorized
+hub.unauthorized.message=Accès refusé
+hub.unauthorized.description=Votre appareil n'a pas encore été autorisé à accéder à ce coffre. Demandez au propriétaire du coffre de l'autoriser.
+### License Exceeded
+hub.licenseExceeded.message=Licence dépassée
+hub.licenseExceeded.description=Cryptomator Hub a donné accès à plus d'utilisateurs qu'autorisé par la licence. Veuillez contacter votre administrateur Hub pour étendre la licence ou un administrateur de coffre pour supprimer des utilisateurs des coffres.
+
# Lock
## Force
diff --git a/src/main/resources/i18n/strings_gl.properties b/src/main/resources/i18n/strings_gl.properties
index 52f38bfcd..1b9b0de1a 100644
--- a/src/main/resources/i18n/strings_gl.properties
+++ b/src/main/resources/i18n/strings_gl.properties
@@ -2,6 +2,17 @@
# Generics
## Button
+generic.button.apply=Aplicar
+generic.button.back=Volver
+generic.button.cancel=Cancelar
+generic.button.change=Cambiar
+generic.button.choose=Elixir…
+generic.button.close=Pechar
+generic.button.copy=Copiar
+generic.button.copied=Copiado!
+generic.button.done=Feito
+generic.button.next=Seguinte
+generic.button.print=Imprimir
# Error
error.message=Produciuse un erro
@@ -31,6 +42,15 @@ error.message=Produciuse un erro
## Success
## Failure
### Invalid Mount Point
+## Hub
+### Waiting
+### Receive Key
+### Register Device
+### Registration Success
+### Registration Failed
+### Unauthorized
+### License Exceeded
+
# Lock
## Force
@@ -66,6 +86,7 @@ lock.forced.retryBtn=Tentar de novo
## Write
# Main Window
+main.closeBtn.tooltip=Pechar
## Drag 'n' Drop
## Vault List
## Vault Detail
diff --git a/src/main/resources/i18n/strings_he.properties b/src/main/resources/i18n/strings_he.properties
index 24ba4984f..ef5e92fdc 100644
--- a/src/main/resources/i18n/strings_he.properties
+++ b/src/main/resources/i18n/strings_he.properties
@@ -125,6 +125,15 @@ unlock.success.revealBtn=חשוף את הכונן
## Failure
unlock.error.message=לא מתאפשר לבטל נעילת הכספת
### Invalid Mount Point
+## Hub
+### Waiting
+### Receive Key
+### Register Device
+### Registration Success
+### Registration Failed
+### Unauthorized
+### License Exceeded
+
# Lock
## Force
diff --git a/src/main/resources/i18n/strings_hi.properties b/src/main/resources/i18n/strings_hi.properties
index fc901da49..d52d27d3b 100644
--- a/src/main/resources/i18n/strings_hi.properties
+++ b/src/main/resources/i18n/strings_hi.properties
@@ -102,6 +102,16 @@ unlock.success.rememberChoice=विकल्प याद रखें, दो
## Failure
unlock.error.message=वॉल्ट को अनलॉक करना असफल हुआ
### Invalid Mount Point
+## Hub
+### Waiting
+### Receive Key
+### Register Device
+hub.register.registerBtn=पुष्टि करें
+### Registration Success
+### Registration Failed
+### Unauthorized
+### License Exceeded
+
# Lock
## Force
diff --git a/src/main/resources/i18n/strings_hr.properties b/src/main/resources/i18n/strings_hr.properties
index 9b17a8785..8352113b2 100644
--- a/src/main/resources/i18n/strings_hr.properties
+++ b/src/main/resources/i18n/strings_hr.properties
@@ -118,6 +118,16 @@ unlock.error.message=Nije moguće otključati trezor
unlock.error.invalidMountPoint.notExisting=Točka montiranja "%s" nije mapa, nije prazna ili ne postoji.
unlock.error.invalidMountPoint.existing=Točka montiranja "%s" već postoji ili nedostaje nadređena mapa.
unlock.error.invalidMountPoint.driveLetterOccupied=Slovna oznaka pogona "%s" se već koristi.
+## Hub
+### Waiting
+### Receive Key
+### Register Device
+hub.register.registerBtn=Potvrdi
+### Registration Success
+### Registration Failed
+### Unauthorized
+### License Exceeded
+
# Lock
## Force
diff --git a/src/main/resources/i18n/strings_hu.properties b/src/main/resources/i18n/strings_hu.properties
index 4412810ef..453ff4d3f 100644
--- a/src/main/resources/i18n/strings_hu.properties
+++ b/src/main/resources/i18n/strings_hu.properties
@@ -116,6 +116,15 @@ unlock.error.message=Nem lehet feloldani a széfet
unlock.error.invalidMountPoint.notExisting=A csatolási pont "%s" nem egy könyvtár, nem üres vagy nem létezik.
unlock.error.invalidMountPoint.existing=A csatolási pont "%s" már létezik vagy a already exists or szülőmappa hiányzik.
unlock.error.invalidMountPoint.driveLetterOccupied=A "%s" meghajtó betűjel már használat alatt van.
+## Hub
+### Waiting
+### Receive Key
+### Register Device
+### Registration Success
+### Registration Failed
+### Unauthorized
+### License Exceeded
+
# Lock
## Force
diff --git a/src/main/resources/i18n/strings_id.properties b/src/main/resources/i18n/strings_id.properties
index c05cbe346..88884792d 100644
--- a/src/main/resources/i18n/strings_id.properties
+++ b/src/main/resources/i18n/strings_id.properties
@@ -118,6 +118,16 @@ unlock.error.message=Tidak dapat membuka vault
unlock.error.invalidMountPoint.notExisting=Mount point "%s" bukanlah sebuah direktori, tidak sedang kosong, atau bahkan tidak ada sama sekali.
unlock.error.invalidMountPoint.existing=Mount point "%s" sudah ada atau folder induknya tidak ditemukan.
unlock.error.invalidMountPoint.driveLetterOccupied=Drive Letter "%s" sedang digunakan.
+## Hub
+### Waiting
+### Receive Key
+### Register Device
+hub.register.registerBtn=Konfirmasi
+### Registration Success
+### Registration Failed
+### Unauthorized
+### License Exceeded
+
# Lock
## Force
diff --git a/src/main/resources/i18n/strings_it.properties b/src/main/resources/i18n/strings_it.properties
index 261be778e..5ba913d86 100644
--- a/src/main/resources/i18n/strings_it.properties
+++ b/src/main/resources/i18n/strings_it.properties
@@ -118,6 +118,16 @@ unlock.error.message=Impossibile sbloccare la cassaforte
unlock.error.invalidMountPoint.notExisting=Il punto di montaggio "%s" non è una cartella, non è vuoto o non esiste.
unlock.error.invalidMountPoint.existing=Il punto di montaggio "%s" esiste già o la cartella madre è mancante.
unlock.error.invalidMountPoint.driveLetterOccupied=La lettera di unità "%s" è già in uso.
+## Hub
+### Waiting
+### Receive Key
+### Register Device
+hub.register.registerBtn=Conferma
+### Registration Success
+### Registration Failed
+### Unauthorized
+### License Exceeded
+
# Lock
## Force
diff --git a/src/main/resources/i18n/strings_ja.properties b/src/main/resources/i18n/strings_ja.properties
index d0e0bd592..cea387bdf 100644
--- a/src/main/resources/i18n/strings_ja.properties
+++ b/src/main/resources/i18n/strings_ja.properties
@@ -128,6 +128,22 @@ unlock.error.message=金庫の解錠に失敗
unlock.error.invalidMountPoint.notExisting=マウントポイントが空のディレクトリか存在していません: %s
unlock.error.invalidMountPoint.existing=マウント ポイント "%s" が既に存在するか、親フォルダーがありません。
unlock.error.invalidMountPoint.driveLetterOccupied=ドライブレター「%s」は既に使用されています。
+## Hub
+### Waiting
+hub.auth.message=認証を待機中…
+hub.auth.description=ログイン ページに自動的にリダイレクトされます。
+hub.auth.loginLink=リダイレクトされませんでしたか? ここをクリックして開いてください。
+### Receive Key
+hub.receive.message=応答を処理中…
+hub.receive.description=Cryptomator が Hub からの応答を受信、処理中です。しばらくお待ちください。
+### Register Device
+hub.register.message=デバイスの名前が必要です
+hub.register.registerBtn=確認
+### Registration Success
+### Registration Failed
+### Unauthorized
+### License Exceeded
+
# Lock
## Force
diff --git a/src/main/resources/i18n/strings_ko.properties b/src/main/resources/i18n/strings_ko.properties
index 2a6cd33df..337bbad28 100644
--- a/src/main/resources/i18n/strings_ko.properties
+++ b/src/main/resources/i18n/strings_ko.properties
@@ -15,9 +15,9 @@ generic.button.next=다음
generic.button.print=인쇄
# Error
-error.message=에러 %s
+error.message=오류가 발생했습니다
error.hyperlink.report=에러 보고하기
-error.technicalDetails=세부정보:
+error.technicalDetails=상세 정보:
# Defaults
defaults.vault.vaultName=Vault
@@ -38,11 +38,11 @@ addvaultwizard.welcome.newButton=새 Vault 생성
addvaultwizard.welcome.existingButton=기존 Vault 열기
## New
### Name
-addvaultwizard.new.nameInstruction=새 Vault의 이름을 입력하십시요.
+addvaultwizard.new.nameInstruction=새 Vault의 이름을 입력하십시요
addvaultwizard.new.namePrompt=Vault 이름
### Location
-addvaultwizard.new.locationInstruction=Cryptomator Vault 내 암호화 파일을 어느 경로에 저장하시겠습니까?
-addvaultwizard.new.locationLabel=저장소 위치
+addvaultwizard.new.locationInstruction=Cryptomator Vault의 암호화 파일을 어디에 저장하시겠습니까?
+addvaultwizard.new.locationLabel=저장 위치
addvaultwizard.new.locationPrompt=…
addvaultwizard.new.directoryPickerLabel=사용자 지정 위치
addvaultwizard.new.directoryPickerButton=선택
@@ -53,13 +53,13 @@ addvaultwizard.new.locationIsNotWritable=지정된 경로에 쓰기 권한이
addvaultwizard.new.locationIsOk=Vault에 적당한 위치
### Password
addvaultwizard.new.createVaultBtn=Vault 생성
-addvaultwizard.new.generateRecoveryKeyChoice=비밀번호가 없으면 데이터에 접근할 수 없습니다. 비밀번호를 잊으신 경우 복구 키를 원하십니까?
-addvaultwizard.new.generateRecoveryKeyChoice.yes=네. 미안한 것 보단 안전함이 더 낫습니다.
+addvaultwizard.new.generateRecoveryKeyChoice=비밀번호가 없으면 데이터에 접근할 수 없습니다. 비밀번호를 잊었을 때를 대비한 복구 키를 원하십니까?
+addvaultwizard.new.generateRecoveryKeyChoice.yes=네, 보안보다 비밀번호를 잊어버리는 것이 더 걱정됩니다
addvaultwizard.new.generateRecoveryKeyChoice.no=아니요, 나는 비밀번호를 잊지 않을겁니다.
### Information
addvault.new.readme.storageLocation.fileName=IMPORTANT.rtf
addvault.new.readme.storageLocation.1=⚠️ VAULT 파일 ⚠️
-addvault.new.readme.storageLocation.2=이것은 당신의 Vault 저장 위치입니다.
+addvault.new.readme.storageLocation.2=해당 디렉토리는 당신의 Vault 저장 위치 입니다.
addvault.new.readme.storageLocation.3=금지사항
addvault.new.readme.storageLocation.4=• 이 디렉터리를 포함한 어떤 파일도 다른 파일로 교체하거나
addvault.new.readme.storageLocation.5=• 암호화를 위한 파일을 이 디렉터리에 붙여넣지 마십시요.
@@ -75,12 +75,14 @@ addvault.new.readme.accessLocation.3=이 볼륨에 추가된 모든 파일은 Cr
addvault.new.readme.accessLocation.4=이 파일은 지우셔도 무방합니다.
## Existing
addvaultwizard.existing.chooseBtn=선택
+addvaultwizard.existing.filePickerTitle=Vault 파일 선택
## Success
addvaultwizard.success.nextStepsInstructions="%s" Vault가 추가되었습니다.\n이 Vault를 접근하거나 컨텐츠를 추가하려면 잠금해제가 필요합니다. 그렇지만 언제든지 잠금해제가 가능합니다.
addvaultwizard.success.unlockNow=지금 잠금해제
# Remove Vault
removeVault.title=Vault 제거
+removeVault.message=Vault를 삭제하시겠습니까?
removeVault.description=이 행위는 단지 Cryptomator에서 이 Vault를 잊게합니다. 나중에 다시 추가 할 수 있습니다. 암호화된 파일은 하드디스크에서 삭제되지 않을 것입니다.
removeVault.confirmBtn=Vault 제거
@@ -100,8 +102,10 @@ unlock.passwordPrompt="%s"의 비밀번호를 입력하십시요.
unlock.savePassword=비밀번호 기억
unlock.unlockBtn=잠금해제
## Select
+unlock.chooseMasterkey.message=마스터키 파일을 찾을 수 없습니다
unlock.chooseMasterkey.description=추정되는 위치에서 이 Vault의 마스터 키를 찾지 못했습니다. 마스터 키 위치를 수동으로 선택하여 주십시요.
unlock.chooseMasterkey.filePickerTitle=마스터키 파일 선택
+unlock.chooseMasterkey.filePickerMimeDesc=Cryptomator 마스터키
## Success
unlock.success.description="%s"이(가) 성공적으로 잠금해제되었습니다. 이제 이 Vault를 가상드라이브로 접근할 수 있습니다.
unlock.success.rememberChoice=선택 기억함, 다시 묻지 않음
@@ -111,6 +115,17 @@ unlock.error.message=Vault 잠금을 해제 할 수 없습니다.
### Invalid Mount Point
unlock.error.invalidMountPoint.notExisting=구성지점이 존재하지 않거나 빈 디렉터리가 아닙니다: %s
unlock.error.invalidMountPoint.existing=구성지점/폴더가 이미 존재하거나 부모 폴더가 없습니다: %s
+unlock.error.invalidMountPoint.driveLetterOccupied="%s"는 이미 사용중인 드라이브 문자입니다
+## Hub
+### Waiting
+### Receive Key
+### Register Device
+hub.register.registerBtn=확인
+### Registration Success
+### Registration Failed
+### Unauthorized
+### License Exceeded
+
# Lock
## Force
@@ -182,8 +197,19 @@ preferences.general.debugDirectory=Log 파일 표시
preferences.general.autoStart=시스템 시작 시 Cryptomator 실행
preferences.general.keychainBackend=다음 경로에 비밀번호 저장
## Interface
+preferences.interface=인터페이스
+preferences.interface.theme=테마설정
+preferences.interface.theme.automatic=자동
preferences.interface.theme.dark=어둡게
preferences.interface.theme.light=밝게
+preferences.interface.unlockThemes=다크모드 해제
+preferences.interface.language=언어 (재시작 필요)
+preferences.interface.language.auto=시스템 기본 설정
+preferences.interface.interfaceOrientation=인터페이스 방향
+preferences.interface.interfaceOrientation.ltr=왼쪽에서 오른쪽으로
+preferences.interface.interfaceOrientation.rtl=오른쪽에서 왼쪽으로
+preferences.interface.showMinimizeButton=최소화 버튼 표시
+preferences.interface.showTrayIcon=트레이 아이콘 보기 (재시작 필요)
## Volume
preferences.volume=가상 드라이브
preferences.volume.type=볼륨 유형
@@ -312,7 +338,7 @@ vaultOptions.mount=드라이브 구성
vaultOptions.mount.readonly=읽기 전용
vaultOptions.mount.customMountFlags=사용자 정의 매개변수 사용
vaultOptions.mount.winDriveLetterOccupied=사용됨
-vaultOptions.mount.mountPoint=구성 지점
+vaultOptions.mount.mountPoint=마운트 지점
vaultOptions.mount.mountPoint.auto=자동으로 적합한 위치를 선택
vaultOptions.mount.mountPoint.driveLetter=드라이브 문자를 지정하여 사용
vaultOptions.mount.mountPoint.custom=사용자 지정 경로
@@ -334,17 +360,17 @@ recoveryKey.display.StorageHints=매우 안전한곳에 보관하십시요. 예
## Reset Password
### Enter Recovery Key
recoveryKey.recover.prompt="%s"의 복구키를 입력하십시요:
-recoveryKey.recover.validKey=올바른 복구 키 입니다.
+recoveryKey.recover.validKey=올바른 복구 키 입니다
recoveryKey.printout.heading=Cryptomator 복구 키\n"%s"\n
### Reset Password
### Recovery Key Password Reset Success
# New Password
newPassword.promptText=새 비밀번호를 입력하세요
-newPassword.reenterPassword=새 비밀번호를 확인하여 주십시요.
+newPassword.reenterPassword=새 비밀번호 확인
newPassword.passwordsMatch=비밀번호가 일치합니다!
-newPassword.passwordsDoNotMatch=비밀번호가 일치하지 않습니다.
-passwordStrength.messageLabel.tooShort=적어도 %d 자 이상 사용하여 주십시요.
+newPassword.passwordsDoNotMatch=비밀번호가 일치하지 않습니다
+passwordStrength.messageLabel.tooShort=적어도 %d 자 이상 사용해야 합니다
passwordStrength.messageLabel.0=매우 취약함
passwordStrength.messageLabel.1=취약함
passwordStrength.messageLabel.2=보통
diff --git a/src/main/resources/i18n/strings_lv.properties b/src/main/resources/i18n/strings_lv.properties
index 0d69c4677..bc230d174 100644
--- a/src/main/resources/i18n/strings_lv.properties
+++ b/src/main/resources/i18n/strings_lv.properties
@@ -107,6 +107,17 @@ unlock.chooseMasterkey.filePickerTitle=Atlasīt galveno atslēgas datni
unlock.success.revealBtn=Atklāt disku
## Failure
### Invalid Mount Point
+## Hub
+### Waiting
+### Receive Key
+### Register Device
+hub.register.nameLabel=Ierīces nosaukums
+hub.register.registerBtn=Apstiprināt
+### Registration Success
+### Registration Failed
+### Unauthorized
+### License Exceeded
+
# Lock
## Force
diff --git a/src/main/resources/i18n/strings_mk.properties b/src/main/resources/i18n/strings_mk.properties
index 17395b3de..a2a8c9737 100644
--- a/src/main/resources/i18n/strings_mk.properties
+++ b/src/main/resources/i18n/strings_mk.properties
@@ -30,6 +30,16 @@
## Success
## Failure
### Invalid Mount Point
+## Hub
+### Waiting
+### Receive Key
+### Register Device
+hub.register.registerBtn=Потврди
+### Registration Success
+### Registration Failed
+### Unauthorized
+### License Exceeded
+
# Lock
## Force
diff --git a/src/main/resources/i18n/strings_nb.properties b/src/main/resources/i18n/strings_nb.properties
index 038497ea7..50fb6b226 100644
--- a/src/main/resources/i18n/strings_nb.properties
+++ b/src/main/resources/i18n/strings_nb.properties
@@ -116,6 +116,16 @@ unlock.error.message=Klarer ikke å låse opp hvelvet
unlock.error.invalidMountPoint.notExisting=Monteringspunktet "%s" er enten ikke en mappe, ikke tom eller eksisterer ikke.
unlock.error.invalidMountPoint.existing=Monteringspunktet "%s" finnes enten allerede eller at overordnet mappe mangler.
unlock.error.invalidMountPoint.driveLetterOccupied=Stasjonsbokstav "%s" er allerede i bruk.
+## Hub
+### Waiting
+### Receive Key
+### Register Device
+hub.register.registerBtn=Bekreft
+### Registration Success
+### Registration Failed
+### Unauthorized
+### License Exceeded
+
# Lock
## Force
diff --git a/src/main/resources/i18n/strings_nl.properties b/src/main/resources/i18n/strings_nl.properties
index 0f868a12c..7f91e1257 100644
--- a/src/main/resources/i18n/strings_nl.properties
+++ b/src/main/resources/i18n/strings_nl.properties
@@ -56,6 +56,7 @@ addvaultwizard.new.locationIsOk=Geschikte locatie voor je kluis
addvaultwizard.new.invalidName=Ongeldige kluisnaam
addvaultwizard.new.validName=Geldige kluisnaam
addvaultwizard.new.validCharacters.message=De kluisnaam mag de volgende karakters bevatten:
+addvaultwizard.new.validCharacters.chars=Woordtekens (b.v. a, ½ of ±)
addvaultwizard.new.validCharacters.numbers=Nummers
addvaultwizard.new.validCharacters.dashes=Koppelteken (%s) of lage streep (%s)
### Password
@@ -112,10 +113,12 @@ unlock.passwordPrompt=Voer wachtwoord voor "%s" in:
unlock.savePassword=Wachtwoord Onthouden
unlock.unlockBtn=Ontgrendel
## Select
+unlock.chooseMasterkey.message=Masterkey-bestand niet gevonden
unlock.chooseMasterkey.description=Kon het sleutelbestand voor deze kluis niet vinden op de gewenste locatie. Kies het sleutelbestand handmatig.
unlock.chooseMasterkey.filePickerTitle=Selecteer het Masterkey-bestand
unlock.chooseMasterkey.filePickerMimeDesc=Cryptomator Masterkey
## Success
+unlock.success.message=Ontgrendelen gelukt
unlock.success.description="%s" is met succes ontgrendeld! Uw kluis is nu toegankelijk via zijn virtuele schijf.
unlock.success.rememberChoice=Keuze onthouden en dit niet opnieuw tonen
unlock.success.revealBtn=Toon Schijf
@@ -125,6 +128,33 @@ unlock.error.message=Kan kluis niet ontgrendelen
unlock.error.invalidMountPoint.notExisting=Koppelpunt "%s" is geen map, is niet leeg of bestaat niet.
unlock.error.invalidMountPoint.existing=Koppelpunt "%s" bestaat reeds of de bovenliggende map ontbreekt.
unlock.error.invalidMountPoint.driveLetterOccupied=Schijf "%s" is al in gebruik.
+## Hub
+### Waiting
+hub.auth.message=Wachten op authenticatie…
+hub.auth.description=U zal automatisch worden doorgestuurd naar de inlogpagina.
+hub.auth.loginLink=Niet omgeleid? Klik hier om het te openen.
+### Receive Key
+hub.receive.message=Antwoord verwerken…
+hub.receive.description=Cryptomator ontvangt en verwerkt de reactie van Hub. Een ogenblik geduld.
+### Register Device
+hub.register.message=Apparaatnaam vereist
+hub.register.description=Dit lijkt de eerste Hub toegang te zijn vanaf dit apparaat. Om dit apparaat te kunnen identificeren voor autorisatie, moet u dit apparaat benoemen.
+hub.register.nameLabel=Apparaatnaam
+hub.register.occupiedMsg=Naam al in gebruik
+hub.register.registerBtn=Bevestig
+### Registration Success
+hub.registerSuccess.message=Apparaat naam
+hub.registerSuccess.description=Om toegang te krijgen tot de kluis, moet je apparaat worden gemachtigd door de eigenaar van de kluis.
+### Registration Failed
+hub.registerFailed.message=Apparaat naamgeving mislukt
+hub.registerFailed.description=Er is een fout in het naamproces geworpen. Kijk in het applicatielogboek.
+### Unauthorized
+hub.unauthorized.message=Toegang geweigerd
+hub.unauthorized.description=Uw apparaat is nog niet gemachtigd om toegang te krijgen tot deze kluis. Vraag de eigenaar van de kluis om toestemming te geven.
+### License Exceeded
+hub.licenseExceeded.message=Licentie vervallen
+hub.licenseExceeded.description=Cryptomator Hub heeft toegang gegeven aan meer gebruikers dan er licentievergunningen zijn. Neem contact op met uw Hub beheerder om de licentie of een kluisbeheerder te upgraden om gebruikers uit kluizen te verwijderen.
+
# Lock
## Force
@@ -361,20 +391,27 @@ vaultOptions.masterkey.changePasswordBtn=Wijzig wachtwoord
vaultOptions.masterkey.forgetSavedPasswordBtn=Opgeslagen wachtwoord vergeten
vaultOptions.masterkey.recoveryKeyExplanation=Een herstelsleutel is je enige manier om de toegang tot een kluis te herstellen als je je wachtwoord kwijtraakt.
vaultOptions.masterkey.showRecoveryKeyBtn=Toon herstelsleutel
+vaultOptions.masterkey.recoverPasswordBtn=Wachtwoord resetten
# Recovery Key
## Display Recovery Key
+recoveryKey.display.title=Toon herstelsleutel
+recoveryKey.create.message=Wachtwoord vereist
recoveryKey.create.description=Voer uw wachtwoord in om de herstelsleutel voor "%s" te tonen:
recoveryKey.display.description=De volgende herstelsleutel kan worden gebruikt om "%s" te herstellen:
recoveryKey.display.StorageHints=Bewaar het op een veilige plek, bv:\n • Bewaar het in een wachtwoordmanager\n • Sla het op op een USB-stick\n • Print het op papier
## Reset Password
### Enter Recovery Key
+recoveryKey.recover.title=Wachtwoord resetten
recoveryKey.recover.prompt=Voer uw herstelsleutel in voor "%s":
recoveryKey.recover.validKey=Dit is een geldige herstelsleutel
recoveryKey.printout.heading=Cryptomator herstelsleutel\n"%s"\n
### Reset Password
+recoveryKey.recover.resetBtn=Resetten
### Recovery Key Password Reset Success
+recoveryKey.recover.resetSuccess.message=Wachtwoord resetten geslaagd
+recoveryKey.recover.resetSuccess.description=Je kunt je kluis ontgrendelen met het nieuwe wachtwoord.
# New Password
newPassword.promptText=Voer een nieuw wachtwoord in
@@ -390,6 +427,11 @@ passwordStrength.messageLabel.4=Zeer sterk
# Quit
quit.title=Applicatie afsluiten
+quit.message=Er zijn kluizen ontgrendeld
+quit.description=Bevestig dat je wilt afsluiten. Cryptomator zal alle ontgrendelde kluizen vergrendelen om dataverlies te voorkomen.
quit.lockAndQuitBtn=Vergrendelen en Afsluiten
-# Forced Quit
\ No newline at end of file
+# Forced Quit
+quit.forced.message=Sommige kluizen konden niet vergrendeld worden
+quit.forced.description=Kluizen vergrendelen is geblokkeerd door openstaande bewerkingen of geopende bestanden. U kunt de resterende kluizen forceren, maar het onderbreken van I/O kan leiden tot het verlies van niet-opgeslagen gegevens.
+quit.forced.forceAndQuitBtn=Forceren en afsluiten
\ No newline at end of file
diff --git a/src/main/resources/i18n/strings_nn.properties b/src/main/resources/i18n/strings_nn.properties
index bfbec2d2a..0473d9d1d 100644
--- a/src/main/resources/i18n/strings_nn.properties
+++ b/src/main/resources/i18n/strings_nn.properties
@@ -96,6 +96,15 @@ unlock.success.rememberChoice=Hugs valet - ikkje vis dette igjen
unlock.success.revealBtn=Gjer eininga synleg
## Failure
### Invalid Mount Point
+## Hub
+### Waiting
+### Receive Key
+### Register Device
+### Registration Success
+### Registration Failed
+### Unauthorized
+### License Exceeded
+
# Lock
## Force
diff --git a/src/main/resources/i18n/strings_pa.properties b/src/main/resources/i18n/strings_pa.properties
index 28d215446..2a0038b47 100644
--- a/src/main/resources/i18n/strings_pa.properties
+++ b/src/main/resources/i18n/strings_pa.properties
@@ -101,6 +101,15 @@ unlock.error.message=ਵਾਲਟ ਅਣ-ਲਾਕ ਕਰਨ ਲਈ ਅਸਮਰ
### Invalid Mount Point
unlock.error.invalidMountPoint.notExisting="%s" ਮਾਊਂਟ ਪੁਆਇੰਟ ਡਾਇਰੈਕਟਰੀ ਨਹੀਂ, ਖਾਲੀ ਨਹੀਂ ਜਾਂ ਮੌਜੂਦ ਹੀ ਨਹੀਂ ਹੈ।
unlock.error.invalidMountPoint.existing="%s" ਮਾਊਂਟ ਪੁਆਇੰਟ ਪਹਿਲਾਂ ਹੀ ਮੌਜੂਦ ਹੈ ਜਾਂ ਉਸ ਦਾ ਮੂਲ ਫੋਲਡਰ ਗੁੰਮ ਹੈ।
+## Hub
+### Waiting
+### Receive Key
+### Register Device
+### Registration Success
+### Registration Failed
+### Unauthorized
+### License Exceeded
+
# Lock
## Force
diff --git a/src/main/resources/i18n/strings_pl.properties b/src/main/resources/i18n/strings_pl.properties
index a15286e35..f747ab970 100644
--- a/src/main/resources/i18n/strings_pl.properties
+++ b/src/main/resources/i18n/strings_pl.properties
@@ -53,6 +53,12 @@ addvaultwizard.new.fileAlreadyExists=Plik lub katalog z nazwą tą sejfu już is
addvaultwizard.new.locationDoesNotExist=Katalog w określonej ścieżce nie istnieje lub nie można uzyskać dostępu
addvaultwizard.new.locationIsNotWritable=Brak możliwości zapisu w podanej ścieżce
addvaultwizard.new.locationIsOk=Odpowiednia lokalizacja dla Twojego sejfu
+addvaultwizard.new.invalidName=Błędna nazwa sejfu
+addvaultwizard.new.validName=Poprawna nazwa sejfu
+addvaultwizard.new.validCharacters.message=Nazwa sejfu może zawierać następujące znaki:
+addvaultwizard.new.validCharacters.chars=Znaki słów (np. a, ж lub 수)
+addvaultwizard.new.validCharacters.numbers=Liczby
+addvaultwizard.new.validCharacters.dashes=Myślnik (%s) lub podkreślenie (%s)
### Password
addvaultwizard.new.createVaultBtn=Utwórz sejf
addvaultwizard.new.generateRecoveryKeyChoice=Nie będziesz mógł uzyskać dostępu do swoich danych bez hasła. Czy chciałbyś klucz odzyskiwania w przypadku utraty hasła?
@@ -122,6 +128,31 @@ unlock.error.message=Nie można odblokować sejfu
unlock.error.invalidMountPoint.notExisting=Punkt montowania nie jest pustym katalogiem lub nie istnieje: %s
unlock.error.invalidMountPoint.existing=Punkt montowania już istnieje lub brakuje katalogu nadrzędnego: %s
unlock.error.invalidMountPoint.driveLetterOccupied=Litera dysku "%s" jest już w użyciu.
+## Hub
+### Waiting
+hub.auth.message=Czekanie na autoryzację…
+hub.auth.description=Przekierowanie na stronę logowania nastąpi automatycznie.
+hub.auth.loginLink=Nie przekierowano? Kliknij tutaj.
+### Receive Key
+hub.receive.message=Przetwarzanie odpowiedzi…
+hub.receive.description=Cryptomator odbiera i przetwarza odpowiedź z Huba, proszę czekać.
+### Register Device
+hub.register.message=Wymagana nazwa urządzenia
+hub.register.description=Wygląda że jest to pierwszy dostęp do Huba z tego urządzenia. Aby zidentyfikować go w celu uzyskania autoryzacji dostępu, musisz nazwać to urządzenie.
+hub.register.nameLabel=Nazwa urządzenia
+hub.register.occupiedMsg=Nazwa jest już używana
+hub.register.registerBtn=Zatwierdź
+### Registration Success
+hub.registerSuccess.message=Urządzenie nazwano
+hub.registerSuccess.description=Aby dostać się do sejfu, Twoje urządzenie musi być autoryzowane przez właściciela sejfu.
+### Registration Failed
+hub.registerFailed.message=Nazwanie urządzenia nie powiodło się
+hub.registerFailed.description=Wystąpił błąd podczas ustawiania nazwy. Aby uzyskać więcej szczegółów, zobacz logi aplikacji.
+### Unauthorized
+hub.unauthorized.message=Brak dostępu
+hub.unauthorized.description=Twoje urządzenie nie zostało jeszcze upoważnione do dostępu do tego sejfu. Poproś właściciela sejfu o autoryzację.
+### License Exceeded
+
# Lock
## Force
@@ -375,6 +406,7 @@ recoveryKey.recover.prompt=Wprowadź swój klucz odzyskiwania dla "%s":
recoveryKey.recover.validKey=To jest prawidłowy klucz odzyskiwania
recoveryKey.printout.heading=Cryptomator - Klucz odzyskiwania "%s"\n
### Reset Password
+recoveryKey.recover.resetBtn=Resetuj
### Recovery Key Password Reset Success
recoveryKey.recover.resetSuccess.message=Hasło zostało zresetowane
recoveryKey.recover.resetSuccess.description=Możesz odblokować sejf przy użyciu nowego hasła.
diff --git a/src/main/resources/i18n/strings_pt.properties b/src/main/resources/i18n/strings_pt.properties
index d7e26f33e..ff3a94c30 100644
--- a/src/main/resources/i18n/strings_pt.properties
+++ b/src/main/resources/i18n/strings_pt.properties
@@ -29,8 +29,8 @@ traymenu.showMainWindow=Mostrar
traymenu.showPreferencesWindow=Preferências
traymenu.lockAllVaults=Bloquear Todos
traymenu.quitApplication=Fechar
-traymenu.vault.unlock=Destrancar
-traymenu.vault.lock=Trancar
+traymenu.vault.unlock=Desbloquear
+traymenu.vault.lock=Bloquear
traymenu.vault.reveal=Revelar
# Add Vault Wizard
@@ -53,11 +53,17 @@ addvaultwizard.new.fileAlreadyExists=Aviso: Já existe um Ficheiro ou Diretório
addvaultwizard.new.locationDoesNotExist=Um diretório no caminho especificado não existe ou não pode ser acessado
addvaultwizard.new.locationIsNotWritable=Sem acesso de escrita no caminho especificado
addvaultwizard.new.locationIsOk=Localização adequada para o seu cofre
+addvaultwizard.new.invalidName=Nome do cofre inválido
+addvaultwizard.new.validName=Nome do cofre válido
+addvaultwizard.new.validCharacters.message=O nome do cofre pode conter os seguintes caracteres:
+addvaultwizard.new.validCharacters.chars=Caracteres válidos (p. ex. a, ж ou 수)
+addvaultwizard.new.validCharacters.numbers=Números
+addvaultwizard.new.validCharacters.dashes=Hífen (%s) ou sublinhado (%s)
### Password
addvaultwizard.new.createVaultBtn=Criar Cofre
-addvaultwizard.new.generateRecoveryKeyChoice=Não será capaz de aceder aos seus dados sem a sua senha. Você quer uma chave de recuperação para caso perca a sua senha?
+addvaultwizard.new.generateRecoveryKeyChoice=Não será capaz de aceder aos seus dados sem a sua palavra-passe. Quer uma chave de recuperação para caso perca a sua palavra-passe?
addvaultwizard.new.generateRecoveryKeyChoice.yes=Sim por favor, melhor prevenir do que remediar
-addvaultwizard.new.generateRecoveryKeyChoice.no=Não obrigado, não vou perder a minha senha
+addvaultwizard.new.generateRecoveryKeyChoice.no=Não obrigado, não vou perder a minha palavra-passe
### Information
addvault.new.readme.storageLocation.fileName=IMPORTANTE.rtf
addvault.new.readme.storageLocation.1=⚠ ARQUIVOS DO COFRE ⚠
@@ -79,24 +85,27 @@ addvault.new.readme.accessLocation.4=Sinta-se livre para remover este ficheiro.
addvaultwizard.existing.instruction=Escolha o ficheiro "vault.cryptomator" do seu cofre. Se encontrar unicamente o ficheiro "masterkey.cryptomator", selecione-o.
addvaultwizard.existing.chooseBtn=Escolher…
addvaultwizard.existing.filePickerTitle=Selecionar o ficheiro do cofre
+addvaultwizard.existing.filePickerMimeDesc=Cofre Cryptomator
## Success
-addvaultwizard.success.nextStepsInstructions=Adicionado cofre "%s".\nPrecisa de destrancar este cofre para aceder ou adicionar conteúdo. Como alternativa, pode destrancá-lo a qualquer momento mais tarde.
-addvaultwizard.success.unlockNow=Destrancar agora
+addvaultwizard.success.nextStepsInstructions=Adicionado cofre "%s".\nPrecisa de desbloquear este cofre para aceder ou adicionar conteúdo. Como alternativa, pode desbloquear a qualquer momento mais tarde.
+addvaultwizard.success.unlockNow=Desbloquear agora
# Remove Vault
removeVault.title=Remover Cofre
+removeVault.message=Remover Cofre?
removeVault.description=Isto fará unicamente com que o Cryptomator esqueça este cofre. Poderá adicioná-lo novamente mais tarde. Nenhum ficheiro encriptado será apagado do seu disco rígido.
removeVault.confirmBtn=Remover Cofre
# Change Password
-changepassword.title=Alterar Senha
-changepassword.enterOldPassword=Digite a senha atual para "%s"
+changepassword.title=Alterar Palavra-passe
+changepassword.enterOldPassword=Introduza a sua palavra-passe atual para "%s"
changepassword.finalConfirmation=Eu entendo que não poderei aceder aos meus dados se esquecer a minha senha
# Forget Password
forgetPassword.title=Esqueci a Senha
+forgetPassword.message=Esquecer a senha guardada?
forgetPassword.description=Isto irá apagar a palavra-passe deste cofre guardada no porta-chaves do seu sistema.
-forgetPassword.confirmBtn=Esqueci a Senha
+forgetPassword.confirmBtn=Esquecer a Palavra-passe
# Unlock
unlock.title=Desbloquear "%s"
@@ -104,9 +113,12 @@ unlock.passwordPrompt=Insira a senha para "%s":
unlock.savePassword=Recordar a palavra-passe
unlock.unlockBtn=Destrancar
## Select
+unlock.chooseMasterkey.message=Chave Mestra não encontrada
unlock.chooseMasterkey.description=Não foi possível encontrar o ficheiro masterkey no local predefinido para este cofre. Por favor, escolha o ficheiro chave manualmente.
unlock.chooseMasterkey.filePickerTitle=Selecionar ficheiro MasterKey
+unlock.chooseMasterkey.filePickerMimeDesc=Chave Mestra Cryptomator
## Success
+unlock.success.message=Desbloqueado com sucesso
unlock.success.description="%s" desbloqueado com sucesso! O seu cofre está agora acessível na correspondente unidade virtual.
unlock.success.rememberChoice=Lembrar escolha, não mostrar isto novamente
unlock.success.revealBtn=Revelar unidade
@@ -116,6 +128,26 @@ unlock.error.message=Não foi possível desbloquear o cofre
unlock.error.invalidMountPoint.notExisting=O ponto de montagem "%s" não é um diretório, não está vazio ou não existe.
unlock.error.invalidMountPoint.existing=O ponto de montagem "%s" já existe ou a pasta antecedente está em falta.
unlock.error.invalidMountPoint.driveLetterOccupied=A letra de unidade "%s" já está sendo usada.
+## Hub
+### Waiting
+hub.auth.message=A aguardar autenticação…
+hub.auth.description=Vai ser redirecionado automaticamente para a página de início de sessão.
+hub.auth.loginLink=Não foi redirecionado? Clique aqui para abrir.
+### Receive Key
+hub.receive.message=A processar a resposta…
+hub.receive.description=Cryptomator está a receber e a processar a resposta do Hub. Por favor aguarde.
+### Register Device
+hub.register.message=Nome do dispositivo necessário
+hub.register.nameLabel=Nome do Dispositivo
+hub.register.occupiedMsg=Nome já utilizado
+hub.register.registerBtn=Confirmar
+### Registration Success
+### Registration Failed
+### Unauthorized
+hub.unauthorized.message=Acesso negado
+### License Exceeded
+hub.licenseExceeded.message=Licença excedida
+
# Lock
## Force
@@ -178,12 +210,23 @@ health.check.detail.checkSkipped=A verificação não foi selecionada para ser e
health.check.detail.checkFinished=A verificação foi concluída com sucesso.
health.check.detail.checkFinishedAndFound=A verificação concluiu. Por favor, reveja os resultados.
## Fix Application
+health.fix.fixBtn=Corrigir
# Preferences
preferences.title=Preferências
## General
preferences.general=Geral
+preferences.general.startHidden=Ocultar janela ao iniciar o Cryptomator
+preferences.general.autoCloseVaults=Bloquear cofres abertos automaticamente ao sair da aplicação
## Interface
+preferences.interface=Interface
+preferences.interface.theme.automatic=Automático
+preferences.interface.theme.dark=Escuro
+preferences.interface.theme.light=Claro
+preferences.interface.unlockThemes=Desbloquear o modo escuro
+preferences.interface.language=Idioma (requer reinício)
+preferences.interface.language.auto=Predefinição do Sistema
+preferences.interface.interfaceOrientation=Orientação da Aplicação
## Volume
preferences.volume.webdav.port=Porta WebDAV
preferences.volume.webdav.scheme=WebDAV Scheme
@@ -200,6 +243,7 @@ preferences.updates.updateAvailable=Atualização para a versão %s disponível.
preferences.about=Sobre
# Vault Statistics
+stats.title=Estatísticas de %s
## Read
## Write
@@ -209,16 +253,26 @@ main.minimizeBtn.tooltip=Minimizar
main.preferencesBtn.tooltip=Preferências
main.supporterCertificateMissing.tooltip=Por favor, considere doar
## Drag 'n' Drop
+main.dropZone.dropVault=Adicionar este cofre
## Vault List
+main.vaultlist.emptyList.onboardingInstruction=Clique aqui para adicionar um cofre
+main.vaultlist.contextMenu.remove=Remover…
main.vaultlist.contextMenu.lock=Trancar
+main.vaultlist.contextMenu.unlock=Desbloquear…
main.vaultlist.contextMenu.unlockNow=Destrancar agora
main.vaultlist.contextMenu.reveal=Revelar unidade
main.vaultlist.addVaultBtn=Adicionar Cofre
## Vault Detail
### Welcome
### Locked
+main.vaultDetail.lockedStatus=BLOQUEADO
+main.vaultDetail.unlockBtn=Desbloquear…
main.vaultDetail.unlockNowBtn=Destrancar agora
+main.vaultDetail.optionsBtn=Opções do Cofre
+main.vaultDetail.passwordSavedInKeychain=Palavra-passe guardada
### Unlocked
+main.vaultDetail.unlockedStatus=DESBLOQUEADO
+main.vaultDetail.accessLocation=O conteúdo do seu cofre está acessível aqui:
main.vaultDetail.revealBtn=Revelar unidade
main.vaultDetail.lockBtn=Trancar
main.vaultDetail.throughput.idle=inativo
diff --git a/src/main/resources/i18n/strings_pt_BR.properties b/src/main/resources/i18n/strings_pt_BR.properties
index b806a0609..853f2c3ed 100644
--- a/src/main/resources/i18n/strings_pt_BR.properties
+++ b/src/main/resources/i18n/strings_pt_BR.properties
@@ -6,7 +6,7 @@ generic.button.apply=Aplicar
generic.button.back=Voltar
generic.button.cancel=Cancelar
generic.button.change=Alterar
-generic.button.choose=Escolher…
+generic.button.choose=Escolha…
generic.button.close=Fechar
generic.button.copy=Copiar
generic.button.copied=Copiado!
@@ -16,7 +16,7 @@ generic.button.print=Imprimir
# Error
error.message=Erro %s
-error.description=Oops! Cryptomator não esperava que isso acontecesse. Você pode procurar soluções existentes para este erro. Ou se isso ainda não foi reportado, fique à vontade para fazê-lo.
+error.description=Oops! Cryptomator não esperava que isso acontecesse. Você pode procurar soluções existentes para este erro. Ou se isso ainda não foi reportado como erro, fique à vontade para fazê-lo.
error.hyperlink.lookup=Procure este erro
error.hyperlink.report=Reportar este erro
error.technicalDetails=Detalhes:
@@ -56,7 +56,7 @@ addvaultwizard.new.locationIsOk=Localização adequada para o seu cofre
addvaultwizard.new.invalidName=Nome do cofre inválido
addvaultwizard.new.validName=Nome do cofre válido
addvaultwizard.new.validCharacters.message=O nome do cofre pode conter os seguintes caracteres:
-addvaultwizard.new.validCharacters.chars=Caracteres de palavra (por exemplo, a, ж or 수)
+addvaultwizard.new.validCharacters.chars=Caracteres de texto (exemplo: a, ж ou 수)
addvaultwizard.new.validCharacters.numbers=Números
addvaultwizard.new.validCharacters.dashes=Hífen (%s) ou sublinhado (%s)
### Password
@@ -91,9 +91,9 @@ addvaultwizard.success.nextStepsInstructions=Cofre "%s" adicionado.\nVocê preci
addvaultwizard.success.unlockNow=Desbloquear Agora
# Remove Vault
-removeVault.title=Remover Cofre
-removeVault.message=Remover Cofre?
-removeVault.description=Isso apenas fará que o Cryptomator esqueça este cofre. Você pode adicioná--lo novamente. Nenhum arquivo encriptado será apagado do seu disco rígido.
+removeVault.title=Remover o cofre "%s"
+removeVault.message=Remover o cofre?
+removeVault.description=Isso só fará com que o Cryptomator esqueça esse cofre. Você pode adicioná-lo novamente. Nenhum arquivo criptografado será excluído do seu disco rígido.
removeVault.confirmBtn=Remover Cofre
# Change Password
@@ -104,16 +104,16 @@ changepassword.finalConfirmation=Eu entendo que não poderei acessar os meus dad
# Forget Password
forgetPassword.title=Esquecer Senha
forgetPassword.message=Esqueceu sua senha?
-forgetPassword.description=Isso removerá a senha salva deste cofre do chaveiro do seu sistema.
+forgetPassword.description=Isso excluirá a senha que você salvou deste cofre, do chaveiro de senhas do sistema.
forgetPassword.confirmBtn=Esquecer Senha
# Unlock
unlock.title=Desbloquear "%s"
unlock.passwordPrompt=Digite a senha para "%s":
-unlock.savePassword=Lembrar Senha
+unlock.savePassword=Lembrar senha
unlock.unlockBtn=Desbloquear
## Select
-unlock.chooseMasterkey.message=Arquivo Masterkey não encontrado
+unlock.chooseMasterkey.message=Arquivo de chave mestra — “masterkey” — não encontrado
unlock.chooseMasterkey.description=Não foi possível encontrar o arquivo Masterkey deste cofre no local esperado. Por favor selecione manualmente o arquivo contendo a chave.
unlock.chooseMasterkey.filePickerTitle=Selecionar Arquivo Masterkey
unlock.chooseMasterkey.filePickerMimeDesc=Chave mestra do Cryptomator
@@ -128,6 +128,33 @@ unlock.error.message=Não foi possível desbloquear o cofre
unlock.error.invalidMountPoint.notExisting=O ponto de montagem não é um diretório vazio ou não existe: %s
unlock.error.invalidMountPoint.existing=Ponto de montagem/pasta já existe ou a pasta pai está faltando: %s
unlock.error.invalidMountPoint.driveLetterOccupied=Letra de unidade "%s" já está em uso.
+## Hub
+### Waiting
+hub.auth.message=Esperando pela autenticação…
+hub.auth.description=Você será redirecionado automaticamente para a página de login.
+hub.auth.loginLink=Não foi redirecionado? Clique aqui para abrir.
+### Receive Key
+hub.receive.message=Processando resposta…
+hub.receive.description=Cryptomator está recebendo e processando a resposta do Hub. Por favor, aguarde.
+### Register Device
+hub.register.message=Nome do dispositivo necessário
+hub.register.description=Este parece ser o seu primeiro acesso ao Hub deste dispositivo. Para ser identificado e ter autorização de acesso, você precisa nomear este dispositivo.
+hub.register.nameLabel=Nome do dispositivo
+hub.register.occupiedMsg=Este nome já está em uso
+hub.register.registerBtn=Confirme
+### Registration Success
+hub.registerSuccess.message=Dispositivo nomeado
+hub.registerSuccess.description=Para acessar este cofre, seu dispositivo precisa ser autorizado pelo proprietário do cofre que está tentando acessar.
+### Registration Failed
+hub.registerFailed.message=Falha ao registrar o nome do dispositivo no Hub
+hub.registerFailed.description=Ocorreu um erro no processo de nomeação do dispositivo junto ao Hub. Para obter mais detalhes, consulte os registros informativos — log's — do aplicativo.
+### Unauthorized
+hub.unauthorized.message=Acesso negado
+hub.unauthorized.description=Seu dispositivo ainda não foi autorizado a acessar este cofre. Peça ao proprietário ou a um administrador deste cofre para autorizá-lo.
+### License Exceeded
+hub.licenseExceeded.message=No. de licenças excedido
+hub.licenseExceeded.description=O Cryptomator Hub deu acesso a mais usuários do que sua licença de uso permite. Entre em contato com o administrador do seu Cryptomator Hub para ele atualizar o número de licenças ou com um administrador do cofre para remover usuários dos cofres.
+
# Lock
## Force
@@ -406,5 +433,5 @@ quit.lockAndQuitBtn=Bloquear e Sair
# Forced Quit
quit.forced.message=Alguns cofres não puderam ser trancados
-quit.forced.description=O bloqueio de cofres foi bloqueado por operações pendentes ou arquivos abertos. Você pode forçar o bloqueio dos cofres restantes, no entanto interromper o I/O pode resultar na perda de dados não salvos.
+quit.forced.description=O bloqueio dos cofres foi impedido por operações pendentes ou arquivos abertos. Você pode forçar o bloqueio dos cofres restantes, no entanto, essa interrupção de E/S pode resultar na perda de dados não salvos nos cofres — “seus dados”.
quit.forced.forceAndQuitBtn=Forçar e Sair
\ No newline at end of file
diff --git a/src/main/resources/i18n/strings_ro.properties b/src/main/resources/i18n/strings_ro.properties
index 42b5acc5a..dd72912bf 100644
--- a/src/main/resources/i18n/strings_ro.properties
+++ b/src/main/resources/i18n/strings_ro.properties
@@ -109,6 +109,16 @@ unlock.error.message=Imposibil de deblocat seiful
### Invalid Mount Point
unlock.error.invalidMountPoint.notExisting=Punctul de montare "%s" nu este un dosar, nu este gol sau nu există.
unlock.error.invalidMountPoint.existing=Punctul de montare "%s" există deja sau dosarul părinte lipsește.
+## Hub
+### Waiting
+### Receive Key
+### Register Device
+hub.register.registerBtn=Confirmați
+### Registration Success
+### Registration Failed
+### Unauthorized
+### License Exceeded
+
# Lock
## Force
diff --git a/src/main/resources/i18n/strings_ru.properties b/src/main/resources/i18n/strings_ru.properties
index 0ad2424bb..a4f8cf979 100644
--- a/src/main/resources/i18n/strings_ru.properties
+++ b/src/main/resources/i18n/strings_ru.properties
@@ -128,6 +128,33 @@ unlock.error.message=Невозможно разблокировать хран
unlock.error.invalidMountPoint.notExisting=Точка монтирования %s - не папка, не пуста или не существует.
unlock.error.invalidMountPoint.existing=Точка монтирования %s уже существует, либо отсутствует родительская папка.
unlock.error.invalidMountPoint.driveLetterOccupied=Буква диска "%s" уже используется.
+## Hub
+### Waiting
+hub.auth.message=Ожидание аутентификации…
+hub.auth.description=Вы должны быть автоматически перенаправлены на страницу входа.
+hub.auth.loginLink=Не перенаправлено? Нажмите здесь, чтобы открыть её.
+### Receive Key
+hub.receive.message=Обработка ответа…
+hub.receive.description=Cryptomator принимает и обрабатывает ответ от хаба. Подождите.
+### Register Device
+hub.register.message=Требуется имя устройства
+hub.register.description=Похоже, это первый доступ к хабу с данного устройства. Чтобы идентифицирваоть его для предоставления доступа, нужно дать устройству имя.
+hub.register.nameLabel=Имя устройства
+hub.register.occupiedMsg=Имя уже используется
+hub.register.registerBtn=Подтвердить
+### Registration Success
+hub.registerSuccess.message=Устройству присвоено имя
+hub.registerSuccess.description=Для доступа к хранилищу ваше устройство должно быть авторизовано владельцем хранилища.
+### Registration Failed
+hub.registerFailed.message=Ошибка присвоения имени устройству
+hub.registerFailed.description=Ошибка присвоения имени. Более подробную информацию см. в журнале приложения.
+### Unauthorized
+hub.unauthorized.message=Нет доступа
+hub.unauthorized.description=Устройство ещё не авторизовано для доступа к этому хранилищу. Попросите владельца хранилища разрешить его.
+### License Exceeded
+hub.licenseExceeded.message=Срок действия лицензии истёк
+hub.licenseExceeded.description=Cryptomator Hub предоставил доступ большему количеству пользователей, чем разрешено лицензией. Обратитесь к администратору Hub для обновления лицензии или администратора хранилища, чтобы удалить пользователей из хранилищ.
+
# Lock
## Force
diff --git a/src/main/resources/i18n/strings_si.properties b/src/main/resources/i18n/strings_si.properties
index 6bd3176c3..4c9ed156d 100644
--- a/src/main/resources/i18n/strings_si.properties
+++ b/src/main/resources/i18n/strings_si.properties
@@ -46,6 +46,15 @@ unlock.unlockBtn=අගුළුහරින්න
## Success
## Failure
### Invalid Mount Point
+## Hub
+### Waiting
+### Receive Key
+### Register Device
+### Registration Success
+### Registration Failed
+### Unauthorized
+### License Exceeded
+
# Lock
## Force
diff --git a/src/main/resources/i18n/strings_sk.properties b/src/main/resources/i18n/strings_sk.properties
index fcd8ffa02..bff6fc50b 100644
--- a/src/main/resources/i18n/strings_sk.properties
+++ b/src/main/resources/i18n/strings_sk.properties
@@ -128,6 +128,33 @@ unlock.error.message=Nie je možné odomknúť trezor
unlock.error.invalidMountPoint.notExisting=Bod pripojenia "%s" nie je adresár, nie je prázdny alebo neexistuje.
unlock.error.invalidMountPoint.existing=Bod pripojenia "%s" už existuje alebo chýba nadradený adresár.
unlock.error.invalidMountPoint.driveLetterOccupied=Písmeno disku %s sa už používa.
+## Hub
+### Waiting
+hub.auth.message=Čakanie na autentifikáciu…
+hub.auth.description=Môžete byť automaticky presmerovaný na prihlasovaciu stránku.
+hub.auth.loginLink=Nepresmerované? Kliknúť tu pre otvorenie.
+### Receive Key
+hub.receive.message=Spracovávanie odpovede…
+hub.receive.description=Cryptomator prijíma a spracúva odpovede z Hub-u. Prosím počkajte.
+### Register Device
+hub.register.message=Názov zariadenia je požadovaný
+hub.register.description=Zdá sa, že ide o prvý prístup k Hub-u z tohto zariadenia. Z dôvodu identifikácie prístupovej autorizácie, je potrebné pomenovať toto zariadenie.
+hub.register.nameLabel=Názov zariadenia
+hub.register.occupiedMsg=Názov už existuje
+hub.register.registerBtn=Potvrdiť
+### Registration Success
+hub.registerSuccess.message=Pomenovanie zariadenia
+hub.registerSuccess.description=Sprístupniť trezor, Vaše zariadenie musí byť autorizované vlastníkom trezora.
+### Registration Failed
+hub.registerFailed.message=Pomenovanie zariadenia zlyhalo
+hub.registerFailed.description=Vznikla chyba počas pomenovávacieho procesu. Pre viac detailov, nazrite do aplikačného logu.
+### Unauthorized
+hub.unauthorized.message=Prístup zamietnutý
+hub.unauthorized.description=Vaše zaradenie zatiaľ ešte nebolo autorizované pre pristúp tohto trezora. Požiadajte majiteľa trezora o autorizovanie.
+### License Exceeded
+hub.licenseExceeded.message=Licencia prekročená
+hub.licenseExceeded.description=Cryptomator Hub má prístup pre viac užívateľov ako povoľuje licencia. Prosím kontaktujte svojho Hub administrátora pre aktualizovanie licencie alebo admina trezoru pre odstránenie užívateľov z trezorov.
+
# Lock
## Force
diff --git a/src/main/resources/i18n/strings_sr.properties b/src/main/resources/i18n/strings_sr.properties
index 346ace354..89cb48dbc 100644
--- a/src/main/resources/i18n/strings_sr.properties
+++ b/src/main/resources/i18n/strings_sr.properties
@@ -106,6 +106,15 @@ unlock.error.message=Sef nije moguće otključati
### Invalid Mount Point
unlock.error.invalidMountPoint.notExisting=Tačka vezivanja "%s" nije direktorijum, nije prazna ili ne postoji.
unlock.error.invalidMountPoint.existing=Tačka vezivanja "%s" već postoji ili je nadređeni direktorijum nepostojeći.
+## Hub
+### Waiting
+### Receive Key
+### Register Device
+### Registration Success
+### Registration Failed
+### Unauthorized
+### License Exceeded
+
# Lock
## Force
diff --git a/src/main/resources/i18n/strings_sr_Latn.properties b/src/main/resources/i18n/strings_sr_Latn.properties
index 1d775d4c6..e0aae541f 100644
--- a/src/main/resources/i18n/strings_sr_Latn.properties
+++ b/src/main/resources/i18n/strings_sr_Latn.properties
@@ -98,6 +98,15 @@ unlock.success.revealBtn=Otvori disk
### Invalid Mount Point
unlock.error.invalidMountPoint.notExisting=Tačka vezivanja "%s" nije direktorijum, nije prazna ili ne postoji.
unlock.error.invalidMountPoint.existing=Tačka vezivanja "%s" već postoji ili je nadređeni direktorijum nepostojeći.
+## Hub
+### Waiting
+### Receive Key
+### Register Device
+### Registration Success
+### Registration Failed
+### Unauthorized
+### License Exceeded
+
# Lock
## Force
diff --git a/src/main/resources/i18n/strings_sv.properties b/src/main/resources/i18n/strings_sv.properties
index 4022678c1..ce827c492 100644
--- a/src/main/resources/i18n/strings_sv.properties
+++ b/src/main/resources/i18n/strings_sv.properties
@@ -128,6 +128,33 @@ unlock.error.message=Kan inte låsa upp valvet
unlock.error.invalidMountPoint.notExisting=Monteringspunkten "%s" saknas eller är inte tom.
unlock.error.invalidMountPoint.existing=Monteringspunkten "%s" finns redan eller så saknas överordnad mapp.
unlock.error.invalidMountPoint.driveLetterOccupied=Enhetsbokstav "%s" används redan.
+## Hub
+### Waiting
+hub.auth.message=Väntar på autentisering…
+hub.auth.description=Du bör automatiskt omdirigeras till inloggningssidan.
+hub.auth.loginLink=Inte omdirigerad? Klicka här för att öppna den.
+### Receive Key
+hub.receive.message=Bearbetar svar…
+hub.receive.description=Cryptomator tar emot och bearbetar svaret från Hub. Vänligen vänta.
+### Register Device
+hub.register.message=Enhetens namn krävs
+hub.register.description=Detta verkar vara den första Hub-åtkomsten från den här enheten. För att identifiera den för åtkomstbehörighet, måste du namnge den här enheten.
+hub.register.nameLabel=Enhetsnamn
+hub.register.occupiedMsg=Namnet används redan
+hub.register.registerBtn=Bekräfta
+### Registration Success
+hub.registerSuccess.message=Enhet namngiven
+hub.registerSuccess.description=För att komma åt valvet måste din enhet godkännas av valvägaren.
+### Registration Failed
+hub.registerFailed.message=Namngivning av enhet misslyckades
+hub.registerFailed.description=Ett fel uppstod i namngivningsprocessen. För mer information, titta i programloggen.
+### Unauthorized
+hub.unauthorized.message=Åtkomst nekad
+hub.unauthorized.description=Din enhet har ännu inte behörighet att komma åt detta valv. Be valvägaren att godkänna det.
+### License Exceeded
+hub.licenseExceeded.message=Licensen överskriden
+hub.licenseExceeded.description=Cryptomator Hub har gett tillgång till fler användare än licensen medger. Kontakta din Hub-administratör för att uppgradera licensen eller en valvadministratör för att minska antalet användare i valv.
+
# Lock
## Force
diff --git a/src/main/resources/i18n/strings_sw.properties b/src/main/resources/i18n/strings_sw.properties
index 52d8facbe..ecdd7ca51 100644
--- a/src/main/resources/i18n/strings_sw.properties
+++ b/src/main/resources/i18n/strings_sw.properties
@@ -53,6 +53,12 @@ addvaultwizard.new.fileAlreadyExists=Faili au saraka iliyo na jina la kuba tayar
addvaultwizard.new.locationDoesNotExist=Faili au saraka iliyo na jina la kuba tayari ipo
addvaultwizard.new.locationIsNotWritable=Hakuna ufikivu wa kuandika katika njia iliyobainishwa
addvaultwizard.new.locationIsOk=Mahali panapofaa kwa kuba yako
+addvaultwizard.new.invalidName=Jina batili la kuba
+addvaultwizard.new.validName=Jina halali la kuba
+addvaultwizard.new.validCharacters.message=Jina la kuhifadhi linaweza kuwa na herufi zifuatazo:
+addvaultwizard.new.validCharacters.chars=Vibambo vya maneno (k.m. a, ж au 수)
+addvaultwizard.new.validCharacters.numbers=Namba
+addvaultwizard.new.validCharacters.dashes=Kistariungio (%s) au kistari (%s)
### Password
addvaultwizard.new.createVaultBtn=Unda Kuba
addvaultwizard.new.generateRecoveryKeyChoice=Hutaweza kufikia data yako bila neno la siri lako. Unataka ufunguo wa kurejesha kwa kesi unayopoteza neno lako la siri?
@@ -86,6 +92,7 @@ addvaultwizard.success.unlockNow=Fungua Sasa
# Remove Vault
removeVault.title=Ondoa Kuba
+removeVault.message=Ungependa kuondoa kuba?
removeVault.description=Hii itafanya tu Cryptomator kusahau kuhusu kuba hii. Unaweza kuiongeza tena baadaye. Hakuna faili zilizosimbwa kwa njia fiche zitafutwa kutoka kwenye diski yako kuu.
removeVault.confirmBtn=Ondoa Kuba
@@ -96,6 +103,7 @@ changepassword.finalConfirmation=Ninaelewa kuwa sitaweza kufikia data yangu ikiw
# Forget Password
forgetPassword.title=Sahau Neno la siri
+forgetPassword.message=Je, umesahau neno la siri lililohifadhiwa?
forgetPassword.description=Hii itafuta neno la siri iliyohifadhiwa ya kuba hii kutoka kwa kitufe cha mfumo wako.
forgetPassword.confirmBtn=Sahau Neno la siri
@@ -105,10 +113,12 @@ unlock.passwordPrompt=Weka neno la siri ya "%s":
unlock.savePassword=Kumbuka neno la siri
unlock.unlockBtn=Fungua
## Select
+unlock.chooseMasterkey.message=Faili la ufunguo mkuu haijapatikana
unlock.chooseMasterkey.description=Haikuweza kupata faili kuu ya kuba hii katika mahali pake palipotarajiwa. Tafadhali chagua faili muhimu kwa mikono.
unlock.chooseMasterkey.filePickerTitle=Teua Faili ya Masterkey
unlock.chooseMasterkey.filePickerMimeDesc=Ufunguo mkuu wan Cryptomator
## Success
+unlock.success.message=Kufungua kumefaulu
unlock.success.description=Imefunguliwa "%s" kwa mafanikio! Kuba yako sasa inapatikana kupitia kiendeshi chake cha kawaida.
unlock.success.rememberChoice=Kumbuka chaguo, usionyeshe hii tena
unlock.success.revealBtn=Fichua Kiendeshaji
@@ -118,6 +128,33 @@ unlock.error.message=Haiwezi kufungua kuba
unlock.error.invalidMountPoint.notExisting=Sehemu ya mlima "%s" sio saraka, sio tupu au haipo.
unlock.error.invalidMountPoint.existing=Sehemu ya mlima "%s" tayari ipo au folda kuu haipo.
unlock.error.invalidMountPoint.driveLetterOccupied=Barua ya Hifadhi "%s" tayari inatumika.
+## Hub
+### Waiting
+hub.auth.message=Inasubiri uthibitishaji…
+hub.auth.description=Unapaswa kuelekezwa upya kiotomatiki kwa ukurasa wa kuingia.
+hub.auth.loginLink=Je, haijaelekezwa kwingine? Bofya hapa ili kuifungua.
+### Receive Key
+hub.receive.message=Inachakata jibu…
+hub.receive.description=Cryptomator inapokea na kuchakata jibu kutoka kwenye Kitovu. Tafadhali subiri.
+### Register Device
+hub.register.message=Jina la kifaa linahitajika
+hub.register.description=Hii inaonekana kuwa ufikiaji wa kwanza wa Hub kutoka kwa kifaa hiki. Ili kukitambua kwa uidhinishaji wa ufikiaji, unahitaji kukipa kifaa hiki jina.
+hub.register.nameLabel=Jina la Kifaa
+hub.register.occupiedMsg=Jina tayari linatumika
+hub.register.registerBtn=Thibitisha
+### Registration Success
+hub.registerSuccess.message=Kifaa kimepewa jina
+hub.registerSuccess.description=Ili kufikia kuba, kifaa chako kinahitaji kuidhinishwa na mmiliki wa kuba.
+### Registration Failed
+hub.registerFailed.message=Imeshindwa kutaja kifaa
+hub.registerFailed.description=Hitilafu imetupwa katika mchakato wa kumtaja. Kwa maelezo zaidi, angalia katika logi ya maombi.
+### Unauthorized
+hub.unauthorized.message=Ufikiaji umekataliwa
+hub.unauthorized.description=Kifaa chako bado hakijaidhinishwa kufikia kuba hii. Uliza mwenye kuba aidhinishe.
+### License Exceeded
+hub.licenseExceeded.message=Leseni imepitwa
+hub.licenseExceeded.description=Cryptomator Hub imetoa ufikiaji kwa watumiaji zaidi ya vibali vyake vya leseni. Tafadhali wasiliana na msimamizi wako wa Hub ili kuboresha leseni au msimamizi wa kuba ili kuondoa watumiaji kwenye kuba.
+
# Lock
## Force
@@ -192,11 +229,13 @@ preferences.title=Mapendeleo
## General
preferences.general=Jumla
preferences.general.startHidden=Ficha dirisha wakati wa kuanza Cryptomator
+preferences.general.autoCloseVaults=Funga kuba kiotomatiki wakati wa kuacha programu
preferences.general.debugLogging=Wezesha utatuzi wa ufunguaji
preferences.general.debugDirectory=Fichua faili za logi
preferences.general.autoStart=Zindua Cryptomator kwenye kuanza kwa mfumo
preferences.general.keychainBackend=Hifadhi neno la siri na
## Interface
+preferences.interface=Kiolesura
preferences.interface.theme=Angalia & Jisikie
preferences.interface.theme.automatic=Otomatiki
preferences.interface.theme.dark=Giza
@@ -336,9 +375,11 @@ vaultOptions.general.actionAfterUnlock.ask=Uliza
vaultOptions.general.startHealthCheckBtn=Anza Ukaguzi wa Afya
## Mount
+vaultOptions.mount=Kuweka
vaultOptions.mount.readonly=Soma-Tu
vaultOptions.mount.customMountFlags=Vipepea Vya Mlima Maalum
vaultOptions.mount.winDriveLetterOccupied=ulichukua
+vaultOptions.mount.mountPoint=Pointi ya kuweka
vaultOptions.mount.mountPoint.auto=Chagua otomatiki mahali panapofaa
vaultOptions.mount.mountPoint.driveLetter=Tumia barua kiendeshi kilichopangiwa
vaultOptions.mount.mountPoint.custom=Kijia maalum
@@ -350,20 +391,27 @@ vaultOptions.masterkey.changePasswordBtn=Badilisha Neno la siri
vaultOptions.masterkey.forgetSavedPasswordBtn=Kusahau Neno la siri Iliyohifadhiwa
vaultOptions.masterkey.recoveryKeyExplanation=Ufunguo wa kurejesha ni njia yako pekee ya kurejesha ufikiaji wa kuba ikiwa utapoteza nenosiri lako.
vaultOptions.masterkey.showRecoveryKeyBtn=Onyesha Ufunguo wa Ufufuzi
+vaultOptions.masterkey.recoverPasswordBtn=Fufua Neno la siri
# Recovery Key
## Display Recovery Key
+recoveryKey.display.title=Onyesha Ufunguo wa Kufufua
+recoveryKey.create.message=Nenosiri linahitajika
recoveryKey.create.description=Ingiza neno la siri lako ili kuonyesha ufunguo wa kurejesha kwa "%s":
recoveryKey.display.description=Ufunguo ufuatao wa kurejesha unaweza kutumika kurejesha ufikiaji wa "%s":
recoveryKey.display.StorageHints=Weka mahali salama sana, kwa mfano:\n • Hifadhi kwa kutumia msimamizi wa nywila\n • Hifadhi kwenye kiendeshi cha USB flash\n • Chapisha kwenye karatasi
## Reset Password
### Enter Recovery Key
+recoveryKey.recover.title=Fufua Neno la siri
recoveryKey.recover.prompt=Ingiza ufunguo wako wa kurejesha kwa "%s":
recoveryKey.recover.validKey=Hii ni ufunguo halali wa kurejesha
recoveryKey.printout.heading=Ufunguo wa Urejeshaji wa Cryptomator\n"%s"\n
### Reset Password
+recoveryKey.recover.resetBtn=Weka upya
### Recovery Key Password Reset Success
+recoveryKey.recover.resetSuccess.message=Kuweka upya nenosiri kumefaulu
+recoveryKey.recover.resetSuccess.description=Unaweza kufungua chumba chako kwa kutumia neno la siri jipya.
# New Password
newPassword.promptText=Ingiza neno jipya la siri
@@ -378,6 +426,12 @@ passwordStrength.messageLabel.3=Imara
passwordStrength.messageLabel.4=Imara sana
# Quit
+quit.title=Acha Maombi
+quit.message=Kuna kuba zilizofunguliwa
+quit.description=Tafadhali thibitisha kuwa unataka kuacha. Cryptomator itafunga kwa uzuri vyumba vyote vilivyofunguliwa ili kuzuia upotezaji wa data.
quit.lockAndQuitBtn=Funga na Acha
-# Forced Quit
\ No newline at end of file
+# Forced Quit
+quit.forced.message=Baadhi ya kuba hazikuweza kufungwa
+quit.forced.description=Kufunga kuba kulizuiwa na shughuli zinazosubiri au kufungua faili. Unaweza kulazimisha kufunga vyumba vilivyosalia, hata hivyo kukatiza I/O kunaweza kusababisha upotevu wa data ambayo haijahifadhiwa.
+quit.forced.forceAndQuitBtn=Lazimisha na Uache
\ No newline at end of file
diff --git a/src/main/resources/i18n/strings_ta.properties b/src/main/resources/i18n/strings_ta.properties
index ebf983d59..b594e0df4 100644
--- a/src/main/resources/i18n/strings_ta.properties
+++ b/src/main/resources/i18n/strings_ta.properties
@@ -122,6 +122,15 @@ unlock.error.message=பெட்டகத்தைத் திறக்க ம
unlock.error.invalidMountPoint.notExisting=ஏற்றப் புள்ளி "%s" என்பது ஒரு கோப்பகம் அல்ல, காலியாக இல்லை அல்லது இல்லை.
unlock.error.invalidMountPoint.existing=ஏற்றப் புள்ளி "%s" ஏற்கனவே உள்ளது அல்லது பெற்றோர் கோப்புறை இல்லை.
unlock.error.invalidMountPoint.driveLetterOccupied=இயக்கி எழுத்து "%s" ஏற்கனவே பயன்பாட்டில் உள்ளது.
+## Hub
+### Waiting
+### Receive Key
+### Register Device
+### Registration Success
+### Registration Failed
+### Unauthorized
+### License Exceeded
+
# Lock
## Force
diff --git a/src/main/resources/i18n/strings_te.properties b/src/main/resources/i18n/strings_te.properties
index b51f7dd26..98bb54590 100644
--- a/src/main/resources/i18n/strings_te.properties
+++ b/src/main/resources/i18n/strings_te.properties
@@ -30,6 +30,15 @@
## Success
## Failure
### Invalid Mount Point
+## Hub
+### Waiting
+### Receive Key
+### Register Device
+### Registration Success
+### Registration Failed
+### Unauthorized
+### License Exceeded
+
# Lock
## Force
diff --git a/src/main/resources/i18n/strings_th.properties b/src/main/resources/i18n/strings_th.properties
index 42b0bc4c2..62c8f2bd2 100644
--- a/src/main/resources/i18n/strings_th.properties
+++ b/src/main/resources/i18n/strings_th.properties
@@ -89,6 +89,15 @@ unlock.unlockBtn=ปลดล็อก
## Success
## Failure
### Invalid Mount Point
+## Hub
+### Waiting
+### Receive Key
+### Register Device
+### Registration Success
+### Registration Failed
+### Unauthorized
+### License Exceeded
+
# Lock
## Force
diff --git a/src/main/resources/i18n/strings_tr.properties b/src/main/resources/i18n/strings_tr.properties
index 7446c85ce..e8dbab2a1 100644
--- a/src/main/resources/i18n/strings_tr.properties
+++ b/src/main/resources/i18n/strings_tr.properties
@@ -128,6 +128,33 @@ unlock.error.message=Kasanın kilidi açılamıyor
unlock.error.invalidMountPoint.notExisting=Bağlantı noktası boş bir dizin değil veya mevcut değil: %s
unlock.error.invalidMountPoint.existing=Bağlama noktası / klasör zaten var veya ana klasör eksik: %s
unlock.error.invalidMountPoint.driveLetterOccupied="%s" sürücü adı zaten kullanılıyor.
+## Hub
+### Waiting
+hub.auth.message=Kimlik doğrulaması için bekleniyor…
+hub.auth.description=Otomatik olarak giriş sayfasına yönlendirilmelisiniz.
+hub.auth.loginLink=Yönlendirilmedi mi? Açmak için buraya tıklayın.
+### Receive Key
+hub.receive.message=Yanıt işleniyor…
+hub.receive.description=Cryptomator, Hub'dan yanıtı alıyor ve işliyor. Lütfen bekleyin.
+### Register Device
+hub.register.message=Cihaz adı gerekli
+hub.register.description=Bu cihazdan ilk Hub erişimi gibi görünüyor. Erişim yetkilendirmesini tanımlamak için bu cihazı isimlendirmeniz gerekir.
+hub.register.nameLabel=Cihaz adı
+hub.register.occupiedMsg=Ad zaten kullanımda
+hub.register.registerBtn=Onayla
+### Registration Success
+hub.registerSuccess.message=Cihaz isimlendirildi
+hub.registerSuccess.description=Kasaya erişmek için cihazınızın kasa sahibi tarafından yetkilendirilmesi gerekir.
+### Registration Failed
+hub.registerFailed.message=Cihaz isimlendirilmesi başarısız
+hub.registerFailed.description=İsimlendirme işleminde bir hata oluştu. Daha fazla bilgi için uygulama günlüğüne bakın.
+### Unauthorized
+hub.unauthorized.message=Erişim engellendi
+hub.unauthorized.description=Cihazınıza henüz bu kasaya erişim yetkisi verilmedi. Kasa sahibinden yetkilendirmesini isteyin.
+### License Exceeded
+hub.licenseExceeded.message=Lisans aşıldı
+hub.licenseExceeded.description=Cryptomator Hub, lisansının izin verdiğinden daha fazla kullanıcıya erişim sağladı. Lisansı yükseltmek için lütfen Hub yöneticinizle veya kullanıcıları kasalardan kaldırmak için bir kasa yöneticisiyle iletişime geçin.
+
# Lock
## Force
diff --git a/src/main/resources/i18n/strings_uk.properties b/src/main/resources/i18n/strings_uk.properties
index abf443e2c..23cddd234 100644
--- a/src/main/resources/i18n/strings_uk.properties
+++ b/src/main/resources/i18n/strings_uk.properties
@@ -84,6 +84,16 @@ unlock.unlockBtn=Розблокувати
## Success
## Failure
### Invalid Mount Point
+## Hub
+### Waiting
+### Receive Key
+### Register Device
+hub.register.registerBtn=Підтвердити
+### Registration Success
+### Registration Failed
+### Unauthorized
+### License Exceeded
+
# Lock
## Force
diff --git a/src/main/resources/i18n/strings_vi.properties b/src/main/resources/i18n/strings_vi.properties
index 4b4938288..856b85463 100644
--- a/src/main/resources/i18n/strings_vi.properties
+++ b/src/main/resources/i18n/strings_vi.properties
@@ -53,6 +53,12 @@ addvaultwizard.new.fileAlreadyExists=Tệp hoặc thư mục có tên vault đã
addvaultwizard.new.locationDoesNotExist=Thư mục trong đường dẫn được chỉ định không tồn tại hoặc không thể truy cập
addvaultwizard.new.locationIsNotWritable=Không có quyền ghi tại đường dẫn được chỉ định
addvaultwizard.new.locationIsOk=Vị trí thích hợp cho vault của bạn
+addvaultwizard.new.invalidName=Tên vault không hợp lệ
+addvaultwizard.new.validName=Tên vault hợp lệ
+addvaultwizard.new.validCharacters.message=Tên vault có thể chứa những kí tự sau:
+addvaultwizard.new.validCharacters.chars=Các ký tự trong từ (ví dụ: a, ж hoặc 수)
+addvaultwizard.new.validCharacters.numbers=Số
+addvaultwizard.new.validCharacters.dashes=Dấu gạch ngang (%s) hoặc dấu gạch dưới (%s)
### Password
addvaultwizard.new.createVaultBtn=Tạo Vault
addvaultwizard.new.generateRecoveryKeyChoice=Bạn sẽ không thể truy cập dữ liệu của mình nếu không có mật khẩu. Bạn có muốn có khóa khôi phục cho trường hợp mất mật khẩu không?
@@ -107,6 +113,27 @@ unlock.success.revealBtn=Hiển thị Drive
## Failure
unlock.error.message=Không thể mở vault
### Invalid Mount Point
+## Hub
+### Waiting
+hub.auth.message=Đang chờ xác thực…
+hub.auth.description=Bạn sẽ tự động được chuyển hướng đến trang đăng nhập.
+hub.auth.loginLink=Chưa được chuyển hướng? Nhấn vào đây để mở.
+### Receive Key
+hub.receive.message=Đang xử lý phản hồi…
+hub.receive.description=Cryptomator đang nhận và xử lý phản hồi từ Hub. Vui lòng chờ.
+### Register Device
+hub.register.message=Tên thiết bị bắt buộc
+hub.register.nameLabel=Tên thiết bị
+hub.register.occupiedMsg=Tên đã sử dụng
+hub.register.registerBtn=Xác nhận
+### Registration Success
+hub.registerSuccess.description=Để truy cập vault, thiết bị của bạn cần được chủ sở hữu cho phép.
+### Registration Failed
+### Unauthorized
+hub.unauthorized.message=Truy cập bị từ chối
+hub.unauthorized.description=Thiết bị của bạn chưa được phép truy cập vault này. Yêu cầu chủ sở hữu cấp phép.
+### License Exceeded
+
# Lock
## Force
@@ -143,6 +170,7 @@ health.intro.remarkBackup=Nếu dữ liệu bị hỏng, chỉ có bản sao lư
health.intro.affirmation=Tôi đã đọc và hiểu thông tin trên
## Start Failure
health.fail.ioError=Đã xảy ra lỗi khi truy cập và đọc tệp config.
+health.fail.moreInfo=Thêm thông tin
## Check Selection
## Detail view
health.check.exportBtn=Xuất Báo Cáo
@@ -282,6 +310,7 @@ recoveryKey.recover.title=Đặt lại Mật khẩu
recoveryKey.recover.validKey=Đây là khóa khôi phục hợp lệ
recoveryKey.printout.heading=Khóa Khôi phục Cryptomator\n"%s"\n
### Reset Password
+recoveryKey.recover.resetBtn=Đặt lại
### Recovery Key Password Reset Success
recoveryKey.recover.resetSuccess.message=Đặt lại mật khẩu thành công
recoveryKey.recover.resetSuccess.description=Bạn có thể mở khóa vault với mật khẩu mới.
diff --git a/src/main/resources/i18n/strings_zh.properties b/src/main/resources/i18n/strings_zh.properties
index eef4153f5..ef2008900 100644
--- a/src/main/resources/i18n/strings_zh.properties
+++ b/src/main/resources/i18n/strings_zh.properties
@@ -128,6 +128,33 @@ unlock.error.message=无法解锁保险库
unlock.error.invalidMountPoint.notExisting=挂载点 "%s" 不是目录、非空或不存在
unlock.error.invalidMountPoint.existing=挂载点 "%s" 已存在或缺少父文件夹
unlock.error.invalidMountPoint.driveLetterOccupied=驱动器号 %s 已被占用。
+## Hub
+### Waiting
+hub.auth.message=正在等待认证…
+hub.auth.description=您应该会被自动重定向到登录页面
+hub.auth.loginLink=未重定向?点此打开
+### Receive Key
+hub.receive.message=正在处理响应…
+hub.receive.description=Cryptomator 正在接收和处理来自 Hub 的响应,请稍等
+### Register Device
+hub.register.message=设备名称(必填)
+hub.register.description=这似乎是设备的首次 Hub 访问。为了识别它以进行访问授权,您需要命名此设备
+hub.register.nameLabel=设备名称
+hub.register.occupiedMsg=名称已被占用
+hub.register.registerBtn=确认
+### Registration Success
+hub.registerSuccess.message=设备命名成功
+hub.registerSuccess.description=要访问保险库,设备需得到保险库所有者的授权
+### Registration Failed
+hub.registerFailed.message=设备命名失败
+hub.registerFailed.description=命名过程中出现错误,详情请查看应用程序日志
+### Unauthorized
+hub.unauthorized.message=拒绝访问
+hub.unauthorized.description=您的设备尚未授权访问此保险库,请联系保险库所有者
+### License Exceeded
+hub.licenseExceeded.message=许可证已逾期
+hub.licenseExceeded.description=Cryptomator Hub 允许访问的用户数量超过其许可证允许的数量,请联系您的 Hub 管理员升级许可证或联系保险库管理员删除用户
+
# Lock
## Force
diff --git a/src/main/resources/i18n/strings_zh_HK.properties b/src/main/resources/i18n/strings_zh_HK.properties
index dddc451ec..e2bff681a 100644
--- a/src/main/resources/i18n/strings_zh_HK.properties
+++ b/src/main/resources/i18n/strings_zh_HK.properties
@@ -118,6 +118,16 @@ unlock.error.message=無法解鎖加密庫
unlock.error.invalidMountPoint.notExisting=掛載點「%s」不是空資料夾或是不存在。
unlock.error.invalidMountPoint.existing=掛載點「%s」已經存在或其上層資料夾不存在。
unlock.error.invalidMountPoint.driveLetterOccupied=磁碟代號「%s」已被使用。
+## Hub
+### Waiting
+### Receive Key
+### Register Device
+hub.register.registerBtn=確認
+### Registration Success
+### Registration Failed
+### Unauthorized
+### License Exceeded
+
# Lock
## Force
diff --git a/src/main/resources/i18n/strings_zh_TW.properties b/src/main/resources/i18n/strings_zh_TW.properties
index 15c6fbc04..e519d868a 100644
--- a/src/main/resources/i18n/strings_zh_TW.properties
+++ b/src/main/resources/i18n/strings_zh_TW.properties
@@ -18,7 +18,7 @@ generic.button.print=列印
error.message=錯誤:%s
error.description=糟糕!Cryptomator 發生了預期外的錯誤。您可以嘗試查找該錯誤的現有解決方案,如果是新錯誤,請隨時向我們報告。
error.hyperlink.lookup=查找該錯誤
-error.hyperlink.report=報告這個錯誤
+error.hyperlink.report=回報錯誤
error.technicalDetails=詳情:
# Defaults
@@ -53,11 +53,17 @@ addvaultwizard.new.fileAlreadyExists=存在與加密檔案庫同名的檔案或
addvaultwizard.new.locationDoesNotExist=指定的目錄不存在或無法存取
addvaultwizard.new.locationIsNotWritable=指定路徑沒有寫入權限
addvaultwizard.new.locationIsOk=可放置您的加密檔案庫
+addvaultwizard.new.invalidName=無效的檔案庫名稱
+addvaultwizard.new.validName=有效的檔案庫名稱
+addvaultwizard.new.validCharacters.message=檔案庫名稱可包含以下字元:
+addvaultwizard.new.validCharacters.chars=單詞字符 (例如 a、ж 或 수)
+addvaultwizard.new.validCharacters.numbers=數字
+addvaultwizard.new.validCharacters.dashes=連字符 (%s) 或下劃線 (%s)
### Password
addvaultwizard.new.createVaultBtn=新建加密檔案庫
addvaultwizard.new.generateRecoveryKeyChoice=若您遺失密碼將無法存取您的資料。您是否希望建立一組在您遺失密碼時可供復原的金鑰?
addvaultwizard.new.generateRecoveryKeyChoice.yes=是,做好安全措施,以免後悔莫及。
-addvaultwizard.new.generateRecoveryKeyChoice.no=否,不用了,我不會弄丟密碼。
+addvaultwizard.new.generateRecoveryKeyChoice.no=否,不用,我不會丟失密碼
### Information
addvault.new.readme.storageLocation.fileName=重要.rtf
addvault.new.readme.storageLocation.1=⚠️ 加密檔案庫的檔案 ⚠️
@@ -79,13 +85,14 @@ addvault.new.readme.accessLocation.4=您可以放心移除這個檔案。
addvaultwizard.existing.instruction=請選擇現有加密檔案庫中名為「vault.cryptomator」的檔案。如果只有一個名為「masterkey.cryptomator」的檔案,則選擇該檔案。
addvaultwizard.existing.chooseBtn=選取…
addvaultwizard.existing.filePickerTitle=選取加密檔案庫的檔案
-addvaultwizard.existing.filePickerMimeDesc=Cryptomator 加密檔案庫
+addvaultwizard.existing.filePickerMimeDesc=Cryptomator 加密庫
## Success
addvaultwizard.success.nextStepsInstructions=已加入加密檔案庫「%s」。您需要將這個加密檔案庫解鎖以存取內容,或是您也可以之後再解鎖。
addvaultwizard.success.unlockNow=立即解鎖
# Remove Vault
removeVault.title=移除加密檔案庫
+removeVault.message=刪除檔案庫?
removeVault.description=這將會讓 Cryptomator 忘記這個加密檔案庫。您未來可以再重新加入。已加密的檔案將不會從您的硬碟中移除。
removeVault.confirmBtn=移除加密檔案庫
@@ -96,6 +103,7 @@ changepassword.finalConfirmation=我明白如果忘記密碼將無法存取資
# Forget Password
forgetPassword.title=忘記密碼
+forgetPassword.message=清除已存密碼?
forgetPassword.description=這將會從系統鑰匙圈中移除這個加密檔案庫已存的密碼。
forgetPassword.confirmBtn=忘記密碼
@@ -105,10 +113,12 @@ unlock.passwordPrompt=輸入「%s」的密碼:
unlock.savePassword=記住密碼
unlock.unlockBtn=解鎖
## Select
+unlock.chooseMasterkey.message=未找到Masterkey檔案
unlock.chooseMasterkey.description=無法在其預期位置找到此加密檔案庫的主密鑰檔案。請手動選擇密鑰文件。
unlock.chooseMasterkey.filePickerTitle=選擇主金鑰檔案
unlock.chooseMasterkey.filePickerMimeDesc=Cryptomator 主密鑰
## Success
+unlock.success.message=解鎖成功
unlock.success.description=成功解鎖「%s」!您現在可以存取您的加密檔案庫。
unlock.success.rememberChoice=記得這個決定,不要再顯示
unlock.success.revealBtn=顯示磁碟
@@ -118,6 +128,33 @@ unlock.error.message=無法解鎖加密檔案庫
unlock.error.invalidMountPoint.notExisting=掛載點不是空資料夾或是不存在:%s
unlock.error.invalidMountPoint.existing=掛載點已經存在或上層資料夾不存在:%s
unlock.error.invalidMountPoint.driveLetterOccupied=磁碟代號 "%s" 已被使用
+## Hub
+### Waiting
+hub.auth.message=等待認證中…
+hub.auth.description=您將自動傳送到登入頁面。
+hub.auth.loginLink=未轉送?點擊這裡打開
+### Receive Key
+hub.receive.message=處理著回應…
+hub.receive.description=Cryptomator正在接收並處理來自Hub的回應。 請等待。
+### Register Device
+hub.register.message=需要設備名稱
+hub.register.description=似乎這是第一次Hub訪問此設備。為了識別它以授權讀取,您需要命名此設備。
+hub.register.nameLabel=設備名稱
+hub.register.occupiedMsg=名稱已被使用
+hub.register.registerBtn=確認
+### Registration Success
+hub.registerSuccess.message=設備命名成功
+hub.registerSuccess.description=想讀取檔案庫,你的設備需得到檔案庫擁有者的授權。
+### Registration Failed
+hub.registerFailed.message=設備命名失敗
+hub.registerFailed.description=命名過程中出現錯誤。更多詳情,請檢查應用程式記錄。
+### Unauthorized
+hub.unauthorized.message=拒絕存取
+hub.unauthorized.description=您的設備權限尚未允許存取檔案庫,請聯絡檔案庫擁有者
+### License Exceeded
+hub.licenseExceeded.message=软件許可已滿額
+hub.licenseExceeded.description=Cryptomator Hub已授權的使用者已超過軟件許可的數量。請聯絡您的Hub管理員升級許可證或聯絡檔案庫管理員移除用戶。
+
# Lock
## Force
@@ -169,7 +206,7 @@ health.fail.parseError=分析設定文件時發生錯誤。
health.fail.moreInfo=更多資訊
## Check Selection
health.checkList.description=在左側列表中選擇檢查或使用下面的按鈕。
-health.checkList.selectAllButton=選擇所有檢查
+health.checkList.selectAllButton=選擇所有選項
health.checkList.deselectAllButton=取消所有檢查
health.check.runBatchBtn=執行選定的檢查
## Detail view
@@ -192,6 +229,7 @@ preferences.title=偏好
## General
preferences.general=一般
preferences.general.startHidden=啟動 Cryptomator 時隱藏視窗
+preferences.general.autoCloseVaults=結束程式自動鎖定啟用中的檔案庫
preferences.general.debugLogging=啟用除錯日誌
preferences.general.debugDirectory=顯示日誌檔
preferences.general.autoStart=系統啟動時同時啟動 Cryptomator
@@ -353,20 +391,27 @@ vaultOptions.masterkey.changePasswordBtn=變更密碼
vaultOptions.masterkey.forgetSavedPasswordBtn=清除已存密碼
vaultOptions.masterkey.recoveryKeyExplanation=在您遺失密碼時,僅能以復原金鑰恢復存取。
vaultOptions.masterkey.showRecoveryKeyBtn=顯示復原金鑰
+vaultOptions.masterkey.recoverPasswordBtn=重設密碼
# Recovery Key
## Display Recovery Key
+recoveryKey.display.title=顯示恢復金鑰
+recoveryKey.create.message=需要密碼
recoveryKey.create.description=請輸入您的密碼以顯示 "%s" 的復原金鑰:
recoveryKey.display.description=下方的復原金鑰可用來恢復 "%s" 的存取能力:
recoveryKey.display.StorageHints=請把它保存在非常安全的地方,例如:\n • 使用密碼管理器保管\n • 存在 USB 隨身碟裡\n • 印在紙上
## Reset Password
### Enter Recovery Key
+recoveryKey.recover.title=重設密碼
recoveryKey.recover.prompt=輸入 "%s" 的復原金鑰:
recoveryKey.recover.validKey=這是有效的復原金鑰
recoveryKey.printout.heading=Cryptomator 復原金鑰\n"%s"\n
### Reset Password
+recoveryKey.recover.resetBtn=重設
### Recovery Key Password Reset Success
+recoveryKey.recover.resetSuccess.message=密碼重設完成
+recoveryKey.recover.resetSuccess.description=您可以用新設的密碼解鎖檔案庫
# New Password
newPassword.promptText=輸入新密碼
@@ -381,6 +426,12 @@ passwordStrength.messageLabel.3=強
passwordStrength.messageLabel.4=非常強
# Quit
+quit.title=結束應用程式
+quit.message=仍有已啟用的檔案庫
+quit.description=請確認結束動作。Cryptomator將會鎖定所有已開啟的檔案庫以防止資料流失。
quit.lockAndQuitBtn=鎖定並離開
-# Forced Quit
\ No newline at end of file
+# Forced Quit
+quit.forced.message=某些檔案庫無法鎖定
+quit.forced.description=仍有未完成的作業或開啟中的檔案以致無法鎖定。您可以強制鎖定這個檔案庫,不過中斷讀寫可能會導致資料遺失或未被儲存。
+quit.forced.forceAndQuitBtn=強制並結束
\ No newline at end of file
diff --git a/src/test/java/org/cryptomator/common/EnvironmentTest.java b/src/test/java/org/cryptomator/common/EnvironmentTest.java
index a4c1179b7..9c048a200 100644
--- a/src/test/java/org/cryptomator/common/EnvironmentTest.java
+++ b/src/test/java/org/cryptomator/common/EnvironmentTest.java
@@ -21,7 +21,7 @@ public class EnvironmentTest {
@BeforeEach
public void init() {
- env = Mockito.spy(new Environment());
+ env = Mockito.spy(Environment.getInstance());
Mockito.when(env.getHomeDir()).thenReturn(Path.of("/home/testuser"));
}