mirror of
https://github.com/cryptomator/cryptomator.git
synced 2024-11-23 03:59:51 +00:00
Merge branch 'cryptomator:develop' into fix/linux-build
This commit is contained in:
commit
279db5ffd0
5
.github/workflows/release.yml
vendored
5
.github/workflows/release.yml
vendored
@ -97,7 +97,7 @@ jobs:
|
||||
echo "::set-output name=semVerNum::${SEM_VER_NUM}"
|
||||
echo "::set-output name=ppaVerStr::${SEM_VER_STR/-/\~}-${REVCOUNT}"
|
||||
echo "::set-output name=revNum::${REVCOUNT}"
|
||||
- uses: rubenesp87/semver-validation-action@0.0.6
|
||||
- uses: skymatic/semver-validation-action@v1
|
||||
with:
|
||||
version: ${{ steps.versions.outputs.semVerStr }}
|
||||
|
||||
@ -283,7 +283,7 @@ jobs:
|
||||
run: |
|
||||
mv appdir/Cryptomator Cryptomator.AppDir
|
||||
cp -r dist/linux/appimage/resources/AppDir/* Cryptomator.AppDir/
|
||||
envsubst '${REVISION_NO}' < dist/linux/appimage/resources/AppDir/bin/cryptomator.sh > Cryptomator.AppDir/bin/cryptomator.sh
|
||||
envsubst '${REVISION_NO} ${SEMVER_STR}' < dist/linux/appimage/resources/AppDir/bin/cryptomator.sh > Cryptomator.AppDir/bin/cryptomator.sh
|
||||
ln -s usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg Cryptomator.AppDir/org.cryptomator.Cryptomator.svg
|
||||
ln -s usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg Cryptomator.AppDir/Cryptomator.svg
|
||||
ln -s usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg Cryptomator.AppDir/.DirIcon
|
||||
@ -291,6 +291,7 @@ jobs:
|
||||
ln -s bin/cryptomator.sh Cryptomator.AppDir/AppRun
|
||||
env:
|
||||
REVISION_NO: ${{ needs.metadata.outputs.revNum }}
|
||||
SEMVER_STR: ${{ needs.metadata.outputs.semVerStr }}
|
||||
- name: Extract libjffi.so # workaround for https://github.com/cryptomator/cryptomator-linux/issues/27
|
||||
run: |
|
||||
JFFI_NATIVE_JAR=`ls lib/app/ | grep -e 'jffi-[1-9]\.[0-9]\{1,2\}.[0-9]\{1,2\}-native.jar'`
|
||||
|
@ -26,12 +26,15 @@ export LD_PRELOAD=lib/app/libjffi.so
|
||||
./lib/runtime/bin/java \
|
||||
-p "lib/app/mods" \
|
||||
-cp "lib/app/*" \
|
||||
-Dfile.encoding="utf-8" \
|
||||
-Dcryptomator.logDir="~/.local/share/Cryptomator/logs" \
|
||||
-Dcryptomator.pluginDir="~/.local/share/Cryptomator/plugins"
|
||||
-Dcryptomator.mountPointsDir="~/.local/share/Cryptomator/mnt" \
|
||||
-Dcryptomator.settingsPath="~/.config/Cryptomator/settings.json:~/.Cryptomator/settings.json" \
|
||||
-Dcryptomator.ipcSocketPath="~/.config/Cryptomator/ipc.socket" \
|
||||
-Dcryptomator.buildNumber="appimage-${REVISION_NO}" \
|
||||
-Dcryptomator.appVersion="${SEMVER_STR}" \
|
||||
$GTK_FLAG \
|
||||
-Xss2m \
|
||||
-Xmx512m \
|
||||
-Xss5m \
|
||||
-Xmx256m \
|
||||
-m org.cryptomator.desktop/org.cryptomator.launcher.Cryptomator
|
||||
|
42
pom.xml
42
pom.xml
@ -27,33 +27,41 @@
|
||||
<nonModularGroupIds>com.github.serceman,com.github.jnr,org.ow2.asm,net.java.dev.jna,org.apache.jackrabbit,org.apache.httpcomponents,de.swiesend,org.purejava,com.github.hypfvieh</nonModularGroupIds>
|
||||
|
||||
<!-- cryptomator dependencies -->
|
||||
<cryptomator.cryptofs.version>2.1.0-beta9</cryptomator.cryptofs.version>
|
||||
<cryptomator.integrations.version>1.0.0-rc1</cryptomator.integrations.version>
|
||||
<cryptomator.integrations.win.version>1.0.0-beta2</cryptomator.integrations.win.version>
|
||||
<cryptomator.integrations.mac.version>1.0.0-beta2</cryptomator.integrations.mac.version>
|
||||
<cryptomator.integrations.linux.version>1.0.0-beta1</cryptomator.integrations.linux.version>
|
||||
<cryptomator.fuse.version>1.3.1</cryptomator.fuse.version>
|
||||
<cryptomator.dokany.version>1.3.2</cryptomator.dokany.version>
|
||||
<cryptomator.cryptofs.version>2.1.0-beta13</cryptomator.cryptofs.version>
|
||||
<cryptomator.integrations.version>1.0.0</cryptomator.integrations.version>
|
||||
<cryptomator.integrations.win.version>1.0.0-rc1</cryptomator.integrations.win.version>
|
||||
<cryptomator.integrations.mac.version>1.0.0-rc1</cryptomator.integrations.mac.version>
|
||||
<cryptomator.integrations.linux.version>1.0.0-rc1</cryptomator.integrations.linux.version>
|
||||
<cryptomator.fuse.version>1.3.2</cryptomator.fuse.version>
|
||||
<cryptomator.dokany.version>1.3.3</cryptomator.dokany.version>
|
||||
<cryptomator.webdav.version>1.2.6</cryptomator.webdav.version>
|
||||
|
||||
<!-- 3rd party dependencies -->
|
||||
<javafx.version>16</javafx.version>
|
||||
<javafx.version>17.0.0.1</javafx.version>
|
||||
<commons-lang3.version>3.12.0</commons-lang3.version>
|
||||
<jwt.version>3.18.1</jwt.version>
|
||||
<jwt.version>3.18.2</jwt.version>
|
||||
<easybind.version>2.2</easybind.version>
|
||||
<guava.version>30.1.1-jre</guava.version>
|
||||
<dagger.version>2.37</dagger.version>
|
||||
<gson.version>2.8.7</gson.version>
|
||||
<guava.version>31.0-jre</guava.version>
|
||||
<dagger.version>2.38.1</dagger.version>
|
||||
<gson.version>2.8.8</gson.version>
|
||||
<zxcvbn.version>1.5.2</zxcvbn.version>
|
||||
<slf4j.version>1.7.31</slf4j.version>
|
||||
<logback.version>1.2.3</logback.version>
|
||||
<slf4j.version>1.7.32</slf4j.version>
|
||||
<logback.version>1.2.6</logback.version>
|
||||
|
||||
<!-- test dependencies -->
|
||||
<junit.jupiter.version>5.7.2</junit.jupiter.version>
|
||||
<mockito.version>3.11.2</mockito.version>
|
||||
<junit.jupiter.version>5.8.1</junit.jupiter.version>
|
||||
<mockito.version>3.12.4</mockito.version>
|
||||
<hamcrest.version>2.2</hamcrest.version>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>google-maven</id>
|
||||
<name>Google Maven Repo</name>
|
||||
<url>https://maven.google.com</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<!-- Cryptomator Libs -->
|
||||
<dependency>
|
||||
@ -263,7 +271,7 @@
|
||||
<plugin>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-maven</artifactId>
|
||||
<version>6.2.2</version>
|
||||
<version>6.3.1</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
|
@ -5,6 +5,7 @@ public interface Constants {
|
||||
String MASTERKEY_FILENAME = "masterkey.cryptomator";
|
||||
String MASTERKEY_BACKUP_SUFFIX = ".bkup";
|
||||
String VAULTCONFIG_FILENAME = "vault.cryptomator";
|
||||
String CRYPTOMATOR_FILENAME_EXT = ".cryptomator";
|
||||
byte[] PEPPER = new byte[0];
|
||||
|
||||
}
|
||||
|
121
src/main/java/org/cryptomator/common/ErrorCode.java
Normal file
121
src/main/java/org/cryptomator/common/ErrorCode.java
Normal file
@ -0,0 +1,121 @@
|
||||
package org.cryptomator.common;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.base.Throwables;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Holds a throwable and provides a human-readable {@link #toString() three-component string representation}
|
||||
* aiming to allow documentation and lookup of same or similar errors.
|
||||
*/
|
||||
public class ErrorCode {
|
||||
|
||||
private final static int A_PRIME = 31;
|
||||
private final static int SEED = 0xdeadbeef;
|
||||
public final static String DELIM = ":";
|
||||
|
||||
private final static int LATEST_FRAME = 1;
|
||||
private final static int ALL_FRAMES = Integer.MAX_VALUE;
|
||||
|
||||
private final Throwable throwable;
|
||||
private final Throwable rootCause;
|
||||
private final int rootCauseSpecificFrames;
|
||||
|
||||
private ErrorCode(Throwable throwable, Throwable rootCause, int rootCauseSpecificFrames) {
|
||||
this.throwable = Objects.requireNonNull(throwable);
|
||||
this.rootCause = Objects.requireNonNull(rootCause);
|
||||
this.rootCauseSpecificFrames = rootCauseSpecificFrames;
|
||||
}
|
||||
|
||||
// visible for testing
|
||||
String methodCode() {
|
||||
return format(traceCode(rootCause, LATEST_FRAME));
|
||||
}
|
||||
|
||||
// visible for testing
|
||||
String rootCauseCode() {
|
||||
return format(traceCode(rootCause, rootCauseSpecificFrames));
|
||||
}
|
||||
|
||||
// visible for testing
|
||||
String throwableCode() {
|
||||
return format(traceCode(throwable, ALL_FRAMES));
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces an error code consisting of three {@value DELIM}-separated components.
|
||||
* <p>
|
||||
* A full match of the error code indicates the exact same throwable (to the extent possible
|
||||
* without hash collisions). A partial match of the first or second component indicates related problems
|
||||
* with the same root cause.
|
||||
*
|
||||
* @return A three-part error code
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return methodCode() + DELIM + rootCauseCode() + DELIM + throwableCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deterministically creates an error code from the stack trace of the given <code>cause</code>.
|
||||
* <p>
|
||||
* The code consists of three parts separated by {@value DELIM}:
|
||||
* <ul>
|
||||
* <li>The first part depends on the root cause and the method that threw it</li>
|
||||
* <li>The second part depends on the root cause and its stack trace</li>
|
||||
* <li>The third part depends on all the cause hierarchy</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* Parts may be identical if the cause is the root cause or the root cause has just one single item in its stack trace.
|
||||
*
|
||||
* @param throwable The exception
|
||||
* @return A three-part error code
|
||||
*/
|
||||
public static ErrorCode of(Throwable throwable) {
|
||||
var causalChain = Throwables.getCausalChain(throwable);
|
||||
if (causalChain.size() > 1) {
|
||||
var rootCause = causalChain.get(causalChain.size() - 1);
|
||||
var parentOfRootCause = causalChain.get(causalChain.size() - 2);
|
||||
var rootSpecificFrames = nonOverlappingFrames(parentOfRootCause.getStackTrace(), rootCause.getStackTrace());
|
||||
return new ErrorCode(throwable, rootCause, rootSpecificFrames);
|
||||
} else {
|
||||
return new ErrorCode(throwable, throwable, ALL_FRAMES);
|
||||
}
|
||||
}
|
||||
|
||||
private String format(int value) {
|
||||
// Cut off highest 12 bits (only leave 20 least significant bits) and XOR rest with cutoff
|
||||
value = (value & 0xfffff) ^ (value >>> 20);
|
||||
return Strings.padStart(Integer.toString(value, 32).toUpperCase(Locale.ROOT), 4, '0');
|
||||
}
|
||||
|
||||
private int traceCode(Throwable e, int frameCount) {
|
||||
int result = SEED;
|
||||
if (e.getCause() != null) {
|
||||
result = traceCode(e.getCause(), frameCount);
|
||||
}
|
||||
result = result * A_PRIME + e.getClass().getName().hashCode();
|
||||
var stack = e.getStackTrace();
|
||||
for (int i = 0; i < Math.min(stack.length, frameCount); i++) {
|
||||
result = result * A_PRIME + stack[i].getClassName().hashCode();
|
||||
result = result * A_PRIME + stack[i].getMethodName().hashCode();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static int nonOverlappingFrames(StackTraceElement[] frames, StackTraceElement[] enclosingFrames) {
|
||||
// Compute the number of elements in `frames` not contained in `enclosingFrames` by iterating backwards
|
||||
// Result should usually be equal to the difference in size of both traces
|
||||
var i = reverseStream(enclosingFrames).iterator();
|
||||
return (int) reverseStream(frames).dropWhile(f -> i.hasNext() && i.next().equals(f)).count();
|
||||
}
|
||||
|
||||
private static <T> Stream<T> reverseStream(T[] array) {
|
||||
return IntStream.rangeClosed(1, array.length).mapToObj(i -> array[array.length - i]);
|
||||
}
|
||||
|
||||
}
|
@ -38,6 +38,11 @@ public class KeychainManager implements KeychainAccessProvider {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String displayName() {
|
||||
return getClass().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storePassphrase(String key, CharSequence passphrase) throws KeychainAccessException {
|
||||
getKeychainOrFail().storePassphrase(key, passphrase);
|
||||
|
@ -43,6 +43,8 @@ public class Settings {
|
||||
public static final NodeOrientation DEFAULT_USER_INTERFACE_ORIENTATION = NodeOrientation.LEFT_TO_RIGHT;
|
||||
public static final String DEFAULT_LICENSE_KEY = "";
|
||||
public static final boolean DEFAULT_SHOW_MINIMIZE_BUTTON = false;
|
||||
public static final String DEFAULT_DISPLAY_CONFIGURATION = "";
|
||||
|
||||
|
||||
private final ObservableList<VaultSettings> directories = FXCollections.observableArrayList(VaultSettings::observables);
|
||||
private final BooleanProperty askedForUpdateCheck = new SimpleBooleanProperty(DEFAULT_ASKED_FOR_UPDATE_CHECK);
|
||||
@ -59,6 +61,12 @@ public class Settings {
|
||||
private final StringProperty licenseKey = new SimpleStringProperty(DEFAULT_LICENSE_KEY);
|
||||
private final BooleanProperty showMinimizeButton = new SimpleBooleanProperty(DEFAULT_SHOW_MINIMIZE_BUTTON);
|
||||
private final BooleanProperty showTrayIcon;
|
||||
private final IntegerProperty windowXPosition = new SimpleIntegerProperty();
|
||||
private final IntegerProperty windowYPosition = new SimpleIntegerProperty();
|
||||
private final IntegerProperty windowWidth = new SimpleIntegerProperty();
|
||||
private final IntegerProperty windowHeight = new SimpleIntegerProperty();
|
||||
private final ObjectProperty<String> displayConfiguration = new SimpleObjectProperty<>(DEFAULT_DISPLAY_CONFIGURATION);
|
||||
|
||||
|
||||
private Consumer<Settings> saveCmd;
|
||||
|
||||
@ -83,6 +91,11 @@ public class Settings {
|
||||
licenseKey.addListener(this::somethingChanged);
|
||||
showMinimizeButton.addListener(this::somethingChanged);
|
||||
showTrayIcon.addListener(this::somethingChanged);
|
||||
windowXPosition.addListener(this::somethingChanged);
|
||||
windowYPosition.addListener(this::somethingChanged);
|
||||
windowWidth.addListener(this::somethingChanged);
|
||||
windowHeight.addListener(this::somethingChanged);
|
||||
displayConfiguration.addListener(this::somethingChanged);
|
||||
}
|
||||
|
||||
void setSaveCmd(Consumer<Settings> saveCmd) {
|
||||
@ -141,7 +154,7 @@ public class Settings {
|
||||
return theme;
|
||||
}
|
||||
|
||||
public ObjectProperty<String> keychainProvider() { return keychainProvider; }
|
||||
public ObjectProperty<String> keychainProvider() {return keychainProvider;}
|
||||
|
||||
public ObjectProperty<NodeOrientation> userInterfaceOrientation() {
|
||||
return userInterfaceOrientation;
|
||||
@ -158,4 +171,24 @@ public class Settings {
|
||||
public BooleanProperty showTrayIcon() {
|
||||
return showTrayIcon;
|
||||
}
|
||||
|
||||
public IntegerProperty windowXPositionProperty() {
|
||||
return windowXPosition;
|
||||
}
|
||||
|
||||
public IntegerProperty windowYPositionProperty() {
|
||||
return windowYPosition;
|
||||
}
|
||||
|
||||
public IntegerProperty windowWidthProperty() {
|
||||
return windowWidth;
|
||||
}
|
||||
|
||||
public IntegerProperty windowHeightProperty() {
|
||||
return windowHeight;
|
||||
}
|
||||
|
||||
public ObjectProperty<String> displayConfigurationProperty() {
|
||||
return displayConfiguration;
|
||||
}
|
||||
}
|
||||
|
@ -52,6 +52,12 @@ public class SettingsJsonAdapter extends TypeAdapter<Settings> {
|
||||
out.name("licenseKey").value(value.licenseKey().get());
|
||||
out.name("showMinimizeButton").value(value.showMinimizeButton().get());
|
||||
out.name("showTrayIcon").value(value.showTrayIcon().get());
|
||||
out.name("windowXPosition").value((value.windowXPositionProperty().get()));
|
||||
out.name("windowYPosition").value((value.windowYPositionProperty().get()));
|
||||
out.name("windowWidth").value((value.windowWidthProperty().get()));
|
||||
out.name("windowHeight").value((value.windowHeightProperty().get()));
|
||||
out.name("displayConfiguration").value((value.displayConfigurationProperty().get()));
|
||||
|
||||
out.endObject();
|
||||
}
|
||||
|
||||
@ -86,6 +92,12 @@ public class SettingsJsonAdapter extends TypeAdapter<Settings> {
|
||||
case "licenseKey" -> settings.licenseKey().set(in.nextString());
|
||||
case "showMinimizeButton" -> settings.showMinimizeButton().set(in.nextBoolean());
|
||||
case "showTrayIcon" -> settings.showTrayIcon().set(in.nextBoolean());
|
||||
case "windowXPosition" -> settings.windowXPositionProperty().set(in.nextInt());
|
||||
case "windowYPosition" -> settings.windowYPositionProperty().set(in.nextInt());
|
||||
case "windowWidth" -> settings.windowWidthProperty().set(in.nextInt());
|
||||
case "windowHeight" -> settings.windowHeightProperty().set(in.nextInt());
|
||||
case "displayConfiguration" -> settings.displayConfigurationProperty().set(in.nextString());
|
||||
|
||||
default -> {
|
||||
LOG.warn("Unsupported vault setting found in JSON: " + name);
|
||||
in.skipValue();
|
||||
|
@ -17,9 +17,6 @@ import org.cryptomator.cryptofs.CryptoFileSystem;
|
||||
import org.cryptomator.cryptofs.CryptoFileSystemProperties;
|
||||
import org.cryptomator.cryptofs.CryptoFileSystemProperties.FileSystemFlags;
|
||||
import org.cryptomator.cryptofs.CryptoFileSystemProvider;
|
||||
import org.cryptomator.cryptofs.VaultConfig;
|
||||
import org.cryptomator.cryptofs.VaultConfig.UnverifiedVaultConfig;
|
||||
import org.cryptomator.cryptofs.VaultConfigLoadException;
|
||||
import org.cryptomator.cryptofs.common.FileSystemCapabilityChecker;
|
||||
import org.cryptomator.cryptolib.api.CryptoException;
|
||||
import org.cryptomator.cryptolib.api.MasterkeyLoader;
|
||||
@ -38,8 +35,6 @@ import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.EnumSet;
|
||||
@ -62,6 +57,7 @@ public class Vault {
|
||||
private final AtomicReference<CryptoFileSystem> cryptoFileSystem;
|
||||
private final VaultState state;
|
||||
private final ObjectProperty<Exception> lastKnownException;
|
||||
private final VaultConfigCache configCache;
|
||||
private final VaultStats stats;
|
||||
private final StringBinding displayName;
|
||||
private final StringBinding displayablePath;
|
||||
@ -78,8 +74,9 @@ public class Vault {
|
||||
private volatile Volume volume;
|
||||
|
||||
@Inject
|
||||
Vault(VaultSettings vaultSettings, Provider<Volume> volumeProvider, @DefaultMountFlags StringBinding defaultMountFlags, AtomicReference<CryptoFileSystem> cryptoFileSystem, VaultState state, @Named("lastKnownException") ObjectProperty<Exception> lastKnownException, VaultStats stats) {
|
||||
Vault(VaultSettings vaultSettings, VaultConfigCache configCache, Provider<Volume> volumeProvider, @DefaultMountFlags StringBinding defaultMountFlags, AtomicReference<CryptoFileSystem> cryptoFileSystem, VaultState state, @Named("lastKnownException") ObjectProperty<Exception> lastKnownException, VaultStats stats) {
|
||||
this.vaultSettings = vaultSettings;
|
||||
this.configCache = configCache;
|
||||
this.volumeProvider = volumeProvider;
|
||||
this.defaultMountFlags = defaultMountFlags;
|
||||
this.cryptoFileSystem = cryptoFileSystem;
|
||||
@ -107,10 +104,10 @@ public class Vault {
|
||||
Set<FileSystemFlags> flags = EnumSet.noneOf(FileSystemFlags.class);
|
||||
if (vaultSettings.usesReadOnlyMode().get()) {
|
||||
flags.add(FileSystemFlags.READONLY);
|
||||
} else if(vaultSettings.maxCleartextFilenameLength().get() == -1) {
|
||||
} else if (vaultSettings.maxCleartextFilenameLength().get() == -1) {
|
||||
LOG.debug("Determining cleartext filename length limitations...");
|
||||
var checker = new FileSystemCapabilityChecker();
|
||||
int shorteningThreshold = getUnverifiedVaultConfig().allegedShorteningThreshold();
|
||||
int shorteningThreshold = configCache.get().allegedShorteningThreshold();
|
||||
int ciphertextLimit = checker.determineSupportedCiphertextFileNameLength(getPath());
|
||||
if (ciphertextLimit < shorteningThreshold) {
|
||||
int cleartextLimit = checker.determineSupportedCleartextFileNameLength(getPath());
|
||||
@ -328,19 +325,6 @@ public class Vault {
|
||||
return stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to read the vault config file and parse it without verifying its integrity.
|
||||
*
|
||||
* @return an unverified vault config
|
||||
* @throws VaultConfigLoadException if the read file cannot be properly parsed
|
||||
* @throws IOException if reading the file fails
|
||||
*
|
||||
*/
|
||||
public UnverifiedVaultConfig getUnverifiedVaultConfig() throws IOException {
|
||||
Path configPath = getPath().resolve(org.cryptomator.common.Constants.VAULTCONFIG_FILENAME);
|
||||
String token = Files.readString(configPath, StandardCharsets.US_ASCII);
|
||||
return VaultConfig.decode(token);
|
||||
}
|
||||
|
||||
public Observable[] observables() {
|
||||
return new Observable[]{state};
|
||||
@ -375,6 +359,10 @@ public class Vault {
|
||||
}
|
||||
}
|
||||
|
||||
public VaultConfigCache getVaultConfigCache() {
|
||||
return configCache;
|
||||
}
|
||||
|
||||
public void setCustomMountFlags(String mountFlags) {
|
||||
vaultSettings.mountFlags().set(mountFlags);
|
||||
}
|
||||
|
@ -25,6 +25,9 @@ public interface VaultComponent {
|
||||
@BindsInstance
|
||||
Builder vaultSettings(VaultSettings vaultSettings);
|
||||
|
||||
@BindsInstance
|
||||
Builder vaultConfigCache(VaultConfigCache configCache);
|
||||
|
||||
@BindsInstance
|
||||
Builder initialVaultState(VaultState.Value vaultState);
|
||||
|
||||
|
@ -0,0 +1,65 @@
|
||||
package org.cryptomator.common.vaults;
|
||||
|
||||
import org.cryptomator.common.Constants;
|
||||
import org.cryptomator.common.settings.VaultSettings;
|
||||
import org.cryptomator.cryptofs.VaultConfig;
|
||||
import org.cryptomator.cryptofs.VaultConfigLoadException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* Wrapper for lazy loading and on-demand reloading of the vault configuration.
|
||||
*/
|
||||
public class VaultConfigCache {
|
||||
|
||||
private final VaultSettings settings;
|
||||
private final AtomicReference<VaultConfig.UnverifiedVaultConfig> config;
|
||||
|
||||
VaultConfigCache(VaultSettings settings) {
|
||||
this.settings = settings;
|
||||
this.config = new AtomicReference<>(null);
|
||||
}
|
||||
|
||||
void reloadConfig() throws IOException {
|
||||
try {
|
||||
config.set(readConfigFromStorage(this.settings.path().get()));
|
||||
} catch (IOException e) {
|
||||
config.set(null);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public VaultConfig.UnverifiedVaultConfig get() throws IOException {
|
||||
if (config.get() == null) {
|
||||
reloadConfig();
|
||||
}
|
||||
return config.get();
|
||||
}
|
||||
|
||||
public VaultConfig.UnverifiedVaultConfig getUnchecked() {
|
||||
try {
|
||||
return get();
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Attempts to read the vault config file and parse it without verifying its integrity.
|
||||
*
|
||||
* @throws VaultConfigLoadException if the read file cannot be properly parsed
|
||||
* @throws IOException if reading the file fails
|
||||
*/
|
||||
static VaultConfig.UnverifiedVaultConfig readConfigFromStorage(Path vaultPath) throws IOException {
|
||||
Path configPath = vaultPath.resolve(Constants.VAULTCONFIG_FILENAME);
|
||||
String token = Files.readString(configPath, StandardCharsets.US_ASCII);
|
||||
return VaultConfig.decode(token);
|
||||
}
|
||||
|
||||
}
|
@ -18,7 +18,6 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
@ -31,6 +30,7 @@ import java.util.ResourceBundle;
|
||||
import static org.cryptomator.common.Constants.MASTERKEY_FILENAME;
|
||||
import static org.cryptomator.common.Constants.VAULTCONFIG_FILENAME;
|
||||
import static org.cryptomator.common.vaults.VaultState.Value.ERROR;
|
||||
import static org.cryptomator.common.vaults.VaultState.Value.LOCKED;
|
||||
|
||||
@Singleton
|
||||
public class VaultListManager {
|
||||
@ -96,6 +96,11 @@ public class VaultListManager {
|
||||
VaultComponent.Builder compBuilder = vaultComponentBuilder.vaultSettings(vaultSettings);
|
||||
try {
|
||||
VaultState.Value vaultState = determineVaultState(vaultSettings.path().get());
|
||||
VaultConfigCache wrapper = new VaultConfigCache(vaultSettings);
|
||||
compBuilder.vaultConfigCache(wrapper); //first set the wrapper in the builder, THEN try to load config
|
||||
if (vaultState == LOCKED) { //for legacy reasons: pre v8 vault do not have a config, but they are in the NEEDS_MIGRATION state
|
||||
wrapper.reloadConfig();
|
||||
}
|
||||
compBuilder.initialVaultState(vaultState);
|
||||
} catch (IOException e) {
|
||||
LOG.warn("Failed to determine vault state for " + vaultSettings.path().get(), e);
|
||||
@ -112,6 +117,9 @@ public class VaultListManager {
|
||||
case LOCKED, NEEDS_MIGRATION, MISSING -> {
|
||||
try {
|
||||
var determinedState = determineVaultState(vault.getPath());
|
||||
if (determinedState == LOCKED) {
|
||||
vault.getVaultConfigCache().reloadConfig();
|
||||
}
|
||||
state.set(determinedState);
|
||||
yield determinedState;
|
||||
} catch (IOException e) {
|
||||
@ -132,7 +140,9 @@ public class VaultListManager {
|
||||
return switch (CryptoFileSystemProvider.checkDirStructureForVault(pathToVault, VAULTCONFIG_FILENAME, MASTERKEY_FILENAME)) {
|
||||
case VAULT -> VaultState.Value.LOCKED;
|
||||
case UNRELATED -> VaultState.Value.MISSING;
|
||||
case MAYBE_LEGACY -> Migrators.get().needsMigration(pathToVault, VAULTCONFIG_FILENAME, MASTERKEY_FILENAME) ? VaultState.Value.NEEDS_MIGRATION : VaultState.Value.MISSING;
|
||||
case MAYBE_LEGACY -> Migrators.get().needsMigration(pathToVault, VAULTCONFIG_FILENAME, MASTERKEY_FILENAME) ? //
|
||||
VaultState.Value.NEEDS_MIGRATION //
|
||||
: VaultState.Value.MISSING;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -29,16 +29,20 @@ import javafx.scene.control.ToggleGroup;
|
||||
import javafx.stage.DirectoryChooser;
|
||||
import javafx.stage.Stage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.UUID;
|
||||
|
||||
@AddVaultWizardScoped
|
||||
public class CreateNewVaultLocationController implements FxController {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(CreateNewVaultLocationController.class);
|
||||
private static final Path DEFAULT_CUSTOM_VAULT_PATH = Paths.get(System.getProperty("user.home"));
|
||||
private static final String TEMP_FILE_FORMAT = "cryptomator-%s.tmp";
|
||||
|
||||
private final Stage window;
|
||||
private final Lazy<Scene> chooseNameScene;
|
||||
@ -92,7 +96,7 @@ public class CreateNewVaultLocationController implements FxController {
|
||||
statusText.set(resourceBundle.getString("addvaultwizard.new.locationDoesNotExist"));
|
||||
statusGraphic.set(badLocation);
|
||||
return false;
|
||||
} else if (!Files.isWritable(p.getParent())) {
|
||||
} else if (!isActuallyWritable(p.getParent())) {
|
||||
statusText.set(resourceBundle.getString("addvaultwizard.new.locationIsNotWritable"));
|
||||
statusGraphic.set(badLocation);
|
||||
return false;
|
||||
@ -107,6 +111,21 @@ public class CreateNewVaultLocationController implements FxController {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isActuallyWritable(Path p) {
|
||||
Path tmpFile = p.resolve(String.format(TEMP_FILE_FORMAT, UUID.randomUUID()));
|
||||
try (var chan = Files.newByteChannel(tmpFile, StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE, StandardOpenOption.DELETE_ON_CLOSE)) {
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
} finally {
|
||||
try {
|
||||
Files.deleteIfExists(tmpFile);
|
||||
} catch (IOException e) {
|
||||
LOG.warn("Unable to delete temporary file {}. Needs to be deleted manually.", tmpFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void initialize() {
|
||||
predefinedLocationToggler.selectedToggleProperty().addListener(this::togglePredefinedLocation);
|
||||
|
@ -182,7 +182,7 @@ public class CreateNewVaultPasswordController implements FxController {
|
||||
|
||||
// 2. initialize vault:
|
||||
try {
|
||||
MasterkeyLoader loader = ignored -> masterkey.clone();
|
||||
MasterkeyLoader loader = ignored -> masterkey.copy();
|
||||
CryptoFileSystemProperties fsProps = CryptoFileSystemProperties.cryptoFileSystemProperties().withCipherCombo(CryptorProvider.Scheme.SIV_CTRMAC).withKeyLoader(loader).build();
|
||||
CryptoFileSystemProvider.initialize(path, fsProps, DEFAULT_KEY_ID);
|
||||
|
||||
|
@ -14,7 +14,7 @@ public class LocationPresets {
|
||||
private static final String USER_HOME = System.getProperty("user.home");
|
||||
private static final String[] ICLOUDDRIVE_LOCATIONS = {"~/Library/Mobile Documents/iCloud~com~setolabs~Cryptomator/Documents", "~/iCloudDrive/iCloud~com~setolabs~Cryptomator"};
|
||||
private static final String[] DROPBOX_LOCATIONS = {"~/Dropbox"};
|
||||
private static final String[] GDRIVE_LOCATIONS = {"~/Google Drive"};
|
||||
private static final String[] GDRIVE_LOCATIONS = {"~/Google Drive/My Drive", "~/Google Drive"};
|
||||
private static final String[] ONEDRIVE_LOCATIONS = {"~/OneDrive"};
|
||||
private static final String[] MEGA_LOCATIONS = {"~/MEGA"};
|
||||
private static final String[] PCLOUD_LOCATIONS = {"~/pCloudDrive"};
|
||||
|
@ -1,22 +1,47 @@
|
||||
package org.cryptomator.ui.common;
|
||||
|
||||
import org.cryptomator.common.ErrorCode;
|
||||
import org.cryptomator.common.Nullable;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javafx.application.Application;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.input.Clipboard;
|
||||
import javafx.scene.input.ClipboardContent;
|
||||
import javafx.stage.Stage;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class ErrorController implements FxController {
|
||||
|
||||
private static final String SEARCH_URL_FORMAT = "https://github.com/cryptomator/cryptomator/discussions/categories/errors?discussions_q=category:Errors+%s";
|
||||
private static final String REPORT_URL_FORMAT = "https://github.com/cryptomator/cryptomator/discussions/new?category=Errors&title=Error+%s&body=%s";
|
||||
private static final String SEARCH_ERRORCODE_DELIM = " OR ";
|
||||
private static final String REPORT_BODY_TEMPLATE = """
|
||||
<!-- ✏️ Please describe what happened as accurately as possible. -->
|
||||
<!-- 📋 Please also copy and paste the detail text from the error window. -->
|
||||
""";
|
||||
|
||||
private final Application application;
|
||||
private final String stackTrace;
|
||||
private final ErrorCode errorCode;
|
||||
private final Scene previousScene;
|
||||
private final Stage window;
|
||||
|
||||
private BooleanProperty copiedDetails = new SimpleBooleanProperty();
|
||||
|
||||
@Inject
|
||||
ErrorController(@Named("stackTrace") String stackTrace, @Nullable Scene previousScene, Stage window) {
|
||||
ErrorController(Application application, @Named("stackTrace") String stackTrace, ErrorCode errorCode, @Nullable Scene previousScene, Stage window) {
|
||||
this.application = application;
|
||||
this.stackTrace = stackTrace;
|
||||
this.errorCode = errorCode;
|
||||
this.previousScene = previousScene;
|
||||
this.window = window;
|
||||
}
|
||||
@ -33,6 +58,31 @@ public class ErrorController implements FxController {
|
||||
window.close();
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void searchError() {
|
||||
var searchTerm = URLEncoder.encode(getErrorCode().replace(ErrorCode.DELIM, SEARCH_ERRORCODE_DELIM), StandardCharsets.UTF_8);
|
||||
application.getHostServices().showDocument(SEARCH_URL_FORMAT.formatted(searchTerm));
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void reportError() {
|
||||
var title = URLEncoder.encode(getErrorCode(), StandardCharsets.UTF_8);
|
||||
var body = URLEncoder.encode(REPORT_BODY_TEMPLATE, StandardCharsets.UTF_8);
|
||||
application.getHostServices().showDocument(REPORT_URL_FORMAT.formatted(title, body));
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void copyDetails() {
|
||||
ClipboardContent clipboardContent = new ClipboardContent();
|
||||
clipboardContent.putString(getDetailText());
|
||||
Clipboard.getSystemClipboard().setContent(clipboardContent);
|
||||
|
||||
copiedDetails.set(true);
|
||||
CompletableFuture.delayedExecutor(2, TimeUnit.SECONDS, Platform::runLater).execute(() -> {
|
||||
copiedDetails.set(false);
|
||||
});
|
||||
}
|
||||
|
||||
/* Getter/Setter */
|
||||
|
||||
public boolean isPreviousScenePresent() {
|
||||
@ -42,4 +92,20 @@ public class ErrorController implements FxController {
|
||||
public String getStackTrace() {
|
||||
return stackTrace;
|
||||
}
|
||||
|
||||
public String getErrorCode() {
|
||||
return errorCode.toString();
|
||||
}
|
||||
|
||||
public String getDetailText() {
|
||||
return "```\nError Code " + getErrorCode() + "\n" + getStackTrace() + "\n```";
|
||||
}
|
||||
|
||||
public BooleanProperty copiedDetailsProperty() {
|
||||
return copiedDetails;
|
||||
}
|
||||
|
||||
public boolean getCopiedDetails() {
|
||||
return copiedDetails.get();
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import dagger.Binds;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import dagger.multibindings.IntoMap;
|
||||
import org.cryptomator.common.ErrorCode;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Provider;
|
||||
@ -31,6 +32,11 @@ abstract class ErrorModule {
|
||||
return baos.toString(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
@Provides
|
||||
static ErrorCode provideErrorCode(Throwable cause) {
|
||||
return ErrorCode.of(cause);
|
||||
}
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FxControllerKey(ErrorController.class)
|
||||
|
@ -12,7 +12,6 @@ public enum FxmlFile {
|
||||
ERROR("/fxml/error.fxml"), //
|
||||
FORGET_PASSWORD("/fxml/forget_password.fxml"), //
|
||||
HEALTH_START("/fxml/health_start.fxml"), //
|
||||
HEALTH_START_FAIL("/fxml/health_start_fail.fxml"), //
|
||||
HEALTH_CHECK_LIST("/fxml/health_check_list.fxml"), //
|
||||
LOCK_FORCED("/fxml/lock_forced.fxml"), //
|
||||
LOCK_FAILED("/fxml/lock_failed.fxml"), //
|
||||
|
@ -12,6 +12,7 @@ public enum FontAwesome5Icon {
|
||||
CARET_RIGHT("\uF0Da"), //
|
||||
CHECK("\uF00C"), //
|
||||
CLOCK("\uF017"), //
|
||||
CLIPBOARD("\uF328"), //
|
||||
COG("\uF013"), //
|
||||
COGS("\uF085"), //
|
||||
COPY("\uF0C5"), //
|
||||
|
@ -10,6 +10,7 @@ package org.cryptomator.ui.controls;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.NamedArg;
|
||||
import javafx.beans.Observable;
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
@ -27,7 +28,6 @@ import javafx.scene.input.KeyCodeCombination;
|
||||
import javafx.scene.input.KeyCombination;
|
||||
import javafx.scene.input.KeyEvent;
|
||||
import javafx.scene.input.TransferMode;
|
||||
import java.awt.Toolkit;
|
||||
import java.nio.CharBuffer;
|
||||
import java.text.Normalizer;
|
||||
import java.text.Normalizer.Form;
|
||||
@ -123,8 +123,7 @@ public class SecurePasswordField extends TextField {
|
||||
}
|
||||
|
||||
private void updateCapsLocked() {
|
||||
//TODO: fixed in JavaFX 17. AWT code needed until update (see https://bugs.openjdk.java.net/browse/JDK-8259680)
|
||||
capsLocked.set(isFocused() && Toolkit.getDefaultToolkit().getLockingKeyState(java.awt.event.KeyEvent.VK_CAPS_LOCK));
|
||||
capsLocked.set(Platform.isKeyLocked(KeyCode.CAPS).orElse(false));
|
||||
}
|
||||
|
||||
private void updateContainingNonPrintableChars() {
|
||||
|
@ -67,7 +67,7 @@ public class CheckExecutor {
|
||||
|
||||
@Override
|
||||
protected Void call() throws Exception {
|
||||
try (var masterkeyClone = masterkey.clone(); //
|
||||
try (var masterkeyClone = masterkey.copy(); //
|
||||
var cryptor = CryptorProvider.forScheme(vaultConfig.getCipherCombo()).provide(masterkeyClone, csprng)) {
|
||||
c.getHealthCheck().check(vaultPath, vaultConfig, masterkeyClone, cryptor, diagnosis -> {
|
||||
Platform.runLater(() -> c.getResults().add(Result.create(diagnosis)));
|
||||
|
@ -16,26 +16,15 @@ import javafx.stage.Stage;
|
||||
@Subcomponent(modules = {HealthCheckModule.class})
|
||||
public interface HealthCheckComponent {
|
||||
|
||||
LoadUnverifiedConfigResult loadConfig();
|
||||
|
||||
@HealthCheckWindow
|
||||
Stage window();
|
||||
|
||||
@FxmlScene(FxmlFile.HEALTH_START)
|
||||
Lazy<Scene> startScene();
|
||||
|
||||
@FxmlScene(FxmlFile.HEALTH_START_FAIL)
|
||||
Lazy<Scene> failScene();
|
||||
|
||||
default Stage showHealthCheckWindow() {
|
||||
Stage stage = window();
|
||||
// TODO reevaluate config loading, as soon as we have the new generic error screen
|
||||
var unverifiedConf = loadConfig();
|
||||
if (unverifiedConf.config() != null) {
|
||||
stage.setScene(startScene().get());
|
||||
} else {
|
||||
stage.setScene(failScene().get());
|
||||
}
|
||||
stage.setScene(startScene().get());
|
||||
stage.show();
|
||||
return stage;
|
||||
}
|
||||
@ -52,5 +41,4 @@ public interface HealthCheckComponent {
|
||||
HealthCheckComponent build();
|
||||
}
|
||||
|
||||
record LoadUnverifiedConfigResult(VaultConfig.UnverifiedVaultConfig config, Throwable error) {}
|
||||
}
|
||||
|
@ -27,7 +27,6 @@ import javafx.scene.Scene;
|
||||
import javafx.stage.Modality;
|
||||
import javafx.stage.Stage;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
@ -37,18 +36,6 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
@Module(subcomponents = {KeyLoadingComponent.class})
|
||||
abstract class HealthCheckModule {
|
||||
|
||||
// TODO reevaluate config loading, as soon as we have the new generic error screen
|
||||
@Provides
|
||||
@HealthCheckScoped
|
||||
static HealthCheckComponent.LoadUnverifiedConfigResult provideLoadConfigResult(@HealthCheckWindow Vault vault) {
|
||||
try {
|
||||
return new HealthCheckComponent.LoadUnverifiedConfigResult(vault.getUnverifiedVaultConfig(), null);
|
||||
} catch (IOException e) {
|
||||
return new HealthCheckComponent.LoadUnverifiedConfigResult(null, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Provides
|
||||
@HealthCheckScoped
|
||||
static AtomicReference<Masterkey> provideMasterkeyRef() {
|
||||
@ -129,13 +116,6 @@ abstract class HealthCheckModule {
|
||||
return fxmlLoaders.createScene(FxmlFile.HEALTH_START);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@FxmlScene(FxmlFile.HEALTH_START_FAIL)
|
||||
@HealthCheckScoped
|
||||
static Scene provideHealthStartFailScene(@HealthCheckWindow FxmlLoaderFactory fxmlLoaders) {
|
||||
return fxmlLoaders.createScene(FxmlFile.HEALTH_START_FAIL);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@FxmlScene(FxmlFile.HEALTH_CHECK_LIST)
|
||||
@HealthCheckScoped
|
||||
@ -148,11 +128,6 @@ abstract class HealthCheckModule {
|
||||
@FxControllerKey(StartController.class)
|
||||
abstract FxController bindStartController(StartController controller);
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FxControllerKey(StartFailController.class)
|
||||
abstract FxController bindStartFailController(StartFailController controller);
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FxControllerKey(CheckListController.class)
|
||||
|
@ -50,7 +50,7 @@ class ResultFixApplier {
|
||||
|
||||
public void fix(DiagnosticResult diagnosis) {
|
||||
Preconditions.checkArgument(diagnosis.getSeverity() == DiagnosticResult.Severity.WARN, "Unfixable result");
|
||||
try (var masterkeyClone = masterkey.clone(); //
|
||||
try (var masterkeyClone = masterkey.copy(); //
|
||||
var cryptor = CryptorProvider.forScheme(vaultConfig.getCipherCombo()).provide(masterkeyClone, csprng)) {
|
||||
diagnosis.fix(vaultPath, vaultConfig, masterkeyClone, cryptor);
|
||||
} catch (Exception e) {
|
||||
|
@ -1,7 +1,8 @@
|
||||
package org.cryptomator.ui.health;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import dagger.Lazy;
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.common.vaults.VaultConfigCache;
|
||||
import org.cryptomator.cryptofs.VaultConfig;
|
||||
import org.cryptomator.cryptofs.VaultConfigLoadException;
|
||||
import org.cryptomator.cryptofs.VaultKeyInvalidException;
|
||||
@ -18,8 +19,6 @@ import org.slf4j.LoggerFactory;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.stage.Stage;
|
||||
@ -35,7 +34,7 @@ public class StartController implements FxController {
|
||||
|
||||
private final Stage window;
|
||||
private final Stage unlockWindow;
|
||||
private final ObjectProperty<VaultConfig.UnverifiedVaultConfig> unverifiedVaultConfig;
|
||||
private final VaultConfigCache vaultConfig;
|
||||
private final KeyLoadingStrategy keyLoadingStrategy;
|
||||
private final ExecutorService executor;
|
||||
private final AtomicReference<Masterkey> masterkeyRef;
|
||||
@ -44,11 +43,10 @@ public class StartController implements FxController {
|
||||
private final Lazy<ErrorComponent.Builder> errorComponent;
|
||||
|
||||
@Inject
|
||||
public StartController(@HealthCheckWindow Stage window, HealthCheckComponent.LoadUnverifiedConfigResult configLoadResult, @HealthCheckWindow KeyLoadingStrategy keyLoadingStrategy, ExecutorService executor, AtomicReference<Masterkey> masterkeyRef, AtomicReference<VaultConfig> vaultConfigRef, @FxmlScene(FxmlFile.HEALTH_CHECK_LIST) Lazy<Scene> checkScene, Lazy<ErrorComponent.Builder> errorComponent, @Named("unlockWindow") Stage unlockWindow) {
|
||||
Preconditions.checkNotNull(configLoadResult.config());
|
||||
public StartController(@HealthCheckWindow Stage window, @HealthCheckWindow Vault vault, @HealthCheckWindow KeyLoadingStrategy keyLoadingStrategy, ExecutorService executor, AtomicReference<Masterkey> masterkeyRef, AtomicReference<VaultConfig> vaultConfigRef, @FxmlScene(FxmlFile.HEALTH_CHECK_LIST) Lazy<Scene> checkScene, Lazy<ErrorComponent.Builder> errorComponent, @Named("unlockWindow") Stage unlockWindow) {
|
||||
this.window = window;
|
||||
this.unlockWindow = unlockWindow;
|
||||
this.unverifiedVaultConfig = new SimpleObjectProperty<>(configLoadResult.config());
|
||||
this.vaultConfig = vault.getVaultConfigCache();
|
||||
this.keyLoadingStrategy = keyLoadingStrategy;
|
||||
this.executor = executor;
|
||||
this.masterkeyRef = masterkeyRef;
|
||||
@ -71,7 +69,6 @@ public class StartController implements FxController {
|
||||
|
||||
private void loadKey() {
|
||||
assert !Platform.isFxApplicationThread();
|
||||
assert unverifiedVaultConfig.get() != null;
|
||||
try {
|
||||
keyLoadingStrategy.use(this::verifyVaultConfig);
|
||||
} catch (VaultConfigLoadException | UnlockCancelledException e) {
|
||||
@ -80,11 +77,11 @@ public class StartController implements FxController {
|
||||
}
|
||||
|
||||
private void verifyVaultConfig(KeyLoadingStrategy keyLoadingStrategy) throws VaultConfigLoadException {
|
||||
var unverifiedCfg = unverifiedVaultConfig.get();
|
||||
var unverifiedCfg = vaultConfig.getUnchecked();
|
||||
try (var masterkey = keyLoadingStrategy.loadKey(unverifiedCfg.getKeyId())) {
|
||||
var verifiedCfg = unverifiedCfg.verify(masterkey.getEncoded(), unverifiedCfg.allegedVaultVersion());
|
||||
vaultConfigRef.set(verifiedCfg);
|
||||
var old = masterkeyRef.getAndSet(masterkey.clone());
|
||||
var old = masterkeyRef.getAndSet(masterkey.copy());
|
||||
if (old != null) {
|
||||
old.destroy();
|
||||
}
|
||||
|
@ -1,79 +0,0 @@
|
||||
package org.cryptomator.ui.health;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import org.cryptomator.cryptofs.VaultConfigLoadException;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.controls.FontAwesome5Icon;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.TitledPane;
|
||||
import javafx.stage.Stage;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
// TODO reevaluate config loading, as soon as we have the new generic error screen
|
||||
@HealthCheckScoped
|
||||
public class StartFailController implements FxController {
|
||||
|
||||
private final Stage window;
|
||||
private final ObjectProperty<Throwable> loadError;
|
||||
private final ObjectProperty<FontAwesome5Icon> moreInfoIcon;
|
||||
|
||||
/* FXML */
|
||||
public TitledPane moreInfoPane;
|
||||
|
||||
@Inject
|
||||
public StartFailController(@HealthCheckWindow Stage window, HealthCheckComponent.LoadUnverifiedConfigResult configLoadResult) {
|
||||
Preconditions.checkNotNull(configLoadResult.error());
|
||||
this.window = window;
|
||||
this.loadError = new SimpleObjectProperty<>(configLoadResult.error());
|
||||
this.moreInfoIcon = new SimpleObjectProperty<>(FontAwesome5Icon.CARET_RIGHT);
|
||||
}
|
||||
|
||||
public void initialize() {
|
||||
moreInfoPane.expandedProperty().addListener(this::setMoreInfoIcon);
|
||||
}
|
||||
|
||||
private void setMoreInfoIcon(ObservableValue<? extends Boolean> observable, boolean wasExpanded, boolean willExpand) {
|
||||
moreInfoIcon.set(willExpand ? FontAwesome5Icon.CARET_DOWN : FontAwesome5Icon.CARET_RIGHT);
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void close() {
|
||||
window.close();
|
||||
}
|
||||
|
||||
/* Getter & Setter */
|
||||
|
||||
public ObjectProperty<FontAwesome5Icon> moreInfoIconProperty() {
|
||||
return moreInfoIcon;
|
||||
}
|
||||
|
||||
public FontAwesome5Icon getMoreInfoIcon() {
|
||||
return moreInfoIcon.getValue();
|
||||
}
|
||||
|
||||
public String getStackTrace() {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
loadError.get().printStackTrace(new PrintStream(baos));
|
||||
return baos.toString(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
public String getLocalizedErrorMessage() {
|
||||
return loadError.get().getLocalizedMessage();
|
||||
}
|
||||
|
||||
public boolean isParseException() {
|
||||
return loadError.get() instanceof VaultConfigLoadException;
|
||||
}
|
||||
|
||||
public boolean isIoException() {
|
||||
return !isParseException();
|
||||
}
|
||||
|
||||
}
|
@ -3,7 +3,6 @@ package org.cryptomator.ui.keyloading;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.cryptofs.VaultConfig.UnverifiedVaultConfig;
|
||||
import org.cryptomator.ui.common.DefaultSceneFactory;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.common.FxmlLoaderFactory;
|
||||
@ -11,9 +10,7 @@ import org.cryptomator.ui.keyloading.masterkeyfile.MasterkeyFileLoadingModule;
|
||||
|
||||
import javax.inject.Provider;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
@Module(includes = {MasterkeyFileLoadingModule.class})
|
||||
@ -31,7 +28,7 @@ abstract class KeyLoadingModule {
|
||||
@KeyLoadingScoped
|
||||
static KeyLoadingStrategy provideKeyLoaderProvider(@KeyLoading Vault vault, Map<String, Provider<KeyLoadingStrategy>> strategies) {
|
||||
try {
|
||||
String scheme = vault.getUnverifiedVaultConfig().getKeyId().getScheme();
|
||||
String scheme = vault.getVaultConfigCache().get().getKeyId().getScheme();
|
||||
var fallback = KeyLoadingStrategy.failed(new IllegalArgumentException("Unsupported key id " + scheme));
|
||||
return strategies.getOrDefault(scheme, () -> fallback).get();
|
||||
} catch (IOException e) {
|
||||
|
@ -11,12 +11,11 @@ import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
import javafx.application.Platform;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import static org.cryptomator.common.Constants.MASTERKEY_FILENAME;
|
||||
import static org.cryptomator.common.Constants.CRYPTOMATOR_FILENAME_EXT;
|
||||
|
||||
@Singleton
|
||||
class AppLaunchEventHandler {
|
||||
@ -69,7 +68,7 @@ class AppLaunchEventHandler {
|
||||
assert Platform.isFxApplicationThread();
|
||||
try {
|
||||
final Vault v;
|
||||
if (potentialVaultPath.getFileName().toString().equals(MASTERKEY_FILENAME)) {
|
||||
if (potentialVaultPath.getFileName().toString().endsWith(CRYPTOMATOR_FILENAME_EXT)) {
|
||||
v = vaultListManager.add(potentialVaultPath.getParent());
|
||||
} else {
|
||||
v = vaultListManager.add(potentialVaultPath);
|
||||
|
@ -23,12 +23,11 @@ import javafx.scene.layout.StackPane;
|
||||
import javafx.stage.Stage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.cryptomator.common.Constants.CRYPTOMATOR_FILENAME_EXT;
|
||||
import static org.cryptomator.common.Constants.MASTERKEY_FILENAME;
|
||||
import static org.cryptomator.common.Constants.VAULTCONFIG_FILENAME;
|
||||
|
||||
@ -55,7 +54,7 @@ public class MainWindowController implements FxController {
|
||||
|
||||
@FXML
|
||||
public void initialize() {
|
||||
LOG.debug("init MainWindowController");
|
||||
LOG.trace("init MainWindowController");
|
||||
root.setOnDragEntered(this::handleDragEvent);
|
||||
root.setOnDragOver(this::handleDragEvent);
|
||||
root.setOnDragDropped(this::handleDragEvent);
|
||||
@ -96,6 +95,9 @@ public class MainWindowController implements FxController {
|
||||
|
||||
private boolean containsVault(Path path) {
|
||||
try {
|
||||
if (path.getFileName().toString().endsWith(CRYPTOMATOR_FILENAME_EXT)) {
|
||||
path = path.getParent();
|
||||
}
|
||||
return CryptoFileSystemProvider.checkDirStructureForVault(path, VAULTCONFIG_FILENAME, MASTERKEY_FILENAME) != DirStructure.UNRELATED;
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
@ -104,7 +106,7 @@ public class MainWindowController implements FxController {
|
||||
|
||||
private void addVault(Path pathToVault) {
|
||||
try {
|
||||
if (pathToVault.getFileName().toString().equals(VAULTCONFIG_FILENAME)) {
|
||||
if (pathToVault.getFileName().toString().endsWith(CRYPTOMATOR_FILENAME_EXT)) {
|
||||
vaultListManager.add(pathToVault.getParent());
|
||||
} else {
|
||||
vaultListManager.add(pathToVault);
|
||||
|
@ -6,17 +6,17 @@ import dagger.Provides;
|
||||
import dagger.multibindings.IntoMap;
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.ui.addvaultwizard.AddVaultWizardComponent;
|
||||
import org.cryptomator.ui.common.FxmlLoaderFactory;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.common.FxControllerKey;
|
||||
import org.cryptomator.ui.common.FxmlFile;
|
||||
import org.cryptomator.ui.common.FxmlLoaderFactory;
|
||||
import org.cryptomator.ui.common.FxmlScene;
|
||||
import org.cryptomator.ui.common.StageFactory;
|
||||
import org.cryptomator.ui.health.HealthCheckComponent;
|
||||
import org.cryptomator.ui.migration.MigrationComponent;
|
||||
import org.cryptomator.ui.removevault.RemoveVaultComponent;
|
||||
import org.cryptomator.ui.vaultoptions.VaultOptionsComponent;
|
||||
import org.cryptomator.ui.stats.VaultStatisticsComponent;
|
||||
import org.cryptomator.ui.vaultoptions.VaultOptionsComponent;
|
||||
import org.cryptomator.ui.wrongfilealert.WrongFileAlertComponent;
|
||||
|
||||
import javax.inject.Provider;
|
||||
@ -49,11 +49,8 @@ abstract class MainWindowModule {
|
||||
@MainWindowScoped
|
||||
static Stage provideStage(StageFactory factory) {
|
||||
Stage stage = factory.create(StageStyle.UNDECORATED);
|
||||
// TODO: min/max values chosen arbitrarily. We might wanna take a look at the user's resolution...
|
||||
stage.setMinWidth(650);
|
||||
stage.setMinHeight(440);
|
||||
stage.setMaxWidth(1000);
|
||||
stage.setMaxHeight(700);
|
||||
stage.setTitle("Cryptomator");
|
||||
return stage;
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.binding.BooleanBinding;
|
||||
import javafx.beans.property.ReadOnlyBooleanProperty;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.input.MouseButton;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
@ -53,22 +54,43 @@ public class MainWindowTitleController implements FxController {
|
||||
|
||||
@FXML
|
||||
public void initialize() {
|
||||
LOG.debug("init MainWindowTitleController");
|
||||
LOG.trace("init MainWindowTitleController");
|
||||
updateChecker.automaticallyCheckForUpdatesIfEnabled();
|
||||
titleBar.setOnMousePressed(event -> {
|
||||
xOffset = event.getSceneX();
|
||||
yOffset = event.getSceneY();
|
||||
|
||||
});
|
||||
titleBar.setOnMouseClicked(event -> {
|
||||
if (event.getButton().equals(MouseButton.PRIMARY) && event.getClickCount() == 2) {
|
||||
window.setFullScreen(!window.isFullScreen());
|
||||
}
|
||||
});
|
||||
titleBar.setOnMouseDragged(event -> {
|
||||
if (window.isFullScreen()) return;
|
||||
window.setX(event.getScreenX() - xOffset);
|
||||
window.setY(event.getScreenY() - yOffset);
|
||||
});
|
||||
titleBar.setOnDragDetected(mouseDragEvent -> {
|
||||
titleBar.startFullDrag();
|
||||
});
|
||||
titleBar.setOnMouseDragReleased(mouseDragEvent -> {
|
||||
saveWindowSettings();
|
||||
});
|
||||
|
||||
window.setOnCloseRequest(event -> {
|
||||
close();
|
||||
event.consume();
|
||||
});
|
||||
}
|
||||
|
||||
private void saveWindowSettings() {
|
||||
settings.windowYPositionProperty().setValue(window.getY());
|
||||
settings.windowXPositionProperty().setValue(window.getX());
|
||||
settings.windowWidthProperty().setValue(window.getWidth());
|
||||
settings.windowHeightProperty().setValue(window.getHeight());
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void close() {
|
||||
if (trayMenuInitialized) {
|
||||
|
@ -1,41 +1,100 @@
|
||||
package org.cryptomator.ui.mainwindow;
|
||||
|
||||
import org.cryptomator.common.settings.Settings;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.binding.BooleanBinding;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.geometry.Rectangle2D;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.layout.Region;
|
||||
import javafx.stage.Screen;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
@MainWindow
|
||||
public class ResizeController implements FxController {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ResizeController.class);
|
||||
|
||||
private final Stage window;
|
||||
|
||||
public Region tlResizer;
|
||||
public Region trResizer;
|
||||
public Region blResizer;
|
||||
public Region brResizer;
|
||||
public Region tResizer;
|
||||
public Region rResizer;
|
||||
public Region bResizer;
|
||||
public Region lResizer;
|
||||
public Region lDefaultRegion;
|
||||
public Region tDefaultRegion;
|
||||
public Region rDefaultRegion;
|
||||
public Region bDefaultRegion;
|
||||
|
||||
private double origX, origY, origW, origH;
|
||||
|
||||
private final Settings settings;
|
||||
|
||||
private final BooleanBinding showResizingArrows;
|
||||
|
||||
@Inject
|
||||
ResizeController(@MainWindow Stage window) {
|
||||
ResizeController(@MainWindow Stage window, Settings settings) {
|
||||
this.window = window;
|
||||
// TODO inject settings and save current position and size
|
||||
this.settings = settings;
|
||||
this.showResizingArrows = Bindings.createBooleanBinding(this::isShowResizingArrows, window.fullScreenProperty());
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void initialize() {
|
||||
tlResizer.setOnMousePressed(this::startResize);
|
||||
trResizer.setOnMousePressed(this::startResize);
|
||||
blResizer.setOnMousePressed(this::startResize);
|
||||
brResizer.setOnMousePressed(this::startResize);
|
||||
tlResizer.setOnMouseDragged(this::resizeTopLeft);
|
||||
trResizer.setOnMouseDragged(this::resizeTopRight);
|
||||
blResizer.setOnMouseDragged(this::resizeBottomLeft);
|
||||
brResizer.setOnMouseDragged(this::resizeBottomRight);
|
||||
LOG.trace("init ResizeController");
|
||||
|
||||
if (neverTouched()) {
|
||||
settings.displayConfigurationProperty().setValue(getMonitorSizes());
|
||||
return;
|
||||
} else {
|
||||
if (didDisplayConfigurationChange()) {
|
||||
//If the position is illegal, then the window appears on the main screen in the middle of the window.
|
||||
Rectangle2D primaryScreenBounds = Screen.getPrimary().getBounds();
|
||||
window.setX((primaryScreenBounds.getWidth() - window.getMinWidth()) / 2);
|
||||
window.setY((primaryScreenBounds.getHeight() - window.getMinHeight()) / 2);
|
||||
window.setWidth(window.getMinWidth());
|
||||
window.setHeight(window.getMinHeight());
|
||||
} else {
|
||||
window.setHeight(settings.windowHeightProperty().get() > window.getMinHeight() ? settings.windowHeightProperty().get() : window.getMinHeight());
|
||||
window.setWidth(settings.windowWidthProperty().get() > window.getMinWidth() ? settings.windowWidthProperty().get() : window.getMinWidth());
|
||||
window.setX(settings.windowXPositionProperty().get());
|
||||
window.setY(settings.windowYPositionProperty().get());
|
||||
}
|
||||
}
|
||||
savePositionalSettings();
|
||||
}
|
||||
|
||||
private boolean neverTouched() {
|
||||
return (settings.windowHeightProperty().get() == 0) && (settings.windowWidthProperty().get() == 0) && (settings.windowXPositionProperty().get() == 0) && (settings.windowYPositionProperty().get() == 0);
|
||||
}
|
||||
|
||||
private boolean didDisplayConfigurationChange() {
|
||||
String currentDisplayConfiguration = getMonitorSizes();
|
||||
String settingsDisplayConfiguration = settings.displayConfigurationProperty().get();
|
||||
boolean configurationHasChanged = !settingsDisplayConfiguration.equals(currentDisplayConfiguration);
|
||||
if (configurationHasChanged) settings.displayConfigurationProperty().setValue(currentDisplayConfiguration);
|
||||
return configurationHasChanged;
|
||||
}
|
||||
|
||||
private String getMonitorSizes() {
|
||||
ObservableList<Screen> screens = Screen.getScreens();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < screens.size(); i++) {
|
||||
Rectangle2D screenBounds = screens.get(i).getBounds();
|
||||
if (!sb.isEmpty()) sb.append(" ");
|
||||
sb.append("displayId: " + i + ", " + screenBounds.getWidth() + "x" + screenBounds.getHeight() + ";");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private void startResize(MouseEvent evt) {
|
||||
@ -45,27 +104,33 @@ public class ResizeController implements FxController {
|
||||
origH = window.getHeight();
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void resizeTopLeft(MouseEvent evt) {
|
||||
resizeTop(evt);
|
||||
resizeLeft(evt);
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void resizeTopRight(MouseEvent evt) {
|
||||
resizeTop(evt);
|
||||
resizeRight(evt);
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void resizeBottomLeft(MouseEvent evt) {
|
||||
resizeBottom(evt);
|
||||
resizeLeft(evt);
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void resizeBottomRight(MouseEvent evt) {
|
||||
resizeBottom(evt);
|
||||
resizeRight(evt);
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void resizeTop(MouseEvent evt) {
|
||||
startResize(evt);
|
||||
double newY = evt.getScreenY();
|
||||
double dy = newY - origY;
|
||||
double newH = origH - dy;
|
||||
@ -75,7 +140,9 @@ public class ResizeController implements FxController {
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void resizeLeft(MouseEvent evt) {
|
||||
startResize(evt);
|
||||
double newX = evt.getScreenX();
|
||||
double dx = newX - origX;
|
||||
double newW = origW - dx;
|
||||
@ -85,6 +152,7 @@ public class ResizeController implements FxController {
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void resizeBottom(MouseEvent evt) {
|
||||
double newH = evt.getSceneY();
|
||||
if (newH < window.getMaxHeight() && newH > window.getMinHeight()) {
|
||||
@ -92,6 +160,7 @@ public class ResizeController implements FxController {
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void resizeRight(MouseEvent evt) {
|
||||
double newW = evt.getSceneX();
|
||||
if (newW < window.getMaxWidth() && newW > window.getMinWidth()) {
|
||||
@ -99,4 +168,21 @@ public class ResizeController implements FxController {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@FXML
|
||||
public void savePositionalSettings() {
|
||||
settings.windowHeightProperty().setValue(window.getHeight());
|
||||
settings.windowWidthProperty().setValue(window.getWidth());
|
||||
settings.windowYPositionProperty().setValue(window.getY());
|
||||
settings.windowXPositionProperty().setValue(window.getX());
|
||||
}
|
||||
|
||||
public BooleanBinding showResizingArrowsProperty() {
|
||||
return showResizingArrows;
|
||||
}
|
||||
|
||||
public boolean isShowResizingArrows() {
|
||||
//If in fullscreen resizing is not be possible;
|
||||
return !window.isFullScreen();
|
||||
}
|
||||
|
||||
}
|
@ -1,12 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import org.cryptomator.ui.controls.FontAwesome5IconView?>
|
||||
<?import org.cryptomator.ui.controls.FormattedLabel?>
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.ButtonBar?>
|
||||
<?import javafx.scene.control.Hyperlink?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.TextArea?>
|
||||
<?import javafx.scene.layout.HBox?>
|
||||
<?import javafx.scene.layout.Region?>
|
||||
<?import javafx.scene.layout.StackPane?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<?import javafx.scene.shape.Circle?>
|
||||
@ -15,7 +18,7 @@
|
||||
fx:controller="org.cryptomator.ui.common.ErrorController"
|
||||
prefWidth="450"
|
||||
prefHeight="450"
|
||||
spacing="12"
|
||||
spacing="18"
|
||||
alignment="TOP_CENTER">
|
||||
<padding>
|
||||
<Insets topRightBottomLeft="24"/>
|
||||
@ -27,12 +30,38 @@
|
||||
<FontAwesome5IconView styleClass="glyph-icon-white" glyph="EXCLAMATION" glyphSize="24"/>
|
||||
</StackPane>
|
||||
<VBox spacing="6" HBox.hgrow="ALWAYS">
|
||||
<Label text="%generic.error.title" wrapText="true"/>
|
||||
<FormattedLabel styleClass="label-large" format="%generic.error.title" arg1="${controller.errorCode}"/>
|
||||
<Label text="%generic.error.instruction" wrapText="true"/>
|
||||
<Hyperlink styleClass="hyperlink-underline" text="%generic.error.hyperlink.lookup" onAction="#searchError" contentDisplay="LEFT">
|
||||
<graphic>
|
||||
<FontAwesome5IconView glyph="LINK" glyphSize="12"/>
|
||||
</graphic>
|
||||
</Hyperlink>
|
||||
<Hyperlink styleClass="hyperlink-underline" text="%generic.error.hyperlink.report" onAction="#reportError" contentDisplay="LEFT">
|
||||
<graphic>
|
||||
<FontAwesome5IconView glyph="LINK" glyphSize="12"/>
|
||||
</graphic>
|
||||
</Hyperlink>
|
||||
</VBox>
|
||||
</HBox>
|
||||
|
||||
<TextArea VBox.vgrow="ALWAYS" text="${controller.stackTrace}" prefRowCount="5" editable="false"/>
|
||||
<VBox spacing="6" VBox.vgrow="ALWAYS">
|
||||
<HBox>
|
||||
<Label text="%generic.error.technicalDetails"/>
|
||||
<Region HBox.hgrow="ALWAYS"/>
|
||||
<Hyperlink styleClass="hyperlink-underline" text="%generic.button.copy" onAction="#copyDetails" contentDisplay="LEFT" visible="${!controller.copiedDetails}" managed="${!controller.copiedDetails}">
|
||||
<graphic>
|
||||
<FontAwesome5IconView glyph="CLIPBOARD" glyphSize="12"/>
|
||||
</graphic>
|
||||
</Hyperlink>
|
||||
<Hyperlink styleClass="hyperlink-underline" text="%generic.button.copied" onAction="#copyDetails" contentDisplay="LEFT" visible="${controller.copiedDetails}" managed="${controller.copiedDetails}">
|
||||
<graphic>
|
||||
<FontAwesome5IconView glyph="CHECK" glyphSize="12"/>
|
||||
</graphic>
|
||||
</Hyperlink>
|
||||
</HBox>
|
||||
<TextArea VBox.vgrow="ALWAYS" text="${controller.detailText}" prefRowCount="5" editable="false"/>
|
||||
</VBox>
|
||||
|
||||
<ButtonBar buttonMinWidth="120" buttonOrder="B+C">
|
||||
<buttons>
|
||||
|
@ -1,44 +0,0 @@
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.ButtonBar?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.TextArea?>
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.TitledPane?>
|
||||
<?import org.cryptomator.ui.controls.FontAwesome5IconView?>
|
||||
<?import javafx.scene.layout.Region?>
|
||||
<?import javafx.scene.layout.HBox?>
|
||||
<?import javafx.scene.text.TextFlow?>
|
||||
<?import javafx.scene.text.Text?>
|
||||
<VBox xmlns="http://javafx.com/javafx"
|
||||
xmlns:fx="http://javafx.com/fxml"
|
||||
fx:controller="org.cryptomator.ui.health.StartFailController"
|
||||
prefWidth="600"
|
||||
prefHeight="400"
|
||||
spacing="12">
|
||||
<padding>
|
||||
<Insets topRightBottomLeft="12"/>
|
||||
</padding>
|
||||
<Label text="%health.fail.header" styleClass="label-large" />
|
||||
<TextFlow fx:id="ioErrorLabel" visible="${controller.ioException}" managed="${controller.ioException}">
|
||||
<Text text="%health.fail.ioError" />
|
||||
<Text text="${controller.localizedErrorMessage}"/>
|
||||
</TextFlow>
|
||||
<Label fx:id="parseErrorLabel" text="%health.fail.parseError" visible="${controller.parseException}" managed="${controller.parseException}"/>
|
||||
<TitledPane fx:id="moreInfoPane" text="%health.fail.moreInfo" expanded="false">
|
||||
<graphic>
|
||||
<HBox alignment="CENTER" minWidth="8">
|
||||
<FontAwesome5IconView glyph="${controller.moreInfoIcon}"/>
|
||||
</HBox>
|
||||
</graphic>
|
||||
<content>
|
||||
<TextArea VBox.vgrow="ALWAYS" text="${controller.stackTrace}" prefRowCount="20" editable="false" />
|
||||
</content>
|
||||
</TitledPane>
|
||||
<Region VBox.vgrow="ALWAYS"/>
|
||||
<ButtonBar buttonMinWidth="120" buttonOrder="+CX">
|
||||
<buttons>
|
||||
<Button text="%generic.button.close" ButtonBar.buttonData="CANCEL_CLOSE" cancelButton="true" onAction="#close"/>
|
||||
</buttons>
|
||||
</ButtonBar>
|
||||
</VBox>
|
@ -12,7 +12,7 @@
|
||||
fx:id="root"
|
||||
fx:controller="org.cryptomator.ui.mainwindow.MainWindowController"
|
||||
styleClass="main-window">
|
||||
<VBox>
|
||||
<VBox minWidth="650">
|
||||
<fx:include source="main_window_title.fxml" VBox.vgrow="NEVER"/>
|
||||
<StackPane VBox.vgrow="ALWAYS">
|
||||
<SplitPane dividerPositions="0.33" orientation="HORIZONTAL">
|
||||
|
@ -9,9 +9,22 @@
|
||||
<fx:define>
|
||||
<Cursor fx:id="nwResize" fx:constant="NW_RESIZE"/>
|
||||
<Cursor fx:id="neResize" fx:constant="NE_RESIZE"/>
|
||||
<Cursor fx:id="nsResize" fx:constant="N_RESIZE"/>
|
||||
<Cursor fx:id="ewResize" fx:constant="E_RESIZE"/>
|
||||
<Cursor fx:id="default" fx:constant="DEFAULT"/>
|
||||
</fx:define>
|
||||
<Region fx:id="tlResizer" cursor="${nwResize}" prefWidth="10" prefHeight="10" maxWidth="-Infinity" maxHeight="-Infinity" AnchorPane.topAnchor="0" AnchorPane.leftAnchor="0"/>
|
||||
<Region fx:id="trResizer" cursor="${neResize}" prefWidth="10" prefHeight="10" maxWidth="-Infinity" maxHeight="-Infinity" AnchorPane.topAnchor="0" AnchorPane.rightAnchor="0"/>
|
||||
<Region fx:id="blResizer" cursor="${neResize}" prefWidth="10" prefHeight="10" maxWidth="-Infinity" maxHeight="-Infinity" AnchorPane.bottomAnchor="0" AnchorPane.leftAnchor="0"/>
|
||||
<Region fx:id="brResizer" cursor="${nwResize}" prefWidth="10" prefHeight="10" maxWidth="-Infinity" maxHeight="-Infinity" AnchorPane.bottomAnchor="0" AnchorPane.rightAnchor="0"/>
|
||||
|
||||
<Region fx:id="tlResizer" cursor="${nwResize}" prefWidth="10" prefHeight="10" maxWidth="-Infinity" maxHeight="-Infinity" visible="${controller.showResizingArrows}" managed="${controller.showResizingArrows}" onMouseDragged="#resizeTopLeft" onMouseReleased="#savePositionalSettings" AnchorPane.topAnchor="0" AnchorPane.leftAnchor="0"/>
|
||||
<Region fx:id="trResizer" cursor="${neResize}" prefWidth="10" prefHeight="10" maxWidth="-Infinity" maxHeight="-Infinity" visible="${controller.showResizingArrows}" managed="${controller.showResizingArrows}" onMouseDragged="#resizeTopRight" onMouseReleased="#savePositionalSettings" AnchorPane.topAnchor="0" AnchorPane.rightAnchor="0"/>
|
||||
<Region fx:id="blResizer" cursor="${neResize}" prefWidth="10" prefHeight="10" maxWidth="-Infinity" maxHeight="-Infinity" visible="${controller.showResizingArrows}" managed="${controller.showResizingArrows}" onMouseDragged="#resizeBottomLeft" onMouseReleased="#savePositionalSettings" AnchorPane.bottomAnchor="0" AnchorPane.leftAnchor="0"/>
|
||||
<Region fx:id="brResizer" cursor="${nwResize}" prefWidth="10" prefHeight="10" maxWidth="-Infinity" maxHeight="-Infinity" visible="${controller.showResizingArrows}" managed="${controller.showResizingArrows}" onMouseDragged="#resizeBottomRight" onMouseReleased="#savePositionalSettings" AnchorPane.bottomAnchor="0" AnchorPane.rightAnchor="0"/>
|
||||
<Region fx:id="tResizer" cursor="${nsResize}" prefWidth="0" prefHeight="6" maxWidth="-Infinity" maxHeight="-Infinity" visible="${controller.showResizingArrows}" managed="${controller.showResizingArrows}" onMouseDragged="#resizeTop" onMouseReleased="#savePositionalSettings" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="0.0"/>
|
||||
<Region fx:id="rResizer" cursor="${ewResize}" prefWidth="6" prefHeight="0" maxWidth="-Infinity" maxHeight="-Infinity" visible="${controller.showResizingArrows}" managed="${controller.showResizingArrows}" onMouseDragged="#resizeRight" onMouseReleased="#savePositionalSettings" AnchorPane.bottomAnchor="10.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="10.0"/>
|
||||
<Region fx:id="bResizer" cursor="${nsResize}" prefWidth="6" prefHeight="6" maxWidth="-Infinity" maxHeight="-Infinity" visible="${controller.showResizingArrows}" managed="${controller.showResizingArrows}" onMouseDragged="#resizeBottom" onMouseReleased="#savePositionalSettings" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0"/>
|
||||
<Region fx:id="lResizer" cursor="${ewResize}" prefWidth="6" prefHeight="6" maxWidth="-Infinity" maxHeight="-Infinity" visible="${controller.showResizingArrows}" managed="${controller.showResizingArrows}" onMouseDragged="#resizeLeft" onMouseReleased="#savePositionalSettings" AnchorPane.bottomAnchor="10.0" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="10.0"/>
|
||||
<Region fx:id="lDefaultRegion" cursor="${default}" prefWidth="1" prefHeight="1" maxWidth="-Infinity" maxHeight="-Infinity" AnchorPane.bottomAnchor="-1" AnchorPane.leftAnchor="-1" AnchorPane.topAnchor="-1"/>
|
||||
<Region fx:id="tDefaultRegion" cursor="${default}" prefWidth="1" prefHeight="1" maxWidth="-Infinity" maxHeight="-Infinity" AnchorPane.leftAnchor="-1" AnchorPane.topAnchor="-1" AnchorPane.rightAnchor="-1"/>
|
||||
<Region fx:id="rDefaultRegion" cursor="${default}" prefWidth="1" prefHeight="1" maxWidth="-Infinity" maxHeight="-Infinity" AnchorPane.topAnchor="-1" AnchorPane.rightAnchor="-1" AnchorPane.bottomAnchor="-1"/>
|
||||
<Region fx:id="bDefaultRegion" cursor="${default}" prefWidth="1" prefHeight="1" maxWidth="-Infinity" maxHeight="-Infinity" AnchorPane.rightAnchor="-1" AnchorPane.bottomAnchor="-1" AnchorPane.leftAnchor="-1"/>
|
||||
|
||||
</AnchorPane>
|
@ -14,8 +14,11 @@ generic.button.done=Done
|
||||
generic.button.next=Next
|
||||
generic.button.print=Print
|
||||
## Error
|
||||
generic.error.title=An unexpected error occurred
|
||||
generic.error.instruction=This should not have happened. Please report the error text below and include a description of what steps did lead to this error.
|
||||
generic.error.title=Error %s
|
||||
generic.error.instruction=Oops! Cryptomator didn't expect this to happen. You can look up existing solutions for this error. Or if it has not been reported yet, feel free to do so.
|
||||
generic.error.hyperlink.lookup=Look up this error
|
||||
generic.error.hyperlink.report=Report this error
|
||||
generic.error.technicalDetails=Details:
|
||||
|
||||
# Defaults
|
||||
defaults.vault.vaultName=Vault
|
||||
|
@ -13,8 +13,6 @@ generic.button.done=تم
|
||||
generic.button.next=التالي
|
||||
generic.button.print=طباعة
|
||||
## Error
|
||||
generic.error.title=حدث خطأ غير متوقع
|
||||
generic.error.instruction=ما كان ينبغي أن يحدث هذا. يرجى الإبلاغ عن نص الخطأ أدناه وإدراج وصف للخطوات التي أدت إلى هذا الخطأ.
|
||||
|
||||
# Defaults
|
||||
defaults.vault.vaultName=مخزن
|
||||
|
@ -13,8 +13,6 @@ generic.button.done=Gotovo
|
||||
generic.button.next=Sljedeće
|
||||
generic.button.print=Ispis
|
||||
## Error
|
||||
generic.error.title=Došlo je do neočekivane greške
|
||||
generic.error.instruction=Ovo se nije trebalo dogoditi. Molimo da prijavite opis greške ispod, kao i korake koji su do greške doveli.
|
||||
|
||||
# Defaults
|
||||
defaults.vault.vaultName=Sef
|
||||
|
@ -13,8 +13,6 @@ generic.button.done=Fet
|
||||
generic.button.next=Següent
|
||||
generic.button.print=Imprimeix
|
||||
## Error
|
||||
generic.error.title=S'ha produït un error inesperat
|
||||
generic.error.instruction=Això no hauria d'haver passat. Si us plau, informeu del text de l'error i inclogueu una descripció de quins passos han dut a aquest error.
|
||||
|
||||
# Defaults
|
||||
defaults.vault.vaultName=Caixa forta
|
||||
|
@ -13,8 +13,11 @@ generic.button.done=Hotovo
|
||||
generic.button.next=Další
|
||||
generic.button.print=Tisk
|
||||
## Error
|
||||
generic.error.title=Došlo k neočekávané chybě
|
||||
generic.error.instruction=Tohle se nemělo stát. Prosím, nahlaste níže uvedený chybový text a popište, jaké kroky vedly k této chybě.
|
||||
generic.error.title=Chyba %s
|
||||
generic.error.instruction=Jejda! Tohle Cryptomator nečekal. Můžete najít již existující řešení pro tuto chybu. Nebo pokud ještě nebyla nahlášena, neváhejte tak učinit.
|
||||
generic.error.hyperlink.lookup=Vyhledat tuto chybu
|
||||
generic.error.hyperlink.report=Nahlásit tuto chybu
|
||||
generic.error.technicalDetails=Podrobnosti:
|
||||
|
||||
# Defaults
|
||||
defaults.vault.vaultName=Trezor
|
||||
|
@ -13,8 +13,11 @@ generic.button.done=Fertig
|
||||
generic.button.next=Weiter
|
||||
generic.button.print=Drucken
|
||||
## Error
|
||||
generic.error.title=Ein unerwarteter Fehler ist aufgetreten
|
||||
generic.error.instruction=Das hätte nicht passieren dürfen. Bitte melde den folgenden Fehlertext und beschreibe kurz, durch welche Schritte der Fehler aufgetreten ist.
|
||||
generic.error.title=Fehler %s
|
||||
generic.error.instruction=Ups! Das hat sich Cryptomator anders vorgestellt. Du kannst Lösungen für diesen Fehler nachschlagen oder einen neuen Fehlerbericht einreichen.
|
||||
generic.error.hyperlink.lookup=Diesen Fehler nachschlagen
|
||||
generic.error.hyperlink.report=Diesen Fehler melden
|
||||
generic.error.technicalDetails=Details:
|
||||
|
||||
# Defaults
|
||||
defaults.vault.vaultName=Tresor
|
||||
@ -45,7 +48,7 @@ addvaultwizard.new.directoryPickerLabel=Eigener Ort
|
||||
addvaultwizard.new.directoryPickerButton=Durchsuchen …
|
||||
addvaultwizard.new.directoryPickerTitle=Verzeichnis auswählen
|
||||
addvaultwizard.new.fileAlreadyExists=Eine Datei oder ein Ordner mit diesem Namen ist bereits vorhanden
|
||||
addvaultwizard.new.locationDoesNotExist=Der Ordner im angegebenen Pfad existiert nicht oder kann nicht geöffnet werden
|
||||
addvaultwizard.new.locationDoesNotExist=Ein Ordner im angegebenen Pfad existiert nicht oder kann nicht geöffnet werden
|
||||
addvaultwizard.new.locationIsNotWritable=Kein Schreibzugriff auf den angegebenen Pfad
|
||||
addvaultwizard.new.locationIsOk=Geeigneter Ort für deinen Tresor
|
||||
addvaultwizard.new.invalidName=Ungültiger Tresorname. Bitte wähle einen regulären Namen, mit dem auch Verzeichnisse erstellt werden können.
|
||||
@ -59,7 +62,7 @@ addvault.new.readme.storageLocation.fileName=WICHTIG.rtf
|
||||
addvault.new.readme.storageLocation.1=⚠️ TRESOR-DATEIEN ⚠️
|
||||
addvault.new.readme.storageLocation.2=Dies ist der Speicherort deines Tresors.
|
||||
addvault.new.readme.storageLocation.3=NICHT
|
||||
addvault.new.readme.storageLocation.4=• in diesem Verzeichnis Dateien ändern oder
|
||||
addvault.new.readme.storageLocation.4=• Dateien in diesem Verzeichnis ändern oder
|
||||
addvault.new.readme.storageLocation.5=• zu verschlüsselnde Dateien in diesem Verzeichnis ablegen.
|
||||
addvault.new.readme.storageLocation.6=Falls du Dateien verschlüsseln und den Inhalt des Tresors anzeigen möchtest, befolge folgende Schritte:
|
||||
addvault.new.readme.storageLocation.7=1. Füge diesen Tresor zu Cryptomator hinzu.
|
||||
@ -73,7 +76,7 @@ addvault.new.readme.accessLocation.3=Alle zu diesem Laufwerk hinzugefügten Date
|
||||
addvault.new.readme.accessLocation.4=Diese Datei kannst du löschen.
|
||||
## Existing
|
||||
addvaultwizard.existing.instruction=Wähle die Datei „masterkey.cryptomator“ deines vorhandenen Tresors aus.
|
||||
addvaultwizard.existing.chooseBtn=Durchsuchen …
|
||||
addvaultwizard.existing.chooseBtn=Durchsuchen…
|
||||
addvaultwizard.existing.filePickerTitle=Masterkey-Datei auswählen
|
||||
## Success
|
||||
addvaultwizard.success.nextStepsInstructions=Tresor „%s“ hinzugefügt.\nUm auf Inhalte zuzugreifen oder welche hinzuzufügen, musst du den Tresor entsperren. Du kannst ihn aber auch zu jedem späteren Zeitpunkt entsperren.
|
||||
@ -95,7 +98,7 @@ forgetPassword.information=Dies löscht das gespeicherte Passwort dieses Tresors
|
||||
forgetPassword.confirmBtn=Passwort vergessen
|
||||
|
||||
# Unlock
|
||||
unlock.title=Entsperre "%s"
|
||||
unlock.title="%s" entsperren
|
||||
unlock.passwordPrompt=Gib das Passwort für „%s“ ein:
|
||||
unlock.savePassword=Passwort merken
|
||||
unlock.unlockBtn=Entsperren
|
||||
@ -147,6 +150,7 @@ migration.impossible.moreInfo=Der Tresor kann auch jetzt noch mit einer älteren
|
||||
|
||||
# Health Check
|
||||
## Start
|
||||
health.title=Integritätstest von "%s"
|
||||
health.intro.header=Zustandsprüfung
|
||||
health.intro.text=Der Zustandscheck ist eine Sammlung von Tests, um Probleme mit der internen Struktur deines Tresores zu finden und möglicherweise zu reparieren. Bitte bedenke:
|
||||
health.intro.remarkSync=Stelle sicher, dass alle Geräte vollständig synchronisiert sind. Dies löst die meisten Probleme.
|
||||
@ -155,6 +159,8 @@ health.intro.remarkBackup=Wenn Daten beschädigt sind, kann nur ein Backup helfe
|
||||
health.intro.affirmation=Ich habe die obenstehende Information gelesen und verstanden
|
||||
## Start Failure
|
||||
health.fail.header=Fehler beim Laden der Tresorkonfiguration
|
||||
health.fail.ioError=Beim Lesezugriff auf die Konfigurationsdatei ist ein Fehler aufgetreten.
|
||||
health.fail.parseError=Beim Parsen der Tresor-Konfiguration ist ein Fehler aufgetreten.
|
||||
health.fail.moreInfo=Weitere Informationen
|
||||
## Check Selection
|
||||
health.checkList.description=Markiere Prüfungen in der linken Liste oder benutze die Knöpfe darunter.
|
||||
@ -288,8 +294,8 @@ main.vaultDetail.stats=Tresorstatistik
|
||||
### Missing
|
||||
main.vaultDetail.missing.info=Cryptomator konnte keinen Tresor mit diesem Pfad finden.
|
||||
main.vaultDetail.missing.recheck=Erneut prüfen
|
||||
main.vaultDetail.missing.remove=Aus Tresorliste entfernen…
|
||||
main.vaultDetail.missing.changeLocation=Speicherort des Tresors ändern…
|
||||
main.vaultDetail.missing.remove=Aus Tresorliste entfernen …
|
||||
main.vaultDetail.missing.changeLocation=Speicherort des Tresors ändern …
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Tresor aktualisieren
|
||||
main.vaultDetail.migratePrompt=Dein Tresor muss auf ein neues Format aktualisiert werden, bevor du auf ihn zugreifen kannst
|
||||
@ -309,12 +315,13 @@ wrongFileAlert.link=Besuche für weitere Hilfe
|
||||
vaultOptions.general=Allgemein
|
||||
vaultOptions.general.vaultName=Tresorname
|
||||
vaultOptions.general.autoLock.lockAfterTimePart1=Nach
|
||||
vaultOptions.general.autoLock.lockAfterTimePart2=Minuten
|
||||
vaultOptions.general.autoLock.lockAfterTimePart2=Minuten Inaktivität sperren
|
||||
vaultOptions.general.unlockAfterStartup=Tresor beim Start von Cryptomator entsperren
|
||||
vaultOptions.general.actionAfterUnlock=Nach erfolgreichem Entsperren
|
||||
vaultOptions.general.actionAfterUnlock.ignore=Nichts tun
|
||||
vaultOptions.general.actionAfterUnlock.reveal=Laufwerk anzeigen
|
||||
vaultOptions.general.actionAfterUnlock.ask=Nachfragen
|
||||
vaultOptions.general.startHealthCheckBtn=Integritätsprüfung starten
|
||||
|
||||
## Mount
|
||||
vaultOptions.mount=Laufwerk
|
||||
|
@ -13,8 +13,6 @@ generic.button.done=Κλείσιμο
|
||||
generic.button.next=Επόμενο
|
||||
generic.button.print=Εκτύπωση
|
||||
## Error
|
||||
generic.error.title=Παρουσιάστηκε ένα απροσδόκητο σφάλμα
|
||||
generic.error.instruction=Αυτό δεν έπρεπε να συμβεί. Παρακαλώ αντιγράψτε το κείμενο του σφάλματος και επισυνάψτε μια περιγραφή των βημάτων που οδήγησαν σε αυτό το σφάλμα.
|
||||
|
||||
# Defaults
|
||||
defaults.vault.vaultName=Vault
|
||||
|
@ -13,8 +13,11 @@ generic.button.done=Hecho
|
||||
generic.button.next=Continuar
|
||||
generic.button.print=Imprimir
|
||||
## Error
|
||||
generic.error.title=Ocurrió un error inesperado
|
||||
generic.error.instruction=Esto no debió suceder. Notifique el error de abajo e incluya una descripción de los pasos que llevaron a este error.
|
||||
generic.error.title=Error %s
|
||||
generic.error.instruction=¡Ups! Cryptomator no esperaba que esto sucediera. Puede buscar soluciones existentes para este error. O si aún no se ha notiicado, siéntase libre de hacerlo.
|
||||
generic.error.hyperlink.lookup=Buscar este error
|
||||
generic.error.hyperlink.report=Notificar este error
|
||||
generic.error.technicalDetails=Detalles:
|
||||
|
||||
# Defaults
|
||||
defaults.vault.vaultName=Bóveda
|
||||
|
@ -13,8 +13,11 @@ generic.button.done=Terminé
|
||||
generic.button.next=Suivant
|
||||
generic.button.print=Imprimer
|
||||
## Error
|
||||
generic.error.title=Une erreur inattendue est survenue
|
||||
generic.error.instruction=Cela n'aurait pas dû se produire. Veuillez reporter le texte d'erreur ci-dessous et inclure une description des étapes qui ont conduit à cette erreur.
|
||||
generic.error.title=Erreur: %s
|
||||
generic.error.instruction=Oups ! Cryptomator ne s'attendait pas à ce que cela se produise. Vous pouvez rechercher des solutions existantes pour cette erreur. Ou si elle n'a pas encore été signalée, n'hésitez pas à le faire.
|
||||
generic.error.hyperlink.lookup=Rechercher cette erreur
|
||||
generic.error.hyperlink.report=Signaler cette erreur
|
||||
generic.error.technicalDetails=Détails:
|
||||
|
||||
# Defaults
|
||||
defaults.vault.vaultName=Coffre
|
||||
@ -160,15 +163,24 @@ health.fail.ioError=Une erreur s'est produite lors de l'accès et de la lecture
|
||||
health.fail.parseError=Une erreur est survenue pendant la lecture de la configuration du coffre.
|
||||
health.fail.moreInfo=Plus d'informations
|
||||
## Check Selection
|
||||
health.checkList.description=Sélectionnez les contrôles dans la liste de gauche ou utilisez les boutons ci-dessous.
|
||||
health.checkList.selectAllButton=Sélectionner toutes les vérifications
|
||||
health.checkList.deselectAllButton=Désélectionner toutes les vérifications
|
||||
health.check.runBatchBtn=Exécuter les vérifications sélectionnées
|
||||
## Detail view
|
||||
health.check.detail.noSelectedCheck=Pour les résultats, sélectionnez un bilan de santé terminé dans la liste de gauche.
|
||||
health.check.detail.checkScheduled=La vérification est programmée.
|
||||
health.check.detail.checkRunning=Vérification en cours d'exécution…
|
||||
health.check.detail.checkSkipped=La vérification n'a pas été sélectionnée pour être exécutée.
|
||||
health.check.detail.checkFinished=La vérification s'est terminée avec succès.
|
||||
health.check.detail.checkFinishedAndFound=La vérification s'est terminée. Veuillez vérifier les résultats.
|
||||
health.check.detail.checkFailed=La vérification s'est arrêtée en raison d'une erreur.
|
||||
health.check.detail.checkCancelled=Vérification annulée.
|
||||
health.check.exportBtn=Exporter le rapport
|
||||
## Fix Application
|
||||
health.fix.fixBtn=Réparer
|
||||
health.fix.successTip=Réparation réussie
|
||||
health.fix.failTip=Correction échouée, voir le journal pour plus de détails
|
||||
|
||||
# Preferences
|
||||
preferences.title=Préférences
|
||||
|
@ -13,8 +13,6 @@ generic.button.done=हो गया
|
||||
generic.button.next=अगला
|
||||
generic.button.print=प्रिंट करें
|
||||
## Error
|
||||
generic.error.title=कोई अनपेक्षित त्रुटि हो गई है
|
||||
generic.error.instruction=ऐसा नहीं होना चाहिए था। कृपया नीचे त्रुटि पाठ की रिपोर्ट करें और इस त्रुटि के लिए क्या कदम उठाए, इसका विवरण शामिल करें।
|
||||
|
||||
# Defaults
|
||||
defaults.vault.vaultName=गुप्त तिजोरी
|
||||
|
@ -13,8 +13,6 @@ generic.button.done=Kész
|
||||
generic.button.next=Következő
|
||||
generic.button.print=Nyomtatás
|
||||
## Error
|
||||
generic.error.title=Egy váratlan hiba történt
|
||||
generic.error.instruction=Ennek nem lett volna szabad megtörténnie. Kérjük jelezze a hibát az alábbi szöveggel valamint a hiba reprodukálásához szükséges lépésekkel.
|
||||
|
||||
# Defaults
|
||||
defaults.vault.vaultName=Széf
|
||||
|
@ -13,8 +13,6 @@ generic.button.done=Selesai
|
||||
generic.button.next=Lanjut
|
||||
generic.button.print=Cetak
|
||||
## Error
|
||||
generic.error.title=Telah terjadi kesalahan tak terduga
|
||||
generic.error.instruction=Ini harusnya tidak terjadi. Harap laporkan pesan kesalahan dibawah dan tulis deskripsi kenapa ini bisa terjadi.
|
||||
|
||||
# Defaults
|
||||
defaults.vault.vaultName=Brankas
|
||||
|
@ -13,20 +13,23 @@ generic.button.done=Fatto
|
||||
generic.button.next=Avanti
|
||||
generic.button.print=Stampa
|
||||
## Error
|
||||
generic.error.title=Si è verificato un errore inatteso
|
||||
generic.error.instruction=Questo non dovrebbe essere accaduto. Si prega di segnalare il testo dell'errore qui sotto e includere una descrizione delle fasi che hanno portato a questo errore.
|
||||
generic.error.title=Errore %s
|
||||
generic.error.instruction=Ops! Cryptomator non si aspettava che ciò succedesse. Puoi cercare le soluzioni esistenti per questo errore. O se non è stato ancora segnalato, sentiti libero di farlo.
|
||||
generic.error.hyperlink.lookup=Cerca questo errore
|
||||
generic.error.hyperlink.report=Segnala questo errore
|
||||
generic.error.technicalDetails=Dettagli:
|
||||
|
||||
# Defaults
|
||||
defaults.vault.vaultName=Cassaforte
|
||||
|
||||
# Tray Menu
|
||||
traymenu.showMainWindow=Visualizza
|
||||
traymenu.showPreferencesWindow=Impostazioni
|
||||
traymenu.showMainWindow=Mostra
|
||||
traymenu.showPreferencesWindow=Preferenze
|
||||
traymenu.lockAllVaults=Blocca Tutto
|
||||
traymenu.quitApplication=Esci
|
||||
traymenu.vault.unlock=Sblocca
|
||||
traymenu.vault.lock=Blocca
|
||||
traymenu.vault.reveal=Mostra
|
||||
traymenu.vault.reveal=Rivela
|
||||
|
||||
# Add Vault Wizard
|
||||
addvaultwizard.title=Aggiungi Cassaforte
|
||||
@ -35,64 +38,64 @@ addvaultwizard.welcome.newButton=Crea Nuova Cassaforte
|
||||
addvaultwizard.welcome.existingButton=Apri Cassaforte Esistente
|
||||
## New
|
||||
### Name
|
||||
addvaultwizard.new.nameInstruction=Scegli un nome per la tua cassaforte
|
||||
addvaultwizard.new.namePrompt=Nome Cassaforte
|
||||
addvaultwizard.new.nameInstruction=Scegli un nome per la cassaforte
|
||||
addvaultwizard.new.namePrompt=Nome della Cassaforte
|
||||
### Location
|
||||
addvaultwizard.new.locationInstruction=Dove dovrebbe memorizzare Cryptomator i file crittografati della tua cassaforte?
|
||||
addvaultwizard.new.locationLabel=Posizione archivio
|
||||
addvaultwizard.new.locationInstruction=Dove Cryptomator dovrebbe memorizzare i file crittografati della tua cassaforte?
|
||||
addvaultwizard.new.locationLabel=Posizione d'archiviazione
|
||||
addvaultwizard.new.locationPrompt=…
|
||||
addvaultwizard.new.directoryPickerLabel=Posizione personalizzata
|
||||
addvaultwizard.new.directoryPickerLabel=Posizione Personalizzata
|
||||
addvaultwizard.new.directoryPickerButton=Scegli…
|
||||
addvaultwizard.new.directoryPickerTitle=Seleziona cartella
|
||||
addvaultwizard.new.fileAlreadyExists=Un file o una cartella con il nome del vault esiste già
|
||||
addvaultwizard.new.directoryPickerTitle=Seleziona la Cartella
|
||||
addvaultwizard.new.fileAlreadyExists=Un file o una cartella con il nome della cassaforte esiste già
|
||||
addvaultwizard.new.locationDoesNotExist=Una cartella nel percorso specificato non esiste o non è accessibile
|
||||
addvaultwizard.new.locationIsNotWritable=Non c'è accesso in scrittura nel percorso specificato
|
||||
addvaultwizard.new.locationIsOk=Posizione adatta per il tuo vault
|
||||
addvaultwizard.new.invalidName=Nome della cassaforte non valido. Si prega di considerare un nome di directory regolare.
|
||||
addvaultwizard.new.locationIsNotWritable=Nessun accesso di scrittura al percorso specificato
|
||||
addvaultwizard.new.locationIsOk=Posizione idonea per la tua cassaforte
|
||||
addvaultwizard.new.invalidName=Nome della cassaforte non valido. Sei pregato di considerare un nome della cartella regolare.
|
||||
### Password
|
||||
addvaultwizard.new.createVaultBtn=Crea Cassaforte
|
||||
addvaultwizard.new.generateRecoveryKeyChoice=Non sarai in grado di accedere ai tuoi dati senza password. Vuoi una chiave di recupero nel caso in cui perdi la password?
|
||||
addvaultwizard.new.generateRecoveryKeyChoice=Non potrai accedere ai tuoi dati senza la tua password. Desideri una chiave di recupero nel caso dovessi perdere la password?
|
||||
addvaultwizard.new.generateRecoveryKeyChoice.yes=Si, per favore, è meglio essere al sicuro
|
||||
addvaultwizard.new.generateRecoveryKeyChoice.no=No grazie, non perderò la mia password
|
||||
### Information
|
||||
addvault.new.readme.storageLocation.fileName=IMPORTANTE.rtf
|
||||
addvault.new.readme.storageLocation.1=⚠ FILE CASSAFORTE ⚠
|
||||
addvault.new.readme.storageLocation.2=Questa è la posizione di archiviazione della tua cassaforte.
|
||||
addvault.new.readme.storageLocation.1=⚠️ FILE DELLA CASSAFORTE ⚠️
|
||||
addvault.new.readme.storageLocation.2=Questa è la posizione d'archiviazione della tua cassaforte.
|
||||
addvault.new.readme.storageLocation.3=NON
|
||||
addvault.new.readme.storageLocation.4=• modificare qualsiasi file in questa cartella o
|
||||
addvault.new.readme.storageLocation.5=• Incolla tutti i file da criptare in questa directory.
|
||||
addvault.new.readme.storageLocation.6=Se si desidera crittografare i file e visualizzare il contenuto della cassaforte, effettuare le seguenti operazioni:
|
||||
addvault.new.readme.storageLocation.4=• alterare alcun file in questa cartella o
|
||||
addvault.new.readme.storageLocation.5=• incollare alcun file per la crittografia in questa cartella.
|
||||
addvault.new.readme.storageLocation.6=Se vuoi crittografare i file e visualizzare il contenuto della cassaforte, fa quanto segue:
|
||||
addvault.new.readme.storageLocation.7=1. Aggiungi questa cassaforte a Cryptomator.
|
||||
addvault.new.readme.storageLocation.8=2. Sblocca la cassaforte in Criptomator.
|
||||
addvault.new.readme.storageLocation.9=3. Apri la posizione di accesso cliccando sul pulsante "Rivela".
|
||||
addvault.new.readme.storageLocation.10=Se hai bisogno di aiuto, leggi la documentazione: %s
|
||||
addvault.new.readme.storageLocation.8=2. Sblocca la cassaforte su Cryptomator.
|
||||
addvault.new.readme.storageLocation.9=3. Apri la posizione d'accesso cliccando sul pulsante "Rivela".
|
||||
addvault.new.readme.storageLocation.10=Se ti serve aiuto, visita la documentazione: %s
|
||||
addvault.new.readme.accessLocation.fileName=BENVENUTO.rtf
|
||||
addvault.new.readme.accessLocation.1=🔐 VOLUME CRIPTATO 🔐
|
||||
addvault.new.readme.accessLocation.2=Questa è la posizione di accesso della tua cassaforte.
|
||||
addvault.new.readme.accessLocation.3=Tutti i file aggiunti a questo volume verranno crittografati da Cryptomator. Puoi lavorare su di esso come su qualsiasi altra unità/cartella. Questa è solo una vista decriptata del suo contenuto, i file rimangono continuamente criptati sul disco rigido.
|
||||
addvault.new.readme.accessLocation.4=Sei libero di rimuovere questo file.
|
||||
addvault.new.readme.accessLocation.1=🔐 VOLUME CRITTOGRAFATO 🔐
|
||||
addvault.new.readme.accessLocation.2=Questa è la posizione d'accesso della tua cassaforte.
|
||||
addvault.new.readme.accessLocation.3=Ogni file aggiunto a questo volume sarà crittografato da Cryptomator. Puoi lavorarci come su ogni altra unità/cartella. Questa è solo una vista decrittografata del suo contenuto, i tuoi file restano sempre crittografati sul tuo disco rigido.
|
||||
addvault.new.readme.accessLocation.4=Sentiti libero di rimuovere questo file.
|
||||
## Existing
|
||||
addvaultwizard.existing.instruction=Scegliere il file "masterkey.cryptomator" del deposito esistente.
|
||||
addvaultwizard.existing.instruction=Scegli il file "masterkey.cryptomator" della tua cassaforte esistente.
|
||||
addvaultwizard.existing.chooseBtn=Scegli…
|
||||
addvaultwizard.existing.filePickerTitle=Seleziona file Masterkey
|
||||
addvaultwizard.existing.filePickerTitle=Seleziona il File Masterkey
|
||||
## Success
|
||||
addvaultwizard.success.nextStepsInstructions=Aggiunta cassaforte"%s".\nÈ necessario sbloccare questa cassaforte per accedere o aggiungere contenuti. In alternativa puoi sbloccarla in qualsiasi momento successivo.
|
||||
addvaultwizard.success.unlockNow=Sblocca adesso
|
||||
addvaultwizard.success.nextStepsInstructions=Cassaforte "%s" aggiunta.\nDevi sbloccare questa cassaforte per accedere o aggiungere contenuti. Altrimenti, puoi sbloccarla in qualsiasi momento successivo.
|
||||
addvaultwizard.success.unlockNow=Sblocca Ora
|
||||
|
||||
# Remove Vault
|
||||
removeVault.title=Rimuovi Cassaforte
|
||||
removeVault.information=Questo farà dimenticare Cryptomator a questo vault. Puoi aggiungerlo di nuovo in seguito. Nessun file crittografato verrà eliminato dal tuo disco rigido.
|
||||
removeVault.information=Questo farà solo dimenticare questa cassaforte a Cryptomator. Puoi aggiungerla nuovamente in seguito. Nessun file crittografato sarà eliminato dal tuo disco rigido.
|
||||
removeVault.confirmBtn=Rimuovi Cassaforte
|
||||
|
||||
# Change Password
|
||||
changepassword.title=Modifica password
|
||||
changepassword.enterOldPassword=Inserisci la password attuale per "%s"
|
||||
changepassword.finalConfirmation=Ho capito che non sarò in grado di accedere ai miei dati se dimentico la mia password
|
||||
changepassword.title=Modifica la Password
|
||||
changepassword.enterOldPassword=Inserisci la password corrente per "%s"
|
||||
changepassword.finalConfirmation=Capisco che non potrò accedere ai miei dati se dimentico la mia password
|
||||
|
||||
# Forget Password
|
||||
forgetPassword.title=Password dimenticata
|
||||
forgetPassword.information=Questo cancellerà la password salvata di questa cassaforte dal tuo portachiavi di sistema.
|
||||
forgetPassword.confirmBtn=Password dimenticata
|
||||
forgetPassword.title=Dimentica la Password
|
||||
forgetPassword.information=Questo eliminerà la password salvata di questa cassaforte dal portachiavi del tuo sistema.
|
||||
forgetPassword.confirmBtn=Dimentica Password
|
||||
|
||||
# Unlock
|
||||
unlock.title=Sblocca "%s"
|
||||
@ -100,126 +103,129 @@ unlock.passwordPrompt=Inserisci la password per "%s":
|
||||
unlock.savePassword=Ricorda la Password
|
||||
unlock.unlockBtn=Sblocca
|
||||
##
|
||||
unlock.chooseMasterkey.prompt=Impossibile trovare il file masterkey per questa cassaforte nella posizione prevista. Scegliere manualmente il file chiave.
|
||||
unlock.chooseMasterkey.filePickerTitle=Seleziona file Masterkey
|
||||
unlock.chooseMasterkey.prompt=Impossibile trovare il file Masterkey per questa cassaforte alla sua posizione prevista. Sei pregato di sceglierlo manualmente.
|
||||
unlock.chooseMasterkey.filePickerTitle=Seleziona il File Masterkey
|
||||
## Success
|
||||
unlock.success.message="%s" sbloccato con successo! La tua cassaforte è ora accessibile tramite il suo drive virtuale.
|
||||
unlock.success.rememberChoice=Ricorda la scelta, non mostrare ancora
|
||||
unlock.success.revealBtn=Rivela Drive
|
||||
unlock.success.message="%s" sbloccato correttamente! La tua cassaforte è ora accessibile tramite la sua unità virtuale.
|
||||
unlock.success.rememberChoice=Ricorda la scelta, non mostrarmelo più
|
||||
unlock.success.revealBtn=Rivela l'Unità
|
||||
## Failure
|
||||
unlock.error.heading=Impossibile sbloccare la cassaforte
|
||||
### Invalid Mount Point
|
||||
unlock.error.invalidMountPoint.notExisting=Il punto di montaggio non è una directory vuota o non esiste: %s
|
||||
unlock.error.invalidMountPoint.existing=Il punto di Mount/cartella esiste già o la cartella superiore è mancante: %s
|
||||
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.
|
||||
|
||||
# Lock
|
||||
## Force
|
||||
lock.forced.heading=Blocco normale fallito
|
||||
lock.forced.message=Il bloccaggio di "%s" è stato impedito da operazioni in sospeso o da file aperti. È possibile forzare il blocco di questa cassaforte, tuttavia interrompere I/O potrebbe causare la perdita di dati non salvati.
|
||||
lock.forced.message=Il bloccaggio di "%s" è stato impedito dalle operazioni in sospeso o dai file aperti. Puoi forzare il blocco di questa cassaforte, tuttavia, interrompere I/O potrebbe risultare nella perdita dei dati non salvati.
|
||||
lock.forced.confirmBtn=Forza Blocco
|
||||
## Failure
|
||||
lock.fail.heading=Blocco cassaforte fallito.
|
||||
lock.fail.message=Impossibile bloccare la cassaforte "%s". Assicurati che il lavoro non salvato sia salvato ovunque e che le operazioni di Lettura/Scrittura importanti siano concluse. Per chiudere la cassaforte, termina il processo di Cryptomator.
|
||||
lock.fail.heading=Blocco della cassaforte fallito.
|
||||
lock.fail.message=Impossibile bloccare la cassaforte "%s". Assicurati che il lavoro non salvato sia salvato altrove e che le importanti operazioni di Lettura/Scrittura siano terminate. Per chiudere la cassaforte, termina il processo di Cryptomator.
|
||||
|
||||
# Migration
|
||||
migration.title=Aggiorna Cassaforte
|
||||
migration.title=Aggiorna la Cassaforte
|
||||
## Start
|
||||
migration.start.prompt=La tua cassaforte "%s" deve essere aggiornata a un formato più recente. Prima di procedere, assicurati che non ci sia nessuna sincronizzazione in sospeso che influisca su questa cassaforte.
|
||||
migration.start.prompt=La tua cassaforte "%s" dev'esser aggiornata a un formato più recente. Prima di procedere, assicurati che non ci sia alcuna sincronizzazione in sospeso relativa a questa cassaforte.
|
||||
migration.start.confirm=Sì, la mia cassaforte è completamente sincronizzata
|
||||
## Run
|
||||
migration.run.enterPassword=Immettere la password per "%s"
|
||||
migration.run.startMigrationBtn=Migra Cassaforte
|
||||
migration.run.progressHint=Potrebbe richiedere un po' di tempo…
|
||||
migration.run.enterPassword=Inserisci la password per "%s"
|
||||
migration.run.startMigrationBtn=Migra la Cassaforte
|
||||
migration.run.progressHint=Questo potrebbe richiedere un po' di tempo…
|
||||
## Success
|
||||
migration.success.nextStepsInstructions=Migrato "%s" con successo.\nOra puoi sbloccare la tua cassaforte.
|
||||
migration.success.unlockNow=Sblocca adesso
|
||||
migration.success.nextStepsInstructions="%s" migrata con successo.\nPuoi ora sbloccare la tua cassaforte.
|
||||
migration.success.unlockNow=Sblocca Ora
|
||||
## Missing file system capabilities
|
||||
migration.error.missingFileSystemCapabilities.title=File System non supportato
|
||||
migration.error.missingFileSystemCapabilities.description=La migrazione non è stata avviata perché la cassaforte è situata su un file system inadeguato.
|
||||
migration.error.missingFileSystemCapabilities.reason.LONG_FILENAMES=Il file system non supporta nomi di file lunghi.
|
||||
migration.error.missingFileSystemCapabilities.reason.LONG_PATHS=Il file system non supporta percorsi lunghi.
|
||||
migration.error.missingFileSystemCapabilities.reason.READ_ACCESS=Il file system non consente di essere letto.
|
||||
migration.error.missingFileSystemCapabilities.reason.WRITE_ACCESS=Il file system non consente di essere scritto.
|
||||
migration.error.missingFileSystemCapabilities.title=File di Sistema Non Supportato
|
||||
migration.error.missingFileSystemCapabilities.description=Migrazione non avviata perché la tua cassaforte si trova su un file di sistema inadeguato.
|
||||
migration.error.missingFileSystemCapabilities.reason.LONG_FILENAMES=Il file di sistema non supporta i nomi dei file lunghi.
|
||||
migration.error.missingFileSystemCapabilities.reason.LONG_PATHS=Il file di sistema non supporta i percorsi lunghi.
|
||||
migration.error.missingFileSystemCapabilities.reason.READ_ACCESS=Il file di sistema non consente di esser letto.
|
||||
migration.error.missingFileSystemCapabilities.reason.WRITE_ACCESS=Il file di sistema non consente di esser scritto.
|
||||
## Impossible
|
||||
migration.impossible.heading=Impossibile migrare la cassaforte
|
||||
migration.impossible.reason=La cassaforte non può essere migrata automaticamente perché la sua posizione di archiviazione di accesso non è compatibile.
|
||||
migration.impossible.moreInfo=La cassaforte può ancora essere aperta con una versione precedente. Per istruzioni su come migrare manualmente una cassaforte, visita
|
||||
migration.impossible.reason=Impossibile migrare automaticamente la cassaforte perché la sua posizione d'archiviazione o punto d'accesso non sono compatibili.
|
||||
migration.impossible.moreInfo=La cassaforte è ancora apribile con una versione precedente. Per le istruzioni su come migrare manualmente una cassaforte, visita
|
||||
|
||||
# Health Check
|
||||
## Start
|
||||
health.intro.remarkSync=Assicurati che tutti i dispositivi siano completamente sincronizzati, questo risolve la maggior parte dei problemi.
|
||||
health.intro.remarkFix=Non tutti i problemi possono essere corretti.
|
||||
health.intro.remarkBackup=Se i dati sono danneggiati, solo un backup può aiutare.
|
||||
health.intro.affirmation=Ho letto e capito le informazioni sopra
|
||||
health.title=Controllo Salute di "%s"
|
||||
health.intro.header=Controllo Salute
|
||||
health.intro.text=Il Controllo della Salute è una raccolta di controlli per rilevare e possibilmente risolvere i problemi nella struttura interna alla tua cassaforte. Sei pregato di tenere a mente:
|
||||
health.intro.remarkSync=Assicurati che tutti i dispositivi siano completamente sincronizzati, questo risolve gran parte dei problemi.
|
||||
health.intro.remarkFix=Non tutti i problemi sono risolvibili.
|
||||
health.intro.remarkBackup=Se i dati sono corrotti, solo un backup può aiutare.
|
||||
health.intro.affirmation=Ho letto e compreso le informazioni suddette
|
||||
## Start Failure
|
||||
health.fail.header=Errore nel caricare la configurazione della cassaforte
|
||||
health.fail.ioError=Si è verificato un errore durante l'accesso e la lettura del file di configurazione.
|
||||
health.fail.parseError=Si è verificato un errore durante l'analisi della configurazione della cassaforte.
|
||||
health.fail.moreInfo=Ulteriori Informazioni
|
||||
health.fail.header=Errore caricando la Configurazione della Cassaforte
|
||||
health.fail.ioError=Si è verificato un errore accedendo e leggendo il file di configurazione.
|
||||
health.fail.parseError=Si è verificato un errore analizzando la configurazione della cassaforte.
|
||||
health.fail.moreInfo=Altre Info
|
||||
## Check Selection
|
||||
health.checkList.description=Seleziona i controlli nell'elenco a sinistra o utilizza i pulsanti in basso.
|
||||
health.checkList.selectAllButton=Seleziona Tutti I Controlli
|
||||
health.checkList.deselectAllButton=Deseleziona Tutti I Controlli
|
||||
health.check.runBatchBtn=Esegui i Controlli selezionati
|
||||
health.checkList.description=Seleziona i controlli nell'elenco a sinistra o usa i seguenti pulsanti.
|
||||
health.checkList.selectAllButton=Seleziona Tutti i Controlli
|
||||
health.checkList.deselectAllButton=Deseleziona Tutti i Controlli
|
||||
health.check.runBatchBtn=Esegui i Controlli Selezionati
|
||||
## Detail view
|
||||
health.check.detail.noSelectedCheck=Per i risultati seleziona un controllo di salute concluso nell'elenco a sinistra.
|
||||
health.check.detail.noSelectedCheck=Per i risultati seleziona un controllo di salute terminato nell'elenco a sinistra.
|
||||
health.check.detail.checkScheduled=Il controllo è pianificato.
|
||||
health.check.detail.checkRunning=Il controllo è attualmente in esecuzione…
|
||||
health.check.detail.checkRunning=Il controllo è correntemente in esecuzione…
|
||||
health.check.detail.checkSkipped=Il controllo non è stato selezionato per l'esecuzione.
|
||||
health.check.detail.checkFinished=Il controllo è terminato con successo.
|
||||
health.check.detail.checkFinishedAndFound=Il controllo ha terminato l'esecuzione. Si prega di rivedere i risultati.
|
||||
health.check.detail.checkFinished=Il controllo è terminato correttamente.
|
||||
health.check.detail.checkFinishedAndFound=Il controllo è terminato. Sei pregato di revisionare i risultati.
|
||||
health.check.detail.checkFailed=Il controllo è terminato a causa di un errore.
|
||||
health.check.detail.checkCancelled=Il controllo è stato annullato.
|
||||
health.check.exportBtn=Esporta Rapporto
|
||||
health.check.exportBtn=Esporta il Rapporto
|
||||
## Fix Application
|
||||
health.fix.fixBtn=Correggi
|
||||
health.fix.successTip=Correzione riuscita
|
||||
health.fix.failTip=Correzione fallita, vedi log per i dettagli
|
||||
health.fix.failTip=Correzione fallita, vedi i registri per i dettagli
|
||||
|
||||
# Preferences
|
||||
preferences.title=Impostazioni
|
||||
preferences.title=Preferenze
|
||||
## General
|
||||
preferences.general=Generali
|
||||
preferences.general=Generale
|
||||
preferences.general.theme=Aspetto
|
||||
preferences.general.theme.automatic=Automatico
|
||||
preferences.general.theme.light=Chiaro
|
||||
preferences.general.theme.dark=Scuro
|
||||
preferences.general.unlockThemes=Sblocca modalità scura
|
||||
preferences.general.showMinimizeButton=Mostra pulsante riduci a icona
|
||||
preferences.general.showTrayIcon=Mostra icona nel tray (richiede riavvio)
|
||||
preferences.general.startHidden=Nascondi la finestra all'avvio di Cryptomator
|
||||
preferences.general.debugLogging=Abilita i registri di debug
|
||||
preferences.general.debugDirectory=Mostra file log
|
||||
preferences.general.unlockThemes=Sblocca la modalità scura
|
||||
preferences.general.showMinimizeButton=Mostra il pulsante minimizza
|
||||
preferences.general.showTrayIcon=Mostra l'icona della barra d'applicazioni (richiede il riavvio)
|
||||
preferences.general.startHidden=Nascondi la finestra avviando Cryptomator
|
||||
preferences.general.debugLogging=Abilita la registrazione di debug
|
||||
preferences.general.debugDirectory=Rivela i file di registro
|
||||
preferences.general.autoStart=Avvia Cryptomator all'avvio del sistema
|
||||
preferences.general.keychainBackend=Memorizza password con
|
||||
preferences.general.interfaceOrientation=Orientamento Interfaccia
|
||||
preferences.general.keychainBackend=Memorizza le password con
|
||||
preferences.general.interfaceOrientation=Orientamento dell'Interfaccia
|
||||
preferences.general.interfaceOrientation.ltr=Da Sinistra a Destra
|
||||
preferences.general.interfaceOrientation.rtl=Da Destra a Sinistra
|
||||
## Volume
|
||||
preferences.volume=Drive virtuale
|
||||
preferences.volume.type=Tipo volume
|
||||
preferences.volume=Unità Virtuale
|
||||
preferences.volume.type=Tipo di Volume
|
||||
preferences.volume.webdav.port=Porta WebDAV
|
||||
preferences.volume.webdav.scheme=Schema WebDAV
|
||||
## Updates
|
||||
preferences.updates=Aggiornamenti
|
||||
preferences.updates.currentVersion=Versione attuale %s
|
||||
preferences.updates.autoUpdateCheck=Controlla automaticamente la presenza di aggiornamenti
|
||||
preferences.updates.checkNowBtn=Controlla adesso
|
||||
preferences.updates.updateAvailable=Disponibile aggiornamento alla versione %s.
|
||||
preferences.updates.currentVersion=Versione Corrente: %s
|
||||
preferences.updates.autoUpdateCheck=Cerca automaticamente gli aggiornamenti
|
||||
preferences.updates.checkNowBtn=Controlla Ora
|
||||
preferences.updates.updateAvailable=Aggiornamento alla versione %s disponibile.
|
||||
## Contribution
|
||||
preferences.contribute=Supportaci
|
||||
preferences.contribute.registeredFor=Certificato del supporto registrato per %s
|
||||
preferences.contribute.noCertificate=Supporta Cryptomator e ricevi un certificato di supporter. È come una chiave di licenza, ma per persone fantastiche che utilizzano software libero. ;-)
|
||||
preferences.contribute.getCertificate=Non ne hai già uno? Impara come puoi ottenerlo.
|
||||
preferences.contribute.promptText=Incolla qui il codice del certificato di supporter
|
||||
preferences.contribute.registeredFor=Certificato del sostenitore registrato per %s
|
||||
preferences.contribute.noCertificate=Supporta Cryptomator e ricevi il certificato da sostenitore. È come una chiave di licenza me per persone fantastiche che usano un software gratuito. ;-)
|
||||
preferences.contribute.getCertificate=Non ne hai ancora uno? Scopri come puoi ottenerlo.
|
||||
preferences.contribute.promptText=Incolla qui il codice del certificato da sostenitore
|
||||
#<-- Add entries for donations and code/translation/documentation contribution -->
|
||||
|
||||
## About
|
||||
preferences.about=Informazioni
|
||||
preferences.about=Info
|
||||
|
||||
# Vault Statistics
|
||||
stats.title=Statistiche per %s
|
||||
stats.cacheHitRate=Tasso di Colpo della Cache
|
||||
stats.cacheHitRate=Frequenza di Raggiungimento della Cache
|
||||
## Read
|
||||
stats.read.throughput.idle=Lettura: inattivo
|
||||
stats.read.throughput.kibs=Lettura: %.2f kiB/s
|
||||
@ -228,13 +234,13 @@ stats.read.total.data.none=Dati letti: -
|
||||
stats.read.total.data.kib=Dati letti: %.1f kiB
|
||||
stats.read.total.data.mib=Dati letti: %.1f MiB
|
||||
stats.read.total.data.gib=Dati letti: %.1f GiB
|
||||
stats.decr.total.data.none=Dati decriptati: -
|
||||
stats.decr.total.data.none=Dati decrittografati: -
|
||||
stats.decr.total.data.kib=Dati decrittografati: %.1f kiB
|
||||
stats.decr.total.data.mib=Dati decriptati: %.1f MiB
|
||||
stats.decr.total.data.mib=Dati decrittografati: %.1f MiB
|
||||
stats.decr.total.data.gib=Dati decrittografati: %.1f GiB
|
||||
stats.read.accessCount=Totale lettura: %d
|
||||
stats.read.accessCount=Letture totali: %d
|
||||
## Write
|
||||
stats.write.throughput.idle=Scrivi: inattivo
|
||||
stats.write.throughput.idle=Scrittura: inattivo
|
||||
stats.write.throughput.kibs=Scrittura: %.2f kiB/s
|
||||
stats.write.throughput.mibs=Scrittura: %.2f MiB/s
|
||||
stats.write.total.data.none=Dati scritti: -
|
||||
@ -245,84 +251,85 @@ stats.encr.total.data.none=Dati crittografati: -
|
||||
stats.encr.total.data.kib=Dati crittografati: %.1f kiB
|
||||
stats.encr.total.data.mib=Dati crittografati: %.1f MiB
|
||||
stats.encr.total.data.gib=Dati crittografati: %.1f GiB
|
||||
stats.write.accessCount=Totale scritture: %d
|
||||
stats.write.accessCount=Scritture totali: %d
|
||||
|
||||
# Main Window
|
||||
main.closeBtn.tooltip=Chiudi
|
||||
main.minimizeBtn.tooltip=Minimizza
|
||||
main.preferencesBtn.tooltip=Impostazioni
|
||||
main.preferencesBtn.tooltip=Preferenze
|
||||
main.debugModeEnabled.tooltip=La modalità di debug è abilitata
|
||||
main.donationKeyMissing.tooltip=Per favore considera una donazione
|
||||
main.donationKeyMissing.tooltip=Sei pregato di considerare di donare
|
||||
## Drag 'n' Drop
|
||||
main.dropZone.dropVault=Aggiungi questa cassaforte
|
||||
main.dropZone.unknownDragboardContent=Se vuoi aggiungere una cassaforte, trascinala in questa finestra
|
||||
main.dropZone.unknownDragboardContent=Se desideri aggiungere una cassaforte, trascinala a questa finestra
|
||||
## Vault List
|
||||
main.vaultlist.emptyList.onboardingInstruction=Clicca qui per aggiungere una cassaforte
|
||||
main.vaultlist.contextMenu.remove=Rimuovi…
|
||||
main.vaultlist.contextMenu.lock=Blocca
|
||||
main.vaultlist.contextMenu.unlock=Sblocca…
|
||||
main.vaultlist.contextMenu.unlockNow=Sblocca Ora
|
||||
main.vaultlist.contextMenu.vaultoptions=Mostra Opzioni Cassaforte
|
||||
main.vaultlist.contextMenu.reveal=Rivela Drive
|
||||
main.vaultlist.contextMenu.vaultoptions=Mostra le Opzioni della Cassaforte
|
||||
main.vaultlist.contextMenu.reveal=Rivela Unità
|
||||
main.vaultlist.addVaultBtn=Aggiungi Cassaforte
|
||||
## Vault Detail
|
||||
### Welcome
|
||||
main.vaultDetail.welcomeOnboarding=Grazie per aver scelto Cryptomator per proteggere i tuoi file. Se hai bisogno di assistenza, dai un'occhiata alle guide per iniziare:
|
||||
main.vaultDetail.welcomeOnboarding=Grazie per aver scelto Cryptomator per proteggere i tuoi file. Se necessiti d'assistenza, dai un'occhiata alle nostre guide per iniziare:
|
||||
### Locked
|
||||
main.vaultDetail.lockedStatus=BLOCCATO
|
||||
main.vaultDetail.unlockBtn=Sblocca…
|
||||
main.vaultDetail.unlockNowBtn=Sblocca adesso
|
||||
main.vaultDetail.optionsBtn=Opzioni Cassaforte
|
||||
main.vaultDetail.unlockNowBtn=Sblocca Ora
|
||||
main.vaultDetail.optionsBtn=Opzioni della Cassaforte
|
||||
main.vaultDetail.passwordSavedInKeychain=Password salvata
|
||||
### Unlocked
|
||||
main.vaultDetail.unlockedStatus=SBLOCCATO
|
||||
main.vaultDetail.unlockedStatus=SBLOCCATA
|
||||
main.vaultDetail.accessLocation=I contenuti della tua cassaforte sono accessibili qui:
|
||||
main.vaultDetail.revealBtn=Visualizza disco
|
||||
main.vaultDetail.revealBtn=Rivela Unità
|
||||
main.vaultDetail.lockBtn=Blocca
|
||||
main.vaultDetail.bytesPerSecondRead=Lettura:
|
||||
main.vaultDetail.bytesPerSecondWritten=Scrittura:
|
||||
main.vaultDetail.throughput.idle=inattivo
|
||||
main.vaultDetail.throughput.kbps=%.1f kiB/s
|
||||
main.vaultDetail.throughput.mbps=%.1f MiB/s
|
||||
main.vaultDetail.stats=Statistiche Cassaforte
|
||||
main.vaultDetail.stats=Statistiche della Cassaforte
|
||||
### Missing
|
||||
main.vaultDetail.missing.info=Cryptomator non ha potuto trovare una cassaforte in questo percorso.
|
||||
main.vaultDetail.missing.recheck=Ricontrollare
|
||||
main.vaultDetail.missing.remove=Rimuovi dalla Lista Cassaforte…
|
||||
main.vaultDetail.missing.changeLocation=Cambia posizione della Cassaforte…
|
||||
main.vaultDetail.missing.info=Cryptomator non è riuscito a trovare una cassaforte in questo percorso.
|
||||
main.vaultDetail.missing.recheck=Ricontrolla
|
||||
main.vaultDetail.missing.remove=Rimuovi dall'Elenco di Cassaforti…
|
||||
main.vaultDetail.missing.changeLocation=Cambia la Posizione della Cassaforte…
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Aggiorna la cassaforte
|
||||
main.vaultDetail.migratePrompt=Prima di potervi accedere la tua cassaforte deve essere aggiornata al nuovo formato
|
||||
main.vaultDetail.migrateButton=Aggiorna la Cassaforte
|
||||
main.vaultDetail.migratePrompt=La tua cassaforte dev'esser aggiornata a un nuovo formato, prima di potervi accedere
|
||||
|
||||
# Wrong File Alert
|
||||
wrongFileAlert.title=Come Criptare i File
|
||||
wrongFileAlert.header.title=Hai provato a cifrare questi file?
|
||||
wrongFileAlert.header.lead=A questo scopo, Cryptomator fornisce un volume nel file manager di sistema.
|
||||
wrongFileAlert.instruction.0=Per cifrare file, segui questi passi:
|
||||
wrongFileAlert.title=Come Crittografare i File
|
||||
wrongFileAlert.header.title=Hai tentato di crittografare questi file?
|
||||
wrongFileAlert.header.lead=Per questo scopo, Cryptomator fornisce un volume nel gestore dei tuoi file di sistema.
|
||||
wrongFileAlert.instruction.0=Per crittografare i file, segui questi passi:
|
||||
wrongFileAlert.instruction.1=1. Sblocca la tua cassaforte.
|
||||
wrongFileAlert.instruction.2=2. Clicca su "Rivela" per aprire il volume nel tuo file manager.
|
||||
wrongFileAlert.instruction.2=2. Clicca su "Rivela" per aprire il volume nel gestore dei tuoi file.
|
||||
wrongFileAlert.instruction.3=3. Aggiungi i tuoi file a questo volume.
|
||||
wrongFileAlert.link=Per ulteriore assistenza, visita
|
||||
|
||||
# Vault Options
|
||||
## General
|
||||
vaultOptions.general=Generali
|
||||
vaultOptions.general.vaultName=Nome Cassaforte
|
||||
vaultOptions.general=Generale
|
||||
vaultOptions.general.vaultName=Nome della Cassaforte
|
||||
vaultOptions.general.autoLock.lockAfterTimePart1=Blocca quando inattivo per
|
||||
vaultOptions.general.autoLock.lockAfterTimePart2=minuti
|
||||
vaultOptions.general.unlockAfterStartup=Sblocca vault all'avvio di Cryptomator
|
||||
vaultOptions.general.actionAfterUnlock=Dopo aver sbloccato con successo
|
||||
vaultOptions.general.unlockAfterStartup=Sblocca la cassaforte all'avvio di Cryptomator
|
||||
vaultOptions.general.actionAfterUnlock=Dopo uno sblocco riuscito
|
||||
vaultOptions.general.actionAfterUnlock.ignore=Non fare nulla
|
||||
vaultOptions.general.actionAfterUnlock.reveal=Visualizza disco
|
||||
vaultOptions.general.actionAfterUnlock.reveal=Rivela Unità
|
||||
vaultOptions.general.actionAfterUnlock.ask=Chiedi
|
||||
vaultOptions.general.startHealthCheckBtn=Avvia il Controllo della Salute
|
||||
|
||||
## Mount
|
||||
vaultOptions.mount=Montaggio
|
||||
vaultOptions.mount.readonly=Sola lettura
|
||||
vaultOptions.mount.customMountFlags=Opzioni personalizzate
|
||||
vaultOptions.mount.readonly=Sola Lettura
|
||||
vaultOptions.mount.customMountFlags=Flag di Montaggio Personalizzati
|
||||
vaultOptions.mount.winDriveLetterOccupied=occupato
|
||||
vaultOptions.mount.mountPoint=Punto di mount
|
||||
vaultOptions.mount.mountPoint.auto=Scegli automaticamente una posizione adatta
|
||||
vaultOptions.mount.mountPoint=Punto di Montaggio
|
||||
vaultOptions.mount.mountPoint.auto=Scegli automaticamente una posizione idonea
|
||||
vaultOptions.mount.mountPoint.driveLetter=Usa la lettera del drive assegnata
|
||||
vaultOptions.mount.mountPoint.custom=Percorso personalizzato
|
||||
vaultOptions.mount.mountPoint.directoryPickerButton=Scegli…
|
||||
|
@ -13,8 +13,11 @@ generic.button.done=完了
|
||||
generic.button.next=次へ
|
||||
generic.button.print=印刷
|
||||
## Error
|
||||
generic.error.title=予期しないエラーが発生しました
|
||||
generic.error.instruction=予期しないことが発生しました。下部のエラーテキストとエラーに至った経緯の説明を報告していただけると幸いです。
|
||||
generic.error.title=エラー %s
|
||||
generic.error.instruction=Cryptomator で予期できない問題が発生しました! 。このエラーの解決方法を検索することができ、まだ報告されていない場合は、報告を行うことができます。
|
||||
generic.error.hyperlink.lookup=このエラーを検索する
|
||||
generic.error.hyperlink.report=このエラーを報告する
|
||||
generic.error.technicalDetails=詳細:
|
||||
|
||||
# Defaults
|
||||
defaults.vault.vaultName=金庫
|
||||
@ -32,7 +35,7 @@ traymenu.vault.reveal=表示
|
||||
addvaultwizard.title=金庫を追加
|
||||
## Welcome
|
||||
addvaultwizard.welcome.newButton=新しい金庫を作成
|
||||
addvaultwizard.welcome.existingButton=既存の金庫を開く
|
||||
addvaultwizard.welcome.existingButton=すでにある金庫を開く
|
||||
## New
|
||||
### Name
|
||||
addvaultwizard.new.nameInstruction=金庫の名前を入力してください
|
||||
@ -95,6 +98,7 @@ forgetPassword.information=システムから金庫の保存済みパスワー
|
||||
forgetPassword.confirmBtn=パスワードを削除
|
||||
|
||||
# Unlock
|
||||
unlock.title="%s" を解錠
|
||||
unlock.passwordPrompt="%s" のパスワードを入力してください:
|
||||
unlock.savePassword=パスワードを記憶させる
|
||||
unlock.unlockBtn=解錠
|
||||
@ -133,12 +137,12 @@ migration.run.progressHint=時間がかかる場合があります...
|
||||
migration.success.nextStepsInstructions="%s" の移行が成功しました。\n金庫を解錠できるようになりました。
|
||||
migration.success.unlockNow=今すぐ解錠
|
||||
## Missing file system capabilities
|
||||
migration.error.missingFileSystemCapabilities.title=サポートされないファイルタイプ
|
||||
migration.error.missingFileSystemCapabilities.description=金庫が不適切なファイルシステムにあるため、移行が開始されませんでした。
|
||||
migration.error.missingFileSystemCapabilities.reason.LONG_FILENAMES=ファイルシステムが長いファイル名をサポートしていません。
|
||||
migration.error.missingFileSystemCapabilities.reason.LONG_PATHS=ファイルシステムが長いパスをサポートしていません。
|
||||
migration.error.missingFileSystemCapabilities.reason.READ_ACCESS=ファイルシステムによって読み込みが許可されていません。
|
||||
migration.error.missingFileSystemCapabilities.reason.WRITE_ACCESS=ファイルシステムによって書き込みが許可されていません。
|
||||
migration.error.missingFileSystemCapabilities.title=サポートされないファイル システム
|
||||
migration.error.missingFileSystemCapabilities.description=金庫が不適切なファイル システムにあるため、移行が開始されませんでした。
|
||||
migration.error.missingFileSystemCapabilities.reason.LONG_FILENAMES=ファイル システムが長いファイル名をサポートしていません。
|
||||
migration.error.missingFileSystemCapabilities.reason.LONG_PATHS=ファイル システムが長いパスをサポートしていません。
|
||||
migration.error.missingFileSystemCapabilities.reason.READ_ACCESS=ファイル システムによって読み込みが許可されていません。
|
||||
migration.error.missingFileSystemCapabilities.reason.WRITE_ACCESS=ファイル システムによって書き込みが許可されていません。
|
||||
## Impossible
|
||||
migration.impossible.heading=金庫の移行に失敗しました
|
||||
migration.impossible.reason=ストレージ場所またはアクセスポイントに互換性がないため、金庫を自動的に移行できません。
|
||||
@ -146,13 +150,37 @@ migration.impossible.moreInfo=金庫を古いバージョンで開くことは
|
||||
|
||||
# Health Check
|
||||
## Start
|
||||
health.title="%s" の正常性チェック
|
||||
health.intro.header=正常性チェック
|
||||
health.intro.text=正常性チェックは、金庫内部で修復できる可能性のある問題を収集します。次の点に注意してください:
|
||||
health.intro.remarkSync=すべてのデバイスが完全に同期されていることを確認してください。これによってほとんどの問題は解決します。
|
||||
health.intro.remarkFix=すべての問題を修復できるわけではありません。
|
||||
health.intro.remarkBackup=データが破損しているときは、バックアップからのみ可能です。
|
||||
health.intro.affirmation=上記の情報を理解しました。
|
||||
## Start Failure
|
||||
health.fail.header=金庫の構成を読み込み中にエラーが発生しました
|
||||
health.fail.ioError=設定ファイルへのアクセスと読み込み中にエラーが発生しました。
|
||||
health.fail.parseError=金庫の構成を解析中にエラーが発生しました。
|
||||
health.fail.moreInfo=詳細
|
||||
## Check Selection
|
||||
health.checkList.description=左のリストを使用してチェックを選択するか、下のボタンで選択してください。
|
||||
health.checkList.selectAllButton=すべてのチェックを選択
|
||||
health.checkList.deselectAllButton=すべてのチェックを解除
|
||||
health.check.runBatchBtn=選択したチェックを実行
|
||||
## Detail view
|
||||
health.check.detail.noSelectedCheck=左のリストを選択して終了した正常性チェックの結果を確認できます。
|
||||
health.check.detail.checkScheduled=チェックが予定されています。
|
||||
health.check.detail.checkRunning=チェック中です...
|
||||
health.check.detail.checkSkipped=実行するチェックが選択されていません。
|
||||
health.check.detail.checkFinished=チェックが正常に終了しました。
|
||||
health.check.detail.checkFinishedAndFound=実行中のチェックが終了しました。結果を確認してください。
|
||||
health.check.detail.checkFailed=エラーが発生したためチェックを終了しました。
|
||||
health.check.detail.checkCancelled=チェックがキャンセルされました。
|
||||
health.check.exportBtn=結果をエクスポート
|
||||
## Fix Application
|
||||
health.fix.fixBtn=修正
|
||||
health.fix.successTip=正常に修正されました
|
||||
health.fix.failTip=修正に失敗しました。詳細はログを参照してください。
|
||||
|
||||
# Preferences
|
||||
preferences.title=設定
|
||||
@ -188,7 +216,7 @@ preferences.updates.updateAvailable=利用可能なバージョン %s に更新
|
||||
preferences.contribute=サポートする
|
||||
preferences.contribute.registeredFor=サポーター証明書が %s に登録されました
|
||||
preferences.contribute.noCertificate=Cryptomator を支援し、サポーター証明書を受け取りましょう。ライセンスキーに似ていますがフリーソフトを使う寄付者向けのキーです。 ;-)
|
||||
preferences.contribute.getCertificate=まだ証明書を手に入れていませんか? 詳細を確認しましょう。
|
||||
preferences.contribute.getCertificate=まだ証明書を手に入れていませんか? 詳細はこちらから確認できます。
|
||||
preferences.contribute.promptText=サポーター証明書をここに張り付けてください
|
||||
#<-- Add entries for donations and code/translation/documentation contribution -->
|
||||
|
||||
@ -254,7 +282,7 @@ main.vaultDetail.optionsBtn=金庫のオプション
|
||||
main.vaultDetail.passwordSavedInKeychain=パスワードを保存しました
|
||||
### Unlocked
|
||||
main.vaultDetail.unlockedStatus=解錠済み
|
||||
main.vaultDetail.accessLocation=アクセス可能な金庫のコンテンツ:
|
||||
main.vaultDetail.accessLocation=金庫の内容はこちらからアクセスできます:
|
||||
main.vaultDetail.revealBtn=ドライブを表示
|
||||
main.vaultDetail.lockBtn=施錠
|
||||
main.vaultDetail.bytesPerSecondRead=読み取り:
|
||||
@ -293,6 +321,7 @@ vaultOptions.general.actionAfterUnlock=解錠に成功したあと
|
||||
vaultOptions.general.actionAfterUnlock.ignore=何もしない
|
||||
vaultOptions.general.actionAfterUnlock.reveal=ドライブを表示
|
||||
vaultOptions.general.actionAfterUnlock.ask=尋ねる
|
||||
vaultOptions.general.startHealthCheckBtn=正常性チェックを開始
|
||||
|
||||
## Mount
|
||||
vaultOptions.mount=マウント
|
||||
|
@ -13,8 +13,6 @@ generic.button.done=완료
|
||||
generic.button.next=다음
|
||||
generic.button.print=인쇄
|
||||
## Error
|
||||
generic.error.title=예기치 않은 오류가 발생되었습니다.
|
||||
generic.error.instruction=이러한 일은 일어나지 말아야 합니다. 아래의 텍스트와 이 오류를 발생시킨 단계에 대한 설명을 포함하여 제출하여 주십시요.
|
||||
|
||||
# Defaults
|
||||
defaults.vault.vaultName=Vault
|
||||
@ -95,6 +93,7 @@ forgetPassword.information=시스템 키체인에서 이 Vault의 저장된 비
|
||||
forgetPassword.confirmBtn=비밀번호 분실
|
||||
|
||||
# Unlock
|
||||
unlock.title="%s" 잠금 해제
|
||||
unlock.passwordPrompt="%s"의 비밀번호를 입력하십시요.
|
||||
unlock.savePassword=비밀번호 기억
|
||||
unlock.unlockBtn=잠금해제
|
||||
@ -146,13 +145,26 @@ migration.impossible.moreInfo=Vault를 이전 버전으로 계속 열수 있습
|
||||
|
||||
# Health Check
|
||||
## Start
|
||||
health.title="%s"의 상태 검사
|
||||
health.intro.header=상태 검사
|
||||
health.intro.text=상태 검사는 Vault의 내부 구조의 문제점을 점검하고 해결할 수 있는 기능입니다. 다음 사항을 유의하시기 바랍니다:
|
||||
## Start Failure
|
||||
health.fail.moreInfo=더 많은 정보
|
||||
## Check Selection
|
||||
health.checkList.selectAllButton=모든 항목 선택
|
||||
health.checkList.deselectAllButton=모든 항목 선택 해제
|
||||
health.check.runBatchBtn=선택된 검사항목 실행
|
||||
## Detail view
|
||||
health.check.detail.noSelectedCheck=결과를 보려면 왼쪽 목록에서 완료된 상태 검사항목을 선택하십시오.
|
||||
health.check.detail.checkScheduled=검사가 예약되었습니다.
|
||||
health.check.detail.checkRunning=검사가 현재 실행중입니다...
|
||||
health.check.detail.checkSkipped=선택된 검사항목이 없습니다.
|
||||
health.check.detail.checkFinished=검사가 성공적으로 완료되었습니다.
|
||||
health.check.exportBtn=보고서 내보내기
|
||||
## Fix Application
|
||||
health.fix.fixBtn=문제해결
|
||||
health.fix.successTip=문제 해결이 성공적으로 완료되었습니다
|
||||
health.fix.failTip=문제 해결 실패, 상세 정보는 로그를 참조하십시요.
|
||||
|
||||
# Preferences
|
||||
preferences.title=환경설정
|
||||
@ -293,6 +305,7 @@ vaultOptions.general.actionAfterUnlock=성공적으로 잠금해제 후
|
||||
vaultOptions.general.actionAfterUnlock.ignore=아무 것도 하지 않음
|
||||
vaultOptions.general.actionAfterUnlock.reveal=드라이브 표시
|
||||
vaultOptions.general.actionAfterUnlock.ask=요청
|
||||
vaultOptions.general.startHealthCheckBtn=상태 검사 시작
|
||||
|
||||
## Mount
|
||||
vaultOptions.mount=드라이브 구성
|
||||
|
@ -13,8 +13,6 @@ generic.button.done=Darīts
|
||||
generic.button.next=Tālāk
|
||||
generic.button.print=Drukāt
|
||||
## Error
|
||||
generic.error.title=Radās neparedzēta kļūda
|
||||
generic.error.instruction=Šis vēl nav atgadījies. Lūdzu ziņo zemāk redzamo kļūdas tekstu un iekļauj aprakstu, kas noveda pie šīs kļūdas.
|
||||
|
||||
# Defaults
|
||||
|
||||
|
@ -13,8 +13,6 @@ generic.button.done=Ferdig
|
||||
generic.button.next=Neste
|
||||
generic.button.print=Skriv ut
|
||||
## Error
|
||||
generic.error.title=Det oppstod en uventet feil
|
||||
generic.error.instruction=Dette skulle ikke ha skjedd. Rapporter feilteksten nedenfor og legg inn en beskrivelse av hvilke trinn som førte til denne feilen.
|
||||
|
||||
# Defaults
|
||||
defaults.vault.vaultName=Hvelv
|
||||
@ -45,6 +43,7 @@ addvaultwizard.new.directoryPickerLabel=Tilpasset lagringssted
|
||||
addvaultwizard.new.directoryPickerButton=Velg…
|
||||
addvaultwizard.new.directoryPickerTitle=Velg mappe
|
||||
addvaultwizard.new.fileAlreadyExists=En fil eller mappe med det hvelvnavnet finnes allerede
|
||||
addvaultwizard.new.locationIsOk=Egnet sted for hvelvet ditt
|
||||
addvaultwizard.new.invalidName=Ugyldig navn på hvelvet. Vennligst vurder et vanlig mappenavn.
|
||||
### Password
|
||||
addvaultwizard.new.createVaultBtn=Opprett hvelv
|
||||
@ -92,6 +91,7 @@ forgetPassword.information=Dette vil slette det lagrede passordet til dette hvel
|
||||
forgetPassword.confirmBtn=Glem passord
|
||||
|
||||
# Unlock
|
||||
unlock.title=Lås opp "%s"
|
||||
unlock.passwordPrompt=Skriv inn passordet for "%s":
|
||||
unlock.savePassword=Husk passord
|
||||
unlock.unlockBtn=Lås opp
|
||||
@ -141,10 +141,15 @@ migration.impossible.moreInfo=Hvelvet kan fortsatt åpnes hvis du bruker en eldr
|
||||
|
||||
# Health Check
|
||||
## Start
|
||||
health.intro.remarkFix=Ikke alle problemer kan løses.
|
||||
## Start Failure
|
||||
health.fail.moreInfo=Mer informasjon
|
||||
## Check Selection
|
||||
## Detail view
|
||||
## Fix Application
|
||||
health.fix.fixBtn=Reparer
|
||||
health.fix.successTip=Vellykket reparering
|
||||
health.fix.failTip=Repareringen feilet. Se loggen for detaljer
|
||||
|
||||
# Preferences
|
||||
preferences.title=Innstillinger
|
||||
@ -224,6 +229,7 @@ main.dropZone.dropVault=Legg til dette hvelvet
|
||||
main.dropZone.unknownDragboardContent=Hvis du vil legge til et hvelv, kan du dra det til dette vinduet
|
||||
## Vault List
|
||||
main.vaultlist.emptyList.onboardingInstruction=Klikk her for å legge til et hvelv
|
||||
main.vaultlist.contextMenu.remove=Fjern…
|
||||
main.vaultlist.contextMenu.lock=Lås
|
||||
main.vaultlist.contextMenu.unlock=Lås opp…
|
||||
main.vaultlist.contextMenu.unlockNow=Lås opp nå
|
||||
|
@ -13,8 +13,11 @@ generic.button.done=Klaar
|
||||
generic.button.next=Volgende
|
||||
generic.button.print=Afdrukken
|
||||
## Error
|
||||
generic.error.title=Er is een onverwachte fout opgetreden
|
||||
generic.error.instruction=Dit had niet moeten gebeuren. Rapporteer de onderstaande fouttekst en voeg een beschrijving toe van de stappen die tot deze fout hebben geleid.
|
||||
generic.error.title=Fout %s
|
||||
generic.error.instruction=Oeps! Cryptomator verwachtte niet dat dit zou gebeuren. U kunt bestaande oplossingen opzoeken voor deze fout, of indien er nog geen melding van deze fout is gemaakt mag u dit ook gerust doen.
|
||||
generic.error.hyperlink.lookup=Deze fout opzoeken
|
||||
generic.error.hyperlink.report=Deze fout melden
|
||||
generic.error.technicalDetails=Details:
|
||||
|
||||
# Defaults
|
||||
defaults.vault.vaultName=Kluis
|
||||
@ -95,6 +98,7 @@ forgetPassword.information=Dit zal het opgeslagen wachtwoord van deze kluis uit
|
||||
forgetPassword.confirmBtn=Wachtwoord vergeten
|
||||
|
||||
# Unlock
|
||||
unlock.title=Ontgrendel "%s"
|
||||
unlock.passwordPrompt=Voer wachtwoord voor "%s" in:
|
||||
unlock.savePassword=Wachtwoord Onthouden
|
||||
unlock.unlockBtn=Ontgrendel
|
||||
@ -146,13 +150,37 @@ migration.impossible.moreInfo=De kluis is nog te openen met een oudere versie. I
|
||||
|
||||
# Health Check
|
||||
## Start
|
||||
health.title=Controle van "%s"
|
||||
health.intro.header=Controle
|
||||
health.intro.text=Controles zijn er voor het detecteren en indien mogelijk oplossen van problemen met de interne structuur van uw kluis. Houd daarbij rekening met het volgende:
|
||||
health.intro.remarkSync=Zorg er voor dat alle apparaten volledig gesynchroniseerd zijn. Dit lost de meeste problemen op.
|
||||
health.intro.remarkFix=Niet alle problemen kunnen opgelost worden.
|
||||
health.intro.remarkBackup=Als data is beschadigd, kan alleen een back-up helpen.
|
||||
health.intro.affirmation=Ik heb de informatie hierboven gelezen en begrepen
|
||||
## Start Failure
|
||||
health.fail.header=Fout bij het laden van de kluisconfiguratie
|
||||
health.fail.ioError=Er is een fout opgetreden tijdens het openen en lezen van het configuratiebestand.
|
||||
health.fail.parseError=Er is een fout opgetreden bij het inladen van de kluisconfiguratie.
|
||||
health.fail.moreInfo=Meer informatie
|
||||
## Check Selection
|
||||
health.checkList.description=Selecteer controles in de lijst aan de linkerkant, of gebruik de onderstaande knoppen.
|
||||
health.checkList.selectAllButton=Selecteer alle controles
|
||||
health.checkList.deselectAllButton=Deselecteer alle controles
|
||||
health.check.runBatchBtn=Geselecteerde controles uitvoeren
|
||||
## Detail view
|
||||
health.check.detail.noSelectedCheck=Voor resultaten selecteert u een voltooide gezondheidscontrole in de linker lijst.
|
||||
health.check.detail.checkScheduled=De controle is ingepland.
|
||||
health.check.detail.checkRunning=De controle wordt momenteel uitgevoerd…
|
||||
health.check.detail.checkSkipped=De controle was niet geselecteerd om uit te voeren.
|
||||
health.check.detail.checkFinished=De controle is succesvol beëindigd.
|
||||
health.check.detail.checkFinishedAndFound=De controle is beëindigd. Bekijk alstublieft de resultaten.
|
||||
health.check.detail.checkFailed=De controle is afgesloten door een fout.
|
||||
health.check.detail.checkCancelled=De controle werd geannuleerd.
|
||||
health.check.exportBtn=Exporteer rapport
|
||||
## Fix Application
|
||||
health.fix.fixBtn=Herstel
|
||||
health.fix.successTip=Hersteld
|
||||
health.fix.failTip=Herstellen mislukt, zie logboek voor details
|
||||
|
||||
# Preferences
|
||||
preferences.title=Voorkeuren
|
||||
@ -293,6 +321,7 @@ vaultOptions.general.actionAfterUnlock=Na een succesvolle ontgrendeling
|
||||
vaultOptions.general.actionAfterUnlock.ignore=Niets doen
|
||||
vaultOptions.general.actionAfterUnlock.reveal=Toon Schijf
|
||||
vaultOptions.general.actionAfterUnlock.ask=Vragen
|
||||
vaultOptions.general.startHealthCheckBtn=Start controle
|
||||
|
||||
## Mount
|
||||
vaultOptions.mount=Aankoppelen
|
||||
|
@ -13,8 +13,6 @@ generic.button.done=Ferdig
|
||||
generic.button.next=Neste
|
||||
generic.button.print=Skriv ut
|
||||
## Error
|
||||
generic.error.title=Eit uventa problem oppstod
|
||||
generic.error.instruction=Dette skulle ikkje ha skjedd. Rapporter feilteksten nedanfor og legg inn ei skildring av kva trinn som førte til denne feilen.
|
||||
|
||||
# Defaults
|
||||
|
||||
|
@ -13,8 +13,6 @@ generic.button.done=ਮੁਕੰਮਲ
|
||||
generic.button.next=ਅੱਗੇ
|
||||
generic.button.print=ਪਰਿੰਟ ਕਰੋ
|
||||
## Error
|
||||
generic.error.title=ਅਣਪਛਾਤੀ ਗਲਤੀ ਵਪਾਰੀ ਹੈ
|
||||
generic.error.instruction=ਇਹ ਵਾਪਰਨਾ ਨਹੀਂ ਚਾਹੀਦਾ ਸੀ। ਹੇਠ ਦਿੱਤੀ ਗਲਤੀ ਲਿਖਤ ਬਾਰੇ ਰਿਪੋਰਟ ਕਰੋ ਅਤੇ ਇਹ ਗਲਤੀ ਹੋਣ ਦੌਰਾਨ ਜਿਹੜੇ ਵੀ ਕਦਮ ਚੁੱਕੇ ਹਨ, ਬਾਰੇ ਵੇਰਵਾ ਦਿਉ।
|
||||
|
||||
# Defaults
|
||||
defaults.vault.vaultName=ਵਾਲਟ
|
||||
|
@ -13,8 +13,11 @@ generic.button.done=Gotowe
|
||||
generic.button.next=Dalej
|
||||
generic.button.print=Drukuj
|
||||
## Error
|
||||
generic.error.title=Wystąpił nieoczekiwany błąd
|
||||
generic.error.instruction=To nie powinno było się zdarzyć. Proszę zgłosić poniższy tekst z błędem i zamieścić opis kroków, które doprowadziły do tego błędu.
|
||||
generic.error.title=Błąd %s
|
||||
generic.error.instruction=Ups! Cryptomator nie spodziewał się czegoś takiego. Możesz wyszukać istniejące rozwiązania dla tego błędu. Lub, jeśli nie został on jeszcze zgłoszony, możesz sam to zrobić.
|
||||
generic.error.hyperlink.lookup=Wyszukaj ten błąd
|
||||
generic.error.hyperlink.report=Zgłoś ten błąd
|
||||
generic.error.technicalDetails=Szczegóły:
|
||||
|
||||
# Defaults
|
||||
defaults.vault.vaultName=Sejf
|
||||
|
@ -13,8 +13,6 @@ generic.button.done=Ok
|
||||
generic.button.next=Seguinte
|
||||
generic.button.print=Imprimir
|
||||
## Error
|
||||
generic.error.title=Ocorreu um erro inesperado
|
||||
generic.error.instruction=Isto não devia ter acontecido. Por favor reporte o texto do erro abaixo e descreva os passos que levaram a este problema.
|
||||
|
||||
# Defaults
|
||||
defaults.vault.vaultName=Cofre
|
||||
|
@ -13,8 +13,11 @@ generic.button.done=Concluído
|
||||
generic.button.next=Próximo
|
||||
generic.button.print=Imprimir
|
||||
## Error
|
||||
generic.error.title=Ocorreu um erro inesperado
|
||||
generic.error.instruction=Isso não deveria ter ocorrido. Por favor, reporte o texto do erro abaixo e inclua uma descrição dos passos que levaram a este erro.
|
||||
generic.error.title=Erro %s
|
||||
generic.error.instruction=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.
|
||||
generic.error.hyperlink.lookup=Procure este erro
|
||||
generic.error.hyperlink.report=Reportar este erro
|
||||
generic.error.technicalDetails=Detalhes:
|
||||
|
||||
# Defaults
|
||||
defaults.vault.vaultName=Cofre
|
||||
|
@ -2,86 +2,363 @@
|
||||
|
||||
# Generics
|
||||
## Button
|
||||
generic.button.apply=Aplică
|
||||
generic.button.back=Înapoi
|
||||
generic.button.cancel=Anulează
|
||||
generic.button.change=Modifică
|
||||
generic.button.close=Închide
|
||||
generic.button.copy=Copiază
|
||||
generic.button.copied=Copiat!
|
||||
generic.button.done=Terminat
|
||||
generic.button.next=Următorul
|
||||
generic.button.print=Tipărește
|
||||
## Error
|
||||
|
||||
# Defaults
|
||||
defaults.vault.vaultName=Seif
|
||||
|
||||
# Tray Menu
|
||||
traymenu.showMainWindow=Afișează
|
||||
traymenu.showPreferencesWindow=Preferințe
|
||||
traymenu.lockAllVaults=Blochează toate
|
||||
traymenu.quitApplication=Ieșire
|
||||
traymenu.vault.unlock=Deblocați
|
||||
traymenu.vault.lock=Blocaţi
|
||||
traymenu.vault.reveal=Afişare
|
||||
|
||||
# Add Vault Wizard
|
||||
addvaultwizard.title=Adaugă un seif
|
||||
## Welcome
|
||||
addvaultwizard.welcome.newButton=Creează seif nou
|
||||
addvaultwizard.welcome.existingButton=Deschide un seif existent
|
||||
## New
|
||||
### Name
|
||||
addvaultwizard.new.nameInstruction=Alege un nume pentru seif
|
||||
addvaultwizard.new.namePrompt=Nume seif
|
||||
### Location
|
||||
addvaultwizard.new.locationInstruction=Unde ar trebui ca Cryptomator să stocheze fișierele criptate din seiful dumneavoastră?
|
||||
addvaultwizard.new.locationLabel=Locație stocare
|
||||
addvaultwizard.new.locationPrompt=…
|
||||
addvaultwizard.new.directoryPickerLabel=Locație personalizată
|
||||
addvaultwizard.new.directoryPickerButton=Alege…
|
||||
addvaultwizard.new.directoryPickerTitle=Alege Dosar
|
||||
addvaultwizard.new.fileAlreadyExists=Există deja un fișier sau un dosar cu numele seifului
|
||||
addvaultwizard.new.locationDoesNotExist=Dosarul în calea specificată nu există sau nu poate fi accesat
|
||||
addvaultwizard.new.locationIsNotWritable=Nu există acces la scriere la calea specificată
|
||||
addvaultwizard.new.locationIsOk=Locația potrivită pentru seiful dumneavoastră
|
||||
addvaultwizard.new.invalidName=Nume seif invalid. Vă rugăm sa luați în considerare un nume de dosar obișnuit.
|
||||
### Password
|
||||
addvaultwizard.new.createVaultBtn=Crează seif
|
||||
addvaultwizard.new.generateRecoveryKeyChoice=Nu veți putea accesa datele dvs. fără parolă. Doriți o cheie de recuperare pentru cazul în care vă pierdeți parola?
|
||||
addvaultwizard.new.generateRecoveryKeyChoice.yes=Da, vă rog, mai bine sigur decât rău
|
||||
addvaultwizard.new.generateRecoveryKeyChoice.no=Nu, mulțumesc, nu îmi voi pierde parola
|
||||
### Information
|
||||
addvault.new.readme.storageLocation.fileName=IMPORTANT.rtf
|
||||
addvault.new.readme.storageLocation.1=⚠️ FIȘIERE SEIF ⚠️
|
||||
addvault.new.readme.storageLocation.2=Aceasta este locația de stocare a seifului dvs.
|
||||
addvault.new.readme.storageLocation.3=Să NU
|
||||
addvault.new.readme.storageLocation.4=• modificați fișierele din acest dosar sau
|
||||
addvault.new.readme.storageLocation.5=• inserați fișiere destinate criptării în acest director.
|
||||
addvault.new.readme.storageLocation.6=Dacă doriți să criptați fișierele și să vizualizați conținutul seifului, faceți următoarele:
|
||||
addvault.new.readme.storageLocation.7=1. Adăugați acest seif la Cryptomator.
|
||||
addvault.new.readme.storageLocation.8=2. Deblocați seiful în Cryptomator.
|
||||
addvault.new.readme.storageLocation.9=3. Deschideți locația de acces făcând clic pe butonul "Reveal".
|
||||
addvault.new.readme.storageLocation.10=Dacă aveți nevoie de ajutor, vizitați documentația: %s
|
||||
addvault.new.readme.accessLocation.fileName=BINEATIVENIT.rtf
|
||||
addvault.new.readme.accessLocation.1=🔐️ UNITATE CRIPTATĂ 🔐️
|
||||
addvault.new.readme.accessLocation.2=Aceasta este locația de acces a seifului dvs.
|
||||
addvault.new.readme.accessLocation.3=Orice fișier adăugat la acest volum va fi criptat de către Cryptomator. Puteți lucra la el ca pe orice altă unitate/folder. Aceasta este doar o vizualizare decriptată a conținutului său, fișierele sunt criptate tot timpul pe hard disk-ul tău.
|
||||
addvault.new.readme.accessLocation.4=Puteți să ștergeți acest fișier.
|
||||
## Existing
|
||||
addvaultwizard.existing.instruction=Alegeți fișierul "masterkey.cryptomator" din seiful dvs. existent.
|
||||
addvaultwizard.existing.chooseBtn=Alege…
|
||||
addvaultwizard.existing.filePickerTitle=Selectaţi fişierul Masterkey
|
||||
## Success
|
||||
addvaultwizard.success.nextStepsInstructions=Seiful "%s" a fost adăugat.\nTrebuie să deblocați acest seif pentru a accesa sau adăuga conținut. Alternativ, îl puteți debloca în orice moment ulterior.
|
||||
addvaultwizard.success.unlockNow=Deblochează acum
|
||||
|
||||
# Remove Vault
|
||||
removeVault.title=Eliminați seiful
|
||||
removeVault.information=Acest lucru va face Cryptomator să uite de acest seif. Îl puteţi adăuga din nou mai târziu. Nici un fişier criptat nu va fi şters din hard disk-ul dvs.
|
||||
removeVault.confirmBtn=Eliminați seiful
|
||||
|
||||
# Change Password
|
||||
changepassword.title=Schimbați parola
|
||||
changepassword.enterOldPassword=Introduceți parola curentă pentru "%s"
|
||||
changepassword.finalConfirmation=Înțeleg că nu voi putea accesa datele mele dacă îmi uit parola
|
||||
|
||||
# Forget Password
|
||||
forgetPassword.title=Parolă uitată
|
||||
forgetPassword.information=Această acțiune va șterge parola salvată a acestui seif din keychain-ul sistemului de operare.
|
||||
forgetPassword.confirmBtn=Parolă uitată
|
||||
|
||||
# Unlock
|
||||
unlock.title=Deblocare "%s"
|
||||
unlock.passwordPrompt=Introduceți parola pentru "%s":
|
||||
unlock.savePassword=Memorează parola
|
||||
unlock.unlockBtn=Deblocați
|
||||
##
|
||||
unlock.chooseMasterkey.prompt=Nu s-a putut găsi fișierul masterkey pentru acest seif la locația așteptată. Vă rugăm să alegeți manual fișierul cheie.
|
||||
unlock.chooseMasterkey.filePickerTitle=Selectaţi fişierul Masterkey
|
||||
## Success
|
||||
unlock.success.message=Deblocat "%s" cu succes! Seiful dvs. este acum accesibil prin unitatea sa virtuală.
|
||||
unlock.success.rememberChoice=Ține minte alegerea, nu mai arăta asta din nou
|
||||
unlock.success.revealBtn=Dezvăluie unitatea
|
||||
## Failure
|
||||
unlock.error.heading=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.
|
||||
|
||||
# Lock
|
||||
## Force
|
||||
lock.forced.heading=Blocarea elegantă a eșuat
|
||||
lock.forced.message=Blocarea "%s" a fost blocată de operațiile în așteptare sau de fișierele deschise. Puteți forța blocarea acestui seif, dar întreruperea I/O poate duce la pierderea datelor nesalvate.
|
||||
lock.forced.confirmBtn=Forțați blocarea
|
||||
## Failure
|
||||
lock.fail.heading=Blocarea seifului a eșuat.
|
||||
lock.fail.message=Seiful "%s" nu a putut fi blocat. Asigurați-vă că lucrările nesalvate sunt salvate altundeva și că operațiunile importante de citire/scriere sunt terminate. Pentru a închide seiful omoară procesul Cryptomator.
|
||||
|
||||
# Migration
|
||||
migration.title=Îmbunătățește seiful
|
||||
## Start
|
||||
migration.start.prompt=Seiful dvs. "%s" trebuie să fie actualizat la un format mai nou. Înainte de a continua, asigurați-vă că nu există sincronizare în așteptare care să afecteze acest seif.
|
||||
migration.start.confirm=Da, seiful meu este complet sincronizat
|
||||
## Run
|
||||
migration.run.enterPassword=Introduceți parola pentru "%s"
|
||||
migration.run.startMigrationBtn=Migrează seiful
|
||||
migration.run.progressHint=Acest lucru poate dura ceva timp…
|
||||
## Success
|
||||
migration.success.nextStepsInstructions=Seiful "%s" a fost migrat cu succes.\nAcum puteți debloca seiful dvs.
|
||||
migration.success.unlockNow=Deblochează acum
|
||||
## Missing file system capabilities
|
||||
migration.error.missingFileSystemCapabilities.title=Tip de fișier nesuportat
|
||||
migration.error.missingFileSystemCapabilities.description=Migrarea nu a fost pornită, deoarece seiful dvs. este localizat pe un sistem de fișiere necorespunzător.
|
||||
migration.error.missingFileSystemCapabilities.reason.LONG_FILENAMES=Sistemul de fişiere nu acceptă nume de fişiere lungi.
|
||||
migration.error.missingFileSystemCapabilities.reason.LONG_PATHS=Sistemul de fișiere nu suportă căi lungi.
|
||||
migration.error.missingFileSystemCapabilities.reason.READ_ACCESS=Sistemul de fișiere nu permite citirea.
|
||||
migration.error.missingFileSystemCapabilities.reason.WRITE_ACCESS=Sistemul de fişiere nu permite scrierea.
|
||||
## Impossible
|
||||
migration.impossible.heading=Imposibil de migrat seiful
|
||||
migration.impossible.reason=Seiful nu poate fi migrat automat deoarece locația sa de stocare sau punctul de acces nu este compatibilă.
|
||||
migration.impossible.moreInfo=Seiful poate fi deschis în continuare cu o versiune mai veche. Pentru instrucţiuni despre cum să migraţi manual un seif, vizitaţi
|
||||
|
||||
# Health Check
|
||||
## Start
|
||||
health.title=Verificarea de sănătate a "%s"
|
||||
health.intro.header=Verificarea stării de sănătate
|
||||
health.intro.text=Verificarea stării de sănătate este o colecție de verificări pentru a detecta și eventual a remedia problemele din structura internă a seifului. Vă rugăm să țineți cont de:
|
||||
health.intro.remarkSync=Asigură că toate dispozitivele sunt complet sincronizate, acest lucru rezolvă majoritatea problemelor.
|
||||
health.intro.remarkFix=Nu toate problemele pot fi rezolvate.
|
||||
health.intro.remarkBackup=În cazul în care datele sunt corupte, numai o copie de rezervă poate ajuta.
|
||||
health.intro.affirmation=Am citit și am înțeles informațiile de mai sus
|
||||
## Start Failure
|
||||
health.fail.header=Eroare la încărcarea configurației seifului
|
||||
health.fail.ioError=A apărut o eroare la accesarea și citirea fișierului de configurare.
|
||||
health.fail.parseError=S-a produs o eroare la analizarea configurației seifului.
|
||||
health.fail.moreInfo=Mai multe informații
|
||||
## Check Selection
|
||||
health.checkList.description=Selectați verificări în lista din stânga sau folosiți butoanele de mai jos.
|
||||
health.checkList.selectAllButton=Selectați toate verificările
|
||||
health.checkList.deselectAllButton=Deselectați toate verificările
|
||||
health.check.runBatchBtn=Execută verificările selectate
|
||||
## Detail view
|
||||
health.check.detail.noSelectedCheck=Pentru rezultate, selectaţi o verificare de sănătate finalizată în lista din stânga.
|
||||
health.check.detail.checkScheduled=Verificarea este programată.
|
||||
health.check.detail.checkRunning=Verificarea se execută la moment…
|
||||
health.check.detail.checkSkipped=Verificarea nu a fost selectată pentru a rula.
|
||||
health.check.detail.checkFinished=Verificarea s-a terminat cu succes.
|
||||
health.check.detail.checkFinishedAndFound=Verificarea s-a terminat. Vă rugăm să examinați rezultatele.
|
||||
health.check.detail.checkFailed=Verificarea a ieșit din cauza unei erori.
|
||||
health.check.detail.checkCancelled=Verificarea a fost anulată.
|
||||
health.check.exportBtn=Exportare raport
|
||||
## Fix Application
|
||||
health.fix.fixBtn=Repară
|
||||
health.fix.successTip=Remediere reușită
|
||||
health.fix.failTip=Remediere eșuată, vezi jurnalul pentru detalii
|
||||
|
||||
# Preferences
|
||||
preferences.title=Preferințe
|
||||
## General
|
||||
preferences.general=Setări Generale
|
||||
preferences.general.theme=Aspect
|
||||
preferences.general.theme.automatic=Automat
|
||||
preferences.general.theme.light=Luminos
|
||||
preferences.general.theme.dark=Întunecat
|
||||
preferences.general.unlockThemes=Deblochează modul întunecat
|
||||
preferences.general.showMinimizeButton=Afișează butonul de minimizare
|
||||
preferences.general.showTrayIcon=Arată tray icon (necesită repornire)
|
||||
preferences.general.startHidden=Ascunde fereastra la pornirea Cryptomator
|
||||
preferences.general.debugLogging=Activează jurnalul de depanare
|
||||
preferences.general.debugDirectory=Dezvăluie fişierele jurnal
|
||||
preferences.general.autoStart=Lansați Cryptomator la pornirea sistemului
|
||||
preferences.general.keychainBackend=Salvează parolele cu
|
||||
preferences.general.interfaceOrientation=Orientarea interfeței
|
||||
preferences.general.interfaceOrientation.ltr=De la stânga la dreapta
|
||||
preferences.general.interfaceOrientation.rtl=De la dreapta la stânga
|
||||
## Volume
|
||||
preferences.volume=Unitate virtuală
|
||||
preferences.volume.type=Tip volum
|
||||
preferences.volume.webdav.port=Port WebDAV
|
||||
preferences.volume.webdav.scheme=Schema WebDAV
|
||||
## Updates
|
||||
preferences.updates=Actualizări
|
||||
preferences.updates.currentVersion=Versiunea actuală: %s
|
||||
preferences.updates.autoUpdateCheck=Verificare automată actualizări
|
||||
preferences.updates.checkNowBtn=Verifică acum
|
||||
preferences.updates.updateAvailable=Actualizare la versiunea %s disponibilă.
|
||||
## Contribution
|
||||
preferences.contribute=Susțineți-ne
|
||||
preferences.contribute.registeredFor=Certificat de suporter înregistrat pentru %s
|
||||
preferences.contribute.noCertificate=Susțineți Cryptomator și primiți un certificat de suport. E ca o cheie de licență dar pentru persoanele minunate care folosesc software gratuit. ;-)
|
||||
preferences.contribute.getCertificate=Nu aveți deja unul? Aflați cum îl puteți obține.
|
||||
preferences.contribute.promptText=Lipiți codul certificatului de suporter aici
|
||||
#<-- Add entries for donations and code/translation/documentation contribution -->
|
||||
|
||||
## About
|
||||
preferences.about=Despre
|
||||
|
||||
# Vault Statistics
|
||||
stats.title=Statistici pentru %s
|
||||
stats.cacheHitRate=Rata de control cache
|
||||
## Read
|
||||
stats.read.throughput.idle=Citire: inactiv
|
||||
stats.read.throughput.kibs=Citire: %.2f kiB/s
|
||||
stats.read.throughput.mibs=Citire: %.2f MiB/s
|
||||
stats.read.total.data.none=Date citite: -
|
||||
stats.read.total.data.kib=Date citite: %.1f kiB
|
||||
stats.read.total.data.mib=Date citite: %.1f MiB
|
||||
stats.read.total.data.gib=Date citite: %.1f GiB
|
||||
stats.decr.total.data.none=Date decriptate: -
|
||||
stats.decr.total.data.kib=Date decriptate: %.1f kiB
|
||||
stats.decr.total.data.mib=Date decriptate: %.1f MiB
|
||||
stats.decr.total.data.gib=Date decriptate: %.1f GiB
|
||||
stats.read.accessCount=Total citit: %d
|
||||
## Write
|
||||
stats.write.throughput.idle=Scriere: inactiv
|
||||
stats.write.throughput.kibs=Scrie: %.2f kiB/s
|
||||
stats.write.throughput.mibs=Scrie: %.2f MiB/s
|
||||
stats.write.total.data.none=Date scrise: -
|
||||
stats.write.total.data.kib=Date scrise: %.1f kiB
|
||||
stats.write.total.data.mib=Date scrise: %.1f MiB
|
||||
stats.write.total.data.gib=Date scrise: %.1f GiB
|
||||
stats.encr.total.data.none=Date criptate: -
|
||||
stats.encr.total.data.kib=Date criptate: %.1f kiB
|
||||
stats.encr.total.data.mib=Date criptate: %.1f MiB
|
||||
stats.encr.total.data.gib=Date criptate: %.1f GiB
|
||||
stats.write.accessCount=Total scrieri: %d
|
||||
|
||||
# Main Window
|
||||
main.closeBtn.tooltip=Închide
|
||||
main.minimizeBtn.tooltip=Minimizează
|
||||
main.preferencesBtn.tooltip=Preferințe
|
||||
main.debugModeEnabled.tooltip=Modul de depanare este activat
|
||||
main.donationKeyMissing.tooltip=Vă rugăm să luați în considerare o donație
|
||||
## Drag 'n' Drop
|
||||
main.dropZone.dropVault=Adaugă acest seif
|
||||
main.dropZone.unknownDragboardContent=Dacă doriţi să adăugaţi un seif, trageţi-l în această fereastră
|
||||
## Vault List
|
||||
main.vaultlist.emptyList.onboardingInstruction=Faceți clic aici pentru a adăuga un seif
|
||||
main.vaultlist.contextMenu.remove=Elimină…
|
||||
main.vaultlist.contextMenu.lock=Blocaţi
|
||||
main.vaultlist.contextMenu.unlock=Deblochează…
|
||||
main.vaultlist.contextMenu.unlockNow=Deblochează acum
|
||||
main.vaultlist.contextMenu.vaultoptions=Arată opțiunile seifului
|
||||
main.vaultlist.contextMenu.reveal=Dezvăluie unitatea
|
||||
main.vaultlist.addVaultBtn=Adaugă un seif
|
||||
## Vault Detail
|
||||
### Welcome
|
||||
main.vaultDetail.welcomeOnboarding=Vă mulțumim că ați ales Cryptomator pentru a vă proteja fișierele. Dacă aveți nevoie de asistență, verificați ghidurile noastre de pornire:
|
||||
### Locked
|
||||
main.vaultDetail.lockedStatus=BLOCAT
|
||||
main.vaultDetail.unlockBtn=Deblochează…
|
||||
main.vaultDetail.unlockNowBtn=Deblochează acum
|
||||
main.vaultDetail.optionsBtn=Opțiuni seif
|
||||
main.vaultDetail.passwordSavedInKeychain=Parola a fost salvată
|
||||
### Unlocked
|
||||
main.vaultDetail.unlockedStatus=DEBLOCAT
|
||||
main.vaultDetail.accessLocation=Conținutul seifului tău este accesibil aici:
|
||||
main.vaultDetail.revealBtn=Dezvăluie unitatea
|
||||
main.vaultDetail.lockBtn=Blocaţi
|
||||
main.vaultDetail.bytesPerSecondRead=Citire:
|
||||
main.vaultDetail.bytesPerSecondWritten=Scriere:
|
||||
main.vaultDetail.throughput.idle=inactiv
|
||||
main.vaultDetail.throughput.kbps=%.1f kiB/s
|
||||
main.vaultDetail.throughput.mbps=%.1f MiB/s
|
||||
main.vaultDetail.stats=Statistici de seif
|
||||
### Missing
|
||||
main.vaultDetail.missing.info=Cryptomator nu a putut găsi un seif pe această cale.
|
||||
main.vaultDetail.missing.recheck=Verifică din nou
|
||||
main.vaultDetail.missing.remove=Eliminați din lista de seifuri…
|
||||
main.vaultDetail.missing.changeLocation=Schimbați locația seifului…
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Îmbunătățește seiful
|
||||
main.vaultDetail.migratePrompt=Înainte de a-l putea accesa, seiful dumneavoastră trebuie actualizat la format nou
|
||||
|
||||
# Wrong File Alert
|
||||
wrongFileAlert.title=Cum să criptați fișierele
|
||||
wrongFileAlert.header.title=Ați încercat să criptați aceste fișiere?
|
||||
wrongFileAlert.header.lead=În acest scop, Cryptomator oferă un volum în managerul de fișiere al sistemului dumneavoastră.
|
||||
wrongFileAlert.instruction.0=Pentru a cripta fișierele, urmați acești pași:
|
||||
wrongFileAlert.instruction.1=1. Deblocați seiful dvs.
|
||||
wrongFileAlert.instruction.2=2. Apăsați pe butonul "Afişare" pentru a deschide volumul în managerul de fișiere.
|
||||
wrongFileAlert.instruction.3=3. Adăugați fişierele la acest volum.
|
||||
wrongFileAlert.link=Pentru asistență suplimentară, vizitați
|
||||
|
||||
# Vault Options
|
||||
## General
|
||||
vaultOptions.general=Setări Generale
|
||||
vaultOptions.general.vaultName=Nume seif
|
||||
vaultOptions.general.autoLock.lockAfterTimePart1=Blocare când inactiv pentru
|
||||
vaultOptions.general.autoLock.lockAfterTimePart2=minute
|
||||
vaultOptions.general.unlockAfterStartup=Deblochează seiful la pornirea Cryptomator
|
||||
vaultOptions.general.actionAfterUnlock=După deblocarea cu succes
|
||||
vaultOptions.general.actionAfterUnlock.ignore=Nu fă nimic
|
||||
vaultOptions.general.actionAfterUnlock.reveal=Dezvăluie unitatea
|
||||
vaultOptions.general.actionAfterUnlock.ask=Întreabă
|
||||
vaultOptions.general.startHealthCheckBtn=Începe verificarea de sănătate
|
||||
|
||||
## Mount
|
||||
vaultOptions.mount=Montare
|
||||
vaultOptions.mount.readonly=Doar citire
|
||||
vaultOptions.mount.customMountFlags=Atribute de montare personalizate
|
||||
vaultOptions.mount.winDriveLetterOccupied=ocupat
|
||||
vaultOptions.mount.mountPoint=Punct de montare
|
||||
vaultOptions.mount.mountPoint.auto=Alegeţi automat o locaţie potrivită
|
||||
vaultOptions.mount.mountPoint.driveLetter=Utilizați litera de unitate atribuită
|
||||
vaultOptions.mount.mountPoint.custom=Cale personalizată
|
||||
vaultOptions.mount.mountPoint.directoryPickerButton=Alege…
|
||||
vaultOptions.mount.mountPoint.directoryPickerTitle=Alegeți un dosar gol
|
||||
## Master Key
|
||||
vaultOptions.masterkey=Parolă
|
||||
vaultOptions.masterkey.changePasswordBtn=Schimbați parola
|
||||
vaultOptions.masterkey.forgetSavedPasswordBtn=Parolă salvată uitată
|
||||
vaultOptions.masterkey.recoveryKeyExplanation=O cheie de recuperare este singurul mijloc de a restabili accesul la un seif în caz că vă pierdeți parola.
|
||||
vaultOptions.masterkey.showRecoveryKeyBtn=Afișează cheia de recuperare
|
||||
vaultOptions.masterkey.recoverPasswordBtn=Recuperează parola
|
||||
|
||||
|
||||
# Recovery Key
|
||||
recoveryKey.title=Cheia de recuperare
|
||||
recoveryKey.enterPassword.prompt=Introduceți parola pentru a afișa cheia de recuperare pentru "%s:
|
||||
recoveryKey.display.message=Următoarea cheie de recuperare poate fi folosită pentru a restabili accesul la "%s":
|
||||
recoveryKey.display.StorageHints=Păstrați cheia de recuperare undeva foarte sigur, de ex.\n • Păstrați-o folosind un manager de parole\n • Salvați-o pe un flash USB stick\n • Imprimați-o pe hârtie
|
||||
recoveryKey.recover.prompt=Introduceți cheia de recuperare pentru "%s:
|
||||
recoveryKey.recover.validKey=Aceasta este o cheie de recuperare validă
|
||||
recoveryKey.printout.heading=Cheia de recuperare Cryptomator\n"%s"\n
|
||||
|
||||
# New Password
|
||||
newPassword.promptText=Introduceți o parolă nouă
|
||||
newPassword.reenterPassword=Confirmaţi noua parolă
|
||||
newPassword.passwordsMatch=Parolele corespund!
|
||||
newPassword.passwordsDoNotMatch=Parolele nu corespund
|
||||
passwordStrength.messageLabel.tooShort=Folosiți cel puțin %d caractere
|
||||
passwordStrength.messageLabel.0=Foarte slabă
|
||||
passwordStrength.messageLabel.1=Slabă
|
||||
passwordStrength.messageLabel.2=Acceptabilă
|
||||
passwordStrength.messageLabel.3=Puternică
|
||||
passwordStrength.messageLabel.4=Foarte puternică
|
||||
|
||||
# Quit
|
||||
quit.prompt=Părăsiți aplicația? Există seifuri deblocate.
|
||||
quit.lockAndQuit=Blocați și ieșiți
|
||||
|
@ -13,8 +13,11 @@ generic.button.done=Готово
|
||||
generic.button.next=Далее
|
||||
generic.button.print=Печать
|
||||
## Error
|
||||
generic.error.title=Неизвестная ошибка
|
||||
generic.error.instruction=Этого не должно было произойти. Создайте отчёт об ошибке ниже и опишите, какие шаги к ней привели.
|
||||
generic.error.title=Ошибка: %s
|
||||
generic.error.instruction=Произошла непредвиденная ситуация. Попробуйте найти уже имеющиеся решения этой ошибки. Если об этой ошибке ещё не сообщали, то сделайте это.
|
||||
generic.error.hyperlink.lookup=Найти ошибку
|
||||
generic.error.hyperlink.report=Сообщить об ошибке
|
||||
generic.error.technicalDetails=Подробности:
|
||||
|
||||
# Defaults
|
||||
defaults.vault.vaultName=Хранилище
|
||||
|
@ -13,8 +13,11 @@ generic.button.done=Hotovo
|
||||
generic.button.next=Ďalej
|
||||
generic.button.print=Tlač
|
||||
## Error
|
||||
generic.error.title=Vyskytla sa neočakávaná chyba
|
||||
generic.error.instruction=Toto sa nemalo stať. Nahláste text chyby uvedený nižšie a uveďte popis krokov, ktoré viedli k tejto chybe.
|
||||
generic.error.title=Chyba %s
|
||||
generic.error.instruction=Ejha! Cryptomator toto neočakával. Môžte nahliadnuť do existujúcich riešení tejto chyby. Alebo v prípade že zatiaľ nebola nahlásená, môžte to slobodne urobiť.
|
||||
generic.error.hyperlink.lookup=Vyhľadať túto chybu
|
||||
generic.error.hyperlink.report=Nahlásiť túto chybu
|
||||
generic.error.technicalDetails=Podrobnosti:
|
||||
|
||||
# Defaults
|
||||
defaults.vault.vaultName=Trezor
|
||||
|
@ -13,8 +13,6 @@ generic.button.done=Завршено
|
||||
generic.button.next=Даље
|
||||
generic.button.print=Штампај
|
||||
## Error
|
||||
generic.error.title=Догодила се неочекивана грешка
|
||||
generic.error.instruction=Ово није требало да се догоди. Молимо вас пријавите текст грешке испод и додајте опис корака који су довели до ове грешке.
|
||||
|
||||
# Defaults
|
||||
defaults.vault.vaultName=Сеф
|
||||
|
@ -13,8 +13,6 @@ generic.button.done=Završeno
|
||||
generic.button.next=Dalje
|
||||
generic.button.print=Štampaj
|
||||
## Error
|
||||
generic.error.title=Dogodila se neočekivana greška
|
||||
generic.error.instruction=Ovo nije trebalo da se dogodi. Molimo vas prijavite tekst greške ispod i dodajte opis koraka koji su doveli do ove greške.
|
||||
|
||||
# Defaults
|
||||
defaults.vault.vaultName=Sef
|
||||
|
@ -13,8 +13,11 @@ generic.button.done=Klar
|
||||
generic.button.next=Nästa
|
||||
generic.button.print=Skriv ut
|
||||
## Error
|
||||
generic.error.title=Ett oväntat fel uppstod
|
||||
generic.error.instruction=Detta borde inte hänt. Vänligen rapportera feltexten nedan och inkludera en beskrivning av vilka steg som ledde till detta fel.
|
||||
generic.error.title=Fel: %s
|
||||
generic.error.instruction=Hoppsan! Cryptomator stötte på något oväntat. Du kan leta upp befintliga lösningar för detta fel. Om det inte har rapporterats ännu får du gärna rapportera in felet.
|
||||
generic.error.hyperlink.lookup=Slå upp detta fel
|
||||
generic.error.hyperlink.report=Rapportera fel
|
||||
generic.error.technicalDetails=Detaljer:
|
||||
|
||||
# Defaults
|
||||
defaults.vault.vaultName=Valv
|
||||
@ -147,13 +150,37 @@ migration.impossible.moreInfo=Valvet kan fortfarande öppnas med en äldre versi
|
||||
|
||||
# Health Check
|
||||
## Start
|
||||
health.title=Hälsokontroll av "%s"
|
||||
health.intro.header=Hälsokontroll
|
||||
health.intro.text=Hälsokontroll är en samling av kontroller för att upptäcka och åtgärda eventuella problem i den interna strukturen i ditt valv. Kom ihåg att:
|
||||
health.intro.remarkSync=Se till att alla enheter är helt synkroniserade, detta löser de flesta problem.
|
||||
health.intro.remarkFix=Alla problem kan inte åtgärdas.
|
||||
health.intro.remarkBackup=Om data är skadad kan endast en tidigare säkerhetskopia hjälpa.
|
||||
health.intro.affirmation=Jag har läst och förstått ovanstående information
|
||||
## Start Failure
|
||||
health.fail.header=Fel vid inläsning av valvkonfiguration
|
||||
health.fail.ioError=Ett fel inträffade vid åtkomst till och läsning av konfigurationsfilen.
|
||||
health.fail.parseError=Ett fel inträffade vid parsning av valvkonfigurationen.
|
||||
health.fail.moreInfo=Mer information
|
||||
## Check Selection
|
||||
health.check.runBatchBtn=Kör utvalda kontroller
|
||||
health.checkList.description=Välj kontroller i den vänstra listan eller använd knapparna nedan.
|
||||
health.checkList.selectAllButton=Markera alla kontroller
|
||||
health.checkList.deselectAllButton=Avmarkera alla kontroller
|
||||
health.check.runBatchBtn=Kör valda kontroller
|
||||
## Detail view
|
||||
health.check.detail.noSelectedCheck=Välj en färdig hälsokontroll i den vänstra listan för att se resultat.
|
||||
health.check.detail.checkScheduled=Kontrollen är schemalagd.
|
||||
health.check.detail.checkRunning=Kontrollen körs för närvarande…
|
||||
health.check.detail.checkSkipped=Kontrollen har inte valts att köra.
|
||||
health.check.detail.checkFinished=Kontrollen har slutförts.
|
||||
health.check.detail.checkFinishedAndFound=Kontrollen är slutförd. Vänligen granska resultatet.
|
||||
health.check.detail.checkFailed=Kontrollen avslutades på grund av ett fel.
|
||||
health.check.detail.checkCancelled=Kontrollen avbröts.
|
||||
health.check.exportBtn=Exportera rapport
|
||||
## Fix Application
|
||||
health.fix.fixBtn=Åtgärda
|
||||
health.fix.successTip=Åtgärden lyckades
|
||||
health.fix.failTip=Rättning misslyckades, se logg för detaljer
|
||||
|
||||
# Preferences
|
||||
preferences.title=Inställningar
|
||||
@ -294,6 +321,7 @@ vaultOptions.general.actionAfterUnlock=Efter lyckad upplåsning
|
||||
vaultOptions.general.actionAfterUnlock.ignore=Gör ingenting
|
||||
vaultOptions.general.actionAfterUnlock.reveal=Visa enhet
|
||||
vaultOptions.general.actionAfterUnlock.ask=Fråga
|
||||
vaultOptions.general.startHealthCheckBtn=Starta hälsokontroll
|
||||
|
||||
## Mount
|
||||
vaultOptions.mount=Montering
|
||||
|
@ -13,8 +13,11 @@ generic.button.done=Tamam
|
||||
generic.button.next=Sonraki
|
||||
generic.button.print=Yazdır
|
||||
## Error
|
||||
generic.error.title=Beklenmedik bir hata oluştu
|
||||
generic.error.instruction=Bu olmamalıydı. Lütfen aşağıdaki hata metnini bildirin ve bu hataya neden olan adımların bir açıklamasını ekleyin.
|
||||
generic.error.title=Hata: %s
|
||||
generic.error.instruction=Uups! Cryptomator bunun olmasını beklemiyordu. Bu hata için mevcut çözümlere bakabilirsiniz. Ya da henüz bildirilmediyse, bunu raporlamaktan çekinmeyin.
|
||||
generic.error.hyperlink.lookup=Bu hatayı ara
|
||||
generic.error.hyperlink.report=Bu hatayı bildir
|
||||
generic.error.technicalDetails=Detaylar:
|
||||
|
||||
# Defaults
|
||||
defaults.vault.vaultName=Kasa
|
||||
|
@ -13,8 +13,11 @@ generic.button.done=完成
|
||||
generic.button.next=下一步
|
||||
generic.button.print=打印
|
||||
## Error
|
||||
generic.error.title=发生一个未知错误
|
||||
generic.error.instruction=这本不该发生的,请报告下面的错误文本,并包含导致该错误的操作步骤的描述信息。
|
||||
generic.error.title=错误 %s
|
||||
generic.error.instruction=糟糕!Cryptomator 未料到会发生这种情况。您可以查找该错误的现有解决方案;或者,如果是新错误,请随时向我们报告。
|
||||
generic.error.hyperlink.lookup=查找该错误
|
||||
generic.error.hyperlink.report=报告该错误
|
||||
generic.error.technicalDetails=详细信息:
|
||||
|
||||
# Defaults
|
||||
defaults.vault.vaultName=保险库
|
||||
@ -47,7 +50,7 @@ addvaultwizard.new.directoryPickerTitle=选择目录
|
||||
addvaultwizard.new.fileAlreadyExists=已存在同名文件或文件夹
|
||||
addvaultwizard.new.locationDoesNotExist=指定路径中的目录不存在或无法访问
|
||||
addvaultwizard.new.locationIsNotWritable=没有对指定路径的写入权限
|
||||
addvaultwizard.new.locationIsOk=合适的保险库路径
|
||||
addvaultwizard.new.locationIsOk=保险库路径合适
|
||||
addvaultwizard.new.invalidName=无效的保险库名称,请考虑一个常规的目录名称
|
||||
### Password
|
||||
addvaultwizard.new.createVaultBtn=创建保险库
|
||||
@ -57,7 +60,7 @@ addvaultwizard.new.generateRecoveryKeyChoice.no=不,谢谢。我不会丢失
|
||||
### Information
|
||||
addvault.new.readme.storageLocation.fileName=重要.rtf
|
||||
addvault.new.readme.storageLocation.1=⚠️ 保险库文件 ⚠️
|
||||
addvault.new.readme.storageLocation.2=这是你的保险库的保存路径
|
||||
addvault.new.readme.storageLocation.2=这是您的保险库的存储路径。
|
||||
addvault.new.readme.storageLocation.3=请勿
|
||||
addvault.new.readme.storageLocation.4=• 更改此目录内的任何文件或者
|
||||
addvault.new.readme.storageLocation.5=• 将任何文件粘贴到此目录内以进行加密
|
||||
@ -68,9 +71,9 @@ addvault.new.readme.storageLocation.9=3. 通过点击“显示”按钮打开
|
||||
addvault.new.readme.storageLocation.10=如果您需要帮助,请阅读文档: %s
|
||||
addvault.new.readme.accessLocation.fileName=欢迎.rtf
|
||||
addvault.new.readme.accessLocation.1=🔐️ 加密卷 🔐️
|
||||
addvault.new.readme.accessLocation.2=这是你的保险库的访问路径
|
||||
addvault.new.readme.accessLocation.3=任何添加到此卷的文件都将被Cryptomator加密。你可以像在一般磁盘/文件夹上那样操作它。 这只是对其内容的解密查看,你的文件在硬盘上会一直保持加密
|
||||
addvault.new.readme.accessLocation.4=随时可以删除此文件。
|
||||
addvault.new.readme.accessLocation.2=这是您的保险库的访问路径。
|
||||
addvault.new.readme.accessLocation.3=任何添加到此卷的文件都将被 Cryptomator 加密。您可以像在一般磁盘/文件夹上那样操作它。 这只是对其内容的解密查看,您的文件会在硬盘上一直保持加密。
|
||||
addvault.new.readme.accessLocation.4=您可以随时删除此文件。
|
||||
## Existing
|
||||
addvaultwizard.existing.instruction=请选择您现有保险库中的 "masterkey.cryptomator" 文件
|
||||
addvaultwizard.existing.chooseBtn=选择...
|
||||
|
@ -13,8 +13,6 @@ generic.button.done=完成
|
||||
generic.button.next=繼續
|
||||
generic.button.print=列印
|
||||
## Error
|
||||
generic.error.title=發生未知錯誤
|
||||
generic.error.instruction=這不應該發生。請回報下方的錯誤訊息,並附上造成這個錯誤的步驟。
|
||||
|
||||
# Defaults
|
||||
defaults.vault.vaultName=加密檔案庫
|
||||
@ -95,10 +93,12 @@ forgetPassword.information=這將會從系統鑰匙圈中移除這個加密檔
|
||||
forgetPassword.confirmBtn=忘記密碼
|
||||
|
||||
# Unlock
|
||||
unlock.title=解鎖 %s
|
||||
unlock.passwordPrompt=輸入 "%s" 的密碼:
|
||||
unlock.savePassword=記住密碼
|
||||
unlock.unlockBtn=解鎖
|
||||
##
|
||||
unlock.chooseMasterkey.prompt=無法在其預期位置找到此保管庫的主密鑰文件。請手動選擇密鑰文件。
|
||||
unlock.chooseMasterkey.filePickerTitle=選擇主金鑰檔案
|
||||
## Success
|
||||
unlock.success.message=成功解鎖 "%s"!您現在可以存存取您的加密檔案庫。
|
||||
@ -145,10 +145,37 @@ migration.impossible.moreInfo=此加密檔案庫仍可被舊版本開啟。如
|
||||
|
||||
# Health Check
|
||||
## Start
|
||||
health.title=對於"%s"的健康檢查
|
||||
health.intro.header=健康檢查
|
||||
health.intro.text=運行狀況檢查用於檢測並修復保管庫內部結構中的問題。請記住:
|
||||
health.intro.remarkSync=確保所有設備完全同步,這可以解決大部分問題。
|
||||
health.intro.remarkFix=並非所有問題都可以解決。
|
||||
health.intro.remarkBackup=如果數據已損壞,則只有備份才有幫助。
|
||||
health.intro.affirmation=我已閱讀並理解上述資訊
|
||||
## Start Failure
|
||||
health.fail.header=加載Vault配寘時出錯
|
||||
health.fail.ioError=訪問和讀取配置文件時發生錯誤。
|
||||
health.fail.parseError=分析vault配寘時出錯。
|
||||
health.fail.moreInfo=更多信息
|
||||
## Check Selection
|
||||
health.checkList.description=在左側列表中選擇檢查或使用下面的按鈕。
|
||||
health.checkList.selectAllButton=選擇所有選項
|
||||
health.checkList.deselectAllButton=取消所有選擇
|
||||
health.check.runBatchBtn=運行選定的檢查
|
||||
## Detail view
|
||||
health.check.detail.noSelectedCheck=請在左側清單中選擇已完成的結果運行狀況檢查。
|
||||
health.check.detail.checkScheduled=檢查已安排。
|
||||
health.check.detail.checkRunning=檢查目前正在運行…
|
||||
health.check.detail.checkSkipped=未選擇運行檢查。
|
||||
health.check.detail.checkFinished=檢查順利完成。
|
||||
health.check.detail.checkFinishedAndFound=檢查結束。請檢查結果。
|
||||
health.check.detail.checkFailed=發生錯誤,檢查意外退出。
|
||||
health.check.detail.checkCancelled=檢查被取消。
|
||||
health.check.exportBtn=匯出報告
|
||||
## Fix Application
|
||||
health.fix.fixBtn=修復
|
||||
health.fix.successTip=修復成功
|
||||
health.fix.failTip=修復失敗,詳情請查看日誌
|
||||
|
||||
# Preferences
|
||||
preferences.title=偏好
|
||||
@ -282,11 +309,14 @@ wrongFileAlert.link=如需進一步協助協助,請參照
|
||||
## General
|
||||
vaultOptions.general=一般
|
||||
vaultOptions.general.vaultName=加密檔案庫名稱
|
||||
vaultOptions.general.autoLock.lockAfterTimePart1=空閒時鎖定
|
||||
vaultOptions.general.autoLock.lockAfterTimePart2=分鐘
|
||||
vaultOptions.general.unlockAfterStartup=啟動 Cryptomator 時解鎖加密檔案庫
|
||||
vaultOptions.general.actionAfterUnlock=成功解鎖後
|
||||
vaultOptions.general.actionAfterUnlock.ignore=無動作
|
||||
vaultOptions.general.actionAfterUnlock.reveal=顯示磁碟
|
||||
vaultOptions.general.actionAfterUnlock.ask=詢問
|
||||
vaultOptions.general.startHealthCheckBtn=開始健康檢查
|
||||
|
||||
## Mount
|
||||
vaultOptions.mount=掛載
|
||||
|
@ -17,14 +17,12 @@ Cryptomator uses 40 third-party dependencies under the following licenses:
|
||||
- jnr-a64asm (com.github.jnr:jnr-a64asm:1.0.0 - http://nexus.sonatype.org/oss-repository-hosting.html/jnr-a64asm)
|
||||
- jnr-constants (com.github.jnr:jnr-constants:0.9.15 - http://github.com/jnr/jnr-constants)
|
||||
- jnr-ffi (com.github.jnr:jnr-ffi:2.1.12 - http://github.com/jnr/jnr-ffi)
|
||||
- Gson (com.google.code.gson:gson:2.8.7 - https://github.com/google/gson/gson)
|
||||
- Dagger (com.google.dagger:dagger:2.37 - https://github.com/google/dagger)
|
||||
- Gson (com.google.code.gson:gson:2.8.8 - https://github.com/google/gson/gson)
|
||||
- Dagger (com.google.dagger:dagger:2.38.1 - https://github.com/google/dagger)
|
||||
- Guava InternalFutureFailureAccess and InternalFutures (com.google.guava:failureaccess:1.0.1 - https://github.com/google/guava/failureaccess)
|
||||
- Guava: Google Core Libraries for Java (com.google.guava:guava:30.1.1-jre - https://github.com/google/guava/guava)
|
||||
- Guava: Google Core Libraries for Java (com.google.guava:guava:31.0-jre - https://github.com/google/guava)
|
||||
- Apache Commons CLI (commons-cli:commons-cli:1.4 - http://commons.apache.org/proper/commons-cli/)
|
||||
- javax.inject (javax.inject:javax.inject:1 - http://code.google.com/p/atinject/)
|
||||
- Java Native Access (net.java.dev.jna:jna:5.7.0 - https://github.com/java-native-access/jna)
|
||||
- Java Native Access Platform (net.java.dev.jna:jna-platform:5.7.0 - https://github.com/java-native-access/jna)
|
||||
- Apache Commons Lang (org.apache.commons:commons-lang3:3.12.0 - https://commons.apache.org/proper/commons-lang/)
|
||||
- Apache HttpCore (org.apache.httpcomponents:httpcore:4.4.14 - http://hc.apache.org/httpcomponents-core-ga)
|
||||
- Jackrabbit WebDAV Library (org.apache.jackrabbit:jackrabbit-webdav:2.21.5 - http://jackrabbit.apache.org/jackrabbit-webdav/)
|
||||
@ -35,6 +33,9 @@ Cryptomator uses 40 third-party dependencies under the following licenses:
|
||||
- Jetty :: Servlet Handling (org.eclipse.jetty:jetty-servlet:10.0.6 - https://eclipse.org/jetty/jetty-servlet)
|
||||
- Jetty :: Utilities (org.eclipse.jetty:jetty-util:10.0.6 - https://eclipse.org/jetty/jetty-util)
|
||||
- Jetty :: Servlet API and Schemas for JPMS and OSGi (org.eclipse.jetty.toolchain:jetty-servlet-api:4.0.6 - https://eclipse.org/jetty/jetty-servlet-api)
|
||||
Apache-2.0:
|
||||
- Java Native Access (net.java.dev.jna:jna:5.9.0 - https://github.com/java-native-access/jna)
|
||||
- Java Native Access Platform (net.java.dev.jna:jna-platform:5.9.0 - https://github.com/java-native-access/jna)
|
||||
BSD:
|
||||
- asm (org.ow2.asm:asm:7.1 - http://asm.ow2.org/)
|
||||
- asm-analysis (org.ow2.asm:asm-analysis:7.1 - http://asm.ow2.org/)
|
||||
@ -51,30 +52,31 @@ Cryptomator uses 40 third-party dependencies under the following licenses:
|
||||
- Jetty :: Servlet Handling (org.eclipse.jetty:jetty-servlet:10.0.6 - https://eclipse.org/jetty/jetty-servlet)
|
||||
- Jetty :: Utilities (org.eclipse.jetty:jetty-util:10.0.6 - https://eclipse.org/jetty/jetty-util)
|
||||
Eclipse Public License - v 1.0:
|
||||
- Logback Classic Module (ch.qos.logback:logback-classic:1.2.3 - http://logback.qos.ch/logback-classic)
|
||||
- Logback Core Module (ch.qos.logback:logback-core:1.2.3 - http://logback.qos.ch/logback-core)
|
||||
- Logback Classic Module (ch.qos.logback:logback-classic:1.2.6 - http://logback.qos.ch/logback-classic)
|
||||
- Logback Core Module (ch.qos.logback:logback-core:1.2.6 - http://logback.qos.ch/logback-core)
|
||||
Eclipse Public License - v 2.0:
|
||||
- jnr-posix (com.github.jnr:jnr-posix:3.0.54 - http://nexus.sonatype.org/oss-repository-hosting.html/jnr-posix)
|
||||
GNU Lesser General Public License:
|
||||
- Logback Classic Module (ch.qos.logback:logback-classic:1.2.3 - http://logback.qos.ch/logback-classic)
|
||||
- Logback Core Module (ch.qos.logback:logback-core:1.2.3 - http://logback.qos.ch/logback-core)
|
||||
- Logback Classic Module (ch.qos.logback:logback-classic:1.2.6 - http://logback.qos.ch/logback-classic)
|
||||
- Logback Core Module (ch.qos.logback:logback-core:1.2.6 - http://logback.qos.ch/logback-core)
|
||||
GPLv2:
|
||||
- jnr-posix (com.github.jnr:jnr-posix:3.0.54 - http://nexus.sonatype.org/oss-repository-hosting.html/jnr-posix)
|
||||
GPLv2+CE:
|
||||
- javafx-base (org.openjfx:javafx-base:16 - https://openjdk.java.net/projects/openjfx/javafx-base/)
|
||||
- javafx-controls (org.openjfx:javafx-controls:16 - https://openjdk.java.net/projects/openjfx/javafx-controls/)
|
||||
- javafx-fxml (org.openjfx:javafx-fxml:16 - https://openjdk.java.net/projects/openjfx/javafx-fxml/)
|
||||
- javafx-graphics (org.openjfx:javafx-graphics:16 - https://openjdk.java.net/projects/openjfx/javafx-graphics/)
|
||||
- javafx-base (org.openjfx:javafx-base:17.0.0.1 - https://openjdk.java.net/projects/openjfx/javafx-base/)
|
||||
- javafx-controls (org.openjfx:javafx-controls:17.0.0.1 - https://openjdk.java.net/projects/openjfx/javafx-controls/)
|
||||
- javafx-fxml (org.openjfx:javafx-fxml:17.0.0.1 - https://openjdk.java.net/projects/openjfx/javafx-fxml/)
|
||||
- javafx-graphics (org.openjfx:javafx-graphics:17.0.0.1 - https://openjdk.java.net/projects/openjfx/javafx-graphics/)
|
||||
LGPL 2.1:
|
||||
- jnr-posix (com.github.jnr:jnr-posix:3.0.54 - http://nexus.sonatype.org/oss-repository-hosting.html/jnr-posix)
|
||||
- Java Native Access (net.java.dev.jna:jna:5.7.0 - https://github.com/java-native-access/jna)
|
||||
- Java Native Access Platform (net.java.dev.jna:jna-platform:5.7.0 - https://github.com/java-native-access/jna)
|
||||
LGPL-2.1-or-later:
|
||||
- Java Native Access (net.java.dev.jna:jna:5.9.0 - https://github.com/java-native-access/jna)
|
||||
- Java Native Access Platform (net.java.dev.jna:jna-platform:5.9.0 - https://github.com/java-native-access/jna)
|
||||
MIT License:
|
||||
- java jwt (com.auth0:java-jwt:3.18.1 - https://github.com/auth0/java-jwt)
|
||||
- java jwt (com.auth0:java-jwt:3.18.2 - https://github.com/auth0/java-jwt)
|
||||
- jnr-x86asm (com.github.jnr:jnr-x86asm:1.0.2 - http://github.com/jnr/jnr-x86asm)
|
||||
- jnr-fuse (com.github.serceman:jnr-fuse:0.5.5 - https://github.com/SerCeMan/jnr-fuse)
|
||||
- zxcvbn4j (com.nulab-inc:zxcvbn:1.5.2 - https://github.com/nulab/zxcvbn4j)
|
||||
- SLF4J API Module (org.slf4j:slf4j-api:1.7.31 - http://www.slf4j.org)
|
||||
- SLF4J API Module (org.slf4j:slf4j-api:1.7.32 - http://www.slf4j.org)
|
||||
The BSD 2-Clause License:
|
||||
- EasyBind (com.tobiasdiez:easybind:2.2 - https://github.com/tobiasdiez/EasyBind)
|
||||
|
||||
|
130
src/test/java/org/cryptomator/common/ErrorCodeTest.java
Normal file
130
src/test/java/org/cryptomator/common/ErrorCodeTest.java
Normal file
@ -0,0 +1,130 @@
|
||||
package org.cryptomator.common;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class ErrorCodeTest {
|
||||
|
||||
private static ErrorCode codeCaughtFrom(RunnableThrowingException<RuntimeException> runnable) {
|
||||
try {
|
||||
runnable.run();
|
||||
throw new IllegalStateException("should not reach this point");
|
||||
} catch (RuntimeException e) {
|
||||
return ErrorCode.of(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("same exception leads to same error code")
|
||||
public void testDifferentErrorCodes() {
|
||||
var code1 = codeCaughtFrom(this::throwNpe);
|
||||
var code2 = codeCaughtFrom(this::throwNpe);
|
||||
|
||||
Assertions.assertEquals(code1.toString(), code2.toString());
|
||||
}
|
||||
|
||||
private void throwNpe() {
|
||||
throwException(new NullPointerException());
|
||||
}
|
||||
|
||||
private void throwException(RuntimeException e) throws RuntimeException {
|
||||
throw e;
|
||||
}
|
||||
|
||||
@DisplayName("when different cause but same root cause")
|
||||
@Nested
|
||||
public class SameRootCauseDifferentCause {
|
||||
|
||||
private final ErrorCode code1 = codeCaughtFrom(this::foo);
|
||||
private final ErrorCode code2 = codeCaughtFrom(this::bar);
|
||||
|
||||
private void foo() throws IllegalArgumentException {
|
||||
try {
|
||||
throwNpe();
|
||||
} catch (NullPointerException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void bar() throws IllegalStateException {
|
||||
try {
|
||||
throwNpe();
|
||||
} catch (NullPointerException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("error codes are different")
|
||||
public void testDifferentCodes() {
|
||||
Assertions.assertNotEquals(code1.toString(), code2.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("throwableCodes are different")
|
||||
public void testDifferentThrowableCodes() {
|
||||
Assertions.assertNotEquals(code1.throwableCode(), code2.throwableCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("rootCauseCodes are equal")
|
||||
public void testSameRootCauseCodes() {
|
||||
Assertions.assertEquals(code1.rootCauseCode(), code2.rootCauseCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("methodCode are equal")
|
||||
public void testSameMethodCodes() {
|
||||
Assertions.assertEquals(code1.methodCode(), code2.methodCode());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@DisplayName("when same cause but different call stack")
|
||||
@Nested
|
||||
public class SameCauseDifferentCallStack {
|
||||
|
||||
private final ErrorCode code1 = codeCaughtFrom(this::foo);
|
||||
private final ErrorCode code2 = codeCaughtFrom(this::bar);
|
||||
|
||||
private void foo() throws NullPointerException {
|
||||
try {
|
||||
throwNpe();
|
||||
} catch (NullPointerException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void bar() throws NullPointerException {
|
||||
foo();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("error codes are different")
|
||||
public void testDifferentCodes() {
|
||||
Assertions.assertNotEquals(code1.toString(), code2.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("throwableCodes are different")
|
||||
public void testDifferentThrowableCodes() {
|
||||
Assertions.assertNotEquals(code1.throwableCode(), code2.throwableCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("rootCauseCodes are equal")
|
||||
public void testSameRootCauseCodes() {
|
||||
Assertions.assertEquals(code1.rootCauseCode(), code2.rootCauseCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("methodCode are equal")
|
||||
public void testSameMethodCodes() {
|
||||
Assertions.assertEquals(code1.methodCode(), code2.methodCode());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -14,6 +14,11 @@ class MapKeychainAccess implements KeychainAccessProvider {
|
||||
|
||||
private final Map<String, char[]> map = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public String displayName() {
|
||||
return getClass().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storePassphrase(String key, CharSequence passphrase) {
|
||||
char[] pw = new char[passphrase.length()];
|
||||
|
Loading…
Reference in New Issue
Block a user