diff --git a/Duplicati/CommandLine/BackendTool/Program.cs b/Duplicati/CommandLine/BackendTool/Program.cs index ca25f403b..0b177c656 100644 --- a/Duplicati/CommandLine/BackendTool/Program.cs +++ b/Duplicati/CommandLine/BackendTool/Program.cs @@ -94,12 +94,12 @@ namespace Duplicati.CommandLine.BackendTool using(var backend = Library.DynamicLoader.BackendLoader.GetBackend(args[1], options)) { if (backend == null) - throw new UserInformationException("Backend not supported"); + throw new UserInformationException("Backend not supported", "InvalidBackend"); if (command == "list") { if (args.Count != 2) - throw new UserInformationException(string.Format("too many arguments: {0}", string.Join(",", args))); + throw new UserInformationException(string.Format("too many arguments: {0}", string.Join(",", args)), "BackendToolTooManyArguments"); Console.WriteLine(string.Format("{0}\t{1}\t{2}\t{3}", "Name", "Dir/File", "LastChange", "Size")); foreach(var e in backend.List()) @@ -110,7 +110,7 @@ namespace Duplicati.CommandLine.BackendTool else if (command == "create") { if (args.Count != 2) - throw new UserInformationException(string.Format("too many arguments: {0}", string.Join(",", args))); + throw new UserInformationException(string.Format("too many arguments: {0}", string.Join(",", args)), "BackendToolTooManyArguments"); backend.CreateFolder(); @@ -119,7 +119,7 @@ namespace Duplicati.CommandLine.BackendTool else if (command == "delete") { if (args.Count < 3) - throw new UserInformationException("DELETE requires a filename argument"); + throw new UserInformationException("DELETE requires a filename argument", "BackendToolDeleteRequiresAnArgument"); if (args.Count > 3) throw new Exception(string.Format("too many arguments: {0}", string.Join(",", args))); backend.Delete(Path.GetFileName(args[2])); @@ -129,11 +129,11 @@ namespace Duplicati.CommandLine.BackendTool else if (command == "get") { if (args.Count < 3) - throw new UserInformationException("GET requires a filename argument"); + throw new UserInformationException("GET requires a filename argument", "BackendToolGetRequiresAnArgument"); if (args.Count > 3) - throw new UserInformationException(string.Format("too many arguments: {0}", string.Join(",", args))); + throw new UserInformationException(string.Format("too many arguments: {0}", string.Join(",", args)), "BackendToolTooManyArguments"); if (File.Exists(args[2])) - throw new UserInformationException("File already exists, not overwriting!"); + throw new UserInformationException("File already exists, not overwriting!", "BackendToolFileAlreadyExists"); backend.Get(Path.GetFileName(args[2]), args[2]); return 0; @@ -141,9 +141,9 @@ namespace Duplicati.CommandLine.BackendTool else if (command == "put") { if (args.Count < 3) - throw new UserInformationException("PUT requires a filename argument"); + throw new UserInformationException("PUT requires a filename argument","BackendToolPutRequiresAndArgument"); if (args.Count > 3) - throw new UserInformationException(string.Format("too many arguments: {0}", string.Join(",", args))); + throw new UserInformationException(string.Format("too many arguments: {0}", string.Join(",", args)), "BackendToolTooManyArguments"); backend.Put(Path.GetFileName(args[2]), args[2]); diff --git a/Duplicati/CommandLine/Commands.cs b/Duplicati/CommandLine/Commands.cs index 1601dac01..fe0d473c0 100644 --- a/Duplicati/CommandLine/Commands.cs +++ b/Duplicati/CommandLine/Commands.cs @@ -143,7 +143,7 @@ namespace Duplicati.CommandLine public static int Affected(TextWriter outwriter, Action setup, List args, Dictionary options, Library.Utility.IFilter filter) { - var fullresult = Duplicati.Library.Utility.Utility.ParseBoolOption(options, "verbose") || Duplicati.Library.Utility.Utility.ParseBoolOption(options, "full-result"); + var fullresult = Duplicati.Library.Utility.Utility.ParseBoolOption(options, "full-result"); var backend = args[0]; args.RemoveAt(0); @@ -172,7 +172,8 @@ namespace Duplicati.CommandLine options["no-encryption"] = "true"; } - using(var i = new Library.Main.Controller(backend, options, new ConsoleOutput(outwriter, options))) + using(var console = new ConsoleOutput(outwriter, options)) + using(var i = new Library.Main.Controller(backend, options, console)) { setup(i); i.ListAffected(args, res => @@ -242,7 +243,8 @@ namespace Duplicati.CommandLine if (Duplicati.Library.Utility.Utility.ParseBoolOption(options, "list-sets-only")) filter = new Duplicati.Library.Utility.FilterExpression(); - using(var i = new Library.Main.Controller(args[0], options, new ConsoleOutput(outwriter, options))) + using (var console = new ConsoleOutput(outwriter, options)) + using(var i = new Library.Main.Controller(args[0], options, console)) { setup(i); var backend = args[0]; @@ -391,7 +393,8 @@ namespace Duplicati.CommandLine return 200; } - using(var i = new Library.Main.Controller(args[0], options, new ConsoleOutput(outwriter, options))) + using (var console = new ConsoleOutput(outwriter, options)) + using(var i = new Library.Main.Controller(args[0], options, console)) { setup(i); args.RemoveAt(0); @@ -422,7 +425,8 @@ namespace Duplicati.CommandLine if (args.Count != 1) return PrintWrongNumberOfArguments(outwriter, args, 1); - using (var i = new Duplicati.Library.Main.Controller(args[0], options, new ConsoleOutput(outwriter, options))) + using (var console = new ConsoleOutput(outwriter, options)) + using (var i = new Duplicati.Library.Main.Controller(args[0], options, console)) { setup(i); i.Repair(filter); @@ -452,11 +456,10 @@ namespace Duplicati.CommandLine if (args[ix].IndexOfAny(new char[] { '*', '?' }) < 0 && !args[ix].StartsWith("[", StringComparison.Ordinal) && args[ix].EndsWith(System.IO.Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal)) args[ix] += "*"; - var output = new ConsoleOutput(outwriter, options); - output.MessageEvent(string.Format("Restore started at {0}", DateTime.Now)); - + using(var output = new ConsoleOutput(outwriter, options)) using (var i = new Library.Main.Controller(backend, options, output)) { + output.MessageEvent(string.Format("Restore started at {0}", DateTime.Now)); setup(i); if (controlFiles) { @@ -517,7 +520,7 @@ namespace Duplicati.CommandLine output.MessageEvent("***********************************************"); } - if (output.VerboseOutput) + if (output.FullResults) Library.Utility.Utility.PrintSerializeObject(res, outwriter); if (res.Warnings.Count() > 0) @@ -537,110 +540,116 @@ namespace Duplicati.CommandLine var backend = args[0]; args.RemoveAt(0); var dirs = args.ToArray(); - var output = new ConsoleOutput(outwriter, options); - Library.Interface.IBackupResults result; - - using(var periodicOutput = new PeriodicOutput(output, TimeSpan.FromSeconds(5))) + using (var output = new ConsoleOutput(outwriter, options)) { - output.MessageEvent(string.Format("Backup started at {0}", DateTime.Now)); - - output.PhaseChanged += (phase, previousPhase) => + using (var periodicOutput = new PeriodicOutput(output, TimeSpan.FromSeconds(5))) { - if (previousPhase == Duplicati.Library.Main.OperationPhase.Backup_PostBackupTest) - output.MessageEvent("Remote backup verification completed"); - - switch (phase) + if ((new Duplicati.Library.Main.Options(options)).DisableOnBattery && (Duplicati.Library.Utility.Power.PowerSupply.GetSource() == Duplicati.Library.Utility.Power.PowerSupply.Source.Battery)) { - case Duplicati.Library.Main.OperationPhase.Backup_ProcessingFiles: - output.MessageEvent("Scanning local files ..."); - periodicOutput.SetReady(); - break; - case Duplicati.Library.Main.OperationPhase.Backup_Finalize: - periodicOutput.SetFinished(); - break; - case Duplicati.Library.Main.OperationPhase.Backup_PreBackupVerify: - output.MessageEvent("Checking remote backup ..."); - break; - case Duplicati.Library.Main.OperationPhase.Backup_PostBackupVerify: - output.MessageEvent("Checking remote backup ..."); - break; - case Duplicati.Library.Main.OperationPhase.Backup_PostBackupTest: - output.MessageEvent("Verifying remote backup ..."); - break; - case Duplicati.Library.Main.OperationPhase.Backup_Compact: - output.MessageEvent("Compacting remote backup ..."); - break; + output.MessageEvent("The \"disable-on-battery\" option only affects scheduled backups and is ignored by backups run manually or from the command line."); } - }; - - periodicOutput.WriteOutput += (progress, files, size, counting) => { - output.MessageEvent(string.Format(" {0} files need to be examined ({1}){2}", files, Library.Utility.Utility.FormatSizeString(size), counting ? " (still counting)" : "")); - }; - using (var i = new Library.Main.Controller(backend, options, output)) - { - setup(i); - result = i.Backup(dirs, filter); + output.MessageEvent(string.Format("Backup started at {0}", DateTime.Now)); + + output.PhaseChanged += (phase, previousPhase) => + { + if (previousPhase == Duplicati.Library.Main.OperationPhase.Backup_PostBackupTest) + output.MessageEvent("Remote backup verification completed"); + + switch (phase) + { + case Duplicati.Library.Main.OperationPhase.Backup_ProcessingFiles: + output.MessageEvent("Scanning local files ..."); + periodicOutput.SetReady(); + break; + case Duplicati.Library.Main.OperationPhase.Backup_Finalize: + periodicOutput.SetFinished(); + break; + case Duplicati.Library.Main.OperationPhase.Backup_PreBackupVerify: + output.MessageEvent("Checking remote backup ..."); + break; + case Duplicati.Library.Main.OperationPhase.Backup_PostBackupVerify: + output.MessageEvent("Checking remote backup ..."); + break; + case Duplicati.Library.Main.OperationPhase.Backup_PostBackupTest: + output.MessageEvent("Verifying remote backup ..."); + break; + case Duplicati.Library.Main.OperationPhase.Backup_Compact: + output.MessageEvent("Compacting remote backup ..."); + break; + } + }; + + periodicOutput.WriteOutput += (progress, files, size, counting) => + { + output.MessageEvent(string.Format(" {0} files need to be examined ({1}){2}", files, Library.Utility.Utility.FormatSizeString(size), counting ? " (still counting)" : "")); + }; + + using (var i = new Library.Main.Controller(backend, options, output)) + { + setup(i); + result = i.Backup(dirs, filter); + } } + + if (output.FullResults) + { + Library.Utility.Utility.PrintSerializeObject(result, outwriter); + outwriter.WriteLine(); + } + + var parsedStats = result.BackendStatistics as Duplicati.Library.Interface.IParsedBackendStatistics; + output.MessageEvent(string.Format(" Duration of backup: {0:hh\\:mm\\:ss}", result.Duration)); + if (parsedStats != null) + { + if (parsedStats.KnownFileCount > 0) + { + output.MessageEvent(string.Format(" Remote files: {0}", parsedStats.KnownFileCount)); + output.MessageEvent(string.Format(" Remote size: {0}", Library.Utility.Utility.FormatSizeString(parsedStats.KnownFileSize))); + } + + if (parsedStats.TotalQuotaSpace >= 0) + { + output.MessageEvent(string.Format(" Total remote quota: {0}", Library.Utility.Utility.FormatSizeString(parsedStats.TotalQuotaSpace))); + } + + if (parsedStats.FreeQuotaSpace >= 0) + { + output.MessageEvent(string.Format(" Available remote quota: {0}", Library.Utility.Utility.FormatSizeString(parsedStats.FreeQuotaSpace))); + } + } + + output.MessageEvent(string.Format(" Files added: {0}", result.AddedFiles)); + output.MessageEvent(string.Format(" Files deleted: {0}", result.DeletedFiles)); + output.MessageEvent(string.Format(" Files changed: {0}", result.ModifiedFiles)); + + output.MessageEvent(string.Format(" Data uploaded: {0}", Library.Utility.Utility.FormatSizeString(result.BackendStatistics.BytesUploaded))); + output.MessageEvent(string.Format(" Data downloaded: {0}", Library.Utility.Utility.FormatSizeString(result.BackendStatistics.BytesDownloaded))); + + if (result.ExaminedFiles == 0 && (filter != null || !filter.Empty)) + output.MessageEvent("No files were processed. If this was not intentional you may want to use the \"test-filters\" command"); + + output.MessageEvent("Backup completed successfully!"); + + //Interrupted = 50 + if (result.PartialBackup) + return 50; + + //Completed with errors = 3 + if (result.ParsedResult == Library.Interface.ParsedResultType.Error) + return 3; + + //Completed with warnings = 2 + if (result.ParsedResult == Library.Interface.ParsedResultType.Warning) + return 2; + + //Success, but no upload = 1 + if (result.BackendStatistics.BytesUploaded == 0) + return 1; + + return 0; } - - if (output.VerboseOutput) - { - Library.Utility.Utility.PrintSerializeObject(result, outwriter); - outwriter.WriteLine(); - } - - var parsedStats = result.BackendStatistics as Duplicati.Library.Interface.IParsedBackendStatistics; - output.MessageEvent(string.Format(" Duration of backup: {0:hh\\:mm\\:ss}", result.Duration)); - if (parsedStats != null) - { - if (parsedStats.KnownFileCount > 0) - { - output.MessageEvent(string.Format(" Remote files: {0}", parsedStats.KnownFileCount)); - output.MessageEvent(string.Format(" Remote size: {0}", Library.Utility.Utility.FormatSizeString(parsedStats.KnownFileSize))); - } - - if (parsedStats.TotalQuotaSpace >= 0) - { - output.MessageEvent(string.Format(" Total remote quota: {0}", Library.Utility.Utility.FormatSizeString(parsedStats.TotalQuotaSpace))); - } - - if (parsedStats.FreeQuotaSpace >= 0) - { - output.MessageEvent(string.Format(" Available remote quota: {0}", Library.Utility.Utility.FormatSizeString(parsedStats.FreeQuotaSpace))); - } - } - - output.MessageEvent(string.Format(" Files added: {0}", result.AddedFiles)); - output.MessageEvent(string.Format(" Files deleted: {0}", result.DeletedFiles)); - output.MessageEvent(string.Format(" Files changed: {0}", result.ModifiedFiles)); - - output.MessageEvent(string.Format(" Data uploaded: {0}", Library.Utility.Utility.FormatSizeString(result.BackendStatistics.BytesUploaded))); - output.MessageEvent(string.Format(" Data downloaded: {0}", Library.Utility.Utility.FormatSizeString(result.BackendStatistics.BytesDownloaded))); - - if (result.ExaminedFiles == 0 && (filter != null || !filter.Empty)) - output.MessageEvent("No files were processed. If this was not intentional you may want to use the \"test-filters\" command"); - - output.MessageEvent("Backup completed successfully!"); - - //Interrupted = 50 - if (result.PartialBackup) - return 50; - - //Completed with errors = 3 - if (result.ParsedResult == Library.Interface.ParsedResultType.Error) - return 3; - - //Completed with warnings = 2 - if (result.ParsedResult == Library.Interface.ParsedResultType.Warning) - return 2; - - //Success, but no upload = 1 - if (result.BackendStatistics.BytesUploaded == 0) - return 1; - - return 0; } public static int Compact(TextWriter outwriter, Action setup, List args, Dictionary options, Library.Utility.IFilter filter) @@ -648,7 +657,8 @@ namespace Duplicati.CommandLine if (args.Count != 1) return PrintWrongNumberOfArguments(outwriter, args, 1); - using (var i = new Library.Main.Controller(args[0], options, new ConsoleOutput(outwriter, options))) + using(var console = new ConsoleOutput(outwriter, options)) + using (var i = new Library.Main.Controller(args[0], options, console)) { setup(i); i.Compact(); @@ -659,7 +669,7 @@ namespace Duplicati.CommandLine public static int Test(TextWriter outwriter, Action setup, List args, Dictionary options, Library.Utility.IFilter filter) { - var verbose = Library.Utility.Utility.ParseBoolOption(options, "verbose") || Duplicati.Library.Utility.Utility.ParseBoolOption(options, "full-result"); + var fullResults = Duplicati.Library.Utility.Utility.ParseBoolOption(options, "full-result"); if (args.Count != 1 && args.Count != 2) return PrintWrongNumberOfArguments(outwriter, args, 1); @@ -673,7 +683,8 @@ namespace Duplicati.CommandLine } Library.Interface.ITestResults result; - using (var i = new Library.Main.Controller(args[0], options, new ConsoleOutput(outwriter, options))) + using (var console = new ConsoleOutput(outwriter, options)) + using (var i = new Library.Main.Controller(args[0], options, console)) { setup(i); result = i.Test(tests); @@ -700,7 +711,7 @@ namespace Duplicati.CommandLine var changecount = n.Value.Count(); if (changecount == 0) { - if (verbose) + if (fullResults) Console.WriteLine("{0}: No errors", n.Key); } else @@ -711,7 +722,7 @@ namespace Duplicati.CommandLine { count++; Console.WriteLine("\t{0}: {1}", c.Key, c.Value); - if (!verbose && count == 10 && changecount > 10) + if (!fullResults && count == 10 && changecount > 10) { Console.WriteLine("\t... and {0} more", changecount - count); break; @@ -764,7 +775,8 @@ namespace Duplicati.CommandLine else if (args.Count == 1) args.Add("report"); - using (var i = new Library.Main.Controller(args[0], options, new ConsoleOutput(outwriter, options))) + using (var console = new ConsoleOutput(outwriter, options)) + using (var i = new Library.Main.Controller(args[0], options, console)) { setup(i); i.CreateLogDatabase(args[1]); @@ -782,7 +794,7 @@ namespace Duplicati.CommandLine public static int ListChanges(TextWriter outwriter, Action setup, List args, Dictionary options, Library.Utility.IFilter filter) { - var fullresult = Duplicati.Library.Utility.Utility.ParseBoolOption(options, "verbose") || Duplicati.Library.Utility.Utility.ParseBoolOption(options, "full-result"); + var fullresult = Duplicati.Library.Utility.Utility.ParseBoolOption(options, "full-result"); if (args.Count < 1) return PrintWrongNumberOfArguments(outwriter, args, 1); @@ -907,7 +919,8 @@ namespace Duplicati.CommandLine outwriter.WriteLine("Size of backup {0}: {1}", result.CompareVersionIndex, Library.Utility.Utility.FormatSizeString(result.CurrentSize)); }; - using (var i = new Library.Main.Controller(args[0], options, new ConsoleOutput(outwriter, options))) + using (var console = new ConsoleOutput(outwriter, options)) + using (var i = new Library.Main.Controller(args[0], options, console)) { setup(i); if (args.Count == 2) @@ -927,9 +940,8 @@ namespace Duplicati.CommandLine return 200; } - options["verbose"] = "true"; - - using(var i = new Library.Main.Controller("dummy://", options, new ConsoleOutput(outwriter, options))) + using (var console = new ConsoleOutput(outwriter, options)) + using(var i = new Library.Main.Controller("dummy://", options, console)) { setup(i); var result = i.TestFilter(args.ToArray(), filter); @@ -948,7 +960,8 @@ namespace Duplicati.CommandLine return 200; } - using (var i = new Library.Main.Controller("dummy://", options, new ConsoleOutput(outwriter, options))) + using (var console = new ConsoleOutput(outwriter, options)) + using (var i = new Library.Main.Controller("dummy://", options, console)) { setup(i); foreach (var line in i.SystemInfo().Lines) @@ -986,7 +999,8 @@ namespace Duplicati.CommandLine } - using (var i = new Library.Main.Controller(args[0], options, new ConsoleOutput(outwriter, options))) + using (var console = new ConsoleOutput(outwriter, options)) + using (var i = new Library.Main.Controller(args[0], options, console)) { setup(i); i.PurgeFiles(filter); @@ -1000,11 +1014,11 @@ namespace Duplicati.CommandLine if (args.Count != 1) return PrintWrongNumberOfArguments(outwriter, args, 1); - var con = new ConsoleOutput(outwriter, options); var previd = -1L; var outputcount = 0L; - var verbose = Duplicati.Library.Utility.Utility.ParseBoolOption(options, "verbose") || Duplicati.Library.Utility.Utility.ParseBoolOption(options, "full-result"); + var fullresult = Duplicati.Library.Utility.Utility.ParseBoolOption(options, "full-result"); + using (var con = new ConsoleOutput(outwriter, options)) using (var i = new Library.Main.Controller(args[0], options, con)) { setup(i); @@ -1019,7 +1033,7 @@ namespace Duplicati.CommandLine con.MessageEvent(string.Format("\t{0} ({1})", path, Library.Utility.Utility.FormatSizeString(size))); outputcount++; - if (outputcount >= 5 && !verbose && count != outputcount) + if (outputcount >= 5 && !fullresult && count != outputcount) { con.MessageEvent(string.Format("\t ... and {0} more, (use --{1} to list all)", count - outputcount, "full-result")); return false; @@ -1038,7 +1052,8 @@ namespace Duplicati.CommandLine if (args.Count != 1) return PrintWrongNumberOfArguments(outwriter, args, 1); - using (var i = new Library.Main.Controller(args[0], options, new ConsoleOutput(outwriter, options))) + using (var console = new ConsoleOutput(outwriter, options)) + using (var i = new Library.Main.Controller(args[0], options, console)) { setup(i); var res = i.PurgeBrokenFiles(filter); @@ -1055,7 +1070,8 @@ namespace Duplicati.CommandLine return 200; } - using (var i = new Library.Main.Controller("dummy://", options, new ConsoleOutput(outwriter, options))) + using (var console = new ConsoleOutput(outwriter, options)) + using (var i = new Library.Main.Controller("dummy://", options, console)) { setup(i); foreach (var l in i.SendMail().Lines) @@ -1074,8 +1090,8 @@ namespace Duplicati.CommandLine if (args.Count != 1) return PrintWrongNumberOfArguments(outwriter, args, 1); - using ( - var controller = new Library.Main.Controller(args[0], options, new ConsoleOutput(outwriter, options))) + using (var console = new ConsoleOutput(outwriter, options)) + using (var controller = new Library.Main.Controller(args[0], options, console)) { setup(controller); controller.Vacuum(); diff --git a/Duplicati/CommandLine/ConsoleLogTarget.cs b/Duplicati/CommandLine/ConsoleLogTarget.cs new file mode 100644 index 000000000..ceb5829ff --- /dev/null +++ b/Duplicati/CommandLine/ConsoleLogTarget.cs @@ -0,0 +1,93 @@ +// Copyright (C) 2018, The Duplicati Team +// http://www.duplicati.com, info@duplicati.com +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +using System; +using System.IO; +using Duplicati.Library.Logging; +using Duplicati.Library.Utility; + +namespace Duplicati.CommandLine +{ + /// + /// Log output handler for the console + /// + public class ConsoleLogTarget : Library.Logging.ILogDestination + { + /// + /// The stdout stream + /// + private readonly TextWriter m_stdout; + /// + /// The stderr stream + /// + private readonly TextWriter m_stderr; + /// + /// The default log level + /// + private readonly LogMessageType m_level; + /// + /// The filter, if any + /// + private readonly IFilter m_filter; + + /// + /// Initializes a new instance of the class. + /// + /// The stdout stream. + /// The stderr stream. + /// The minimum log level to consider. + /// The log filter, if any. + public ConsoleLogTarget(TextWriter stdout, TextWriter stderr, LogMessageType level, string logfilter) + { + m_stdout = stdout; + m_stderr = stderr; + m_level = level; + m_filter = Library.Main.Options.ParseLogFilter(logfilter); + } + + /// + /// Writes the message to stdout or stderr. + /// + /// The entry to write. + public void WriteMessage(LogEntry entry) + { + var found = m_filter.Matches(entry.Tag, out var result, out var match); + // If there is a filter match, use that + if (found) + { + if (!result) + return; + + if (entry.Level == LogMessageType.Error) + m_stderr.WriteLine(entry.ToString()); + else + m_stdout.WriteLine(entry.ToString()); + } + else + { + // Otherwise, filter by log-level + if (entry.Level < m_level) + return; + } + + if (entry.Level == LogMessageType.Error) + m_stderr.WriteLine(entry.FormattedMessage); + else + m_stdout.WriteLine(entry.FormattedMessage); + + } + } +} diff --git a/Duplicati/CommandLine/ConsoleOutput.cs b/Duplicati/CommandLine/ConsoleOutput.cs index d64d59f34..6ff5814aa 100644 --- a/Duplicati/CommandLine/ConsoleOutput.cs +++ b/Duplicati/CommandLine/ConsoleOutput.cs @@ -22,21 +22,21 @@ using Duplicati.Library.Main; namespace Duplicati.CommandLine { - public class ConsoleOutput : Library.Main.IMessageSink + public class ConsoleOutput : Library.Main.IMessageSink, IDisposable { - private object m_lock = new object(); + private readonly object m_lock = new object(); public bool QuietConsole { get; private set; } - public bool VerboseOutput { get; private set; } public bool VerboseErrors { get; private set; } public TextWriter Output { get; private set; } + public bool FullResults { get; private set; } public ConsoleOutput(TextWriter output, Dictionary options) { this.Output = output; this.QuietConsole = Library.Utility.Utility.ParseBoolOption(options, "quiet-console"); - this.VerboseOutput = Library.Utility.Utility.ParseBoolOption(options, "verbose"); this.VerboseErrors = Library.Utility.Utility.ParseBoolOption(options, "debug-output"); + this.FullResults = Library.Utility.Utility.ParseBoolOption(options, "full-results"); } #region IMessageSink implementation @@ -92,43 +92,37 @@ namespace Duplicati.CommandLine } } } - - public void VerboseEvent(string message, object[] args) + + public void WriteMessage(Library.Logging.LogEntry entry) { - if (VerboseOutput) - lock(m_lock) - Output.WriteLine(message, args); + if (QuietConsole) + return; + + lock (m_lock) + { + if (entry.Exception != null) + Output.WriteLine("{0} => {1}", entry.FormattedMessage, VerboseErrors ? entry.Exception.ToString() : entry.Exception.Message); + else if (entry.Level == Library.Logging.LogMessageType.DryRun) + Output.WriteLine("[Dryrun]: {0}", entry.FormattedMessage); + + else + Output.WriteLine(entry.FormattedMessage); + } + } + public void MessageEvent(string message) { - if (!QuietConsole) - lock(m_lock) - Output.WriteLine(message); + if (QuietConsole) + return; + + lock (m_lock) + Output.WriteLine(message); + } - - public void RetryEvent(string message, Exception ex) + + public void Dispose() { - if (!QuietConsole) - lock(m_lock) - Output.WriteLine(ex == null ? message : string.Format("{0} => {1}", message, VerboseErrors ? ex.ToString() : ex.Message)); - } - public void WarningEvent(string message, Exception ex) - { - if (!QuietConsole) - lock(m_lock) - Output.WriteLine(ex == null ? message : string.Format("{0} => {1}", message, VerboseErrors ? ex.ToString() : ex.Message)); - } - public void ErrorEvent(string message, Exception ex) - { - if (!QuietConsole) - lock(m_lock) - Output.WriteLine(ex == null ? message : string.Format("{0} => {1}", message, VerboseErrors ? ex.ToString() : ex.Message)); - } - public void DryrunEvent(string message) - { - if (!QuietConsole) - lock(m_lock) - Output.WriteLine(string.Format("[Dryrun]: {0}", message)); } #endregion } diff --git a/Duplicati/CommandLine/Duplicati.CommandLine.csproj b/Duplicati/CommandLine/Duplicati.CommandLine.csproj index e9a6898ff..cb5e91dd1 100644 --- a/Duplicati/CommandLine/Duplicati.CommandLine.csproj +++ b/Duplicati/CommandLine/Duplicati.CommandLine.csproj @@ -54,6 +54,7 @@ + diff --git a/Duplicati/CommandLine/Program.cs b/Duplicati/CommandLine/Program.cs index a9ce8e319..713a5f996 100644 --- a/Duplicati/CommandLine/Program.cs +++ b/Duplicati/CommandLine/Program.cs @@ -29,6 +29,8 @@ namespace Duplicati.CommandLine { public class Program { + private static string LOGTAG = Library.Logging.Log.LogTagFromType(); + public static bool FROM_COMMANDLINE = false; /// @@ -125,7 +127,6 @@ namespace Duplicati.CommandLine var filter = tmpparsed.Item2; verboseErrors = Library.Utility.Utility.ParseBoolOption(options, "debug-output"); - verbose = Library.Utility.Utility.ParseBoolOption(options, "verbose"); if (cargs.Count == 1 && string.Equals(cargs[0], "changelog", StringComparison.OrdinalIgnoreCase)) { @@ -284,6 +285,13 @@ namespace Duplicati.CommandLine } } + /*if (ex is Duplicati.Library.Interface.UserInformationException) + { + errwriter.WriteLine(Strings.Program.YouMayGetMoreHelpHere( + Library.Logging.Log.CreateHelpLink(null, null, ((Library.Interface.UserInformationException)(ex)).HelpID, true) + )); + }*/ + //Error = 100 return 100; } @@ -351,7 +359,7 @@ namespace Duplicati.CommandLine // If the user specifies parameters-file, all filters must be in the file. // Allowing to specify some filters on the command line could result in wrong filter ordering if (!filter.Empty && !newfilter.Empty) - throw new Duplicati.Library.Interface.UserInformationException(Strings.Program.FiltersCannotBeUsedWithFileError2); + throw new Duplicati.Library.Interface.UserInformationException(Strings.Program.FiltersCannotBeUsedWithFileError2, "FiltersCannotBeUsedOnCommandLineAndInParameterFile"); if (!newfilter.Empty) filter = newfilter; @@ -378,8 +386,8 @@ namespace Duplicati.CommandLine if (cargs.Count >= 1 && cargs[0].Equals("backup", StringComparison.OrdinalIgnoreCase)) cargs.AddRange(newsource); - else if (newsource.Count > 0 && Library.Utility.Utility.ParseBoolOption(options, "verbose")) - outwriter.WriteLine(Strings.Program.SkippingSourceArgumentsOnNonBackupOperation); + else if (newsource.Count > 0) + Library.Logging.Log.WriteVerboseMessage(LOGTAG, "NotUsingBackupSources", Strings.Program.SkippingSourceArgumentsOnNonBackupOperation); return true; } diff --git a/Duplicati/CommandLine/RecoveryTool/List.cs b/Duplicati/CommandLine/RecoveryTool/List.cs index fb3cc7408..67f44586d 100644 --- a/Duplicati/CommandLine/RecoveryTool/List.cs +++ b/Duplicati/CommandLine/RecoveryTool/List.cs @@ -91,7 +91,7 @@ namespace Duplicati.CommandLine.RecoveryTool { var items = ParseListFiles(folder); if (index < 0 || index >= items.Length) - throw new Duplicati.Library.Interface.UserInformationException(string.Format("Valid range for version is 0 to {0}", items.Length - 1)); + throw new Duplicati.Library.Interface.UserInformationException(string.Format("Valid range for version is 0 to {0}", items.Length - 1), "RecoveryToolInvalidVersion"); return items[index].Value; } diff --git a/Duplicati/CommandLine/RecoveryTool/Program.cs b/Duplicati/CommandLine/RecoveryTool/Program.cs index 265f94659..eb74817c3 100644 --- a/Duplicati/CommandLine/RecoveryTool/Program.cs +++ b/Duplicati/CommandLine/RecoveryTool/Program.cs @@ -115,7 +115,7 @@ namespace Duplicati.CommandLine.RecoveryTool // If the user specifies parameters-file, all filters must be in the file. // Allowing to specify some filters on the command line could result in wrong filter ordering if (!filter.Empty && !newfilter.Empty) - throw new Duplicati.Library.Interface.UserInformationException("Filters cannot be specified on the commandline if filters are also present in the parameter file"); + throw new Duplicati.Library.Interface.UserInformationException("Filters cannot be specified on the commandline if filters are also present in the parameter file", "RecoveryToolFiltersOnCommandLineAndInParameterFile"); if (!newfilter.Empty) filter = newfilter; diff --git a/Duplicati/CommandLine/RecoveryTool/Restore.cs b/Duplicati/CommandLine/RecoveryTool/Restore.cs index 686de93d1..ef5f9fb9d 100644 --- a/Duplicati/CommandLine/RecoveryTool/Restore.cs +++ b/Duplicati/CommandLine/RecoveryTool/Restore.cs @@ -94,9 +94,9 @@ namespace Duplicati.CommandLine.RecoveryTool var filehasher = string.IsNullOrWhiteSpace(filehash_str) ? null : Library.Utility.HashAlgorithmHelper.Create(filehash_str); if (blockhasher == null) - throw new Duplicati.Library.Interface.UserInformationException(string.Format("Block hash algorithm not valid: {0}", blockhash_str)); + throw new Duplicati.Library.Interface.UserInformationException(string.Format("Block hash algorithm not valid: {0}", blockhash_str), "BlockHashAlgorithmNotSupported"); if (filehasher == null) - throw new Duplicati.Library.Interface.UserInformationException(string.Format("File hash algorithm not valid: {0}", filehash_str)); + throw new Duplicati.Library.Interface.UserInformationException(string.Format("File hash algorithm not valid: {0}", filehash_str), "FileHashAlgorithmNotSupported"); var hashesprblock = blocksize / (blockhasher.HashSize / 8); diff --git a/Duplicati/CommandLine/Strings.cs b/Duplicati/CommandLine/Strings.cs index ef9a45258..a358b2b8a 100644 --- a/Duplicati/CommandLine/Strings.cs +++ b/Duplicati/CommandLine/Strings.cs @@ -31,5 +31,6 @@ namespace Duplicati.CommandLine.Strings { public static string QuietConsoleOptionLong { get { return LC.L(@"If this option is set, progress reports and other messages that would normally go to the console will be redirected to the log."); } } public static string QuietConsoleOptionShort { get { return LC.L(@"Disable console output"); } } public static string SkippingSourceArgumentsOnNonBackupOperation { get { return @"The --source argument was specified in the parameter file, but the current operation is not a backup operation, so the argument is ignored"; } } + public static string YouMayGetMoreHelpHere(string url) { return LC.L(@"This link may provide additional information: {0}", url); } } } diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/Duplicati.GUI.TrayIcon.csproj b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Duplicati.GUI.TrayIcon.csproj index a72a42307..4245a3399 100644 --- a/Duplicati/GUI/Duplicati.GUI.TrayIcon/Duplicati.GUI.TrayIcon.csproj +++ b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Duplicati.GUI.TrayIcon.csproj @@ -73,10 +73,10 @@ ..\..\..\thirdparty\appindicator-sharp\appindicator-sharp.dll False - + ..\..\..\thirdparty\appindicator-sharp\gdk-sharp.dll - + ..\..\..\thirdparty\appindicator-sharp\gtk-sharp.dll diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/HostedInstanceKeeper.cs b/Duplicati/GUI/Duplicati.GUI.TrayIcon/HostedInstanceKeeper.cs index ab18b26c3..8d348213c 100644 --- a/Duplicati/GUI/Duplicati.GUI.TrayIcon/HostedInstanceKeeper.cs +++ b/Duplicati/GUI/Duplicati.GUI.TrayIcon/HostedInstanceKeeper.cs @@ -49,7 +49,7 @@ namespace Duplicati.GUI.TrayIcon if (m_runnerException != null) throw m_runnerException; else - throw new Duplicati.Library.Interface.UserInformationException("Hosted server startup timed out"); + throw new Duplicati.Library.Interface.UserInformationException("Hosted server startup timed out", "HostedStartupError"); } if (m_runnerException != null) diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/HttpServerConnection.cs b/Duplicati/GUI/Duplicati.GUI.TrayIcon/HttpServerConnection.cs index 11e8d4098..3c8eb53bd 100644 --- a/Duplicati/GUI/Duplicati.GUI.TrayIcon/HttpServerConnection.cs +++ b/Duplicati/GUI/Duplicati.GUI.TrayIcon/HttpServerConnection.cs @@ -62,15 +62,15 @@ namespace Duplicati.GUI.TrayIcon private readonly Dictionary m_updateRequest; private readonly Dictionary m_options; - private readonly bool m_dbPasswordSourceDatabase; - private string m_TrayIconHeaderValue => m_dbPasswordSourceDatabase ? "database" : "user"; + private readonly Program.PasswordSource m_passwordSource; + private string m_TrayIconHeaderValue => (m_passwordSource == Program.PasswordSource.Database) ? "database" : "user"; public IServerStatus Status { get { return m_status; } } - private object m_lock = new object(); + private readonly object m_lock = new object(); private Queue m_workQueue = new Queue(); - public HttpServerConnection(Uri server, string password, bool saltedpassword, bool dbPasswordSourceDatabase, Dictionary options) + public HttpServerConnection(Uri server, string password, bool saltedpassword, Program.PasswordSource passwordSource, Dictionary options) { m_baseUri = server.ToString(); if (!m_baseUri.EndsWith("/", StringComparison.Ordinal)) @@ -83,7 +83,7 @@ namespace Duplicati.GUI.TrayIcon m_password = password; m_saltedpassword = saltedpassword; m_options = options; - m_dbPasswordSourceDatabase = dbPasswordSourceDatabase; + m_passwordSource = passwordSource; m_updateRequest = new Dictionary(); m_updateRequest["longpoll"] = "false"; @@ -364,15 +364,25 @@ namespace Duplicati.GUI.TrayIcon wex.Status == System.Net.WebExceptionStatus.ProtocolError && httpex.StatusCode == System.Net.HttpStatusCode.Unauthorized) { - if (m_dbPasswordSourceDatabase) + //Can survive if server password is changed via web ui + switch (m_passwordSource) { - Program.databaseConnection.ApplicationSettings.ReloadSettings(); - - //Can survive if server password is changed via web ui - if (Program.databaseConnection.ApplicationSettings.WebserverPasswordTrayIcon != m_password) - m_password = Program.databaseConnection.ApplicationSettings.WebserverPasswordTrayIcon; - else - hasTriedPassword = true; + case Program.PasswordSource.Database: + Program.databaseConnection.ApplicationSettings.ReloadSettings(); + + if (Program.databaseConnection.ApplicationSettings.WebserverPasswordTrayIcon != m_password) + m_password = Program.databaseConnection.ApplicationSettings.WebserverPasswordTrayIcon; + else + hasTriedPassword = true; + break; + case Program.PasswordSource.HostedServer: + if (Server.Program.DataConnection.ApplicationSettings.WebserverPassword != m_password) + m_password = Server.Program.DataConnection.ApplicationSettings.WebserverPassword; + else + hasTriedPassword = true; + break; + default: + throw new ArgumentOutOfRangeException(); } m_authtoken = GetAuthToken(); diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/Program.cs b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Program.cs index 6566bb4cb..57e72e9dd 100644 --- a/Duplicati/GUI/Duplicati.GUI.TrayIcon/Program.cs +++ b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Program.cs @@ -8,6 +8,12 @@ namespace Duplicati.GUI.TrayIcon { public static class Program { + public enum PasswordSource + { + Database, + HostedServer + } + public static HttpServerConnection Connection; private const string TOOLKIT_OPTION = "toolkit"; @@ -150,28 +156,30 @@ namespace Duplicati.GUI.TrayIcon openui = Duplicati.Server.Program.IsFirstRun || Duplicati.Server.Program.ServerPortChanged; password = Duplicati.Server.Program.DataConnection.ApplicationSettings.WebserverPassword; saltedpassword = true; - serverURL = (new UriBuilder(serverURL) { Port = Duplicati.Server.Program.ServerPort }).Uri; + // Tell the hosted server it was started by the TrayIcon + Duplicati.Server.Program.Origin = "Tray icon"; + + var cert = Duplicati.Server.Program.DataConnection.ApplicationSettings.ServerSSLCertificate; + var scheme = "http"; + + if (cert != null && cert.HasPrivateKey) + scheme = "https"; + + serverURL = (new UriBuilder(serverURL) + { + Port = Duplicati.Server.Program.ServerPort, + Scheme = scheme + }).Uri; } if (Library.Utility.Utility.ParseBoolOption(options, NOHOSTEDSERVER_OPTION) && Library.Utility.Utility.ParseBoolOption(options, READCONFIGFROMDB_OPTION)) databaseConnection = Server.Program.GetDatabaseConnection(options); - string pwd; - - if (options.TryGetValue("webserver-password", out pwd)) - { - password = pwd; - saltedpassword = false; - } - if (databaseConnection != null) { password = databaseConnection.ApplicationSettings.WebserverPasswordTrayIcon; saltedpassword = false; - } - if (databaseConnection != null) - { var cert = databaseConnection.ApplicationSettings.ServerSSLCertificate; var scheme = "http"; @@ -185,6 +193,14 @@ namespace Duplicati.GUI.TrayIcon }).Uri; } + string pwd; + + if (options.TryGetValue("webserver-password", out pwd)) + { + password = pwd; + saltedpassword = false; + } + string url; if (options.TryGetValue(HOSTURL_OPTION, out url)) @@ -200,7 +216,7 @@ namespace Duplicati.GUI.TrayIcon { System.Net.ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; - using (Connection = new HttpServerConnection(serverURL, password, saltedpassword, databaseConnection != null, options)) + using (Connection = new HttpServerConnection(serverURL, password, saltedpassword, databaseConnection != null ? PasswordSource.Database : PasswordSource.HostedServer, options)) { using (var tk = RunTrayIcon(toolkit)) { @@ -280,7 +296,7 @@ namespace Duplicati.GUI.TrayIcon else if (toolkit == TOOLKIT_RUMPS) return GetRumpsRunnerInstance(); else - throw new UserInformationException(string.Format("The selected toolkit '{0}' is invalid", toolkit)); + throw new UserInformationException(string.Format("The selected toolkit '{0}' is invalid", toolkit), "TrayIconInvalidToolKit"); } //We keep these in functions to avoid attempting to load the instance, diff --git a/Duplicati/Library/Backend/AlternativeFTP/AlternativeFTPBackend.cs b/Duplicati/Library/Backend/AlternativeFTP/AlternativeFTPBackend.cs index 588b624be..817462b05 100644 --- a/Duplicati/Library/Backend/AlternativeFTP/AlternativeFTPBackend.cs +++ b/Duplicati/Library/Backend/AlternativeFTP/AlternativeFTPBackend.cs @@ -361,11 +361,11 @@ namespace Duplicati.Library.Backend.AlternativeFTP return; } - throw new UserInformationException(Strings.ListVerifySizeFailure(remotename, fileEntry.Size, streamLen)); + throw new UserInformationException(Strings.ListVerifySizeFailure(remotename, fileEntry.Size, streamLen), "AftpListVerifySizeFailure"); } } - throw new UserInformationException(Strings.ListVerifyFailure(remotename, fileEntries.Select(n => n.Name))); + throw new UserInformationException(Strings.ListVerifyFailure(remotename, fileEntries.Select(n => n.Name)), "AftpListVerifySizeFailure"); } } catch (FtpCommandException ex) @@ -450,9 +450,9 @@ namespace Duplicati.Library.Backend.AlternativeFTP } } - public string DNSName + public string[] DNSName { - get { return null; } + get { return new string[] { new Uri(_url).Host }; } } private static System.IO.Stream StringToStream(string str) diff --git a/Duplicati/Library/Backend/AmazonCloudDrive/AmzCD.cs b/Duplicati/Library/Backend/AmazonCloudDrive/AmzCD.cs index 099eed1b3..6b695950a 100644 --- a/Duplicati/Library/Backend/AmazonCloudDrive/AmzCD.cs +++ b/Duplicati/Library/Backend/AmazonCloudDrive/AmzCD.cs @@ -224,7 +224,7 @@ namespace Duplicati.Library.Backend.AmazonCloudDrive m_waitUntil = DateTime.Now + m_delayTimeSpan; } else if (self != null && self.Count > 1) - throw new UserInformationException(Strings.AmzCD.MultipleEntries(p, "/" + string.Join("/", curpath))); + throw new UserInformationException(Strings.AmzCD.MultipleEntries(p, "/" + string.Join("/", curpath)), "AmzCDMultipleEntries"); else parent = self.Data.First(); } @@ -458,9 +458,27 @@ namespace Duplicati.Library.Backend.AmazonCloudDrive } } - public string DNSName + public string[] DNSName { - get { return null; } + get + { + var contentUrl = string.Empty; + var metdataUrl = string.Empty; + + if (m_endPointInfo != null) + { + if (!string.IsNullOrWhiteSpace(m_endPointInfo.ContentUrl)) + contentUrl = new Uri(m_endPointInfo.ContentUrl).Host; + if (!string.IsNullOrWhiteSpace(m_endPointInfo.MetadataUrl)) + metdataUrl = new Uri(m_endPointInfo.MetadataUrl).Host; + } + + return new string[] { + new Uri(CLOUDRIVE_MASTER_URL).Host, + contentUrl, + metdataUrl + }; + } } #endregion diff --git a/Duplicati/Library/Backend/AzureBlob/AzureBlobBackend.cs b/Duplicati/Library/Backend/AzureBlob/AzureBlobBackend.cs index a6cb8af56..176e42a6b 100644 --- a/Duplicati/Library/Backend/AzureBlob/AzureBlobBackend.cs +++ b/Duplicati/Library/Backend/AzureBlob/AzureBlobBackend.cs @@ -57,11 +57,11 @@ namespace Duplicati.Library.Backend.AzureBlob if (string.IsNullOrWhiteSpace(storageAccountName)) { - throw new UserInformationException(Strings.AzureBlobBackend.NoStorageAccountName); + throw new UserInformationException(Strings.AzureBlobBackend.NoStorageAccountName, "AzureNoAccountName"); } if (string.IsNullOrWhiteSpace(accessKey)) { - throw new UserInformationException(Strings.AzureBlobBackend.NoAccessKey); + throw new UserInformationException(Strings.AzureBlobBackend.NoAccessKey, "AzureNoAccessKey"); } _azureBlob = new AzureBlobWrapper(storageAccountName, accessKey, containerName); @@ -159,9 +159,9 @@ namespace Duplicati.Library.Backend.AzureBlob } } - public string DNSName + public string[] DNSName { - get { return null; } + get { return _azureBlob.DnsNames; } } public void Test() diff --git a/Duplicati/Library/Backend/AzureBlob/AzureBlobWrapper.cs b/Duplicati/Library/Backend/AzureBlob/AzureBlobWrapper.cs index b4925dd02..24cf5cf5b 100644 --- a/Duplicati/Library/Backend/AzureBlob/AzureBlobWrapper.cs +++ b/Duplicati/Library/Backend/AzureBlob/AzureBlobWrapper.cs @@ -36,6 +36,29 @@ namespace Duplicati.Library.Backend.AzureBlob private readonly string _containerName; private readonly CloudBlobContainer _container; + public string[] DnsNames + { + get + { + var lst = new List(); + if (_container != null) + { + if (_container.Uri != null) + lst.Add(_container.Uri.Host); + + if (_container.StorageUri != null) + { + if (_container.StorageUri.PrimaryUri != null) + lst.Add(_container.StorageUri.PrimaryUri.Host); + if (_container.StorageUri.SecondaryUri != null) + lst.Add(_container.StorageUri.SecondaryUri.Host); + } + } + + return lst.ToArray(); + } + } + public AzureBlobWrapper(string accountName, string accessKey, string containerName) { _containerName = containerName; diff --git a/Duplicati/Library/Backend/Backblaze/B2.cs b/Duplicati/Library/Backend/Backblaze/B2.cs index a93afb06d..471eb1e53 100644 --- a/Duplicati/Library/Backend/Backblaze/B2.cs +++ b/Duplicati/Library/Backend/Backblaze/B2.cs @@ -88,9 +88,9 @@ namespace Duplicati.Library.Backend.Backblaze accountKey = uri.Password; if (string.IsNullOrEmpty(accountId)) - throw new UserInformationException(Strings.B2.NoB2UserIDError); + throw new UserInformationException(Strings.B2.NoB2UserIDError, "B2MissingUserID"); if (string.IsNullOrEmpty(accountKey)) - throw new UserInformationException(Strings.B2.NoB2KeyError); + throw new UserInformationException(Strings.B2.NoB2KeyError, "B2MissingKey"); m_helper = new B2AuthHelper(accountId, accountKey); @@ -100,7 +100,7 @@ namespace Duplicati.Library.Backend.Backblaze int.TryParse(options[B2_PAGESIZE_OPTION], out m_pagesize); if (m_pagesize <= 0) - throw new UserInformationException(Strings.B2.InvalidPageSizeError(B2_PAGESIZE_OPTION, options[B2_PAGESIZE_OPTION])); + throw new UserInformationException(Strings.B2.InvalidPageSizeError(B2_PAGESIZE_OPTION, options[B2_PAGESIZE_OPTION]), "B2InvalidPageSize"); } } @@ -422,9 +422,9 @@ namespace Duplicati.Library.Backend.Backblaze get { return Strings.B2.Description; } } - public string DNSName + public string[] DNSName { - get { return null; } + get { return new string[] { new System.Uri(B2AuthHelper.AUTH_URL).Host, m_helper?.APIDnsName, m_helper?.DownloadDnsName} ; } } public void Dispose() diff --git a/Duplicati/Library/Backend/Backblaze/B2AuthHelper.cs b/Duplicati/Library/Backend/Backblaze/B2AuthHelper.cs index 55197519c..d0d960ff5 100644 --- a/Duplicati/Library/Backend/Backblaze/B2AuthHelper.cs +++ b/Duplicati/Library/Backend/Backblaze/B2AuthHelper.cs @@ -27,7 +27,7 @@ namespace Duplicati.Library.Backend.Backblaze private readonly string m_credentials; private AuthResponse m_config; private DateTime m_configExpires; - private const string AUTH_URL = "https://api.backblazeb2.com/b2api/v1/b2_authorize_account"; + internal const string AUTH_URL = "https://api.backblazeb2.com/b2api/v1/b2_authorize_account"; public B2AuthHelper(string userid, string password) : base() @@ -54,6 +54,26 @@ namespace Duplicati.Library.Backend.Backblaze return url; } + public string APIDnsName + { + get + { + if (m_config == null || string.IsNullOrWhiteSpace(m_config.APIUrl)) + return null; + return new System.Uri(m_config.APIUrl).Host; + } + } + + public string DownloadDnsName + { + get + { + if (m_config == null || string.IsNullOrWhiteSpace(m_config.DownloadUrl)) + return null; + return new System.Uri(m_config.DownloadUrl).Host; + } + } + private AuthResponse Config { get diff --git a/Duplicati/Library/Backend/Box/BoxBackend.cs b/Duplicati/Library/Backend/Box/BoxBackend.cs index 71d67227c..67bed1232 100644 --- a/Duplicati/Library/Backend/Box/BoxBackend.cs +++ b/Duplicati/Library/Backend/Box/BoxBackend.cs @@ -337,9 +337,9 @@ namespace Duplicati.Library.Backend.Box } } - public string DNSName + public string[] DNSName { - get { return null; } + get { return new string[] { new Uri(BOX_API_URL).Host, new Uri(BOX_UPLOAD_URL).Host }; } } #endregion diff --git a/Duplicati/Library/Backend/CloudFiles/CloudFiles.cs b/Duplicati/Library/Backend/CloudFiles/CloudFiles.cs index 62a0cdcc1..ad1d553db 100644 --- a/Duplicati/Library/Backend/CloudFiles/CloudFiles.cs +++ b/Duplicati/Library/Backend/CloudFiles/CloudFiles.cs @@ -73,9 +73,9 @@ namespace Duplicati.Library.Backend m_password = uri.Password; if (string.IsNullOrEmpty(m_username)) - throw new UserInformationException(Strings.CloudFiles.NoUserIDError); + throw new UserInformationException(Strings.CloudFiles.NoUserIDError, "CloudFilesNoUserID"); if (string.IsNullOrEmpty(m_password)) - throw new UserInformationException(Strings.CloudFiles.NoAPIKeyError); + throw new UserInformationException(Strings.CloudFiles.NoAPIKeyError, "CloudFilesNoApiKey"); //Fallback to the previous format if (url.Contains(DUMMY_HOSTNAME)) @@ -290,9 +290,9 @@ namespace Duplicati.Library.Backend get { return true; } } - public string DNSName + public string[] DNSName { - get { return null; } + get { return new string[] { new Uri(m_authUrl).Host, string.IsNullOrWhiteSpace(m_storageUrl) ? null : new Uri(m_storageUrl).Host }; } } public void Get(string remotename, System.IO.Stream stream) diff --git a/Duplicati/Library/Backend/Dropbox/Dropbox.cs b/Duplicati/Library/Backend/Dropbox/Dropbox.cs index c98ef226d..4374bd8a3 100644 --- a/Duplicati/Library/Backend/Dropbox/Dropbox.cs +++ b/Duplicati/Library/Backend/Dropbox/Dropbox.cs @@ -136,9 +136,9 @@ namespace Duplicati.Library.Backend public string Description { get { return Strings.Dropbox.Description; } } - public string DNSName + public string[] DNSName { - get { return null; } + get { return new string[] { new Uri(DropboxHelper.API_URL).Host, new Uri(DropboxHelper.CONTENT_API_URL).Host }; } } public void Test() diff --git a/Duplicati/Library/Backend/Dropbox/DropboxHelper.cs b/Duplicati/Library/Backend/Dropbox/DropboxHelper.cs index 5573b1c78..15d998d9e 100644 --- a/Duplicati/Library/Backend/Dropbox/DropboxHelper.cs +++ b/Duplicati/Library/Backend/Dropbox/DropboxHelper.cs @@ -11,8 +11,8 @@ namespace Duplicati.Library.Backend { public class DropboxHelper : OAuthHelper { - private const string API_URL = "https://api.dropboxapi.com/2"; - private const string CONTENT_API_URL = "https://content.dropboxapi.com/2"; + internal const string API_URL = "https://api.dropboxapi.com/2"; + internal const string CONTENT_API_URL = "https://content.dropboxapi.com/2"; private const int DROPBOX_MAX_CHUNK_UPLOAD = 10 * 1024 * 1024; // 10 MB max upload private const string API_ARG_HEADER = "DROPBOX-API-arg"; diff --git a/Duplicati/Library/Backend/FTP/FTPBackend.cs b/Duplicati/Library/Backend/FTP/FTPBackend.cs index 6f3e8b9dc..0083afd51 100644 --- a/Duplicati/Library/Backend/FTP/FTPBackend.cs +++ b/Duplicati/Library/Backend/FTP/FTPBackend.cs @@ -355,9 +355,9 @@ namespace Duplicati.Library.Backend } } - public string DNSName + public string[] DNSName { - get { return null; } + get { return new string[] { new Uri(m_url).Host }; } } public void Test() diff --git a/Duplicati/Library/Backend/File/FileBackend.cs b/Duplicati/Library/Backend/File/FileBackend.cs index dec47fcf1..5d10a05fa 100644 --- a/Duplicati/Library/Backend/File/FileBackend.cs +++ b/Duplicati/Library/Backend/File/FileBackend.cs @@ -113,7 +113,7 @@ namespace Duplicati.Library.Backend } if (m_path == null) - throw new UserInformationException(Strings.FileBackend.NoDestinationWithMarkerFileError(markerfile, paths.ToArray())); + throw new UserInformationException(Strings.FileBackend.NoDestinationWithMarkerFileError(markerfile, paths.ToArray()), "NoDestinationWithMarker"); } m_moveFile = Utility.Utility.ParseBoolOption(options, OPTION_MOVE_FILE); @@ -351,7 +351,7 @@ namespace Duplicati.Library.Backend } } - public string DNSName + public string[] DNSName { get { return null; } } diff --git a/Duplicati/Library/Backend/GoogleServices/GoogleCloudStorage.cs b/Duplicati/Library/Backend/GoogleServices/GoogleCloudStorage.cs index 2bca35acb..b426eab5b 100644 --- a/Duplicati/Library/Backend/GoogleServices/GoogleCloudStorage.cs +++ b/Duplicati/Library/Backend/GoogleServices/GoogleCloudStorage.cs @@ -93,7 +93,7 @@ namespace Duplicati.Library.Backend.GoogleCloudStorage options.TryGetValue(STORAGECLASS_OPTION, out m_storage_class); if (string.IsNullOrEmpty(authid)) - throw new UserInformationException(Strings.GoogleCloudStorage.MissingAuthID(AUTHID_OPTION)); + throw new UserInformationException(Strings.GoogleCloudStorage.MissingAuthID(AUTHID_OPTION), "GoogleCloudStorageMissingAuthID"); m_oauth = new OAuthHelper(authid, this.ProtocolKey); m_oauth.AutoAuthHeader = true; @@ -203,7 +203,7 @@ namespace Duplicati.Library.Backend.GoogleCloudStorage public void CreateFolder() { if (string.IsNullOrEmpty(m_project)) - throw new UserInformationException(Strings.GoogleCloudStorage.ProjectIDMissingError(PROJECT_OPTION)); + throw new UserInformationException(Strings.GoogleCloudStorage.ProjectIDMissingError(PROJECT_OPTION), "GoogleCloudStorageMissingProjectID"); var data = System.Text.Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new CreateBucketRequest() { name = m_bucket, @@ -261,9 +261,9 @@ namespace Duplicati.Library.Backend.GoogleCloudStorage get { return Strings.GoogleCloudStorage.Description; } } - public string DNSName + public string[] DNSName { - get { return null; } + get { return new string[] { new System.Uri(UPLOAD_API_URL).Host, new System.Uri(API_URL).Host }; } } #endregion diff --git a/Duplicati/Library/Backend/GoogleServices/GoogleDrive.cs b/Duplicati/Library/Backend/GoogleServices/GoogleDrive.cs index 0c69c2813..fe846c529 100644 --- a/Duplicati/Library/Backend/GoogleServices/GoogleDrive.cs +++ b/Duplicati/Library/Backend/GoogleServices/GoogleDrive.cs @@ -81,7 +81,7 @@ namespace Duplicati.Library.Backend.GoogleDrive curparent = CreateFolder(p, curparent).id; } else if (res.Length > 1) - throw new UserInformationException(Strings.GoogleDrive.MultipleEntries(p, curdisplay)); + throw new UserInformationException(Strings.GoogleDrive.MultipleEntries(p, curdisplay), "GoogleDriveMultipleEntries"); else curparent = res[0].id; @@ -347,9 +347,9 @@ namespace Duplicati.Library.Backend.GoogleDrive } } - public string DNSName + public string[] DNSName { - get { return null; } + get { return new string[] { new System.Uri(DRIVE_API_URL).Host, new System.Uri(DRIVE_API_UPLOAD_URL).Host }; } } #endregion @@ -361,7 +361,7 @@ namespace Duplicati.Library.Backend.GoogleDrive { var files = GetFileEntries(oldname, true); if (files.Length > 1) - throw new UserInformationException(string.Format(Strings.GoogleDrive.MultipleEntries(oldname, m_path))); + throw new UserInformationException(string.Format(Strings.GoogleDrive.MultipleEntries(oldname, m_path)), "GoogleDriveMultipleEntries"); var newfile = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(files[0])); newfile.title = newname; diff --git a/Duplicati/Library/Backend/HubiC/HubiCBackend.cs b/Duplicati/Library/Backend/HubiC/HubiCBackend.cs index ea42996ca..ec604c063 100644 --- a/Duplicati/Library/Backend/HubiC/HubiCBackend.cs +++ b/Duplicati/Library/Backend/HubiC/HubiCBackend.cs @@ -28,7 +28,7 @@ namespace Duplicati.Library.Backend.HubiC private const string HUBIC_API_URL = "https://api.hubic.com/1.0/"; private const string HUBIC_API_CREDENTIAL_URL = HUBIC_API_URL + "account/credentials"; - private OpenStackStorage m_openstack; + private OpenStackHelper m_openstack; private class HubiCAuthResponse { @@ -77,6 +77,17 @@ namespace Duplicati.Library.Backend.HubiC { get { return AuthToken.endpoint; } } + + public string EndPointDnsName + { + get + { + if (m_token == null || string.IsNullOrWhiteSpace(m_token.endpoint)) + return null; + + return new Uri(m_token.endpoint).Host; + } + } } public HubiCBackend() @@ -171,9 +182,9 @@ namespace Duplicati.Library.Backend.HubiC } } - public string DNSName + public string[] DNSName { - get { return null; } + get { return new string[] { new Uri(HUBIC_API_URL).Host, m_openstack.EndPointDnsName }; } } #endregion diff --git a/Duplicati/Library/Backend/Jottacloud/Jottacloud.cs b/Duplicati/Library/Backend/Jottacloud/Jottacloud.cs index 4f44940be..39640de6f 100644 --- a/Duplicati/Library/Backend/Jottacloud/Jottacloud.cs +++ b/Duplicati/Library/Backend/Jottacloud/Jottacloud.cs @@ -89,7 +89,7 @@ namespace Duplicati.Library.Backend { // Check that it is not set to one of the special built-in mount points that we definitely cannot make use of. if (Array.FindIndex(JFS_BUILTIN_ILLEGAL_MOUNT_POINTS, x => x.Equals(m_mountPoint, StringComparison.OrdinalIgnoreCase)) != -1) - throw new UserInformationException(Strings.Jottacloud.IllegalMountPoint); + throw new UserInformationException(Strings.Jottacloud.IllegalMountPoint, "JottaIllegalMountPoint"); // Check if it is one of the legal built-in mount points. // What to do if it is not is open for discussion: The JFS API supports creation of custom mount points not only // for custom (backup) devices, but also for the built-in device. But this will not be visible via the official @@ -99,7 +99,7 @@ namespace Duplicati.Library.Backend if (i != -1) m_mountPoint = JFS_BUILTIN_MOUNT_POINTS[i]; // Ensure correct casing (doesn't seem to matter, but in theory it could). else - throw new UserInformationException(Strings.Jottacloud.IllegalMountPoint); // User defined mount points on built-in device currently not allowed. + throw new UserInformationException(Strings.Jottacloud.IllegalMountPoint, "JottaIllegalMountPoint"); // User defined mount points on built-in device currently not allowed. } } else @@ -114,7 +114,7 @@ namespace Duplicati.Library.Backend var u = new Utility.Uri(url); m_path = u.HostAndPath; // Host and path of "jottacloud://folder/subfolder" is "folder/subfolder", so the actual folder path within the mount point. if (string.IsNullOrEmpty(m_path)) // Require a folder. Actually it is possible to store files directly on the root level of the mount point, but that does not seem to be a good option. - throw new UserInformationException(Strings.Jottacloud.NoPathError); + throw new UserInformationException(Strings.Jottacloud.NoPathError, "JottaNoPath"); if (!m_path.EndsWith("/", StringComparison.Ordinal)) m_path += "/"; if (!string.IsNullOrEmpty(u.Username)) @@ -137,9 +137,9 @@ namespace Duplicati.Library.Backend } } if (m_userInfo == null || string.IsNullOrEmpty(m_userInfo.UserName)) - throw new UserInformationException(Strings.Jottacloud.NoUsernameError); + throw new UserInformationException(Strings.Jottacloud.NoUsernameError, "JottaNoUsername"); if (m_userInfo == null || string.IsNullOrEmpty(m_userInfo.Password)) - throw new UserInformationException(Strings.Jottacloud.NoPasswordError); + throw new UserInformationException(Strings.Jottacloud.NoPasswordError, "JottaNoPassword"); if (m_userInfo != null) // Bugfix, see http://connect.microsoft.com/VisualStudio/feedback/details/695227/networkcredential-default-constructor-leaves-domain-null-leading-to-null-object-reference-exceptions-in-framework-code m_userInfo.Domain = ""; m_url_device = JFS_ROOT + "/" + m_userInfo.UserName + "/" + m_device; @@ -318,9 +318,9 @@ namespace Duplicati.Library.Backend get { return true; } } - public string DNSName + public string[] DNSName { - get { return null; } + get { return new string[] { new Uri(JFS_ROOT).Host, new Uri(JFS_ROOT_UPLOAD).Host }; } } public void Get(string remotename, System.IO.Stream stream) diff --git a/Duplicati/Library/Backend/Mega/MegaBackend.cs b/Duplicati/Library/Backend/Mega/MegaBackend.cs index 0e6719db9..21a72e24b 100644 --- a/Duplicati/Library/Backend/Mega/MegaBackend.cs +++ b/Duplicati/Library/Backend/Mega/MegaBackend.cs @@ -66,9 +66,9 @@ namespace Duplicati.Library.Backend.Mega m_password = uri.Password; if (string.IsNullOrEmpty(m_username)) - throw new UserInformationException(Strings.MegaBackend.NoUsernameError); + throw new UserInformationException(Strings.MegaBackend.NoUsernameError, "MegaNoUsername"); if (string.IsNullOrEmpty(m_password)) - throw new UserInformationException(Strings.MegaBackend.NoPasswordError); + throw new UserInformationException(Strings.MegaBackend.NoPasswordError, "MegaNoPassword"); m_prefix = uri.HostAndPath ?? ""; } @@ -260,7 +260,7 @@ namespace Duplicati.Library.Backend.Mega } } - public string DNSName + public string[] DNSName { get { return null; } } diff --git a/Duplicati/Library/Backend/OAuthHelper/OAuthHelper.cs b/Duplicati/Library/Backend/OAuthHelper/OAuthHelper.cs index 2b7a83b90..823107039 100644 --- a/Duplicati/Library/Backend/OAuthHelper/OAuthHelper.cs +++ b/Duplicati/Library/Backend/OAuthHelper/OAuthHelper.cs @@ -92,7 +92,7 @@ namespace Duplicati.Library OAuthLoginUrl = OAUTH_LOGIN_URL(servicename); if (string.IsNullOrEmpty(authid)) - throw new Duplicati.Library.Interface.UserInformationException(Strings.OAuthHelper.MissingAuthID(OAuthLoginUrl)); + throw new Duplicati.Library.Interface.UserInformationException(Strings.OAuthHelper.MissingAuthID(OAuthLoginUrl), "MissingAuthID"); } public T GetTokenResponse() @@ -150,9 +150,9 @@ namespace Duplicati.Library if (resp.StatusCode == HttpStatusCode.ServiceUnavailable) { if (msg == resp.StatusDescription) - throw new Duplicati.Library.Interface.UserInformationException(Strings.OAuthHelper.OverQuotaError); + throw new Duplicati.Library.Interface.UserInformationException(Strings.OAuthHelper.OverQuotaError, "OAuthOverQuotaError"); else - throw new Duplicati.Library.Interface.UserInformationException(Strings.OAuthHelper.AuthorizationFailure(msg, OAuthLoginUrl), ex); + throw new Duplicati.Library.Interface.UserInformationException(Strings.OAuthHelper.AuthorizationFailure(msg, OAuthLoginUrl), "OAuthLoginError", ex); } //Fail faster on client errors @@ -161,7 +161,7 @@ namespace Duplicati.Library } if (retries >= (clienterror ? 1 : 5)) - throw new Duplicati.Library.Interface.UserInformationException(Strings.OAuthHelper.AuthorizationFailure(msg, OAuthLoginUrl), ex); + throw new Duplicati.Library.Interface.UserInformationException(Strings.OAuthHelper.AuthorizationFailure(msg, OAuthLoginUrl), "OAuthLoginError", ex); System.Threading.Thread.Sleep(TimeSpan.FromSeconds(Math.Pow(2, retries))); retries++; @@ -175,15 +175,15 @@ namespace Duplicati.Library public void ThrowOverQuotaError() { - throw new Duplicati.Library.Interface.UserInformationException(Strings.OAuthHelper.OverQuotaError); + throw new Duplicati.Library.Interface.UserInformationException(Strings.OAuthHelper.OverQuotaError, "OAuthOverQuotaError"); } public void ThrowAuthException(string msg, Exception ex) { if (ex == null) - throw new Duplicati.Library.Interface.UserInformationException(Strings.OAuthHelper.AuthorizationFailure(msg, OAuthLoginUrl)); + throw new Duplicati.Library.Interface.UserInformationException(Strings.OAuthHelper.AuthorizationFailure(msg, OAuthLoginUrl), "OAuthLoginError"); else - throw new Duplicati.Library.Interface.UserInformationException(Strings.OAuthHelper.AuthorizationFailure(msg, OAuthLoginUrl), ex); + throw new Duplicati.Library.Interface.UserInformationException(Strings.OAuthHelper.AuthorizationFailure(msg, OAuthLoginUrl), "OAuthLoginError", ex); } diff --git a/Duplicati/Library/Backend/OneDrive/OneDrive.cs b/Duplicati/Library/Backend/OneDrive/OneDrive.cs index 4f5a59a98..4f4719d56 100644 --- a/Duplicati/Library/Backend/OneDrive/OneDrive.cs +++ b/Duplicati/Library/Backend/OneDrive/OneDrive.cs @@ -500,9 +500,9 @@ namespace Duplicati.Library.Backend } } - public string DNSName + public string[] DNSName { - get { return null; } + get { return new string[] { new Uri(WLID_SERVER).Host, new Uri(ONEDRIVE_SERVICE_URL).Host, string.IsNullOrWhiteSpace(m_userid) ? null : string.Format("cid-{0}.users.storage.live.com", m_userid) }; } } #endregion diff --git a/Duplicati/Library/Backend/OpenStack/OpenStackStorage.cs b/Duplicati/Library/Backend/OpenStack/OpenStackStorage.cs index 83c6758be..a494ad2b3 100644 --- a/Duplicati/Library/Backend/OpenStack/OpenStackStorage.cs +++ b/Duplicati/Library/Backend/OpenStack/OpenStackStorage.cs @@ -203,16 +203,16 @@ namespace Duplicati.Library.Backend.OpenStack options.TryGetValue(REGION_OPTION, out m_region); if (string.IsNullOrWhiteSpace(m_username)) - throw new UserInformationException(Strings.OpenStack.MissingOptionError(USERNAME_OPTION)); + throw new UserInformationException(Strings.OpenStack.MissingOptionError(USERNAME_OPTION), "OpenStackMissingUsername"); if (string.IsNullOrWhiteSpace(m_authUri)) - throw new UserInformationException(Strings.OpenStack.MissingOptionError(AUTHURI_OPTION)); + throw new UserInformationException(Strings.OpenStack.MissingOptionError(AUTHURI_OPTION), "OpenStackMissingAuthUri"); if (string.IsNullOrWhiteSpace(m_apikey)) { if (string.IsNullOrWhiteSpace(m_password)) - throw new UserInformationException(Strings.OpenStack.MissingOptionError(PASSWORD_OPTION)); + throw new UserInformationException(Strings.OpenStack.MissingOptionError(PASSWORD_OPTION), "OpenStackMissingPassword"); if (string.IsNullOrWhiteSpace(m_tenantName)) - throw new UserInformationException(Strings.OpenStack.MissingOptionError(TENANTNAME_OPTION)); + throw new UserInformationException(Strings.OpenStack.MissingOptionError(TENANTNAME_OPTION), "OpenStackMissingTenantName"); } m_helper = new WebHelper(this); @@ -423,9 +423,15 @@ namespace Duplicati.Library.Backend.OpenStack } } - public string DNSName + public virtual string[] DNSName { - get { return null; } + get + { + return new string[] { + new System.Uri(m_authUri).Host, + string.IsNullOrWhiteSpace(m_simplestorageendpoint) ? null : new System.Uri(m_simplestorageendpoint).Host + }; + } } #endregion diff --git a/Duplicati/Library/Backend/Rclone/Rclone.cs b/Duplicati/Library/Backend/Rclone/Rclone.cs index 67771aeba..d8030ff6d 100644 --- a/Duplicati/Library/Backend/Rclone/Rclone.cs +++ b/Duplicati/Library/Backend/Rclone/Rclone.cs @@ -284,9 +284,9 @@ namespace Duplicati.Library.Backend } } - public string DNSName + public string[] DNSName { - get { return null; } + get { return new string[] { remote_repo }; } } public void Test() diff --git a/Duplicati/Library/Backend/S3/S3Backend.cs b/Duplicati/Library/Backend/S3/S3Backend.cs index 08d1eb8e9..c5de25661 100644 --- a/Duplicati/Library/Backend/S3/S3Backend.cs +++ b/Duplicati/Library/Backend/S3/S3Backend.cs @@ -169,9 +169,9 @@ namespace Duplicati.Library.Backend awsKey = uri.Password; if (string.IsNullOrEmpty(awsID)) - throw new UserInformationException(Strings.S3Backend.NoAMZUserIDError); + throw new UserInformationException(Strings.S3Backend.NoAMZUserIDError, "S3NoAmzUserID"); if (string.IsNullOrEmpty(awsKey)) - throw new UserInformationException(Strings.S3Backend.NoAMZKeyError); + throw new UserInformationException(Strings.S3Backend.NoAMZKeyError, "S3NoAmzKey"); bool euBuckets = Utility.Utility.ParseBoolOption(options, EU_BUCKETS_OPTION); bool useRRS = Utility.Utility.ParseBoolOption(options, RRS_OPTION); @@ -181,7 +181,7 @@ namespace Duplicati.Library.Backend options.TryGetValue(LOCATION_OPTION, out locationConstraint); if (!string.IsNullOrEmpty(locationConstraint) && euBuckets) - throw new UserInformationException(Strings.S3Backend.OptionsAreMutuallyExclusiveError(LOCATION_OPTION, EU_BUCKETS_OPTION)); + throw new UserInformationException(Strings.S3Backend.OptionsAreMutuallyExclusiveError(LOCATION_OPTION, EU_BUCKETS_OPTION), "S3CannotMixLocationAndEuOptions"); if (euBuckets) locationConstraint = S3_EU_REGION_NAME; @@ -240,7 +240,7 @@ namespace Duplicati.Library.Backend m_prefix = m_prefix.Substring(1); } else - throw new UserInformationException(Strings.S3Backend.UnableToDecodeBucketnameError(url)); + throw new UserInformationException(Strings.S3Backend.UnableToDecodeBucketnameError(url), "S3CannotDecodeBucketName"); } try { Console.Error.WriteLine(Strings.S3Backend.DeprecatedUrlFormat("s3://" + m_bucket + "/" + m_prefix)); } @@ -474,9 +474,9 @@ namespace Duplicati.Library.Backend get { return m_wrapper; } } - public string DNSName + public string[] DNSName { - get { return null; } + get { return new string[] { m_wrapper.DNSHost }; } } private string GetFullKey(string name) diff --git a/Duplicati/Library/Backend/S3/S3IAM.cs b/Duplicati/Library/Backend/S3/S3IAM.cs index 606f52d89..184552d5b 100644 --- a/Duplicati/Library/Backend/S3/S3IAM.cs +++ b/Duplicati/Library/Backend/S3/S3IAM.cs @@ -138,7 +138,7 @@ namespace Duplicati.Library.Backend private string GeneratePolicyDoc(string path) { if (string.IsNullOrWhiteSpace(path)) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); path = path.Trim().Trim('/').Trim(); diff --git a/Duplicati/Library/Backend/S3/S3Wrapper.cs b/Duplicati/Library/Backend/S3/S3Wrapper.cs index 667d6f5f9..16dd42401 100644 --- a/Duplicati/Library/Backend/S3/S3Wrapper.cs +++ b/Duplicati/Library/Backend/S3/S3Wrapper.cs @@ -38,6 +38,8 @@ namespace Duplicati.Library.Backend protected string m_storageClass; protected AmazonS3Client m_client; + public readonly string DNSHost; + public S3Wrapper(string awsID, string awsKey, string locationConstraint, string servername, string storageClass, bool useSSL, Dictionary options) { var cfg = new AmazonS3Config(); @@ -73,6 +75,7 @@ namespace Duplicati.Library.Backend m_locationConstraint = locationConstraint; m_storageClass = storageClass; + DNSHost = string.IsNullOrWhiteSpace(cfg.ServiceURL) ? null : new Uri(cfg.ServiceURL).Host; } public void AddBucket(string bucketName) diff --git a/Duplicati/Library/Backend/SSHv2/KeyGenerator.cs b/Duplicati/Library/Backend/SSHv2/KeyGenerator.cs index bc0e1140f..4a09c6096 100644 --- a/Duplicati/Library/Backend/SSHv2/KeyGenerator.cs +++ b/Duplicati/Library/Backend/SSHv2/KeyGenerator.cs @@ -204,7 +204,7 @@ namespace Duplicati.Library.Backend } else { - throw new UserInformationException(string.Format("Unsupported key type: {0}", keytype)); + throw new UserInformationException(string.Format("Unsupported key type: {0}", keytype), "SSHUnsupportedKey"); } } public string Key { get { return "ssh-keygen"; } } diff --git a/Duplicati/Library/Backend/SSHv2/SSHv2Backend.cs b/Duplicati/Library/Backend/SSHv2/SSHv2Backend.cs index 45a8ce8f4..7c5407e94 100644 --- a/Duplicati/Library/Backend/SSHv2/SSHv2Backend.cs +++ b/Duplicati/Library/Backend/SSHv2/SSHv2Backend.cs @@ -355,7 +355,7 @@ namespace Duplicati.Library.Backend } catch (Exception ex) { - throw new UserInformationException(string.Format("Failed to parse the keyfile, check the key format and passphrase. Error message was {0}", ex.Message), ex); + throw new UserInformationException(string.Format("Failed to parse the keyfile, check the key format and passphrase. Error message was {0}", ex.Message), "SSHFailedToParseKeyFile", ex); } } @@ -369,9 +369,9 @@ namespace Duplicati.Library.Backend } } - public string DNSName + public string[] DNSName { - get { return null; } + get { return new string[] { m_server }; } } } } diff --git a/Duplicati/Library/Backend/SharePoint/SharePointBackend.cs b/Duplicati/Library/Backend/SharePoint/SharePointBackend.cs index d011237cc..f38792b91 100644 --- a/Duplicati/Library/Backend/SharePoint/SharePointBackend.cs +++ b/Duplicati/Library/Backend/SharePoint/SharePointBackend.cs @@ -115,9 +115,9 @@ namespace Duplicati.Library.Backend } } - public string DNSName + public string[] DNSName { - get { return null; } + get { return new string[] { m_orgUrl.Host, string.IsNullOrWhiteSpace(m_spWebUrl) ? null : new Utility.Uri(m_spWebUrl).Host }; } } #endregion @@ -417,7 +417,7 @@ namespace Duplicati.Library.Backend public CustomWebRequestExecutorFactory(WebRequestExecutorFactory parent) { if (parent == null) - throw new ArgumentNullException("parent"); + throw new ArgumentNullException(nameof(parent)); m_parent = parent; } diff --git a/Duplicati/Library/Backend/Sia/Sia.cs b/Duplicati/Library/Backend/Sia/Sia.cs index ae9c33fe7..c573de452 100644 --- a/Duplicati/Library/Backend/Sia/Sia.cs +++ b/Duplicati/Library/Backend/Sia/Sia.cs @@ -440,9 +440,9 @@ namespace Duplicati.Library.Backend.Sia } } - public string DNSName + public string[] DNSName { - get { return null; } + get { return new string[] { new System.Uri(m_apihost).Host }; } } #endregion diff --git a/Duplicati/Library/Backend/TahoeLAFS/TahoeBackend.cs b/Duplicati/Library/Backend/TahoeLAFS/TahoeBackend.cs index 33ab2a91d..ede3695d1 100644 --- a/Duplicati/Library/Backend/TahoeLAFS/TahoeBackend.cs +++ b/Duplicati/Library/Backend/TahoeLAFS/TahoeBackend.cs @@ -100,7 +100,7 @@ namespace Duplicati.Library.Backend u.RequireHost(); if (!u.Path.StartsWith("uri/URI:DIR2:", StringComparison.Ordinal) && !u.Path.StartsWith("uri/URI%3ADIR2%3A", StringComparison.Ordinal)) - throw new UserInformationException(Strings.TahoeBackend.UnrecognizedUriError); + throw new UserInformationException(Strings.TahoeBackend.UnrecognizedUriError, "TahoeInvalidUri"); m_useSSL = Utility.Utility.ParseBoolOption(options, "use-ssl"); @@ -254,9 +254,9 @@ namespace Duplicati.Library.Backend get { return Strings.TahoeBackend.Description; } } - public string DNSName + public string[] DNSName { - get { return null; } + get { return new string[] { new Uri(m_url).Host }; } } #endregion diff --git a/Duplicati/Library/Backend/WEBDAV/WEBDAV.cs b/Duplicati/Library/Backend/WEBDAV/WEBDAV.cs index 97a8127f6..ccaea82f0 100644 --- a/Duplicati/Library/Backend/WEBDAV/WEBDAV.cs +++ b/Duplicati/Library/Backend/WEBDAV/WEBDAV.cs @@ -140,7 +140,7 @@ namespace Duplicati.Library.Backend throw new Interface.FolderMissingException(Strings.WEBDAV.MissingFolderError(m_path, wex.Message), wex); if (wex.Response as System.Net.HttpWebResponse != null && (wex.Response as System.Net.HttpWebResponse).StatusCode == System.Net.HttpStatusCode.MethodNotAllowed) - throw new UserInformationException(Strings.WEBDAV.MethodNotAllowedError((wex.Response as System.Net.HttpWebResponse).StatusCode), wex); + throw new UserInformationException(Strings.WEBDAV.MethodNotAllowedError((wex.Response as System.Net.HttpWebResponse).StatusCode), "WebdavMethodNotAllowed", wex); throw; } @@ -313,9 +313,9 @@ namespace Duplicati.Library.Backend get { return Strings.WEBDAV.Description; } } - public string DNSName + public string[] DNSName { - get { return m_dnsName; } + get { return new string[] { m_dnsName }; } } public void Test() diff --git a/Duplicati/Library/Compression/FileArchiveZip.cs b/Duplicati/Library/Compression/FileArchiveZip.cs index 4ce923bf4..33c78e77c 100644 --- a/Duplicati/Library/Compression/FileArchiveZip.cs +++ b/Duplicati/Library/Compression/FileArchiveZip.cs @@ -33,10 +33,15 @@ namespace Duplicati.Library.Compression { /// /// An abstraction of a zip archive as a FileArchive, based on SharpCompress. - /// Please note, duplicati does not require both Read & Write access at the same time so this has not been implemented. + /// Please note, duplicati does not require both Read & Write access at the same time so this has not been implemented. /// public class FileArchiveZip : ICompression { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(); + private const string CannotReadWhileWriting = "Cannot read while writing"; private const string CannotWriteWhileReading = "Cannot write while reading"; @@ -353,7 +358,7 @@ namespace Duplicati.Library.Compression if (m_using_reader) throw; - Logging.Log.WriteMessage("Zip archive appears to have a broken Central Record Header, switching to stream mode", Logging.LogMessageType.Warning, ex); + Logging.Log.WriteWarningMessage(LOGTAG, "BrokenCentralHeaderFallback", ex, "Zip archive appears to have a broken Central Record Header, switching to stream mode"); SwitchToReader(); var d = new Dictionary(Duplicati.Library.Utility.Utility.ClientFilenameStringComparer); @@ -377,7 +382,7 @@ namespace Duplicati.Library.Compression if (d.Count < 2) throw; - Logging.Log.WriteMessage(string.Format("Zip archive appears to have broken records, returning the {0} records that could be recovered", d.Count), Logging.LogMessageType.Warning, ex2); + Logging.Log.WriteWarningMessage(LOGTAG, "BrokenCentralHeader", ex2, "Zip archive appears to have broken records, returning the {0} records that could be recovered", d.Count); } m_entryDict = d; diff --git a/Duplicati/Library/Compression/Strings.cs b/Duplicati/Library/Compression/Strings.cs index 8a1e336b0..acbe477a2 100644 --- a/Duplicati/Library/Compression/Strings.cs +++ b/Duplicati/Library/Compression/Strings.cs @@ -16,8 +16,8 @@ namespace Duplicati.Library.Compression.Strings { public static string NoWriterError { get { return LC.L(@"Archive not opened for writing"); } } public static string NoReaderError { get { return LC.L(@"Archive not opened for reading"); } } public static string FileNotFoundError { get { return LC.L(@"The given file is not part of this archive"); } } - public static string Description { get { return LC.L(@"7z Archive with LZMA2 support."); } } - public static string DisplayName { get { return LC.L(@"7z Archive"); } } + public static string Description { get { return LC.L(@"*Experimental*: 7z Archive with LZMA2 support."); } } + public static string DisplayName { get { return LC.L(@"Experimental - 7z Archive"); } } public static string ThreadcountLong { get { return LC.L(@"The number of threads used in LZMA 2 compression. Defaults to the number of processor cores."); } } public static string ThreadcountShort { get { return LC.L(@"Number of threads used in compression"); } } public static string CompressionlevelLong { get { return LC.L(@"This option controls the compression level used. A setting of zero gives no compression, and a setting of 9 gives maximum compression."); } } diff --git a/Duplicati/Library/DynamicLoader/BackendLoader.cs b/Duplicati/Library/DynamicLoader/BackendLoader.cs index 78632b3a2..4eec1a3bb 100644 --- a/Duplicati/Library/DynamicLoader/BackendLoader.cs +++ b/Duplicati/Library/DynamicLoader/BackendLoader.cs @@ -160,7 +160,7 @@ namespace Duplicati.Library.DynamicLoader public static IList GetSupportedCommands(string url) { if (string.IsNullOrEmpty(url)) - throw new ArgumentNullException("url"); + throw new ArgumentNullException(nameof(url)); return _backendLoader.GetSupportedCommands(url); } diff --git a/Duplicati/Library/DynamicLoader/CompressionLoader.cs b/Duplicati/Library/DynamicLoader/CompressionLoader.cs index 293132f65..3426f09cd 100644 --- a/Duplicati/Library/DynamicLoader/CompressionLoader.cs +++ b/Duplicati/Library/DynamicLoader/CompressionLoader.cs @@ -57,13 +57,14 @@ namespace Duplicati.Library.DynamicLoader /// Instanciates a specific compression module, given the file extension and options /// /// The file extension to create the instance for - /// The filename used to compress/decompress contents + /// The stream of the file used to compress/decompress contents + /// The mode for compression/decompression /// The options to pass to the instance constructor /// The instanciated encryption module or null if the file extension is not supported public ICompression GetModule(string fileExtension, Stream stream, ArchiveMode mode, Dictionary options) { if (string.IsNullOrEmpty(fileExtension)) - throw new ArgumentNullException("fileExtension"); + throw new ArgumentNullException(nameof(fileExtension)); LoadInterfaces(); @@ -84,7 +85,7 @@ namespace Duplicati.Library.DynamicLoader public IList GetSupportedCommands(string key) { if (string.IsNullOrEmpty(key)) - throw new ArgumentNullException("key"); + throw new ArgumentNullException(nameof(key)); LoadInterfaces(); @@ -131,7 +132,7 @@ namespace Duplicati.Library.DynamicLoader /// /// The file extension to create the instance for /// The stream of the file used to compress/decompress contents - /// True is the file opened for writing + /// The mode for compression/decompression /// The options to pass to the instance constructor /// The instanciated compression module or null if the file extension is not supported public static ICompression GetModule(string fileextension, Stream stream, ArchiveMode mode, Dictionary options) diff --git a/Duplicati/Library/DynamicLoader/DynamicLoader.cs b/Duplicati/Library/DynamicLoader/DynamicLoader.cs index 69d9be4f4..26f243d95 100644 --- a/Duplicati/Library/DynamicLoader/DynamicLoader.cs +++ b/Duplicati/Library/DynamicLoader/DynamicLoader.cs @@ -29,10 +29,15 @@ namespace Duplicati.Library.DynamicLoader /// The interface that the class loads internal abstract class DynamicLoader where T : class { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType>(); + /// /// A lock used to guarantee threadsafe access to the interface lookup table /// - protected object m_lock = new object(); + protected readonly object m_lock = new object(); /// /// A cached list of interfaces @@ -130,14 +135,15 @@ namespace Duplicati.Library.DynamicLoader } catch (Exception ex) { - Duplicati.Library.Logging.Log.WriteMessage(Strings.DynamicLoader.DynamicTypeLoadError(t.FullName, s, ex.ToString()), Duplicati.Library.Logging.LogMessageType.Warning); + Duplicati.Library.Logging.Log.WriteWarningMessage(LOGTAG, "SoftError", ex, Strings.DynamicLoader.DynamicTypeLoadError(t.FullName, s, ex.Message)); } } } - catch // (Exception ex) - { // Since this is locating the assemblies that have the proper interface, it isn't an error to not. + catch(Exception ex) + { + // Since this is locating the assemblies that have the proper interface, it isn't an error to not. // This was loading the log with errors about additional DLL's that are not plugins and do not have manifests. - // Duplicati.Library.Logging.Log.WriteMessage(string.Format(Strings.DynamicLoader.DynamicAssemblyLoadError, s, ex.ToString()), Duplicati.Library.Logging.LogMessageType.Warning); + Duplicati.Library.Logging.Log.WriteExplicitMessage(LOGTAG, "HardError", ex, Strings.DynamicLoader.DynamicAssemblyLoadError(s, ex.Message)); } } diff --git a/Duplicati/Library/DynamicLoader/EncryptionLoader.cs b/Duplicati/Library/DynamicLoader/EncryptionLoader.cs index dacf9087d..822336ad3 100644 --- a/Duplicati/Library/DynamicLoader/EncryptionLoader.cs +++ b/Duplicati/Library/DynamicLoader/EncryptionLoader.cs @@ -62,10 +62,10 @@ namespace Duplicati.Library.DynamicLoader public IEncryption GetModule(string fileExtension, string passphrase, Dictionary options) { if (string.IsNullOrEmpty(fileExtension)) - throw new ArgumentNullException("fileExtension"); + throw new ArgumentNullException(nameof(fileExtension)); if (string.IsNullOrEmpty(passphrase)) - throw new ArgumentNullException("passphrase"); + throw new ArgumentNullException(nameof(passphrase)); LoadInterfaces(); @@ -86,7 +86,7 @@ namespace Duplicati.Library.DynamicLoader public IList GetSupportedCommands(string key) { if (string.IsNullOrEmpty(key)) - throw new ArgumentNullException("key"); + throw new ArgumentNullException(nameof(key)); LoadInterfaces(); diff --git a/Duplicati/Library/Interface/CustomExceptions.cs b/Duplicati/Library/Interface/CustomExceptions.cs index fcdfe32bf..066d8a5f2 100644 --- a/Duplicati/Library/Interface/CustomExceptions.cs +++ b/Duplicati/Library/Interface/CustomExceptions.cs @@ -33,14 +33,21 @@ namespace Duplicati.Library.Interface [Serializable] public class UserInformationException : Exception { - public UserInformationException(string message) + /// + /// The help ID for the exception + /// + public readonly string HelpID; + + public UserInformationException(string message, string helpId) : base(message) { + HelpID = helpId; } - public UserInformationException(string message, Exception innerException) + public UserInformationException(string message, string helpId, Exception innerException) : base(message, innerException) { + HelpID = helpId; } } @@ -51,19 +58,19 @@ namespace Duplicati.Library.Interface public class FolderMissingException : UserInformationException { public FolderMissingException() - : base(Strings.Common.FolderMissingError) + : base(Strings.Common.FolderMissingError, "FolderMissing") { } public FolderMissingException(string message) - : base(message) + : base(message, "FolderMissing") { } public FolderMissingException(Exception innerException) - : base(Strings.Common.FolderMissingError, innerException) + : base(Strings.Common.FolderMissingError, "FolderMissing", innerException) { } public FolderMissingException(string message, Exception innerException) - : base(message, innerException) + : base(message, "FolderMissing", innerException) { } } @@ -74,19 +81,19 @@ namespace Duplicati.Library.Interface public class FileMissingException : UserInformationException { public FileMissingException() - : base(LC.L("The requested file does not exist")) + : base(LC.L("The requested file does not exist"), "FileMissing") { } public FileMissingException(string message) - : base(message) + : base(message, "FileMissing") { } public FileMissingException(Exception innerException) - : base(LC.L("The requested file does not exist"), innerException) + : base(LC.L("The requested file does not exist"), "FileMissing", innerException) { } public FileMissingException(string message, Exception innerException) - : base(message, innerException) + : base(message, "FileMissing", innerException) { } } @@ -97,19 +104,19 @@ namespace Duplicati.Library.Interface public class FolderAreadyExistedException : UserInformationException { public FolderAreadyExistedException() - : base(Strings.Common.FolderAlreadyExistsError) + : base(Strings.Common.FolderAlreadyExistsError, "FolderAlreadyExists") { } public FolderAreadyExistedException(string message) - : base(message) + : base(message, "FolderAlreadyExists") { } public FolderAreadyExistedException(Exception innerException) - : base(Strings.Common.FolderAlreadyExistsError, innerException) + : base(Strings.Common.FolderAlreadyExistsError, "FolderAlreadyExists", innerException) { } public FolderAreadyExistedException(string message, Exception innerException) - : base(message, innerException) + : base(message, "FolderAlreadyExists", innerException) { } } @@ -120,19 +127,19 @@ namespace Duplicati.Library.Interface public class CancelException : UserInformationException { public CancelException() - : base(Strings.Common.CancelExceptionError) + : base(Strings.Common.CancelExceptionError, "Cancelled") { } public CancelException(string message) - : base(message) + : base(message, "Cancelled") { } public CancelException(Exception innerException) - : base(Strings.Common.CancelExceptionError, innerException) + : base(Strings.Common.CancelExceptionError, "Cancelled", innerException) { } public CancelException(string message, Exception innerException) - : base(message, innerException) + : base(message, "Cancelled", innerException) { } } } diff --git a/Duplicati/Library/Interface/IBackend.cs b/Duplicati/Library/Interface/IBackend.cs index 709006e54..ba9571e6f 100644 --- a/Duplicati/Library/Interface/IBackend.cs +++ b/Duplicati/Library/Interface/IBackend.cs @@ -82,9 +82,9 @@ namespace Duplicati.Library.Interface string Description { get; } /// - /// The DNS name used to resolve the IP address for this backend + /// The DNS names used to resolve the IP addresses for this backend /// - string DNSName { get; } + string[] DNSName { get; } /// /// The purpose of this method is to test the connection to the remote backend. diff --git a/Duplicati/Library/Logging/Duplicati.Library.Logging.csproj b/Duplicati/Library/Logging/Duplicati.Library.Logging.csproj index 8075f2276..512a87951 100644 --- a/Duplicati/Library/Logging/Duplicati.Library.Logging.csproj +++ b/Duplicati/Library/Logging/Duplicati.Library.Logging.csproj @@ -39,12 +39,17 @@ - - + - + + + + + + + diff --git a/Duplicati/Library/Logging/ILog.cs b/Duplicati/Library/Logging/ILogDestination.cs similarity index 77% rename from Duplicati/Library/Logging/ILog.cs rename to Duplicati/Library/Logging/ILogDestination.cs index 61660ac5a..86061901d 100644 --- a/Duplicati/Library/Logging/ILog.cs +++ b/Duplicati/Library/Logging/ILogDestination.cs @@ -26,14 +26,12 @@ namespace Duplicati.Library.Logging /// /// Interface for a loggin destination /// - public interface ILog + public interface ILogDestination { /// /// The function called when a message is logged /// - /// The message logged - /// The type of message logged - /// An exception, may be null - void WriteMessage(string message, LogMessageType type, Exception exception); + /// The message to log + void WriteMessage(LogEntry entry); } } diff --git a/Duplicati/Library/Logging/ILogFilter.cs b/Duplicati/Library/Logging/ILogFilter.cs new file mode 100644 index 000000000..9e1568ad9 --- /dev/null +++ b/Duplicati/Library/Logging/ILogFilter.cs @@ -0,0 +1,32 @@ +// Copyright (C) 2018, The Duplicati Team +// http://www.duplicati.com, info@duplicati.com +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +using System; +namespace Duplicati.Library.Logging +{ + /// + /// An interface for filtering log messages + /// + public interface ILogFilter + { + /// + /// A method called to determine if a given message should be filtered or not + /// + /// true if the message is included; false otherwise + /// The entry to examine + bool Accepts(LogEntry entry); + } +} diff --git a/Duplicati/Library/Logging/LambdaSupport.cs b/Duplicati/Library/Logging/LambdaSupport.cs new file mode 100644 index 000000000..213a85262 --- /dev/null +++ b/Duplicati/Library/Logging/LambdaSupport.cs @@ -0,0 +1,78 @@ +// Copyright (C) 2018, The Duplicati Team +// http://www.duplicati.com, info@duplicati.com +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +using System; +namespace Duplicati.Library.Logging +{ + /// + /// A log destinations that invokes a method + /// + internal class FunctionLogDestination : ILogDestination + { + /// + /// The method to call for logging + /// + private readonly Action m_entry; + + /// + /// Initializes a new instance of the class. + /// + /// The method to call for logging. + public FunctionLogDestination(Action entry) + { + m_entry = entry ?? throw new ArgumentNullException(nameof(entry)); + } + + /// + /// Writes the message by invoking the handler. + /// + /// The entry to log. + public void WriteMessage(LogEntry entry) + { + m_entry.Invoke(entry); + } + } + + /// + /// A log filter that wraps a callback method + /// + internal class FunctionFilter : ILogFilter + { + /// + /// The method to call for filtering + /// + private readonly Func m_handler; + + /// + /// Initializes a new instance of the class. + /// + /// The method to call for filtering. + public FunctionFilter(Func handler) + { + m_handler = handler ?? throw new ArgumentNullException(nameof(handler)); + } + + /// + /// Determines if the element is accepted or nor + /// + /// A value indicating if the value is accepted or not. + /// The log entry to filter. + public bool Accepts(LogEntry entry) + { + return m_handler(entry); + } + } +} diff --git a/Duplicati/Library/Logging/Log.cs b/Duplicati/Library/Logging/Log.cs index 126be4010..7346a95f4 100644 --- a/Duplicati/Library/Logging/Log.cs +++ b/Duplicati/Library/Logging/Log.cs @@ -1,4 +1,4 @@ -#region Disclaimer / License +#region Disclaimer / License // Copyright (C) 2015, The Duplicati Team // http://www.duplicati.com, info@duplicati.com // @@ -28,15 +28,31 @@ namespace Duplicati.Library.Logging /// public enum LogMessageType { + /// + /// The message should only be shown if it is explicitly requested + /// + ExplicitOnly, /// /// The message is a profiling message /// Profiling, /// + /// Messags that are normally not wanted for display + /// + Verbose, + /// + /// The message is from a retry + /// + Retry, + /// /// The message is informative but does not indicate problems /// Information, /// + /// The message is from dry-run output + /// + DryRun, + /// /// The message is a warning, meaning that later errors may be releated to this message /// Warning, @@ -59,7 +75,7 @@ namespace Duplicati.Library.Logging /// /// The root scope /// - private static readonly LogScope m_root = new LogScope(null, LogMessageType.Error, null); + private static readonly LogScope m_root = new LogScope(null, new LogTagFilter(LogMessageType.Error, null, null), null); /// /// The stored log instances @@ -69,26 +85,219 @@ namespace Duplicati.Library.Logging /// /// Static lock object to provide thread safe logging /// - private static object m_lock = new object(); - - /// - /// Flag used to block recursion - /// - private static bool m_is_active = false; + private static readonly object m_lock = new object(); /// /// Gets the lock instance used to protect the logging calls /// public static object Lock { get { return m_lock; } } + /// + /// Gets a log tag taht reflects the type + /// + /// The log-tag for the type. + /// The type to get the tag for. + public static string LogTagFromType() + { + return LogTagFromType(typeof(T)); + } + + + /// + /// Gets a log tag taht reflects the type + /// + /// The log-tag for the type. + /// The type to get the tag for. + public static string LogTagFromType(Type t) + { + return t.Namespace + "." + t.Name; + } + + /// + /// Gets a common list of items to include in the help-url + /// + /// The basic help url items. + /// A flag indicating if the link is for commandline + private static List GetBasicHelpUrlItems(bool fromCommandLine) + { + var items = new List(); + items.Add("version=" + System.Uri.EscapeDataString(typeof(Log).Assembly.GetName().Version.ToString())); + items.Add("cli=" + (fromCommandLine ? "t" : "f")); + // TOOD: Add OS type? mono version? install id? app-name? + + return items; + } + + /// + /// Encodes a list of query string values and appends them to the help url + /// + /// The help URL. + /// The items to include. + private static string EncodeHelpUrl(IEnumerable items) + { + var query = string.Join("&", items); + if (!string.IsNullOrWhiteSpace(query)) + query = "?" + query; + + return "https://help.duplicati.com/" + query; + } + + /// + /// Creates a link to look up further information on a particular message + /// + /// The help link. + /// The id to use. + /// A flag indicating if the link is for commandline + public static string CreateHelpLink(string id, bool fromCommandLine) + { + var items = GetBasicHelpUrlItems(fromCommandLine); + if (!string.IsNullOrWhiteSpace(id)) + items.Add("id=" + System.Uri.EscapeDataString(id)); + return EncodeHelpUrl(items); + } + + /// + /// Creates a link to look up further information on a particular message + /// + /// The help link. + /// The log tag, if any. + /// The message id, if any. + /// The exception id, if any. + /// A flag indicating if the link is for commandline + public static string CreateHelpLink(string tag, string messageid, string exceptionid, bool fromCommandLine) + { + var items = GetBasicHelpUrlItems(fromCommandLine); + if (!string.IsNullOrWhiteSpace(tag)) + items.Add("tag=" + System.Uri.EscapeDataString(tag)); + if (!string.IsNullOrWhiteSpace(messageid)) + items.Add("msgid=" + System.Uri.EscapeDataString(messageid)); + if (!string.IsNullOrWhiteSpace(exceptionid)) + items.Add("exid=" + System.Uri.EscapeDataString(exceptionid)); + + return EncodeHelpUrl(items); + } + + /// + /// Writes an explicit message to the current log destination + /// + /// The message to write + /// The tag-type for this message + /// The message id + /// The message format arguments + public static void WriteExplicitMessage(string tag, string id, string message, params object[] arguments) + { + WriteMessage(LogMessageType.ExplicitOnly, tag, id, null, message, arguments); + } + + /// + /// Writes an explicit message to the current log destination + /// + /// The message to write + /// The tag-type for this message + /// The message id + /// The exception to log + /// The message format arguments + public static void WriteExplicitMessage(string tag, string id, Exception ex, string message, params object[] arguments) + { + WriteMessage(LogMessageType.ExplicitOnly, tag, id, ex, message, arguments); + } + + /// + /// Writes a verbose message to the current log destination + /// + /// The message to write + /// The tag-type for this message + /// The message id + /// The message format arguments + public static void WriteVerboseMessage(string tag, string id, string message, params object[] arguments) + { + WriteMessage(LogMessageType.Verbose, tag, id, null, message, arguments); + } + + /// + /// Writes a profiling message to the current log destination + /// + /// The message to write + /// The tag-type for this message + /// The message id + /// The message format arguments + public static void WriteProfilingMessage(string tag, string id, string message, params object[] arguments) + { + WriteMessage(LogMessageType.Profiling, tag, id, null, message, arguments); + } + + /// + /// Writes a dry-run message to the current log destination + /// + /// The message to write + /// The tag-type for this message + /// The message id + /// The message format arguments + public static void WriteDryrunMessage(string tag, string id, string message, params object[] arguments) + { + WriteMessage(LogMessageType.DryRun, tag, id, null, message, arguments); + } + + /// + /// Writes a retry message to the current log destination + /// + /// The message to write + /// The tag-type for this message + /// The message id + /// The exception to attach + /// The message format arguments + public static void WriteRetryMessage(string tag, string id, Exception ex, string message, params object[] arguments) + { + WriteMessage(LogMessageType.Retry, tag, id, ex, message, arguments); + } + + /// + /// Writes an information message to the current log destination + /// + /// The message to write + /// The tag-type for this message + /// The message id + /// The message format arguments + public static void WriteInformationMessage(string tag, string id, string message, params object[] arguments) + { + WriteMessage(LogMessageType.Information, tag, id, null, message, arguments); + } + + /// + /// Writes a warning message to the current log destination + /// + /// The message to write + /// The tag-type for this message + /// The message id + /// The exception to attach + /// The message format arguments + public static void WriteWarningMessage(string tag, string id, Exception ex, string message, params object[] arguments) + { + WriteMessage(LogMessageType.Warning, tag, id, ex, message, arguments); + } + + /// + /// Writes an error message to the current log destination + /// + /// The message to write + /// The tag-type for this message + /// The message id + /// The message format arguments + public static void WriteErrorMessage(string tag, string id, Exception ex, string message, params object[] arguments) + { + WriteMessage(LogMessageType.Error, tag, id, ex, message, arguments); + } + /// /// Writes a message to the current log destination /// /// The message to write /// The type of the message - public static void WriteMessage(string message, LogMessageType type) + /// The tag-type for this message + /// The message id + public static void WriteMessage(LogMessageType type, string tag, string id, string message, params object[] arguments) { - WriteMessage(message, type, null); + WriteMessage(type, tag, id, null, message, arguments); } /// @@ -97,67 +306,23 @@ namespace Duplicati.Library.Logging /// The message to write /// The type of the message /// An exception value - public static void WriteMessage(string message, LogMessageType type, Exception ex) + /// The tag-type for this message + /// The message id + public static void WriteMessage(LogMessageType type, string tag, string id, Exception ex, string message, params object[] arguments) { + var msg = new LogEntry(message, arguments, type, type + "-" + tag + "-" + id, id, ex); + lock (m_lock) - { - if (m_is_active) - return; - - try - { - m_is_active = true; - var cs = CurrentScope; - while (cs != null) - { - if (cs.Log != null && type >= cs.LogLevel) - cs.Log.WriteMessage(message, type, ex); - cs = cs.Parent; - } - } - finally - { - m_is_active = false; - } - } - } - - /// - /// Gets or sets the level of log messages to write to the CurrentLog - /// - public static LogMessageType LogLevel - { - get { var cs = CurrentScope; - var ll = (int)cs.LogLevel; while (cs != null) { - ll = Math.Min(ll, (int)cs.LogLevel); + cs.WriteMessage(msg); cs = cs.Parent; } - return (LogMessageType)ll; - } - set - { - CurrentScope.LogLevel = value; } } - /// - /// Gets or sets the current log destination - /// - public static ILog CurrentLog - { - get - { - return CurrentScope.Log; - } - set - { - CurrentScope.Log = value; - } - } /// /// Starts a new scope, that can be closed by disposing the returned instance @@ -165,16 +330,40 @@ namespace Duplicati.Library.Logging /// The new scope. public static IDisposable StartScope() { - return StartScope((ILog)null); + return StartScope((ILogDestination)null, null); } /// /// Starts a new scope, that can be stopped by disposing the returned instance /// + /// The log target + /// The log level /// The new scope. - public static IDisposable StartScope(ILog log) + public static IDisposable StartScope(ILogDestination log, LogMessageType level) { - return new LogScope(log, LogLevel, CurrentScope); + return StartScope(log, new LogTagFilter(level, null, null)); + } + + /// + /// Starts a new scope, that can be stopped by disposing the returned instance + /// + /// The log target + /// The log filter + /// The new scope. + public static IDisposable StartScope(ILogDestination log, ILogFilter filter = null) + { + return new LogScope(log, filter, CurrentScope); + } + + /// + /// Starts a new scope, that can be stopped by disposing the returned instance + /// + /// The log target + /// The log filter + /// The new scope. + public static IDisposable StartScope(Action log, Func filter = null) + { + return new LogScope(new FunctionLogDestination(log), filter == null ? null : new FunctionFilter(filter), CurrentScope); } /// diff --git a/Duplicati/Library/Logging/LogEntry.cs b/Duplicati/Library/Logging/LogEntry.cs new file mode 100644 index 000000000..7dc32649a --- /dev/null +++ b/Duplicati/Library/Logging/LogEntry.cs @@ -0,0 +1,174 @@ +// Copyright (C) 2018, The Duplicati Team +// http://www.duplicati.com, info@duplicati.com +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Duplicati.Library.Logging +{ + /// + /// Instance of a log entry + /// + public class LogEntry + { + /// + /// The time when the entry was logged + /// + public DateTime When; + + /// + /// The message that was logged + /// + public readonly string Message; + + /// + /// The string format arguments, if any + /// + public readonly object[] Arguments; + + /// + /// The message level + /// + public LogMessageType Level; + + /// + /// The tag for the message + /// + public readonly string Tag; + + /// + /// The message help-id + /// + public readonly string Id; + + /// + /// An optional exception + /// + public readonly Exception Exception; + + /// + /// The log context data, if any + /// + private Dictionary m_logContext; + + /// + /// Gets or sets the with the specified value. + /// + /// The key to use. + public string this[string key] + { + get + { + if (m_logContext == null) + return null; + m_logContext.TryGetValue(key, out var s); + return s; + } + + set + { + if (m_logContext == null) + m_logContext = new Dictionary(); + + m_logContext[key] = value; + + } + } + + /// + /// Gets the keys in this log context + /// + /// The context keys. + public IEnumerable ContextKeys + { + get + { + if (m_logContext == null) + return new string[0]; + + return m_logContext.Keys; + } + } + + /// + /// Gets the message, formatted with arguments + /// + /// The formatted message. + public string FormattedMessage + { + get + { + if (Arguments == null || Arguments.Length == 0) + return Message; + + try + { + return string.Format(Message, Arguments); + } + catch + { + // Try no to crash ... + return string.Format("Error while formating: \"{0}\" with arguments: [{1}]", Message, string.Join(", ", Arguments.Select(x => x == null ? "(null)" : x.ToString()))); + + } + } + } + + + /// + /// Initializes a new instance of the class. + /// + /// The message to use. + /// An optional set of arguments. + /// The log level. + /// The tag to use. + /// The message ID. + /// An optional exception. + public LogEntry(string message, object[] arguments, LogMessageType level, string tag, string id, Exception exception) + { + When = DateTime.Now; + Message = message; + Arguments = arguments; + Level = level; + Tag = tag; + Id = id; + Exception = exception; + } + + /// + /// Returns a that represents the current . + /// + /// A that represents the current . + public override string ToString() + { + return string.Format("{0:yyyy-MM-dd HH:mm:ss zz} - [{1}]: {2}", When.ToLocalTime(), Tag, FormattedMessage); + } + + /// + /// Returns the item as a string optionally with exception details + /// + /// A that represents the current . + /// If set to true the result has expanded exception details. + public string AsString(bool withExceptionDetails) + { + return this.ToString() + + ((withExceptionDetails && Exception != null) + ? Environment.NewLine + Exception.ToString() + : string.Empty); + } + } +} diff --git a/Duplicati/Library/Logging/LogScope.cs b/Duplicati/Library/Logging/LogScope.cs index a0de5a09c..81b43bfc1 100644 --- a/Duplicati/Library/Logging/LogScope.cs +++ b/Duplicati/Library/Logging/LogScope.cs @@ -15,6 +15,8 @@ // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA using System; +using System.Linq; + namespace Duplicati.Library.Logging { /// @@ -30,12 +32,12 @@ namespace Duplicati.Library.Logging /// /// The log instance assigned to this scope /// - public ILog Log; + private readonly ILogDestination m_log; /// - /// The current log level + /// The log filter /// - public LogMessageType LogLevel; + private readonly ILogFilter m_filter; /// /// The log scope parent @@ -51,16 +53,28 @@ namespace Duplicati.Library.Logging /// Initializes a new instance of the class. /// /// The log instance to wrap. - public LogScope(ILog self, LogMessageType level, LogScope parent) + /// The log filter to use + public LogScope(ILogDestination self, ILogFilter filter, LogScope parent) { - Log = self; - LogLevel = level; Parent = parent; + m_log = self; + m_filter = filter; + if (parent != null) Logging.Log.StartScope(this); } + /// + /// The function called when a message is logged + /// + /// The log entry + public void WriteMessage(LogEntry entry) + { + if (m_log != null && (m_filter == null || m_filter.Accepts(entry))) + m_log.WriteMessage(entry); + } + /// /// Releases all resource used by the object. /// diff --git a/Duplicati/Library/Logging/LogTagFilter.cs b/Duplicati/Library/Logging/LogTagFilter.cs new file mode 100644 index 000000000..d858297ac --- /dev/null +++ b/Duplicati/Library/Logging/LogTagFilter.cs @@ -0,0 +1,67 @@ +// Copyright (C) 2018, The Duplicati Team +// http://www.duplicati.com, info@duplicati.com +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +using System; +using System.Linq; + +namespace Duplicati.Library.Logging +{ + /// + /// Implements a filter that removes log messages based on tags + /// + public class LogTagFilter : ILogFilter + { + /// + /// The tag prefixes we exclude + /// + private readonly string[] m_excludeTags; + + /// + /// The tag prefixes we include + /// + private readonly string[] m_includeTags; + + /// + /// The minimum log level to consider + /// + private readonly LogMessageType m_logLevel; + + /// + /// Initializes a new instance of the class. + /// + public LogTagFilter(LogMessageType logLevel, string[] excludeTags, string[] includeTags) + { + m_logLevel = logLevel; + m_excludeTags = excludeTags ?? new string[0]; + m_includeTags = includeTags ?? new string[0]; + } + + /// + /// A method called to determine if a given message should be filtered or not + /// + /// true if the message is included; false otherwise + /// The entry to examine + public bool Accepts(LogEntry entry) + { + // Skip all explicitly excluded + if (m_excludeTags.Any(x => entry.Tag.StartsWith(x, StringComparison.OrdinalIgnoreCase))) + return false; + + // Include all explicitly included or under threshold + return entry.Level >= m_logLevel || m_includeTags.Any(x => entry.Tag.StartsWith(x, StringComparison.OrdinalIgnoreCase)); + } + } +} diff --git a/Duplicati/Library/Logging/RepeatingLogScope.cs b/Duplicati/Library/Logging/RepeatingLogScope.cs new file mode 100644 index 000000000..aad8096d3 --- /dev/null +++ b/Duplicati/Library/Logging/RepeatingLogScope.cs @@ -0,0 +1,119 @@ +// Copyright (C) 2018, The Duplicati Team +// http://www.duplicati.com, info@duplicati.com +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +using System; +using System.Threading.Tasks; + +namespace Duplicati.Library.Logging +{ + /// + /// Creates a log-scope that repeats the last emitted message, if there is no log activity + /// + public class RepeatingLogScope : ILogDestination, IDisposable + { + /// + /// A string that is written as the message to the log + /// + private const string STILL_RUNNING = "..."; + /// + /// The scope that we dispose when we are done + /// + private readonly IDisposable m_scope; + /// + /// The max time to wait before repeating the message (in ticks) + /// + private readonly long m_maxIdleTime = TimeSpan.FromSeconds(10).Ticks; + /// + /// The time the last message was written, in ticks + /// + private long m_lastWritten; + /// + /// A flag to keep track of when this instance is disposed + /// + private bool m_completed = false; + /// + /// The last log entry seen + /// + private LogEntry m_lastEntry; + + /// + /// Initializes a new instance of the class. + /// + public RepeatingLogScope() + { + m_scope = Log.StartScope(this); + Task.Run(() => RepeatedRunner()); + } + + /// + /// The repeating run task + /// + private async void RepeatedRunner() + { + var remainingTime = m_maxIdleTime; + while (!m_completed) + { + await Task.Delay(new TimeSpan(Math.Max(TimeSpan.FromMilliseconds(500).Ticks, remainingTime))); + if (m_completed) + return; + if (m_lastEntry == null) + continue; + + var now = DateTime.Now.Ticks; + remainingTime = (m_lastWritten + m_maxIdleTime) - now; + + if (remainingTime < 0) + { + Logging.Log.WriteMessage( + m_lastEntry.Level, + m_lastEntry.Tag, + m_lastEntry.Id, + m_lastEntry.Exception, + STILL_RUNNING, + m_lastEntry.Arguments + ); + + remainingTime = m_maxIdleTime; + } + } + } + + /// + /// Releases all resource used by the object. + /// + /// Call when you are finished using the + /// . The method leaves the + /// in an unusable state. After calling + /// , you must release all references to the + /// so the garbage collector can reclaim the memory + /// that the was occupying. + public void Dispose() + { + m_completed = true; + m_scope.Dispose(); + } + + /// + /// Records the message and updates the timestamp + /// + /// The entry that is being written. + public void WriteMessage(LogEntry entry) + { + m_lastWritten = DateTime.Now.Ticks; + m_lastEntry = entry; + } + } +} diff --git a/Duplicati/Library/Logging/StreamLog.cs b/Duplicati/Library/Logging/StreamLogDestination.cs similarity index 76% rename from Duplicati/Library/Logging/StreamLog.cs rename to Duplicati/Library/Logging/StreamLogDestination.cs index eb3137406..375e3a0ca 100644 --- a/Duplicati/Library/Logging/StreamLog.cs +++ b/Duplicati/Library/Logging/StreamLogDestination.cs @@ -26,15 +26,18 @@ namespace Duplicati.Library.Logging /// /// Writes log messages to a stream /// - public class StreamLog : ILog, IDisposable + public class StreamLogDestination : ILogDestination, IDisposable { + /// + /// The stream to log to + /// private System.IO.StreamWriter m_stream; /// /// Constructs a new log destination, writing to the supplied stream /// /// The stream to write log messages into - public StreamLog(System.IO.Stream stream) + public StreamLogDestination(System.IO.Stream stream) { m_stream = new System.IO.StreamWriter(stream); m_stream.AutoFlush = true; @@ -44,7 +47,7 @@ namespace Duplicati.Library.Logging /// Constructs a new log destination, writing to the supplied file /// /// The file to write to - public StreamLog(string filename) + public StreamLogDestination(string filename) : this(new System.IO.FileStream(filename, System.IO.FileMode.Append, System.IO.FileAccess.Write)) { } @@ -54,17 +57,18 @@ namespace Duplicati.Library.Logging /// /// The function called when a message is logged /// - /// The message logged - /// The type of message logged - /// An exception, may be null - public virtual void WriteMessage(string message, LogMessageType type, Exception exception) + /// The entry to write + public virtual void WriteMessage(LogEntry entry) { - m_stream.WriteLine("{0:u} - {1}: {2}", DateTime.UtcNow.ToString("u"), type, message); - if (exception != null) + + /*m_stream.WriteLine("{0:u} - {1}: {2}", entry.When.ToLocalTime(), entry.Level, entry.FormattedMessage); + if (entry.Exception != null) { - m_stream.WriteLine(exception); + m_stream.WriteLine(entry.Exception); m_stream.WriteLine(); - } + }*/ + + m_stream.WriteLine(entry.AsString(true)); } #endregion diff --git a/Duplicati/Library/Logging/Timer.cs b/Duplicati/Library/Logging/Timer.cs index 1bb6fc7cc..65ceb5ac7 100644 --- a/Duplicati/Library/Logging/Timer.cs +++ b/Duplicati/Library/Logging/Timer.cs @@ -28,20 +28,29 @@ namespace Duplicati.Library.Logging /// public class Timer : IDisposable { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = "Timer"; + private DateTime m_begin; private string m_operation; + private readonly string m_logtag; + private readonly string m_logid; /// /// Constructs a new timer, and starts timing /// /// The name of the operation being performed - public Timer(string operation) + /// The log tag addition to use + /// The ID for this log message + public Timer(string logtag, string logid, string operation) { m_operation = operation; m_begin = DateTime.Now; - if (Log.LogLevel == LogMessageType.Profiling) - Log.WriteMessage(string.Format("Starting - {0}", m_operation), LogMessageType.Profiling); - + m_logtag = logtag; + m_logid = logid; + Log.WriteProfilingMessage(LOGTAG + ".Begin-" + m_logtag, m_logid, "Starting - {0}", m_operation); } #region IDisposable Members @@ -54,8 +63,7 @@ namespace Duplicati.Library.Logging if (m_operation == null) return; - if (Log.LogLevel == LogMessageType.Profiling) - Log.WriteMessage(string.Format("{0} took {1:hh\\:mm\\:ss\\.fff}", m_operation, DateTime.Now - m_begin), LogMessageType.Profiling); + Log.WriteProfilingMessage(LOGTAG + ".Finished-" + m_logtag, m_logid, "{0} took {1:d\\:hh\\:mm\\:ss\\.fff}", m_operation, DateTime.Now - m_begin); m_operation = null; } diff --git a/Duplicati/Library/Main/BackendManager.cs b/Duplicati/Library/Main/BackendManager.cs index 671769527..19c42d5ed 100644 --- a/Duplicati/Library/Main/BackendManager.cs +++ b/Duplicati/Library/Main/BackendManager.cs @@ -12,6 +12,11 @@ namespace Duplicati.Library.Main { internal class BackendManager : IDisposable { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(); + public const string VOLUME_HASH = "SHA256"; /// @@ -209,7 +214,7 @@ namespace Duplicati.Library.Main { if (this.LocalTempfile != null) try { this.LocalTempfile.Dispose(); } - catch (Exception ex) { stat.AddWarning(string.Format("Failed to dispose temporary file: {0}", this.LocalTempfile), ex); } + catch (Exception ex) { Logging.Log.WriteWarningMessage(LOGTAG, "DeleteTemporaryFileError", ex, "Failed to dispose temporary file: {0}", this.LocalTempfile); } finally { this.LocalTempfile = null; } } @@ -239,7 +244,7 @@ namespace Duplicati.Library.Main private class DatabaseCollector { - private object m_dbqueuelock = new object(); + private readonly object m_dbqueuelock = new object(); private LocalDatabase m_database; private System.Threading.Thread m_callerThread; private List m_dbqueue; @@ -333,7 +338,7 @@ namespace Duplicati.Library.Main else if (e is DbRename) db.RenameRemoteFile(((DbRename)e).Oldname, ((DbRename)e).Newname, transaction); else if (e != null) - m_stats.AddError(string.Format("Queue had element of type: {0}, {1}", e.GetType(), e), null); + Logging.Log.WriteErrorMessage(LOGTAG, "InvalidQueueElement", null, "Queue had element of type: {0}, {1}", e.GetType(), e); // Finally remove volumes from DB. if (volsRemoved.Count > 0) @@ -384,14 +389,14 @@ namespace Duplicati.Library.Main try { shortname = new Library.Utility.Uri(shortname).Scheme; } catch { } - throw new Duplicati.Library.Interface.UserInformationException(string.Format("Backend not supported: {0}", shortname)); + throw new Duplicati.Library.Interface.UserInformationException(string.Format("Backend not supported: {0}", shortname), "BackendNotSupported"); } if (!m_options.NoEncryption) { m_encryption = DynamicLoader.EncryptionLoader.GetModule(m_options.EncryptionModule, m_options.Passphrase, m_options.RawOptions); if (m_encryption == null) - throw new Duplicati.Library.Interface.UserInformationException(string.Format("Encryption method not supported: {0}", m_options.EncryptionModule)); + throw new Duplicati.Library.Interface.UserInformationException(string.Format("Encryption method not supported: {0}", m_options.EncryptionModule), "EncryptionMethodNotSupported"); } if (m_taskControl != null) @@ -472,7 +477,7 @@ namespace Duplicati.Library.Main if (m_backend == null) throw new Exception("Backend failed to re-load"); - using (new Logging.Timer(string.Format("RemoteOperation{0}", item.Operation))) + using (new Logging.Timer(LOGTAG, string.Format("RemoteOperation{0}", item.Operation), string.Format("RemoteOperation{0}", item.Operation))) switch (item.Operation) { case OperationType.Put: @@ -508,7 +513,7 @@ namespace Duplicati.Library.Main { retries++; lastException = ex; - m_statwriter.AddRetryAttempt(string.Format("Operation {0} with file {1} attempt {2} of {3} failed with message: {4}", item.Operation, item.RemoteFilename, retries, m_numberofretries, ex.Message), ex); + Logging.Log.WriteRetryMessage(LOGTAG, $"Retry{item.Operation}", ex, "Operation {0} with file {1} attempt {2} of {3} failed with message: {4}", item.Operation, item.RemoteFilename, retries, m_numberofretries, ex.Message); // If the thread is aborted, we exit here if (ex is System.Threading.ThreadAbortException) @@ -526,8 +531,10 @@ namespace Duplicati.Library.Main { try { - if (!string.IsNullOrWhiteSpace(m_backend.DNSName)) - System.Net.Dns.GetHostEntry(m_backend.DNSName); + var names = m_backend.DNSName ?? new string[0]; + foreach(var name in names) + if (!string.IsNullOrWhiteSpace(name)) + System.Net.Dns.GetHostEntry(name); } catch { @@ -548,7 +555,7 @@ namespace Duplicati.Library.Main } catch (Exception dex) { - m_statwriter.AddWarning(string.Format("Failed to create folder: {0}", ex.Message), dex); + Logging.Log.WriteWarningMessage(LOGTAG, "FolderCreateError", dex, "Failed to create folder: {0}", ex.Message); } } @@ -559,7 +566,7 @@ namespace Duplicati.Library.Main if (!recovered) { try { m_backend.Dispose(); } - catch (Exception dex) { m_statwriter.AddWarning(LC.L("Failed to dispose backend instance: {0}", ex.Message), dex); } + catch (Exception dex) { Logging.Log.WriteWarningMessage(LOGTAG, "BackendDisposeError", dex, "Failed to dispose backend instance: {0}", ex.Message); } m_backend = null; @@ -582,18 +589,18 @@ namespace Duplicati.Library.Main if (lastException != null && !(lastException is Duplicati.Library.Interface.FileMissingException) && item.Operation == OperationType.Delete) { - m_statwriter.AddMessage(LC.L("Failed to delete file {0}, testing if file exists", item.RemoteFilename)); + Logging.Log.WriteInformationMessage(LOGTAG, "DeleteFileFailed", LC.L("Failed to delete file {0}, testing if file exists", item.RemoteFilename)); try { if (!m_backend.List().Select(x => x.Name).Contains(item.RemoteFilename)) { lastException = null; - m_statwriter.AddMessage(LC.L("Recovered from problem with attempting to delete non-existing file {0}", item.RemoteFilename)); + Logging.Log.WriteInformationMessage(LOGTAG, "DeleteFileFailureRecovered", LC.L("Recovered from problem with attempting to delete non-existing file {0}", item.RemoteFilename)); } } catch (Exception ex) { - m_statwriter.AddWarning(LC.L("Failed to recover from error deleting file {0}", item.RemoteFilename), ex); + Logging.Log.WriteWarningMessage(LOGTAG, "DeleteFileFailure", ex, LC.L("Failed to recover from error deleting file {0}", item.RemoteFilename), ex); } } @@ -633,7 +640,7 @@ namespace Duplicati.Library.Main m_statwriter.SendEvent(item.BackendActionType, BackendEventType.Rename, oldname, item.Size); m_statwriter.SendEvent(item.BackendActionType, BackendEventType.Rename, newname, item.Size); - m_statwriter.AddMessage(string.Format("Renaming \"{0}\" to \"{1}\"", oldname, newname)); + Logging.Log.WriteInformationMessage(LOGTAG, "RenameRemoteTargetFile", "Renaming \"{0}\" to \"{1}\"", oldname, newname); m_db.LogDbRename(oldname, newname); item.RemoteFilename = newname; @@ -735,7 +742,7 @@ namespace Duplicati.Library.Main m_backend.Put(item.RemoteFilename, item.LocalFilename); var duration = DateTime.Now - begin; - Logging.Log.WriteMessage(string.Format("Uploaded {0} in {1}, {2}/s", Library.Utility.Utility.FormatSizeString(item.Size), duration, Library.Utility.Utility.FormatSizeString((long)(item.Size / duration.TotalSeconds))), Duplicati.Library.Logging.LogMessageType.Profiling); + Logging.Log.WriteProfilingMessage(LOGTAG, "UploadSpeed", "Uploaded {0} in {1}, {2}/s", Library.Utility.Utility.FormatSizeString(item.Size), duration, Library.Utility.Utility.FormatSizeString((long)(item.Size / duration.TotalSeconds))); if (!item.NotTrackedInDb) m_db.LogDbUpdate(item.RemoteFilename, RemoteVolumeState.Uploaded, item.Size, item.Hash); @@ -821,7 +828,7 @@ namespace Duplicati.Library.Main { using (var ss = new ShaderStream(nextTierWriter, false)) { - using (var ts = new ThrottledStream(ss, m_options.MaxUploadPrSecond, m_options.MaxDownloadPrSecond)) + using (var ts = new ThrottledStream(ss, m_options.MaxDownloadPrSecond, m_options.MaxUploadPrSecond)) using (var pgs = new Library.Utility.ProgressReportingStream(ts, item.Size, pg => HandleProgress(ts, pg))) { taskHasher.Start(); // We do not start tasks earlier to be sure the input always gets closed. @@ -906,7 +913,7 @@ namespace Duplicati.Library.Main using (var hs = GetFileHasherStream(fs, System.Security.Cryptography.CryptoStreamMode.Write, out getFileHash)) using (var ss = new ShaderStream(hs, true)) { - using (var ts = new ThrottledStream(ss, m_options.MaxUploadPrSecond, m_options.MaxDownloadPrSecond)) + using (var ts = new ThrottledStream(ss, m_options.MaxDownloadPrSecond, m_options.MaxUploadPrSecond)) using (var pgs = new Library.Utility.ProgressReportingStream(ts, item.Size, pg => HandleProgress(ts, pg))) { ((Library.Interface.IStreamingBackend)m_backend).Get(item.RemoteFilename, pgs); } ss.Flush(); @@ -979,20 +986,20 @@ namespace Duplicati.Library.Main // Check if the file is encrypted with something else if (DynamicLoader.EncryptionLoader.Keys.Contains(ext, StringComparer.OrdinalIgnoreCase)) { - m_statwriter.AddVerboseMessage("Filename extension \"{0}\" does not match encryption module \"{1}\", using matching encryption module", ext, m_options.EncryptionModule); + Logging.Log.WriteVerboseMessage(LOGTAG, "AutomaticDecryptionDetection", "Filename extension \"{0}\" does not match encryption module \"{1}\", using matching encryption module", ext, m_options.EncryptionModule); useDecrypter = DynamicLoader.EncryptionLoader.GetModule(ext, m_options.Passphrase, m_options.RawOptions); useDecrypter = useDecrypter ?? m_encryption; } // Check if the file is not encrypted else if (DynamicLoader.CompressionLoader.Keys.Contains(ext, StringComparer.OrdinalIgnoreCase)) { - m_statwriter.AddVerboseMessage("Filename extension \"{0}\" does not match encryption module \"{1}\", guessing that it is not encrypted", ext, m_options.EncryptionModule); + Logging.Log.WriteVerboseMessage(LOGTAG, "AutomaticDecryptionDetection", "Filename extension \"{0}\" does not match encryption module \"{1}\", guessing that it is not encrypted", ext, m_options.EncryptionModule); useDecrypter = null; } // Fallback, lets see what happens... else { - m_statwriter.AddVerboseMessage("Filename extension \"{0}\" does not match encryption module \"{1}\", attempting to use specified encryption module as no others match", ext, m_options.EncryptionModule); + Logging.Log.WriteVerboseMessage(LOGTAG, "AutomaticDecryptionDetection", "Filename extension \"{0}\" does not match encryption module \"{1}\", attempting to use specified encryption module as no others match", ext, m_options.EncryptionModule); } } } @@ -1011,9 +1018,9 @@ namespace Duplicati.Library.Main tmpfile = coreDoGetPiping(item, useDecrypter, out dataSizeDownloaded, out fileHash); var duration = DateTime.Now - begin; - Logging.Log.WriteMessage(string.Format("Downloaded {3}{0} in {1}, {2}/s", Library.Utility.Utility.FormatSizeString(dataSizeDownloaded), + Logging.Log.WriteProfilingMessage(LOGTAG, "DownloadSpeed", "Downloaded {3}{0} in {1}, {2}/s", Library.Utility.Utility.FormatSizeString(dataSizeDownloaded), duration, Library.Utility.Utility.FormatSizeString((long)(dataSizeDownloaded / duration.TotalSeconds)), - useDecrypter == null ? "" : "and decrypted "), Duplicati.Library.Logging.LogMessageType.Profiling); + useDecrypter == null ? "" : "and decrypted "); m_db.LogDbOperation("get", item.RemoteFilename, JsonConvert.SerializeObject(new { Size = dataSizeDownloaded, Hash = fileHash })); m_statwriter.SendEvent(BackendActionType.Get, BackendEventType.Completed, item.RemoteFilename, dataSizeDownloaded); @@ -1098,7 +1105,7 @@ namespace Duplicati.Library.Main if (isFileMissingException || (wr != null && wr.StatusCode == System.Net.HttpStatusCode.NotFound)) { - m_statwriter.AddWarning(LC.L("Delete operation failed for {0} with FileNotFound, listing contents", item.RemoteFilename), ex); + Logging.Log.WriteWarningMessage(LOGTAG, "DeleteRemoteFileFailed", ex, LC.L("Delete operation failed for {0} with FileNotFound, listing contents", item.RemoteFilename)); bool success = false; try @@ -1111,7 +1118,7 @@ namespace Duplicati.Library.Main if (success) { - m_statwriter.AddMessage(LC.L("Listing indicates file {0} is deleted correctly", item.RemoteFilename)); + Logging.Log.WriteInformationMessage(LOGTAG, "DeleteRemoteFileSuccess", LC.L("Listing indicates file {0} is deleted correctly", item.RemoteFilename)); return; } @@ -1501,7 +1508,7 @@ namespace Duplicati.Library.Main } try { m_db.FlushDbMessages(true); } - catch (Exception ex) { m_statwriter.AddError(string.Format("Backend Shutdown error: {0}", ex.Message), ex); } + catch (Exception ex) { Logging.Log.WriteErrorMessage(LOGTAG, "ShutdownError", ex, "Backend Shutdown error: {0}", ex.Message); } } } } diff --git a/Duplicati/Library/Main/Blockprocessor.cs b/Duplicati/Library/Main/Blockprocessor.cs index fa8d8e75a..f502e1878 100644 --- a/Duplicati/Library/Main/Blockprocessor.cs +++ b/Duplicati/Library/Main/Blockprocessor.cs @@ -15,10 +15,10 @@ namespace Duplicati.Library.Main public Blockprocessor(Stream stream, byte[] buffer) { if (stream == null) - throw new ArgumentNullException("stream"); + throw new ArgumentNullException(nameof(stream)); if (buffer == null) - throw new ArgumentNullException("buffer"); + throw new ArgumentNullException(nameof(buffer)); m_stream = stream; m_buffer = buffer; diff --git a/Duplicati/Library/Main/Controller.cs b/Duplicati/Library/Main/Controller.cs index 5997ab7c6..eb579bf59 100644 --- a/Duplicati/Library/Main/Controller.cs +++ b/Duplicati/Library/Main/Controller.cs @@ -29,6 +29,10 @@ namespace Duplicati.Library.Main { public class Controller : IDisposable { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(); /// /// The backend url /// @@ -42,16 +46,6 @@ namespace Duplicati.Library.Main /// private IMessageSink m_messageSink; - /// - /// The stream log, if any - /// - private Logging.StreamLog m_logfile = null; - - /// - /// The logging filescope - /// - private IDisposable m_logfilescope = null; - /// /// The current executing task /// @@ -88,78 +82,9 @@ namespace Duplicati.Library.Main private bool m_doResetLocale; /// - /// The caffeinate process runner + /// The multi-controller log target /// - private System.Diagnostics.Process m_caffeinate; - - /// - /// This gets called whenever execution of an operation is started or stopped; it currently handles the AllowSleep option - /// - /// Flag indicating execution state - private void OperationRunning(bool isRunning) - { - if (m_options != null && !m_options.AllowSleep) - { - if (Duplicati.Library.Utility.Utility.IsClientWindows) - { - try - { - Win32.SetThreadExecutionState(Win32.EXECUTION_STATE.ES_CONTINUOUS | (isRunning ? Win32.EXECUTION_STATE.ES_SYSTEM_REQUIRED : 0)); - } - catch (Exception ex) - { - Logging.Log.WriteMessage("Failed to set sleep prevention", Logging.LogMessageType.Warning, ex); - } - } - else if (Duplicati.Library.Utility.Utility.IsClientOSX) - { - if (isRunning) - { - try - { - if (m_caffeinate == null) - { - // -s prevents sleep on AC, -i prevents sleep generally - var psi = new System.Diagnostics.ProcessStartInfo("caffeinate", "-s"); - psi.RedirectStandardInput = true; - psi.UseShellExecute = false; - m_caffeinate = System.Diagnostics.Process.Start(psi); - } - } - catch (Exception ex) - { - Logging.Log.WriteMessage("Failed to set sleep prevention", Logging.LogMessageType.Warning, ex); - } - } - else - { - try - { - if (m_caffeinate != null && !m_caffeinate.HasExited) - { - // Send CTRL+C - m_caffeinate.StandardInput.Write("\x3"); - m_caffeinate.StandardInput.Flush(); - m_caffeinate.WaitForExit(500); - - if (!m_caffeinate.HasExited) - { - m_caffeinate.Kill(); - m_caffeinate.WaitForExit(500); - if (!m_caffeinate.HasExited) - throw new Exception("Failed to kill the caffeinate process"); - } - } - } - catch (Exception ex) - { - Logging.Log.WriteMessage("Failed to unset sleep prevention", Logging.LogMessageType.Warning, ex); - } - - } - } - } - } + private ControllerMultiLogTarget m_logTarget; /// /// Constructs a new interface for performing backup and restore operations @@ -191,10 +116,10 @@ namespace Duplicati.Library.Main /// /// The expanded and filtered sources. /// The paths to use. - public string[] ExpandInputSources(string[] inputsources, IFilter filter, ILogWriter log) + public string[] ExpandInputSources(string[] inputsources, IFilter filter) { if (inputsources == null || inputsources.Length == 0) - throw new Duplicati.Library.Interface.UserInformationException(Strings.Controller.NoSourceFoldersError); + throw new Duplicati.Library.Interface.UserInformationException(Strings.Controller.NoSourceFoldersError, "NoSourceFolders"); var sources = new List(inputsources.Length); @@ -216,7 +141,7 @@ namespace Duplicati.Library.Main foreach (System.IO.DriveInfo drive in drives) { string expandedSource = drive.Name[0] + sourcePath; - log.AddVerboseMessage(@"Adding source path ""{0}"" due to wildcard source path ""{1}""", expandedSource, inputsources[i]); + Logging.Log.WriteVerboseMessage(LOGTAG, "AddingSourcePathFromWildcard", @"Adding source path ""{0}"" due to wildcard source path ""{1}""", expandedSource, inputsources[i]); expandedSources.Add(expandedSource); } } @@ -233,21 +158,21 @@ namespace Duplicati.Library.Main if (!string.IsNullOrEmpty(driveLetter)) { string expandedSource = driveLetter + inputsources[i].Substring(@"\\?\Volume{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}".Length); - log.AddVerboseMessage(@"Adding source path ""{0}"" in place of volume guid source path ""{1}""", expandedSource, inputsources[i]); + Logging.Log.WriteVerboseMessage(LOGTAG, "AddingSourceFromGuid", @"Adding source path ""{0}"" in place of volume guid source path ""{1}""", expandedSource, inputsources[i]); expandedSources.Add(expandedSource); } else { // If we aren't allow to have missing sources, throw an exception indicating we couldn't find a drive where this volume is mounted if (!m_options.AllowMissingSource) - throw new Duplicati.Library.Interface.UserInformationException(Strings.Controller.SourceVolumeNameNotFoundError(inputsources[i], volumeGuid)); + throw new Duplicati.Library.Interface.UserInformationException(Strings.Controller.SourceVolumeNameNotFoundError(inputsources[i], volumeGuid), "MissingSourceFolder"); } } else { // If we aren't allow to have missing sources, throw an exception indicating we couldn't find this volume if (!m_options.AllowMissingSource) - throw new Duplicati.Library.Interface.UserInformationException(Strings.Controller.SourceVolumeNameInvalidError(inputsources[i])); + throw new Duplicati.Library.Interface.UserInformationException(Strings.Controller.SourceVolumeNameInvalidError(inputsources[i]), "SourceVolumeNameInvalid"); } } else @@ -266,7 +191,7 @@ namespace Duplicati.Library.Main catch (Exception ex) { // Note that we use the original source (with the *) in the error - throw new Duplicati.Library.Interface.UserInformationException(Strings.Controller.InvalidPathError(expandedSource, ex.Message), ex); + throw new Duplicati.Library.Interface.UserInformationException(Strings.Controller.InvalidPathError(expandedSource, ex.Message), "InputSourceInvalid", ex); } var fi = new System.IO.FileInfo(source); @@ -292,7 +217,7 @@ namespace Duplicati.Library.Main sources = Library.Utility.Utility.GetUniqueItems(sources, Library.Utility.Utility.ClientFilenameStringComparer, out pathDuplicates).OrderBy(a => a).ToList(); foreach (var pathDuplicate in pathDuplicates) - log.AddVerboseMessage(string.Format("Removing duplicate source: {0}", pathDuplicate)); + Logging.Log.WriteVerboseMessage(LOGTAG, "RemoveDuplicateSource", "Removing duplicate source: {0}", pathDuplicate); //Sanity check for multiple inclusions of the same folder for (int i = 0; i < sources.Count; i++) @@ -309,14 +234,14 @@ namespace Duplicati.Library.Main // If there are no excludes, there is no need to keep the folder as a filter if (excludes) { - log.AddVerboseMessage("Removing source \"{0}\" because it is a subfolder of \"{1}\", and using it as an include filter", sources[i], sources[j]); + Logging.Log.WriteVerboseMessage(LOGTAG, "RemovingSubfolderSource", "Removing source \"{0}\" because it is a subfolder of \"{1}\", and using it as an include filter", sources[i], sources[j]); filter = Library.Utility.JoinedFilterExpression.Join(new FilterExpression(sources[i]), filter); } else - log.AddVerboseMessage("Removing source \"{0}\" because it is a subfolder or subfile of \"{1}\"", sources[i], sources[j]); + Logging.Log.WriteVerboseMessage(LOGTAG, "RemovingSubfolderSource", "Removing source \"{0}\" because it is a subfolder or subfile of \"{1}\"", sources[i], sources[j]); } else - log.AddVerboseMessage("Removing source \"{0}\" because it is a subfolder or subfile of \"{1}\"", sources[i], sources[j]); + Logging.Log.WriteVerboseMessage(LOGTAG, "RemovingSubfolderSource", "Removing source \"{0}\" because it is a subfolder or subfile of \"{1}\"", sources[i], sources[j]); sources.RemoveAt(i); i--; @@ -335,7 +260,7 @@ namespace Duplicati.Library.Main return RunAction(new BackupResults(), ref inputsources, ref filter, (result) => { using (var h = new Operation.BackupHandler(m_backend, m_options, result)) - h.Run(ExpandInputSources(inputsources, filter, result), filter); + h.Run(ExpandInputSources(inputsources, filter), filter); Library.UsageReporter.Reporter.Report("BACKUP_FILECOUNT", result.ExaminedFiles); Library.UsageReporter.Reporter.Report("BACKUP_FILESIZE", result.SizeOfExaminedFiles); @@ -436,7 +361,7 @@ namespace Duplicati.Library.Main } catch (Exception ex) { - result.AddWarning(string.Format("Failed to delete remote file: {0}", list[i].File.Name), ex); + Logging.Log.WriteWarningMessage(LOGTAG, "DeleteFilesetError", ex, "Failed to delete remote file: {0}", list[i].File.Name); } result.OperationProgressUpdater.UpdateProgress((float)i / list.Count); } @@ -511,13 +436,18 @@ namespace Duplicati.Library.Main public Library.Interface.ITestFilterResults TestFilter(string[] paths, Library.Utility.IFilter filter = null) { - m_options.RawOptions["verbose"] = "true"; m_options.RawOptions["dry-run"] = "true"; m_options.RawOptions["dbpath"] = "INVALID!"; - return RunAction(new TestFilterResults(), ref paths, ref filter, (result) => { - new Operation.TestFilterHandler(m_options, result).Run(ExpandInputSources(paths, filter, result), filter); - }); + // Redirect all messages from the filter to the message sink + var filtertag = Logging.Log.LogTagFromType(); + using (Logging.Log.StartScope(m_messageSink.WriteMessage, x => x.Tag.Contains(filtertag))) + { + return RunAction(new TestFilterResults(), ref paths, ref filter, (result) => + { + new Operation.TestFilterHandler(m_options, result).Run(ExpandInputSources(paths, filter), filter); + }); + } } public Library.Interface.ISystemInfoResults SystemInfo() @@ -560,23 +490,25 @@ namespace Duplicati.Library.Main if (string.IsNullOrWhiteSpace(targetmail)) throw new Exception(string.Format("No email specified, please use --{0}", "send-mail-to")); - if (m_options.Loglevel == Logging.LogMessageType.Error) - m_options.RawOptions["log-level"] = Logging.LogMessageType.Warning.ToString(); - m_options.RawOptions["disable-module"] = string.Join( ",", DynamicLoader.GenericLoader.Modules .Where(m => - !(m is Library.Interface.IConnectionModule) && m.GetType().FullName != "Duplicati.Library.Modules.Builtin.SendMail" + !(m is Modules.Builtin.SendMail) ) .Select(x => x.Key) ); - return RunAction(new SendMailResults(), result => + /// Forward all messages from the email module to the message sink + var filtertag = Logging.Log.LogTagFromType(); + using (Logging.Log.StartScope(m_messageSink.WriteMessage, x => x.Tag.Contains(filtertag))) { - result.Lines = new string[0]; - System.Threading.Thread.Sleep(5); - }); + return RunAction(new SendMailResults(), result => + { + result.Lines = new string[0]; + System.Threading.Thread.Sleep(5); + }); + } } public Library.Interface.IVacuumResults Vacuum() @@ -587,7 +519,7 @@ namespace Duplicati.Library.Main } private T RunAction(T result, Action method) - where T : ISetCommonOptions, ITaskControl, Logging.ILog + where T : ISetCommonOptions, ITaskControl, Logging.ILogDestination { var tmp = new string[0]; IFilter tempfilter = null; @@ -595,33 +527,39 @@ namespace Duplicati.Library.Main } private T RunAction(T result, ref string[] paths, Action method) - where T : ISetCommonOptions, ITaskControl, Logging.ILog + where T : ISetCommonOptions, ITaskControl, Logging.ILogDestination { IFilter tempfilter = null; return RunAction(result, ref paths, ref tempfilter, method); } private T RunAction(T result, ref IFilter filter, Action method) - where T : ISetCommonOptions, ITaskControl, Logging.ILog + where T : ISetCommonOptions, ITaskControl, Logging.ILogDestination { var tmp = new string[0]; return RunAction(result, ref tmp, ref filter, method); } private T RunAction(T result, ref string[] paths, ref IFilter filter, Action method) - where T : ISetCommonOptions, ITaskControl, Logging.ILog + where T : ISetCommonOptions, ITaskControl, Logging.ILogDestination { - using (Logging.Log.StartScope(result)) + m_logTarget = new ControllerMultiLogTarget(result, Logging.LogMessageType.Information, null); + using (Logging.Log.StartScope(m_logTarget, null)) { + m_logTarget.AddTarget(m_messageSink, m_options.ConsoleLoglevel, m_options.ConsoleLogFilter); + result.MessageSink = m_messageSink; + try { m_currentTask = result; m_currentTaskThread = System.Threading.Thread.CurrentThread; + SetupCommonOptions(result, ref paths, ref filter); + Logging.Log.WriteInformationMessage(LOGTAG, "StartingOperation", Strings.Controller.StartingOperationMessage(m_options.MainAction)); - result.WriteLogMessageDirect(Strings.Controller.StartingOperationMessage(m_options.MainAction), Logging.LogMessageType.Information, null); - - using (new Logging.Timer(string.Format("Running {0}", result.MainOperation))) + using (new ProcessController(m_options)) + using (new Logging.Timer(LOGTAG, string.Format("Run{0}", result.MainOperation), string.Format("Running {0}", result.MainOperation))) + using (new Logging.RepeatingLogScope()) method(result); if (result.EndTime.Ticks == 0) @@ -630,7 +568,7 @@ namespace Duplicati.Library.Main OnOperationComplete(result); - result.WriteLogMessageDirect(Strings.Controller.CompletedOperationMessage(m_options.MainAction), Logging.LogMessageType.Information, null); + Logging.Log.WriteInformationMessage(LOGTAG, "CompletedOperation", Strings.Controller.CompletedOperationMessage(m_options.MainAction)); return result; } @@ -643,7 +581,7 @@ namespace Duplicati.Library.Main OnOperationComplete(ex); - result.WriteLogMessageDirect(Strings.Controller.FailedOperationMessage(m_options.MainAction, ex.Message), Logging.LogMessageType.Error, ex); + Logging.Log.WriteErrorMessage(LOGTAG, "FailedOperation", ex, Strings.Controller.FailedOperationMessage(m_options.MainAction, ex.Message)); throw; } @@ -682,15 +620,14 @@ namespace Duplicati.Library.Main foreach (KeyValuePair mx in m_options.LoadedModules) if (mx.Key && mx.Value is Duplicati.Library.Interface.IGenericCallbackModule) try { ((Duplicati.Library.Interface.IGenericCallbackModule)mx.Value).OnFinish(result); } - catch (Exception ex) { Logging.Log.WriteMessage(string.Format("OnFinish callback {0} failed: {1}", mx.Key, ex.Message), Duplicati.Library.Logging.LogMessageType.Warning, ex); } + catch (Exception ex) { Logging.Log.WriteWarningMessage(LOGTAG, $"OnFinishError{mx.Key}", ex, "OnFinish callback {0} failed: {1}", mx.Key, ex.Message); } foreach (KeyValuePair mx in m_options.LoadedModules) if (mx.Key && mx.Value is IDisposable) try { ((IDisposable)mx.Value).Dispose(); } - catch (Exception ex) { Logging.Log.WriteMessage(string.Format("Dispose for {0} failed: {1}", mx.Key, ex.Message), Duplicati.Library.Logging.LogMessageType.Warning, ex); } + catch (Exception ex) { Logging.Log.WriteWarningMessage(LOGTAG, $"DisposeError{mx.Key}", ex, "Dispose for {0} failed: {1}", mx.Key, ex.Message); } m_options.LoadedModules.Clear(); - OperationRunning(false); } if (m_resetPriority != null) @@ -724,24 +661,16 @@ namespace Duplicati.Library.Main } } - if (m_logfilescope != null) + if (m_logTarget != null) { - m_logfilescope.Dispose(); - m_logfilescope = null; + m_logTarget.Dispose(); + m_logTarget = null; } - - if (m_logfile != null) - { - m_logfile.Dispose(); - m_logfile = null; - } - } private void SetupCommonOptions(ISetCommonOptions result, ref string[] paths, ref IFilter filter) { m_options.MainAction = result.MainOperation; - result.MessageSink = m_messageSink; switch (m_options.MainAction) { @@ -815,22 +744,20 @@ namespace Duplicati.Library.Main } m_options.RawOptions.Remove("filter"); // "--filter" is not a supported command line option - OperationRunning(true); - - if (m_options.HasLoglevel) - Library.Logging.Log.LogLevel = m_options.Loglevel; - if (!string.IsNullOrEmpty(m_options.Logfile)) { var path = System.IO.Path.GetDirectoryName(System.IO.Path.GetFullPath(m_options.Logfile)); if (!System.IO.Directory.Exists(path)) System.IO.Directory.CreateDirectory(path); - m_logfilescope = Logging.Log.StartScope(m_logfile = new Library.Logging.StreamLog(m_options.Logfile)); + m_logTarget.AddTarget( + new Library.Logging.StreamLogDestination(m_options.Logfile), + m_options.LogFileLoglevel, + m_options.LogFileLogFilter + ); } - result.VerboseErrors = m_options.DebugOutput; - result.VerboseOutput = m_options.Verbose; + if (m_options.HasTempDir) { @@ -861,7 +788,7 @@ namespace Duplicati.Library.Main } catch (Exception ex) // or only: MissingMethodException { - Library.Logging.Log.WriteMessage(Strings.Controller.FailedForceLocaleError(ex.Message), Logging.LogMessageType.Warning); + Library.Logging.Log.WriteWarningMessage(LOGTAG, "LocaleChangeError", ex, Strings.Controller.FailedForceLocaleError(ex.Message)); m_doResetLocale = false; m_resetLocale = m_resetLocaleUI = null; } @@ -876,15 +803,14 @@ namespace Duplicati.Library.Main if (string.IsNullOrEmpty(m_options.Dbpath)) m_options.Dbpath = DatabaseLocator.GetDatabasePath(m_backend, m_options); - ValidateOptions(result); + ValidateOptions(); } /// /// This function will examine all options passed on the commandline, and test for unsupported or deprecated values. /// Any errors will be logged into the statistics module. /// - /// The log instance - private void ValidateOptions(ILogWriter log) + private void ValidateOptions() { // Check if only one of the retention options is set var selectedRetentionOptions = new List(); @@ -907,33 +833,30 @@ namespace Duplicati.Library.Main if (selectedRetentionOptions.Count() > 1) { throw new Interface.UserInformationException(string.Format("Setting multiple retention options ({0}) is not permitted", - String.Join(", ", selectedRetentionOptions.Select(x => "--" + x)))); + String.Join(", ", selectedRetentionOptions.Select(x => "--" + x))), "MultipleRetentionOptionsNotSupported"); } // Check Prefix if (!string.IsNullOrWhiteSpace(m_options.Prefix) && m_options.Prefix.Contains("-")) - throw new Interface.UserInformationException("The prefix cannot contain hyphens (-)"); + throw new Interface.UserInformationException("The prefix cannot contain hyphens (-)", "PrefixCannotContainHyphens"); //Check validity of retention-policy option value try { foreach (var configEntry in m_options.RetentionPolicy) { - if (configEntry.Value >= configEntry.Key) + if (!configEntry.IsKeepAllVersions() && !configEntry.IsUnlimtedTimeframe() && + configEntry.Interval >= configEntry.Timeframe) { - throw new Interface.UserInformationException("A time frame cannot be smaller than its interval"); + throw new Interface.UserInformationException("An interval cannot be bigger than the timeframe it is in", "IntervalCannotBeBiggerThanTimeFrame"); } } } catch (Exception e) // simply reading the option value might also result in an exception due to incorrect formatting { - throw new Interface.UserInformationException(string.Format("An error occoured while processing the value of --{0}", "retention-policy"), e); + throw new Interface.UserInformationException(string.Format("An error occoured while processing the value of --{0}", "retention-policy"), "RetentionPolicyParseError", e); } - //No point in going through with this if we can't report - if (log == null) - return; - //Keep a list of all supplied options Dictionary ropts = new Dictionary(m_options.RawOptions); @@ -980,7 +903,7 @@ namespace Duplicati.Library.Main foreach (Library.Interface.ICommandLineArgument a in l) { if (supportedOptions.ContainsKey(a.Name) && Array.IndexOf(Options.KnownDuplicates, a.Name.ToLower()) < 0) - log.AddWarning(Strings.Controller.DuplicateOptionNameWarning(a.Name), null); + Logging.Log.WriteWarningMessage(LOGTAG, "DuplicateOption", null, Strings.Controller.DuplicateOptionNameWarning(a.Name)); supportedOptions[a.Name] = a; @@ -988,7 +911,7 @@ namespace Duplicati.Library.Main foreach (string s in a.Aliases) { if (supportedOptions.ContainsKey(s) && Array.IndexOf(Options.KnownDuplicates, s.ToLower()) < 0) - log.AddWarning(Strings.Controller.DuplicateOptionNameWarning(s), null); + Logging.Log.WriteWarningMessage(LOGTAG, "DuplicateOption", null, Strings.Controller.DuplicateOptionNameWarning(s)); supportedOptions[s] = a; } @@ -1007,7 +930,7 @@ namespace Duplicati.Library.Main if (a.Name != s) optname += " (" + s + ")"; - log.AddWarning(Strings.Controller.DeprecatedOptionUsedWarning(optname, a.DeprecationMessage), null); + Logging.Log.WriteWarningMessage(LOGTAG, "DeprecatedOption", null, Strings.Controller.DeprecatedOptionUsedWarning(optname, a.DeprecationMessage), null); } } @@ -1018,9 +941,9 @@ namespace Duplicati.Library.Main foreach (string s in ropts.Keys) if (!supportedOptions.ContainsKey(s)) if (disabledModuleOptions.ContainsKey(s)) - log.AddWarning(Strings.Controller.UnsupportedOptionDisabledModuleWarning(s, disabledModuleOptions[s]), null); + Logging.Log.WriteWarningMessage(LOGTAG, "UnsupportedDisabledModule", null, Strings.Controller.UnsupportedOptionDisabledModuleWarning(s, disabledModuleOptions[s]), null); else - log.AddWarning(Strings.Controller.UnsupportedOptionWarning(s), null); + Logging.Log.WriteWarningMessage(LOGTAG, "UnsupportedOption", null, Strings.Controller.UnsupportedOptionWarning(s), null); //Look at the value supplied for each argument and see if is valid according to its type foreach (string s in ropts.Keys) @@ -1030,10 +953,14 @@ namespace Duplicati.Library.Main { string validationMessage = ValidateOptionValue(arg, s, ropts[s]); if (validationMessage != null) - log.AddWarning(validationMessage, null); + Logging.Log.WriteWarningMessage(LOGTAG, "OptionValidationError", null, validationMessage); } } + // For now, warn not to use 7z + if (string.Equals(m_options.CompressionModule, "7z", StringComparison.OrdinalIgnoreCase)) + Logging.Log.WriteWarningMessage(LOGTAG, "7zModuleHasIssues", null, "The 7z compression module has known issues and should only be used for experimental purposes"); + //TODO: Based on the action, see if all options are relevant } diff --git a/Duplicati/Library/Main/ControllerMultiLogTarget.cs b/Duplicati/Library/Main/ControllerMultiLogTarget.cs new file mode 100644 index 000000000..becc1b809 --- /dev/null +++ b/Duplicati/Library/Main/ControllerMultiLogTarget.cs @@ -0,0 +1,102 @@ +// Copyright (C) 2018, The Duplicati Team +// http://www.duplicati.com, info@duplicati.com +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +using System; +using System.Collections.Generic; +using Duplicati.Library.Logging; + +namespace Duplicati.Library.Main +{ + /// + /// The log target handler for the controller, which sends to multiple log targets + /// + public class ControllerMultiLogTarget : Logging.ILogDestination, IDisposable + { + /// + /// The list of log targets to handle + /// + private List> m_targets = new List>(); + + /// + /// Initializes a new instance of the class. + /// + /// The log target. + /// The minimum log level to consider + /// The log filter. + public ControllerMultiLogTarget(ILogDestination target, Logging.LogMessageType loglevel, Library.Utility.IFilter filter) + { + AddTarget(target, loglevel, filter); + } + + /// + /// Adds the target to the list. + /// + /// The log target. + /// The minimum log level to consider + /// The log filter. + public void AddTarget(ILogDestination target, LogMessageType loglevel, Library.Utility.IFilter filter) + { + if (target == null) + return; + + m_targets.Add(new Tuple(target, loglevel, filter ?? new Library.Utility.FilterExpression())); + } + + /// + /// Releases all resource used by the object. + /// + /// Call when you are finished using the + /// . The method leaves the + /// in an unusable state. After calling + /// , you must release all references to the + /// so the garbage collector can reclaim the + /// memory that the was occupying. + public void Dispose() + { + foreach (var m in m_targets) + (m.Item1 as IDisposable)?.Dispose(); + m_targets.Clear(); + } + + /// + /// Writes the message to all the destinations. + /// + /// Entry. + public void WriteMessage(LogEntry entry) + { + foreach (var e in m_targets) + { + var found = e.Item3.Matches(entry.Tag, out var result, out var match); + + // If there is a filter match, use that + if (found) + { + if (!result) + continue; + } + else + { + // Otherwise, filter by log-level + if (entry.Level < e.Item2) + continue; + } + + // If we get here, write the message + e.Item1.WriteMessage(entry); + } + } + } +} diff --git a/Duplicati/Library/Main/Database/ExtensionMethods.cs b/Duplicati/Library/Main/Database/ExtensionMethods.cs index 00658dc57..2280be590 100644 --- a/Duplicati/Library/Main/Database/ExtensionMethods.cs +++ b/Duplicati/Library/Main/Database/ExtensionMethods.cs @@ -8,6 +8,11 @@ namespace Duplicati.Library.Main.Database { public static class ExtensionMethods { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(typeof(ExtensionMethods)); + public static void AddParameters(this System.Data.IDbCommand self, int count) { for(var i = 0; i < count; i++) @@ -45,7 +50,7 @@ namespace Duplicati.Library.Main.Database self.AddParameter(n); } - using(new Logging.Timer(string.Format("ExecuteNonQuery: {0}", self.CommandText))) + using(new Logging.Timer(LOGTAG, "ExecuteNonQuery", string.Format("ExecuteNonQuery: {0}", self.CommandText))) return self.ExecuteNonQuery(); } @@ -61,7 +66,7 @@ namespace Duplicati.Library.Main.Database self.AddParameter(n); } - using(new Logging.Timer(string.Format("ExecuteScalar: {0}", self.CommandText))) + using(new Logging.Timer(LOGTAG, "ExecuteScalar", string.Format("ExecuteScalar: {0}", self.CommandText))) return self.ExecuteScalar(); } @@ -87,7 +92,7 @@ namespace Duplicati.Library.Main.Database self.AddParameter(n); } - using(new Logging.Timer(string.Format("ExecuteScalarInt64: {0}", self.CommandText))) + using(new Logging.Timer(LOGTAG, "ExecuteScalarInt64", string.Format("ExecuteScalarInt64: {0}", self.CommandText))) using(var rd = self.ExecuteReader()) if (rd.Read()) return ConvertValueToInt64(rd, 0, defaultvalue); @@ -107,7 +112,7 @@ namespace Duplicati.Library.Main.Database self.AddParameter(n); } - using(new Logging.Timer(string.Format("ExecuteReader: {0}", self.CommandText))) + using(new Logging.Timer(LOGTAG, "ExcuteReader", string.Format("ExecuteReader: {0}", self.CommandText))) return self.ExecuteReader(); } diff --git a/Duplicati/Library/Main/Database/HashLookupHelper.cs b/Duplicati/Library/Main/Database/HashLookupHelper.cs index 2c42ad09e..a1edba9e1 100644 --- a/Duplicati/Library/Main/Database/HashLookupHelper.cs +++ b/Duplicati/Library/Main/Database/HashLookupHelper.cs @@ -35,7 +35,7 @@ namespace Duplicati.Library.Main private readonly ulong m_entries; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The maximum amount of bytes to use for the lookup table public HashLookupHelper (ulong maxmemory) diff --git a/Duplicati/Library/Main/Database/LocalBackupDatabase.cs b/Duplicati/Library/Main/Database/LocalBackupDatabase.cs index 5f3a7c799..8c3e20984 100644 --- a/Duplicati/Library/Main/Database/LocalBackupDatabase.cs +++ b/Duplicati/Library/Main/Database/LocalBackupDatabase.cs @@ -9,6 +9,11 @@ namespace Duplicati.Library.Main.Database { internal class LocalBackupDatabase : LocalDatabase { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(); + private class PathEntryKeeper { public DateTime Lastmodified; @@ -202,7 +207,7 @@ namespace Duplicati.Library.Main.Database @" AND ""F"".""ID"" = ""E"".""BlocksetID"" "; if (m_pathLookup != null) - using(new Logging.Timer("Build path lastmodified lookup table")) + using(new Logging.Timer(LOGTAG, "BuildLastModified", "Build path lastmodified lookup table")) using (var rd = cmd.ExecuteReader(string.Format(@" SELECT ""FileID"", ""Lastmodified"", ""Length"", ""Path"", ""Metahash"", ""Metasize"" FROM ({0}) WHERE ""BlocksetID"" >= 0 ", scantableDefinition))) while (rd.Read()) { @@ -218,7 +223,7 @@ namespace Duplicati.Library.Main.Database if (m_pathLookup != null) try { - using(new Logging.Timer("Build path lookup table")) + using(new Logging.Timer(LOGTAG, "BuildPathTable", "Build path lookup table")) using (var rd = cmd.ExecuteReader(string.Format(@" SELECT ""Path"", ""BlocksetID"", ""MetadataID"", ""ID"" FROM ""File"" "))) while (rd.Read()) { @@ -265,8 +270,8 @@ namespace Duplicati.Library.Main.Database } catch (Exception ex) { - Logging.Log.WriteMessage(string.Format("Failed to create block cache, this could mean you have hash collisions in your table, the hash that failed is {0}. Error message: {1}.", failedhash, ex.Message), Logging.LogMessageType.Warning); - Logging.Log.WriteMessage(string.Format("Disabling block cache due to error"), Logging.LogMessageType.Warning); + Logging.Log.WriteWarningMessage(LOGTAG, "BlockCacheFailure", ex, "Failed to create block cache, this could mean you have hash collisions in your table, the hash that failed is {0}. Error message: {1}.", failedhash, ex.Message); + Logging.Log.WriteWarningMessage(LOGTAG, "BlockCacheFailure", null, "Disabling block cache due to error"); } } } @@ -285,7 +290,7 @@ namespace Duplicati.Library.Main.Database if (exsize == size) return false; - Logging.Log.WriteMessage(string.Format("Found hash collision on {0}, sizes {1} vs {2}. Disabling cache from now on.", key, size, exsize), Logging.LogMessageType.Warning); + Logging.Log.WriteWarningMessage(LOGTAG, "HashCollisionsFound", null, "Found hash collision on {0}, sizes {1} vs {2}. Disabling cache from now on.", key, size, exsize); m_blockCache = null; } @@ -366,14 +371,14 @@ namespace Duplicati.Library.Main.Database var c = m_insertblocksetentryCommand.ExecuteNonQuery(); if (c != 1) { - m_result.AddError(string.Format("Checking errors, related to #1400. Unexpected result count: {0}, expected {1}, hash: {2}, size: {3}, blocksetid: {4}, ix: {5}, fullhash: {6}, fullsize: {7}", c, 1, h, exsize, blocksetid, ix, filehash, size), null); + Logging.Log.WriteErrorMessage(LOGTAG, "CheckingErrorsForIssue1400", null, "Checking errors, related to #1400. Unexpected result count: {0}, expected {1}, hash: {2}, size: {3}, blocksetid: {4}, ix: {5}, fullhash: {6}, fullsize: {7}", c, 1, h, exsize, blocksetid, ix, filehash, size); using (var cmd = m_connection.CreateCommand(tr.Parent)) { var bid = cmd.ExecuteScalarInt64(@"SELECT ""ID"" FROM ""Block"" WHERE ""Hash"" = ?", -1, h); if (bid == -1) throw new Exception(string.Format("Could not find any blocks with the given hash: {0}", h)); foreach(var rd in cmd.ExecuteReaderEnumerable(@"SELECT ""Size"" FROM ""Block"" WHERE ""Hash"" = ?", h)) - m_result.AddError(string.Format("Found block with ID {0} and hash {1} and size {2}", bid, h, rd.ConvertValueToInt64(0, -1)), null); + Logging.Log.WriteErrorMessage(LOGTAG, "FoundIssue1400Error", null, "Found block with ID {0} and hash {1} and size {2}", bid, h, rd.ConvertValueToInt64(0, -1)); } throw new Exception(string.Format("Unexpected result count: {0}, expected {1}, check log for more messages", c, 1)); @@ -648,9 +653,9 @@ namespace Duplicati.Library.Main.Database finally { try { cmd.ExecuteNonQuery(string.Format(@"DROP TABLE IF EXISTS ""{0}"";", tmpName1)); } - catch (Exception ex) { m_result.AddWarning("Dispose temp table error", ex); } + catch (Exception ex) { Logging.Log.WriteWarningMessage(LOGTAG, "DisposeError", ex, "Dispose temp table error"); } try { cmd.ExecuteNonQuery(string.Format(@"DROP TABLE IF EXISTS ""{0}"";", tmpName2)); } - catch (Exception ex) { m_result.AddWarning("Dispose temp table error", ex); } + catch (Exception ex) { Logging.Log.WriteWarningMessage(LOGTAG, "DisposeError", ex, "Dispose temp table error"); } } } } diff --git a/Duplicati/Library/Main/Database/LocalBugReportDatabase.cs b/Duplicati/Library/Main/Database/LocalBugReportDatabase.cs index ec1fccc5b..e77a31ef3 100644 --- a/Duplicati/Library/Main/Database/LocalBugReportDatabase.cs +++ b/Duplicati/Library/Main/Database/LocalBugReportDatabase.cs @@ -21,6 +21,11 @@ namespace Duplicati.Library.Main.Database { internal class LocalBugReportDatabase : LocalDatabase { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(typeof(LocalBugReportDatabase)); + public LocalBugReportDatabase(string path) : base(path, "BugReportCreate", false) { @@ -59,7 +64,7 @@ namespace Duplicati.Library.Main.Database cmd.ExecuteNonQuery(string.Format(@"DROP TABLE IF EXISTS ""{0}"" ", tablename)); - using(new Logging.Timer("CommitUpdateBugReport")) + using(new Logging.Timer(LOGTAG, "CommitUpdateBugReport", "CommitUpdateBugReport")) tr.Commit(); cmd.Transaction = null; diff --git a/Duplicati/Library/Main/Database/LocalDatabase.cs b/Duplicati/Library/Main/Database/LocalDatabase.cs index 6bd6fe44d..c7c28b273 100644 --- a/Duplicati/Library/Main/Database/LocalDatabase.cs +++ b/Duplicati/Library/Main/Database/LocalDatabase.cs @@ -8,6 +8,11 @@ namespace Duplicati.Library.Main.Database { internal class LocalDatabase : IDisposable { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(typeof(LocalDatabase)); + protected readonly System.Data.IDbConnection m_connection; protected readonly long m_operationid = -1; @@ -233,7 +238,7 @@ namespace Duplicati.Library.Main.Database qs += "?,"; } else - m_result.AddWarning(string.Format("Skipping invalid version: {0}", v), null); + Logging.Log.WriteWarningMessage(LOGTAG, "SkipInvalidVersion", null, "Skipping invalid version: {0}", v); if (qs.Length > 0) @@ -518,9 +523,9 @@ namespace Duplicati.Library.Main.Database res.Add(rd.ConvertValueToInt64(0)); if (res.Count == 0) - throw new Duplicati.Library.Interface.UserInformationException("No backup at the specified date"); + throw new Duplicati.Library.Interface.UserInformationException("No backup at the specified date", "NoBackupAtDate"); else - m_result.AddWarning(string.Format("Restore time or version did not match any existing backups, selecting newest backup"), null); + Logging.Log.WriteWarningMessage(LOGTAG, "RestoreTimeNoMatch", null, "Restore time or version did not match any existing backups, selecting newest backup"); } return res; @@ -1069,7 +1074,7 @@ ORDER BY var metablocklisthash = rd.GetValue(7).ToString(); if (path == lastpath) - m_result.AddWarning(string.Format("Duplicate path detected: {0}!", path), null); + Logging.Log.WriteWarningMessage(LOGTAG, "DuplicatePathFound", null, "Duplicate path detected: {0}!", path); lastpath = path; @@ -1392,9 +1397,6 @@ ORDER BY (prop, item) => !typeof(IBackendProgressUpdater).IsAssignableFrom(prop.PropertyType) && !typeof(IMessageSink).IsAssignableFrom(prop.PropertyType) && - !typeof(ILogWriter).IsAssignableFrom(prop.PropertyType) && - prop.Name != "VerboseOutput" && - prop.Name != "VerboseErrors" && !(prop.Name == "MainOperation" && item is BackendWriter) && !(prop.Name == "EndTime" && item is BackendWriter) && !(prop.Name == "Duration" && item is BackendWriter) && diff --git a/Duplicati/Library/Main/Database/LocalDeleteDatabase.cs b/Duplicati/Library/Main/Database/LocalDeleteDatabase.cs index 28f4f5b4c..3a28024d1 100644 --- a/Duplicati/Library/Main/Database/LocalDeleteDatabase.cs +++ b/Duplicati/Library/Main/Database/LocalDeleteDatabase.cs @@ -25,6 +25,11 @@ namespace Duplicati.Library.Main.Database { internal class LocalDeleteDatabase : LocalDatabase { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(); + private System.Data.IDbCommand m_moveBlockToNewVolumeCommand; public LocalDeleteDatabase(string path, string operation) @@ -164,7 +169,7 @@ namespace Duplicati.Library.Main.Database IEnumerable CompactableVolumes { get; } bool ShouldReclaim { get; } bool ShouldCompact { get; } - void ReportCompactData(ILogWriter log); + void ReportCompactData(); } private class CompactReport : ICompactReport @@ -204,26 +209,23 @@ namespace Duplicati.Library.Main.Database m_smallvolumecount = m_smallvolumes.Count(); } - public void ReportCompactData(ILogWriter log) + public void ReportCompactData() { var wastepercentage = ((m_wastedspace / (float)m_fullsize) * 100); - if (log.VerboseOutput) - { - log.AddVerboseMessage(string.Format("Found {0} fully deletable volume(s)", m_deletablevolumes)); - log.AddVerboseMessage(string.Format("Found {0} small volumes(s) with a total size of {1}", m_smallvolumes.Count(), Library.Utility.Utility.FormatSizeString(m_smallspace))); - log.AddVerboseMessage(string.Format("Found {0} volume(s) with a total of {1:F2}% wasted space ({2} of {3})", m_wastevolumes.Count(), wastepercentage, Library.Utility.Utility.FormatSizeString(m_wastedspace), Library.Utility.Utility.FormatSizeString(m_fullsize))); - } - + Logging.Log.WriteVerboseMessage(LOGTAG, "FullyDeletableCount", "Found {0} fully deletable volume(s)", m_deletablevolumes); + Logging.Log.WriteVerboseMessage(LOGTAG, "SmallVolumeCount", "Found {0} small volumes(s) with a total size of {1}", m_smallvolumes.Count(), Library.Utility.Utility.FormatSizeString(m_smallspace)); + Logging.Log.WriteVerboseMessage(LOGTAG, "WastedSpaceVolumes", "Found {0} volume(s) with a total of {1:F2}% wasted space ({2} of {3})", m_wastevolumes.Count(), wastepercentage, Library.Utility.Utility.FormatSizeString(m_wastedspace), Library.Utility.Utility.FormatSizeString(m_fullsize)); + if (m_deletablevolumes > 0) - log.AddMessage(string.Format("Compacting because there are {0} fully deletable volume(s)", m_deletablevolumes)); + Logging.Log.WriteInformationMessage(LOGTAG, "CompactReason", "Compacting because there are {0} fully deletable volume(s)", m_deletablevolumes); else if (wastepercentage >= m_wastethreshold && m_wastevolumes.Count() >= 2) - log.AddMessage(string.Format("Compacting because there is {0:F2}% wasted space and the limit is {1}%", wastepercentage, m_wastethreshold)); + Logging.Log.WriteInformationMessage(LOGTAG, "CompactReason", "Compacting because there is {0:F2}% wasted space and the limit is {1}%", wastepercentage, m_wastethreshold); else if (m_smallspace > m_volsize) - log.AddMessage(string.Format("Compacting because there are {0} in small volumes and the volume size is {1}", Library.Utility.Utility.FormatSizeString(m_smallspace), Library.Utility.Utility.FormatSizeString(m_volsize))); + Logging.Log.WriteInformationMessage(LOGTAG, "CompactReason", "Compacting because there are {0} in small volumes and the volume size is {1}", Library.Utility.Utility.FormatSizeString(m_smallspace), Library.Utility.Utility.FormatSizeString(m_volsize)); else if (m_smallvolumecount > m_maxsmallfilecount) - log.AddMessage(string.Format("Compacting because there are {0} small volumes and the maximum is {1}", m_smallvolumecount, m_maxsmallfilecount)); + Logging.Log.WriteInformationMessage(LOGTAG, "CompactReason", "Compacting because there are {0} small volumes and the maximum is {1}", m_smallvolumecount, m_maxsmallfilecount); else - log.AddMessage("Compacting not required"); + Logging.Log.WriteInformationMessage(LOGTAG, "CompactReason", "Compacting not required"); } public bool ShouldReclaim diff --git a/Duplicati/Library/Main/Database/LocalPurgeDatabase.cs b/Duplicati/Library/Main/Database/LocalPurgeDatabase.cs index e0d9938b2..eb1850a54 100644 --- a/Duplicati/Library/Main/Database/LocalPurgeDatabase.cs +++ b/Duplicati/Library/Main/Database/LocalPurgeDatabase.cs @@ -159,7 +159,7 @@ namespace Duplicati.Library.Main.Database RemovedFileSize = cmd.ExecuteScalarInt64(string.Format(@"SELECT SUM(""C"".""Length"") FROM ""{0}"" A, ""File"" B, ""Blockset"" C WHERE ""A"".""FileID"" = ""B"".""ID"" AND ""B"".""BlocksetID"" = ""C"".""ID"" ", m_tablename), 0); var filesetcount = cmd.ExecuteScalarInt64(string.Format(@"SELECT COUNT(*) FROM ""FilesetEntry"" WHERE ""FilesetID"" = " + ParentID), 0); if (filesetcount == RemovedFileCount) - throw new Duplicati.Library.Interface.UserInformationException(string.Format("Refusing to purge {0} files from fileset with ID {1}, as that would remove the entire fileset.\nTo delete a fileset, use the \"delete\" command.", RemovedFileCount, ParentID)); + throw new Duplicati.Library.Interface.UserInformationException(string.Format("Refusing to purge {0} files from fileset with ID {1}, as that would remove the entire fileset.\nTo delete a fileset, use the \"delete\" command.", RemovedFileCount, ParentID), "PurgeWouldRemoveEntireFileset"); } } diff --git a/Duplicati/Library/Main/Database/LocalRecreateDatabase.cs b/Duplicati/Library/Main/Database/LocalRecreateDatabase.cs index c927b411a..f2a05f5b9 100644 --- a/Duplicati/Library/Main/Database/LocalRecreateDatabase.cs +++ b/Duplicati/Library/Main/Database/LocalRecreateDatabase.cs @@ -8,6 +8,11 @@ namespace Duplicati.Library.Main.Database { internal partial class LocalRecreateDatabase : LocalRestoreDatabase { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(typeof(LocalRecreateDatabase)); + private class PathEntryKeeper { private SortedList, long> m_versions; @@ -274,7 +279,7 @@ namespace Duplicati.Library.Main.Database } catch (Exception ex) { - m_result.AddError("Blockset insert failed, comitting temporary tables for trace purposes", ex); + Logging.Log.WriteErrorMessage(LOGTAG, "BlocksetInsertFailed", ex, "Blockset insert failed, comitting temporary tables for trace purposes"); using (var fixcmd = m_connection.CreateCommand()) { @@ -408,7 +413,7 @@ namespace Duplicati.Library.Main.Database } if (c != expectedblocklisthashes) - m_result.AddWarning(string.Format("Mismatching number of blocklist hashes detected on blockset {2}. Expected {0} blocklist hashes, but found {1}", expectedblocklisthashes, c, blocksetid), null); + Logging.Log.WriteWarningMessage(LOGTAG, "MismatchInBlocklistHashCount", null, "Mismatching number of blocklist hashes detected on blockset {2}. Expected {0} blocklist hashes, but found {1}", expectedblocklisthashes, c, blocksetid); return blocksetid; } diff --git a/Duplicati/Library/Main/Database/LocalRepairDatabase.cs b/Duplicati/Library/Main/Database/LocalRepairDatabase.cs index ed4236980..facbbfb38 100644 --- a/Duplicati/Library/Main/Database/LocalRepairDatabase.cs +++ b/Duplicati/Library/Main/Database/LocalRepairDatabase.cs @@ -23,6 +23,11 @@ namespace Duplicati.Library.Main.Database { internal class LocalRepairDatabase : LocalDatabase { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(typeof(LocalRepairDatabase)); + public LocalRepairDatabase(string path) : base(path, "Repair", true) { @@ -250,7 +255,7 @@ namespace Duplicati.Library.Main.Database var x = cmd.ExecuteScalarInt64(sql_count, 0); if (x > 1) { - m_result.AddMessage("Found duplicate metadatahashes, repairing"); + Logging.Log.WriteInformationMessage(LOGTAG, "DuplicateMetadataHashes", "Found duplicate metadatahashes, repairing"); var tablename = "TmpFile-" + Guid.NewGuid().ToString("N"); @@ -288,9 +293,9 @@ namespace Duplicati.Library.Main.Database cmd.CommandText = sql_count; x = cmd.ExecuteScalarInt64(0); if (x > 1) - throw new Duplicati.Library.Interface.UserInformationException("Repair failed, there are still duplicate metadatahashes!"); + throw new Duplicati.Library.Interface.UserInformationException("Repair failed, there are still duplicate metadatahashes!", "DuplicateHashesRepairFailed"); - m_result.AddMessage("Duplicate metadatahashes repaired succesfully"); + Logging.Log.WriteInformationMessage(LOGTAG, "DuplicateMetadataHashesFixed", "Duplicate metadatahashes repaired succesfully"); tr.Commit(); } } @@ -306,7 +311,7 @@ namespace Duplicati.Library.Main.Database var x = cmd.ExecuteScalarInt64(sql_count, 0); if (x > 0) { - m_result.AddMessage("Found duplicate file entries, repairing"); + Logging.Log.WriteInformationMessage(LOGTAG, "DuplicateFileEntries", "Found duplicate file entries, repairing"); var sql = @"SELECT ""ID"", ""Path"", ""BlocksetID"", ""MetadataID"", ""Entries"" FROM ( SELECT MIN(""ID"") AS ""ID"", ""Path"", ""BlocksetID"", ""MetadataID"", COUNT(*) as ""Entries"" FROM ""File"" GROUP BY ""Path"", ""BlocksetID"", ""MetadataID"") @@ -323,9 +328,9 @@ namespace Duplicati.Library.Main.Database cmd.CommandText = sql_count; x = cmd.ExecuteScalarInt64(0); if (x > 1) - throw new Duplicati.Library.Interface.UserInformationException("Repair failed, there are still duplicate file entries!"); + throw new Duplicati.Library.Interface.UserInformationException("Repair failed, there are still duplicate file entries!", "DuplicateFilesRepairFailed"); - m_result.AddMessage("Duplicate file entries repaired succesfully"); + Logging.Log.WriteInformationMessage(LOGTAG, "DuplicateFileEntriesFixed", "Duplicate file entries repaired succesfully"); tr.Commit(); } } @@ -350,7 +355,7 @@ namespace Duplicati.Library.Main.Database var itemswithnoblocklisthash = cmd.ExecuteScalarInt64(countsql, 0); if (itemswithnoblocklisthash != 0) { - m_result.AddMessage(string.Format("Found {0} missing blocklisthash entries, repairing", itemswithnoblocklisthash)); + Logging.Log.WriteInformationMessage(LOGTAG, "MissingBlocklistHashes", "Found {0} missing blocklisthash entries, repairing", itemswithnoblocklisthash); using(var c2 = m_connection.CreateCommand(tr)) using(var c3 = m_connection.CreateCommand(tr)) using(var c4 = m_connection.CreateCommand(tr)) @@ -429,9 +434,9 @@ namespace Duplicati.Library.Main.Database itemswithnoblocklisthash = cmd.ExecuteScalarInt64(countsql, 0); if (itemswithnoblocklisthash != 0) - throw new Duplicati.Library.Interface.UserInformationException(string.Format("Failed to repair, after repair {0} blocklisthashes were missing", itemswithnoblocklisthash)); + throw new Duplicati.Library.Interface.UserInformationException(string.Format("Failed to repair, after repair {0} blocklisthashes were missing", itemswithnoblocklisthash), "MissingBlocklistHashesRepairFailed"); - m_result.AddMessage("Missing blocklisthashes repaired succesfully"); + Logging.Log.WriteInformationMessage(LOGTAG, "MissingBlocklisthashesRepaired", "Missing blocklisthashes repaired succesfully"); tr.Commit(); } } @@ -450,7 +455,7 @@ namespace Duplicati.Library.Main.Database var x = cmd.ExecuteScalarInt64(sql_count, 0); if (x > 0) { - m_result.AddMessage("Found duplicate blocklisthash entries, repairing"); + Logging.Log.WriteInformationMessage(LOGTAG, "DuplicateBlocklistHashes", "Found duplicate blocklisthash entries, repairing"); var unique_count = cmd.ExecuteScalarInt64(@"SELECT COUNT(*) FROM (SELECT DISTINCT ""BlocksetID"", ""Index"" FROM ""BlocklistHash"")", 0); @@ -474,7 +479,7 @@ namespace Duplicati.Library.Main.Database var real_count = cmd.ExecuteScalarInt64(@"SELECT Count(*) FROM ""BlocklistHash""", 0); if (real_count != unique_count) - throw new Duplicati.Library.Interface.UserInformationException(string.Format("Failed to repair, result should have been {0} blocklist hashes, but result was {1} blocklist hashes", unique_count, real_count)); + throw new Duplicati.Library.Interface.UserInformationException(string.Format("Failed to repair, result should have been {0} blocklist hashes, but result was {1} blocklist hashes", unique_count, real_count), "DuplicateBlocklistHashesRepairFailed"); try { @@ -482,10 +487,10 @@ namespace Duplicati.Library.Main.Database } catch(Exception ex) { - throw new Duplicati.Library.Interface.UserInformationException("Repaired blocklisthashes, but the database was broken afterwards, rolled back changes", ex); + throw new Duplicati.Library.Interface.UserInformationException("Repaired blocklisthashes, but the database was broken afterwards, rolled back changes", "DuplicateBlocklistHashesRepairFailed", ex); } - m_result.AddMessage("Duplicate blocklisthashes repaired succesfully"); + Logging.Log.WriteInformationMessage(LOGTAG, "DuplicateBlocklistHashesRepaired", "Duplicate blocklisthashes repaired succesfully"); tr.Commit(); } } diff --git a/Duplicati/Library/Main/Database/LocalRestoreDatabase.cs b/Duplicati/Library/Main/Database/LocalRestoreDatabase.cs index 61a217450..6555ac307 100644 --- a/Duplicati/Library/Main/Database/LocalRestoreDatabase.cs +++ b/Duplicati/Library/Main/Database/LocalRestoreDatabase.cs @@ -8,6 +8,11 @@ namespace Duplicati.Library.Main.Database { internal partial class LocalRestoreDatabase : LocalDatabase { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(typeof(LocalRestoreDatabase)); + protected string m_temptabsetguid = Library.Utility.Utility.ByteArrayAsHexString(Guid.NewGuid().ToByteArray()); protected string m_tempfiletable; protected string m_tempblocktable; @@ -173,7 +178,7 @@ namespace Duplicati.Library.Main.Database } - public Tuple PrepareRestoreFilelist(DateTime restoretime, long[] versions, Library.Utility.IFilter filter, ILogWriter log) + public Tuple PrepareRestoreFilelist(DateTime restoretime, long[] versions, Library.Utility.IFilter filter) { var guid = Library.Utility.Utility.ByteArrayAsHexString(Guid.NewGuid().ToByteArray()); @@ -195,7 +200,7 @@ namespace Duplicati.Library.Main.Database .Select(pair => pair.index + 1) .FirstOrDefault() - 1; - log.AddMessage(string.Format("Searching backup {0} ({1}) ...", ix, m_restoreTime)); + Logging.Log.WriteInformationMessage(LOGTAG, "SearchingBackup", "Searching backup {0} ({1}) ...", ix, m_restoreTime); cmd.Parameters.Clear(); @@ -251,13 +256,13 @@ namespace Duplicati.Library.Main.Database sb.AppendLine(rd.GetValue(0).ToString()); var actualrestoretime = ParseFromEpochSeconds(cmd.ExecuteScalarInt64(@"SELECT ""Timestamp"" FROM ""Fileset"" WHERE ""ID"" = ?", 0, filesetId)); - log.AddWarning(string.Format("{0} File(s) were not found in list of files for backup at {1}, will not be restored: {2}", p.Length - c, actualrestoretime.ToLocalTime(), sb), null); + Logging.Log.WriteWarningMessage(LOGTAG, "FilesNotFoundInBackupList", null, "{0} File(s) were not found in list of files for backup at {1}, will not be restored: {2}", p.Length - c, actualrestoretime.ToLocalTime(), sb); cmd.Parameters.Clear(); } cmd.ExecuteNonQuery(string.Format(@"DROP TABLE IF EXISTS ""{0}"" ", m_filenamestable)); - using(new Logging.Timer("CommitPrepareFileset")) + using(new Logging.Timer(LOGTAG, "CommitPrepareFileset", "CommitPrepareFileset")) tr.Commit(); } } @@ -305,7 +310,7 @@ namespace Duplicati.Library.Main.Database if (filecount > 0) { - log.AddVerboseMessage("Needs to restore {0} files ({1})", filecount, Library.Utility.Utility.FormatSizeString(filesize)); + Logging.Log.WriteVerboseMessage(LOGTAG, "RestoreTargetFileCount", "Needs to restore {0} files ({1})", filecount, Library.Utility.Utility.FormatSizeString(filesize)); return new Tuple(filecount, filesize); } } @@ -440,7 +445,7 @@ namespace Duplicati.Library.Main.Database } } - public void FindMissingBlocks(ILogWriter log, bool skipMetadata) + public void FindMissingBlocks(bool skipMetadata) { using(var cmd = m_connection.CreateCommand()) { @@ -454,11 +459,8 @@ namespace Duplicati.Library.Main.Database p2 = cmd.ExecuteNonQuery(); } - if (log.VerboseOutput) - { - var size = cmd.ExecuteScalarInt64(string.Format(@"SELECT SUM(""Size"") FROM ""{0}"" ", m_tempblocktable), 0); - log.AddVerboseMessage("Restore list contains {0} blocks with a total size of {1}", p1 + p2, Library.Utility.Utility.FormatSizeString(size)); - } + var size = cmd.ExecuteScalarInt64(string.Format(@"SELECT SUM(""Size"") FROM ""{0}"" ", m_tempblocktable), 0); + Logging.Log.WriteVerboseMessage(LOGTAG, "RestoreSourceSize", "Restore list contains {0} blocks with a total size of {1}", p1 + p2, Library.Utility.Utility.FormatSizeString(size)); } } @@ -947,7 +949,7 @@ namespace Duplicati.Library.Main.Database cmd.CommandText = string.Format(@"DROP TABLE IF EXISTS ""{0}""", m_tempfiletable); cmd.ExecuteNonQuery(); } - catch(Exception ex) { if (m_result != null) m_result.AddWarning(string.Format("Cleanup error: {0}", ex.Message), ex); } + catch(Exception ex) { Logging.Log.WriteWarningMessage(LOGTAG, "CleanupError", ex, "Cleanup error: {0}", ex.Message); } finally { m_tempfiletable = null; } if (m_tempblocktable != null) @@ -956,7 +958,7 @@ namespace Duplicati.Library.Main.Database cmd.CommandText = string.Format(@"DROP TABLE IF EXISTS ""{0}""", m_tempblocktable); cmd.ExecuteNonQuery(); } - catch(Exception ex) { if (m_result != null) m_result.AddWarning(string.Format("Cleanup error: {0}", ex.Message), ex); } + catch(Exception ex) { Logging.Log.WriteWarningMessage(LOGTAG, "CleanupError", ex, "Cleanup error: {0}", ex.Message); } finally { m_tempblocktable = null; } @@ -966,7 +968,7 @@ namespace Duplicati.Library.Main.Database cmd.CommandText = string.Format(@"DROP TABLE IF EXISTS ""{0}""", m_fileprogtable); cmd.ExecuteNonQuery(); } - catch (Exception ex) { if (m_result != null) m_result.AddWarning(string.Format("Cleanup error: {0}", ex.Message), ex); } + catch (Exception ex) { Logging.Log.WriteWarningMessage(LOGTAG, "CleanupError", ex, "Cleanup error: {0}", ex.Message); } finally { m_fileprogtable = null; } if (m_totalprogtable != null) @@ -975,7 +977,7 @@ namespace Duplicati.Library.Main.Database cmd.CommandText = string.Format(@"DROP TABLE IF EXISTS ""{0}""", m_totalprogtable); cmd.ExecuteNonQuery(); } - catch (Exception ex) { if (m_result != null) m_result.AddWarning(string.Format("Cleanup error: {0}", ex.Message), ex); } + catch (Exception ex) { Logging.Log.WriteWarningMessage(LOGTAG, "CleanupError", ex, "Cleanup error: {0}", ex.Message); } finally { m_totalprogtable = null; } if (m_filesnewlydonetable != null) @@ -984,7 +986,7 @@ namespace Duplicati.Library.Main.Database cmd.CommandText = string.Format(@"DROP TABLE IF EXISTS ""{0}""", m_filesnewlydonetable); cmd.ExecuteNonQuery(); } - catch (Exception ex) { if (m_result != null) m_result.AddWarning(string.Format("Cleanup error: {0}", ex.Message), ex); } + catch (Exception ex) { Logging.Log.WriteWarningMessage(LOGTAG, "CleanupError", ex, "Cleanup error: {0}", ex.Message); } finally { m_filesnewlydonetable = null; } } @@ -996,7 +998,7 @@ namespace Duplicati.Library.Main.Database void SetAllBlocksMissing(long targetfileid); void SetAllBlocksRestored(long targetfileid, bool includeMetadata); void SetFileDataVerified(long targetfileid); - void Commit(ILogWriter log); + void Commit(); void UpdateProcessed(IOperationProgressUpdater writer); System.Data.IDbTransaction Transaction { get; } } @@ -1132,12 +1134,12 @@ namespace Duplicati.Library.Main.Database } - public void Commit(ILogWriter log) + public void Commit() { var tr = m_insertblockCommand.Transaction; m_insertblockCommand.Dispose(); m_insertblockCommand = null; - using (new Logging.Timer("CommitBlockMarker")) + using (new Logging.Timer(LOGTAG, "CommitBlockMarker", "CommitBlockMarker")) tr.Commit(); tr.Dispose(); } diff --git a/Duplicati/Library/Main/Database/PathLookupHelper.cs b/Duplicati/Library/Main/Database/PathLookupHelper.cs index 80cd71767..8146691b3 100644 --- a/Duplicati/Library/Main/Database/PathLookupHelper.cs +++ b/Duplicati/Library/Main/Database/PathLookupHelper.cs @@ -30,7 +30,7 @@ namespace Duplicati.Library.Main.Database private readonly List> m_lookup; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// If set to true use hotpath optimization public PathLookupHelper(bool useHotPath = true) diff --git a/Duplicati/Library/Main/DatabaseLocator.cs b/Duplicati/Library/Main/DatabaseLocator.cs index 1d38c22a4..5b82bfde8 100644 --- a/Duplicati/Library/Main/DatabaseLocator.cs +++ b/Duplicati/Library/Main/DatabaseLocator.cs @@ -134,7 +134,7 @@ namespace Duplicati.Library.Main select n).ToList(); if (matches.Count > 1) - throw new Duplicati.Library.Interface.UserInformationException(string.Format("Multiple sources found for: {0}", backend)); + throw new Duplicati.Library.Interface.UserInformationException(string.Format("Multiple sources found for: {0}", backend), "MultipleLocalDatabaseSourcesFound"); // Re-select if (matches.Count == 0 && anyUsername && string.IsNullOrEmpty(username)) @@ -149,7 +149,7 @@ namespace Duplicati.Library.Main select n).ToList(); if (matches.Count > 1) - throw new Duplicati.Library.Interface.UserInformationException(String.Format("Multiple sources found for \"{0}\", try supplying --{1}", backend, "auth-username")); + throw new Duplicati.Library.Interface.UserInformationException(String.Format("Multiple sources found for \"{0}\", try supplying --{1}", backend, "auth-username"), "MultipleLocalDatabaseSourcesFound"); } if (matches.Count == 0 && !autoCreate) @@ -172,7 +172,7 @@ namespace Duplicati.Library.Main newpath = System.IO.Path.Combine(folder, GenerateRandomName()); if (System.IO.File.Exists(newpath)) - throw new Duplicati.Library.Interface.UserInformationException("Unable to find a unique name for the database, please use --dbpath"); + throw new Duplicati.Library.Interface.UserInformationException("Unable to find a unique name for the database, please use --dbpath", "CannotCreateRandomName"); //Create a new one, add it to the list, and save it configs.Add(new BackendEntry() { diff --git a/Duplicati/Library/Main/Duplicati.Library.Main.csproj b/Duplicati/Library/Main/Duplicati.Library.Main.csproj index 892c33d1f..657f584aa 100644 --- a/Duplicati/Library/Main/Duplicati.Library.Main.csproj +++ b/Duplicati/Library/Main/Duplicati.Library.Main.csproj @@ -111,6 +111,8 @@ + + @@ -149,6 +151,10 @@ {BB014EA5-CE2C-4444-8D30-38983A0E8553} Duplicati.Library.UsageReporter + + {52826615-7964-47FE-B4B3-1B2DBDF605B9} + Duplicati.Library.Modules.Builtin + diff --git a/Duplicati/Library/Main/Operation/BackupHandler.cs b/Duplicati/Library/Main/Operation/BackupHandler.cs index 0aa895ae0..fabe7e7ac 100644 --- a/Duplicati/Library/Main/Operation/BackupHandler.cs +++ b/Duplicati/Library/Main/Operation/BackupHandler.cs @@ -12,6 +12,11 @@ namespace Duplicati.Library.Main.Operation { internal class BackupHandler : IDisposable { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(); + private readonly Options m_options; private string m_backendurl; @@ -57,24 +62,24 @@ namespace Duplicati.Library.Main.Operation m_symlinkPolicy = m_options.SymlinkPolicy; if (options.AllowPassphraseChange) - throw new UserInformationException(Strings.Common.PassphraseChangeUnsupported); + throw new UserInformationException(Strings.Common.PassphraseChangeUnsupported, "PassphraseChangeUnsupported"); } public class FilterHandler { + private static readonly string FILTER_LOGTAG = Logging.Log.LogTagFromType(); private Snapshots.ISnapshotService m_snapshot; private FileAttributes m_attributeFilter; private Duplicati.Library.Utility.IFilter m_enumeratefilter; private Duplicati.Library.Utility.IFilter m_emitfilter; private Options.SymlinkStrategy m_symlinkPolicy; private Options.HardlinkStrategy m_hardlinkPolicy; - private ILogWriter m_logWriter; private Dictionary m_hardlinkmap; private Duplicati.Library.Utility.IFilter m_sourcefilter; private Queue m_mixinqueue; - public FilterHandler(Snapshots.ISnapshotService snapshot, FileAttributes attributeFilter, Duplicati.Library.Utility.IFilter sourcefilter, Duplicati.Library.Utility.IFilter filter, Options.SymlinkStrategy symlinkPolicy, Options.HardlinkStrategy hardlinkPolicy, ILogWriter logWriter) + public FilterHandler(Snapshots.ISnapshotService snapshot, FileAttributes attributeFilter, Duplicati.Library.Utility.IFilter sourcefilter, Duplicati.Library.Utility.IFilter filter, Options.SymlinkStrategy symlinkPolicy, Options.HardlinkStrategy hardlinkPolicy) { m_snapshot = snapshot; m_attributeFilter = attributeFilter; @@ -82,7 +87,6 @@ namespace Duplicati.Library.Main.Operation m_emitfilter = filter; m_symlinkPolicy = symlinkPolicy; m_hardlinkPolicy = hardlinkPolicy; - m_logWriter = logWriter; m_hardlinkmap = new Dictionary(); m_mixinqueue = new Queue(); @@ -99,8 +103,7 @@ namespace Duplicati.Library.Main.Operation public void ReportError(string rootpath, string path, Exception ex) { - if (m_logWriter != null) - m_logWriter.AddWarning(string.Format("Error reported while accessing file: {0}", path), ex); + Logging.Log.WriteWarningMessage(FILTER_LOGTAG, "FileAccessError", ex, "Error reported while accessing file: {0}", path); } public bool AttributeFilter(string rootpath, string path, FileAttributes attributes) @@ -109,15 +112,13 @@ namespace Duplicati.Library.Main.Operation { if (m_snapshot.IsBlockDevice(path)) { - if (m_logWriter != null) - m_logWriter.AddVerboseMessage("Excluding block device: {0}", path); + Logging.Log.WriteVerboseMessage(FILTER_LOGTAG, "ExcludingBlockDevice", "Excluding block device: {0}", path); return false; } } catch (Exception ex) { - if (m_logWriter != null) - m_logWriter.AddWarning(string.Format("Failed to process path: {0}", path), ex); + Logging.Log.WriteWarningMessage(FILTER_LOGTAG, "PathProcessingError", ex, "Failed to process path: {0}", path); return false; } @@ -125,8 +126,7 @@ namespace Duplicati.Library.Main.Operation bool sourcematches; if (m_sourcefilter.Matches(path, out sourcematches, out sourcematch) && sourcematches) { - if (m_logWriter != null) - m_logWriter.AddVerboseMessage("Including source path: {0}", path); + Logging.Log.WriteVerboseMessage(FILTER_LOGTAG, "IncludingSourcePath", "Including source path: {0}", path); return true; } @@ -140,8 +140,7 @@ namespace Duplicati.Library.Main.Operation { if (m_hardlinkPolicy == Options.HardlinkStrategy.None) { - if (m_logWriter != null) - m_logWriter.AddVerboseMessage("Excluding hardlink: {0} ({1})", path, id); + Logging.Log.WriteVerboseMessage(FILTER_LOGTAG, "ExcludingHardlinkByPolicy", "Excluding hardlink: {0} ({1})", path, id); return false; } else if (m_hardlinkPolicy == Options.HardlinkStrategy.First) @@ -149,8 +148,7 @@ namespace Duplicati.Library.Main.Operation string prevPath; if (m_hardlinkmap.TryGetValue(id, out prevPath)) { - if (m_logWriter != null) - m_logWriter.AddVerboseMessage("Excluding hardlink ({1}) for: {0}, previous hardlink: {2}", path, id, prevPath); + Logging.Log.WriteVerboseMessage(FILTER_LOGTAG, "ExcludingDuplicateHardlink", "Excluding hardlink ({1}) for: {0}, previous hardlink: {2}", path, id, prevPath); return false; } else @@ -162,44 +160,38 @@ namespace Duplicati.Library.Main.Operation } catch (Exception ex) { - if (m_logWriter != null) - m_logWriter.AddWarning(string.Format("Failed to process path: {0}", path), ex); + Logging.Log.WriteWarningMessage(FILTER_LOGTAG, "PathProcessingError", ex, "Failed to process path: {0}", path); return false; } } if ((m_attributeFilter & attributes) != 0) { - if (m_logWriter != null) - m_logWriter.AddVerboseMessage("Excluding path due to attribute filter: {0}", path); + Logging.Log.WriteVerboseMessage(FILTER_LOGTAG, "ExcludingPathFromAttributes", "Excluding path due to attribute filter: {0}", path); return false; } Library.Utility.IFilter match; if (!Library.Utility.FilterExpression.Matches(m_enumeratefilter, path, out match)) { - if (m_logWriter != null) - m_logWriter.AddVerboseMessage("Excluding path due to filter: {0} => {1}", path, match == null ? "null" : match.ToString()); + Logging.Log.WriteVerboseMessage(FILTER_LOGTAG, "ExcludingPathFromFilter", "Excluding path due to filter: {0} => {1}", path, match == null ? "null" : match.ToString()); return false; } else if (match != null) { - if (m_logWriter != null) - m_logWriter.AddVerboseMessage("Including path due to filter: {0} => {1}", path, match.ToString()); + Logging.Log.WriteVerboseMessage(FILTER_LOGTAG, "IncludingPathFromFilter", "Including path due to filter: {0} => {1}", path, match.ToString()); } var isSymlink = m_snapshot.IsSymlink(path, attributes); if (isSymlink && m_symlinkPolicy == Options.SymlinkStrategy.Ignore) { - if (m_logWriter != null) - m_logWriter.AddVerboseMessage("Excluding symlink: {0}", path); + Logging.Log.WriteVerboseMessage(FILTER_LOGTAG, "ExcludeSymlink", "Excluding symlink: {0}", path); return false; } if (isSymlink && m_symlinkPolicy == Options.SymlinkStrategy.Store) { - if (m_logWriter != null) - m_logWriter.AddVerboseMessage("Storing symlink: {0}", path); + Logging.Log.WriteVerboseMessage(FILTER_LOGTAG, "StoreSymlink", "Storing symlink: {0}", path); m_mixinqueue.Enqueue(path); return false; @@ -231,7 +223,7 @@ namespace Duplicati.Library.Main.Operation foreach(var s in list.Where(x => { var fa = FileAttributes.Normal; try { fa = m_snapshot.GetAttributes(x); } - catch { } + catch(Exception ex) { Logging.Log.WriteVerboseMessage(FILTER_LOGTAG, "FailedAttributeRead", "Failed to read attributes from {0}: {1}", x, ex.Message); } return AttributeFilter(null, x, fa); })) @@ -248,7 +240,7 @@ namespace Duplicati.Library.Main.Operation } - public static Snapshots.ISnapshotService GetSnapshot(string[] sources, Options options, ILogWriter log) + public static Snapshots.ISnapshotService GetSnapshot(string[] sources, Options options) { try { @@ -260,7 +252,7 @@ namespace Duplicati.Library.Main.Operation if (options.SnapShotStrategy == Options.OptimizationStrategy.Required) throw; else if (options.SnapShotStrategy == Options.OptimizationStrategy.On) - log.AddWarning(Strings.Common.SnapshotFailedError(ex.ToString()), ex); + Logging.Log.WriteWarningMessage(LOGTAG, "SnapshotFailed", ex, Strings.Common.SnapshotFailedError(ex.ToString())); } return Library.Utility.Utility.IsClientLinux ? @@ -271,17 +263,18 @@ namespace Duplicati.Library.Main.Operation private void CountFilesThread(object state) { + var COUNTER_LOGTAG = LOGTAG + ".Counter"; var snapshot = (Snapshots.ISnapshotService)state; var updater = m_result.OperationProgressUpdater; var count = 0L; var size = 0L; var followSymlinks = m_options.SymlinkPolicy != Duplicati.Library.Main.Options.SymlinkStrategy.Follow; - foreach(var path in new FilterHandler(snapshot, m_attributeFilter, m_sourceFilter, m_filter, m_symlinkPolicy, m_options.HardlinkPolicy, null).EnumerateFilesAndFolders()) + foreach(var path in new FilterHandler(snapshot, m_attributeFilter, m_sourceFilter, m_filter, m_symlinkPolicy, m_options.HardlinkPolicy).EnumerateFilesAndFolders()) { var fa = FileAttributes.Normal; try { fa = snapshot.GetAttributes(path); } - catch { } + catch (Exception ex) { Logging.Log.WriteVerboseMessage(COUNTER_LOGTAG, "FailedAttributeRead", "Failed to read attributes from {0}: {1}", path, ex.Message); } if (followSymlinks && snapshot.IsSymlink(path, fa)) continue; @@ -291,7 +284,7 @@ namespace Duplicati.Library.Main.Operation count++; try { size += snapshot.GetFileSize(path); } - catch { } + catch (Exception ex) { Logging.Log.WriteVerboseMessage(COUNTER_LOGTAG, "SizeReadFailed", "Failed to read length of file {0}: {1}", path, ex.Message); } m_result.OperationProgressUpdater.UpdatefileCount(count, size, false); } @@ -305,7 +298,7 @@ namespace Duplicati.Library.Main.Operation var incompleteFilesets = m_database.GetIncompleteFilesets(null).OrderBy(x => x.Value).ToList(); m_result.OperationProgressUpdater.UpdatePhase(OperationPhase.Backup_PreviousBackupFinalize); - m_result.AddMessage(string.Format("Uploading filelist from previous interrupted backup")); + Logging.Log.WriteInformationMessage(LOGTAG, "PreviousBackupFilelistUpload", "Uploading filelist from previous interrupted backup"); using(var trn = m_database.BeginTransaction()) { var incompleteSet = incompleteFilesets.Last(); @@ -353,13 +346,13 @@ namespace Duplicati.Library.Main.Operation if (m_options.Dryrun) { - m_result.AddDryrunMessage(string.Format("Would upload fileset: {0}, size: {1}", fsw.RemoteFilename, Library.Utility.Utility.FormatSizeString(new FileInfo(fsw.LocalFilename).Length))); + Logging.Log.WriteDryrunMessage(LOGTAG, "WouldUploadFileset", "Would upload fileset: {0}, size: {1}", fsw.RemoteFilename, Library.Utility.Utility.FormatSizeString(new FileInfo(fsw.LocalFilename).Length)); } else { m_database.UpdateRemoteVolume(fsw.RemoteFilename, RemoteVolumeState.Uploading, -1, null, trn); - using(new Logging.Timer("CommitUpdateFilelistVolume")) + using(new Logging.Timer(LOGTAG, "CommitUpdateFilelistVolume", "CommitUpdateFilelistVolume")) trn.Commit(); backend.Put(fsw); @@ -384,7 +377,7 @@ namespace Duplicati.Library.Main.Operation foreach (var blockfile in m_database.GetMissingIndexFiles()) { - m_result.AddMessage(string.Format("Re-creating missing index file for {0}", blockfile)); + Logging.Log.WriteInformationMessage(LOGTAG, "RecreateMissingIndexFile", "Re-creating missing index file for {0}", blockfile); var w = new IndexVolumeWriter(m_options); w.VolumeID = m_database.RegisterRemoteVolume(w.RemoteFilename, RemoteVolumeType.Index, RemoteVolumeState.Temporary, null); @@ -406,7 +399,7 @@ namespace Duplicati.Library.Main.Operation m_database.AddIndexBlockLink(w.VolumeID, volumeid, null); if (m_options.Dryrun) - m_result.AddDryrunMessage(string.Format("would upload new index file {0}, with size {1}, previous size {2}", w.RemoteFilename, Library.Utility.Utility.FormatSizeString(new System.IO.FileInfo(w.LocalFilename).Length), Library.Utility.Utility.FormatSizeString(w.Filesize))); + Logging.Log.WriteDryrunMessage(LOGTAG, "WouldUpdateIndexFile", "Would upload new index file {0}, with size {1}, previous size {2}", w.RemoteFilename, Library.Utility.Utility.FormatSizeString(new System.IO.FileInfo(w.LocalFilename).Length), Library.Utility.Utility.FormatSizeString(w.Filesize)); else { m_database.UpdateRemoteVolume(w.RemoteFilename, RemoteVolumeState.Uploading, -1, null, null); @@ -419,7 +412,7 @@ namespace Duplicati.Library.Main.Operation private void PreBackupVerify(BackendManager backend, string protectedfile) { m_result.OperationProgressUpdater.UpdatePhase(OperationPhase.Backup_PreBackupVerify); - using(new Logging.Timer("PreBackupVerify")) + using(new Logging.Timer(LOGTAG, "PreBackupVerify", "PreBackupVerify")) { try { @@ -435,11 +428,11 @@ namespace Duplicati.Library.Main.Operation { if (m_options.AutoCleanup) { - m_result.AddWarning("Backend verification failed, attempting automatic cleanup", ex); + Logging.Log.WriteWarningMessage(LOGTAG, "BackendVerifyFailedAttemptingCleanup", ex, "Backend verification failed, attempting automatic cleanup"); m_result.RepairResults = new RepairResults(m_result); new RepairHandler(backend.BackendUrl, m_options, (RepairResults)m_result.RepairResults).Run(); - m_result.AddMessage("Backend cleanup finished, retrying verification"); + Logging.Log.WriteInformationMessage(LOGTAG, "BackendCleanupFinished", "Backend cleanup finished, retrying verification"); FilelistProcessor.VerifyRemoteList(backend, m_options, m_database, m_result.BackendWriter); } else @@ -450,20 +443,20 @@ namespace Duplicati.Library.Main.Operation private void RunMainOperation(Snapshots.ISnapshotService snapshot, BackendManager backend) { - var filterhandler = new FilterHandler(snapshot, m_attributeFilter, m_sourceFilter, m_filter, m_symlinkPolicy, m_options.HardlinkPolicy, m_result); + var filterhandler = new FilterHandler(snapshot, m_attributeFilter, m_sourceFilter, m_filter, m_symlinkPolicy, m_options.HardlinkPolicy); - using(new Logging.Timer("BackupMainOperation")) + using(new Logging.Timer(LOGTAG, "BackupMainOperation", "BackupMainOperation")) { if (m_options.ChangedFilelist != null && m_options.ChangedFilelist.Length >= 1) { - m_result.AddVerboseMessage("Processing supplied change list instead of enumerating filesystem"); + Logging.Log.WriteVerboseMessage(LOGTAG, "UsingChangeList", "Processing supplied change list instead of enumerating filesystem"); m_result.OperationProgressUpdater.UpdatefileCount(m_options.ChangedFilelist.Length, 0, true); foreach(var p in filterhandler.Mixin(m_options.ChangedFilelist)) { if (m_result.TaskControlRendevouz() == TaskControlState.Stop) { - m_result.AddMessage("Stopping backup operation on request"); + Logging.Log.WriteInformationMessage(LOGTAG, "StopBackup", "Stopping backup operation on request"); break; } @@ -473,7 +466,7 @@ namespace Duplicati.Library.Main.Operation } catch (Exception ex) { - m_result.AddWarning(string.Format("Failed to process element: {0}, message: {1}", p, ex.Message), ex); + Logging.Log.WriteWarningMessage(LOGTAG, "FailedToProcessEntry", ex, "Failed to process element: {0}, message: {1}", p, ex.Message); } } @@ -485,13 +478,13 @@ namespace Duplicati.Library.Main.Operation { if (m_result.TaskControlRendevouz() == TaskControlState.Stop) { - m_result.AddMessage("Stopping backup operation on request"); + Logging.Log.WriteInformationMessage(LOGTAG, "StopBackup", "Stopping backup operation on request"); break; } var fa = FileAttributes.Normal; try { fa = snapshot.GetAttributes(path); } - catch { } + catch (Exception ex) { Logging.Log.WriteVerboseMessage(LOGTAG, "FailedAttributeRead", "Failed to read attributes from {0}: {1}", path, ex.Message); } this.HandleFilesystemEntry(snapshot, backend, path, fa); } @@ -506,7 +499,7 @@ namespace Duplicati.Library.Main.Operation { var lastVolumeSize = -1L; m_result.OperationProgressUpdater.UpdatePhase(OperationPhase.Backup_Finalize); - using(new Logging.Timer("FinalizeRemoteVolumes")) + using(new Logging.Timer(LOGTAG, "FinalizeRemoteVolumes", "FinalizeRemoteVolumes")) { if (m_blockvolume != null && m_blockvolume.SourceSize > 0) { @@ -514,13 +507,13 @@ namespace Duplicati.Library.Main.Operation if (m_options.Dryrun) { - m_result.AddDryrunMessage(string.Format("Would upload block volume: {0}, size: {1}", m_blockvolume.RemoteFilename, Library.Utility.Utility.FormatSizeString(new FileInfo(m_blockvolume.LocalFilename).Length))); + Logging.Log.WriteDryrunMessage(LOGTAG, "WouldUploadBlock", "Would upload block volume: {0}, size: {1}", m_blockvolume.RemoteFilename, Library.Utility.Utility.FormatSizeString(new FileInfo(m_blockvolume.LocalFilename).Length)); if (m_indexvolume != null) { m_blockvolume.Close(); UpdateIndexVolume(); m_indexvolume.FinishVolume(Library.Utility.Utility.CalculateHash(m_blockvolume.LocalFilename), new FileInfo(m_blockvolume.LocalFilename).Length); - m_result.AddDryrunMessage(string.Format("Would upload index volume: {0}, size: {1}", m_indexvolume.RemoteFilename, Library.Utility.Utility.FormatSizeString(new FileInfo(m_indexvolume.LocalFilename).Length))); + Logging.Log.WriteDryrunMessage(LOGTAG, "WouldUploadIndex", "Would upload index volume: {0}, size: {1}", m_indexvolume.RemoteFilename, Library.Utility.Utility.FormatSizeString(new FileInfo(m_indexvolume.LocalFilename).Length)); } m_blockvolume.Dispose(); @@ -534,13 +527,13 @@ namespace Duplicati.Library.Main.Operation m_blockvolume.Close(); UpdateIndexVolume(); - using(new Logging.Timer("CommitUpdateRemoteVolume")) + using(new Logging.Timer(LOGTAG, "CommitUpdateRemoteVolume", "CommitUpdateRemoteVolume")) m_transaction.Commit(); m_transaction = m_database.BeginTransaction(); backend.Put(m_blockvolume, m_indexvolume); - using(new Logging.Timer("CommitUpdateRemoteVolume")) + using(new Logging.Timer(LOGTAG, "CommitUpdateRemoteVolume", "CommitUpdateRemoteVolume")) m_transaction.Commit(); m_transaction = m_database.BeginTransaction(); @@ -563,7 +556,7 @@ namespace Duplicati.Library.Main.Operation //Changes in the filelist triggers a filelist upload if (m_options.UploadUnchangedBackups || changeCount > 0) { - using(new Logging.Timer("Uploading a new fileset")) + using(new Logging.Timer(LOGTAG, "UploadNewFileset", "Uploading a new fileset")) { if (!string.IsNullOrEmpty(m_options.ControlFiles)) foreach(var p in m_options.ControlFiles.Split(new char[] { System.IO.Path.PathSeparator }, StringSplitOptions.RemoveEmptyEntries)) @@ -573,18 +566,18 @@ namespace Duplicati.Library.Main.Operation filesetvolume.Close(); if (m_options.Dryrun) - m_result.AddDryrunMessage(string.Format("Would upload fileset volume: {0}, size: {1}", filesetvolume.RemoteFilename, Library.Utility.Utility.FormatSizeString(new FileInfo(filesetvolume.LocalFilename).Length))); + Logging.Log.WriteDryrunMessage(LOGTAG, "WouldUploadFileset", "Would upload fileset volume: {0}, size: {1}", filesetvolume.RemoteFilename, Library.Utility.Utility.FormatSizeString(new FileInfo(filesetvolume.LocalFilename).Length)); else { m_database.UpdateRemoteVolume(filesetvolume.RemoteFilename, RemoteVolumeState.Uploading, -1, null, m_transaction); - using(new Logging.Timer("CommitUpdateRemoteVolume")) + using(new Logging.Timer(LOGTAG, "CommitUpdateRemoteVolume", "CommitUpdateRemoteVolume")) m_transaction.Commit(); m_transaction = m_database.BeginTransaction(); backend.Put(filesetvolume); - using(new Logging.Timer("CommitUpdateRemoteVolume")) + using(new Logging.Timer(LOGTAG, "CommitUpdateRemoteVolume", "CommitUpdateRemoteVolume")) m_transaction.Commit(); m_transaction = m_database.BeginTransaction(); @@ -593,7 +586,7 @@ namespace Duplicati.Library.Main.Operation } else { - m_result.AddVerboseMessage("removing temp files, as no data needs to be uploaded"); + Logging.Log.WriteVerboseMessage(LOGTAG, "RemovingLeftoverTempFile", "removing temp files, as no data needs to be uploaded"); m_database.RemoveRemoteVolume(filesetvolume.RemoteFilename, m_transaction); } } @@ -624,7 +617,7 @@ namespace Duplicati.Library.Main.Operation m_result.OperationProgressUpdater.UpdatePhase(OperationPhase.Backup_PostBackupVerify); using(var backend = new BackendManager(m_backendurl, m_options, m_result.BackendWriter, m_database)) { - using(new Logging.Timer("AfterBackupVerify")) + using(new Logging.Timer(LOGTAG, "AfterBackupVerify", "AfterBackupVerify")) FilelistProcessor.VerifyRemoteList(backend, m_options, m_database, m_result.BackendWriter); backend.WaitForComplete(m_database, null); } @@ -689,13 +682,13 @@ namespace Duplicati.Library.Main.Operation var probe_path = m_database.GetFirstPath(); if (probe_path != null && Duplicati.Library.Utility.Utility.GuessDirSeparator(probe_path) != System.IO.Path.DirectorySeparatorChar.ToString()) - throw new UserInformationException(string.Format("The backup contains files that belong to another operating system. Proceeding with a backup would cause the database to contain paths from two different operation systems, which is not supported. To proceed without losing remote data, delete all filesets and make sure the --{0} option is set, then run the backup again to re-use the existing data on the remote store.", "no-auto-compact")); + throw new UserInformationException(string.Format("The backup contains files that belong to another operating system. Proceeding with a backup would cause the database to contain paths from two different operation systems, which is not supported. To proceed without losing remote data, delete all filesets and make sure the --{0} option is set, then run the backup again to re-use the existing data on the remote store.", "no-auto-compact"), "CrossOsDatabaseReuseNotSupported"); if (m_database.PartiallyRecreated) - throw new UserInformationException("The database was only partially recreated. This database may be incomplete and the repair process is not allowed to alter remote files as that could result in data loss."); + throw new UserInformationException("The database was only partially recreated. This database may be incomplete and the repair process is not allowed to alter remote files as that could result in data loss.", "DatabaseIsPartiallyRecreated"); if (m_database.RepairInProgress) - throw new UserInformationException("The database was attempted repaired, but the repair did not complete. This database may be incomplete and the backup process cannot continue. You may delete the local database and attempt to repair it again."); + throw new UserInformationException("The database was attempted repaired, but the repair did not complete. This database may be incomplete and the backup process cannot continue. You may delete the local database and attempt to repair it again.", "DatabaseRepairInProgress"); m_blocksize = m_options.Blocksize; m_maxmetadatasize = (m_blocksize / (long)m_options.BlockhashSize) * m_blocksize; @@ -707,14 +700,14 @@ namespace Duplicati.Library.Main.Operation m_filehasher = Library.Utility.HashAlgorithmHelper.Create(m_options.FileHashAlgorithm); if (m_blockhasher == null) - throw new UserInformationException(Strings.Common.InvalidHashAlgorithm(m_options.BlockHashAlgorithm)); + throw new UserInformationException(Strings.Common.InvalidHashAlgorithm(m_options.BlockHashAlgorithm), "BlockHashAlgoithmNotSupported"); if (m_filehasher == null) - throw new UserInformationException(Strings.Common.InvalidHashAlgorithm(m_options.FileHashAlgorithm)); + throw new UserInformationException(Strings.Common.InvalidHashAlgorithm(m_options.FileHashAlgorithm), "FileHashAlgoithmNotSupported"); if (!m_blockhasher.CanReuseTransform) - throw new UserInformationException(Strings.Common.InvalidCryptoSystem(m_options.BlockHashAlgorithm)); + throw new UserInformationException(Strings.Common.InvalidCryptoSystem(m_options.BlockHashAlgorithm), "BlockHashAlgoithmNotSupported"); if (!m_filehasher.CanReuseTransform) - throw new UserInformationException(Strings.Common.InvalidCryptoSystem(m_options.FileHashAlgorithm)); + throw new UserInformationException(Strings.Common.InvalidCryptoSystem(m_options.FileHashAlgorithm), "FileHashAlgoithmNotSupported"); m_database.VerifyConsistency(null, m_options.Blocksize, m_options.BlockhashSize, false); // If there is no filter, we set an empty filter to simplify the code @@ -730,7 +723,7 @@ namespace Duplicati.Library.Main.Operation using(var backend = new BackendManager(m_backendurl, m_options, m_result.BackendWriter, m_database)) using(var filesetvolume = new FilesetVolumeWriter(m_options, m_database.OperationTimestamp)) { - using(var snapshot = GetSnapshot(sources, m_options, m_result)) + using(var snapshot = GetSnapshot(sources, m_options)) { // Start parallel scan, or use the database if (m_options.ChangedFilelist == null || m_options.ChangedFilelist.Length < 1) @@ -778,22 +771,22 @@ namespace Duplicati.Library.Main.Operation // Remove the protected file if (syntbase.State == RemoteVolumeState.Uploading) { - m_result.AddMessage(string.Format("removing incomplete remote file listed as {0}: {1}", syntbase.State, syntbase.Name)); + Logging.Log.WriteInformationMessage(LOGTAG, "RemoveIncompleteFilelist", "Removing incomplete remote file listed as {0}: {1}", syntbase.State, syntbase.Name); backend.Delete(syntbase.Name, syntbase.Size); } else if (syntbase.State == RemoteVolumeState.Temporary) { - m_result.AddMessage(string.Format("removing file listed as {0}: {1}", syntbase.State, syntbase.Name)); + Logging.Log.WriteInformationMessage(LOGTAG, "RemoveTemporaryFile", "Removing file listed as {0}: {1}", syntbase.State, syntbase.Name); m_database.RemoveRemoteVolume(syntbase.Name); } } else if (syntbase.Name == null || syntbase.State != RemoteVolumeState.Uploaded) - m_result.AddWarning(string.Format("Expected there to be a temporary fileset for synthetic filelist ({0}, {1}), but none was found?", lasttempfileid, lasttempfilelist), null); + Logging.Log.WriteWarningMessage(LOGTAG, "MissingTemporaryFilelist", null, "Expected there to be a temporary fileset for synthetic filelist ({0}, {1}), but none was found?", lasttempfileid, lasttempfilelist); } var prevfileset = m_database.FilesetTimes.FirstOrDefault(); if (prevfileset.Value.ToUniversalTime() > m_database.OperationTimestamp.ToUniversalTime()) - throw new UserInformationException(string.Format("The previous backup has time {0}, but this backup has time {1}. Something is wrong with the clock.", prevfileset.Value.ToLocalTime(), m_database.OperationTimestamp.ToLocalTime())); + throw new UserInformationException(string.Format("The previous backup has time {0}, but this backup has time {1}. Something is wrong with the clock.", prevfileset.Value.ToLocalTime(), m_database.OperationTimestamp.ToLocalTime()), "FilesetIntervalClockIssue"); m_lastfilesetid = prevfileset.Value.Ticks == 0 ? -1 : prevfileset.Key; @@ -823,21 +816,21 @@ namespace Duplicati.Library.Main.Operation var lastVolumeSize = FinalizeRemoteVolumes(backend); - using(new Logging.Timer("UpdateChangeStatistics")) + using(new Logging.Timer(LOGTAG, "UpdateChangeStatistics", "UpdateChangeStatistics")) m_database.UpdateChangeStatistics(m_result); - using(new Logging.Timer("VerifyConsistency")) + using(new Logging.Timer(LOGTAG, "VerifyConsistency", "VerifyConsistency")) m_database.VerifyConsistency(m_transaction, m_options.Blocksize, m_options.BlockhashSize, false); UploadRealFileList(backend, filesetvolume); m_result.OperationProgressUpdater.UpdatePhase(OperationPhase.Backup_WaitForUpload); - using(new Logging.Timer("Async backend wait")) + using(new Logging.Timer(LOGTAG, "AsyncBackendWait", "Async backend wait")) backend.WaitForEmpty(m_database, m_transaction); if (m_result.TaskControlRendevouz() != TaskControlState.Stop) CompactIfRequired(backend, lastVolumeSize); - using (new Logging.Timer("Async backend wait")) + using (new Logging.Timer(LOGTAG, "AsyncBackendWait", "Async backend wait")) backend.WaitForComplete(m_database, m_transaction); if (m_options.UploadVerificationFile) @@ -853,7 +846,7 @@ namespace Duplicati.Library.Main.Operation } else { - using(new Logging.Timer("CommitFinalizingBackup")) + using(new Logging.Timer(LOGTAG, "CommitFinalizingBackupe", "CommitFinalizingBackup")) m_transaction.Commit(); m_transaction = null; @@ -879,7 +872,7 @@ namespace Duplicati.Library.Main.Operation } catch (Exception ex) { - m_result.AddError("Fatal error", ex); + Logging.Log.WriteErrorMessage(LOGTAG, "FatalError", ex, "Fatal error"); throw; } finally @@ -889,18 +882,19 @@ namespace Duplicati.Library.Main.Operation parallelScanner.Abort(); parallelScanner.Join(500); if (parallelScanner.IsAlive) - m_result.AddWarning("Failed to terminate filecounter thread", null); + Logging.Log.WriteWarningMessage(LOGTAG, "FileCounterTerminateFailed", null, "Failed to terminate filecounter thread"); } if (m_transaction != null) try { m_transaction.Rollback(); } - catch (Exception ex) { m_result.AddError(string.Format("Rollback error: {0}", ex.Message), ex); } + catch (Exception ex) { Logging.Log.WriteErrorMessage(LOGTAG, "RollbackError", ex, "Rollback error: {0}", ex.Message); } } } } private Dictionary GenerateMetadata(Snapshots.ISnapshotService snapshot, string path, System.IO.FileAttributes attributes) { + string METALOGTAG = LOGTAG + ".Metadata"; try { Dictionary metadata; @@ -922,7 +916,7 @@ namespace Duplicati.Library.Main.Operation } catch (Exception ex) { - m_result.AddWarning(string.Format("Failed to read timestamp on \"{0}\"", path), ex); + Logging.Log.WriteWarningMessage(METALOGTAG, "TimestampReadFailed", ex, "Failed to read timestamp on \"{0}\"", path); } } @@ -934,7 +928,7 @@ namespace Duplicati.Library.Main.Operation } catch (Exception ex) { - m_result.AddWarning(string.Format("Failed to read timestamp on \"{0}\"", path), ex); + Logging.Log.WriteWarningMessage(METALOGTAG, "TimestampReadFailed", ex, "Failed to read timestamp on \"{0}\"", path); } } } @@ -947,13 +941,15 @@ namespace Duplicati.Library.Main.Operation } catch(Exception ex) { - m_result.AddWarning(string.Format("Failed to process metadata for \"{0}\", storing empty metadata", path), ex); + Logging.Log.WriteWarningMessage(METALOGTAG, "MetadataProcessFailed", ex, "Failed to process metadata for \"{0}\", storing empty metadata", path); return new Dictionary(); } } private bool HandleFilesystemEntry(Snapshots.ISnapshotService snapshot, BackendManager backend, string path, System.IO.FileAttributes attributes) { + string FILELOGTAG = LOGTAG + ".FileEntry"; + // If we lost the connection, there is no point in keeping on processing if (backend.HasDied) throw backend.LastException; @@ -975,7 +971,7 @@ namespace Duplicati.Library.Main.Operation } catch (Exception ex) { - m_result.AddWarning(string.Format("Failed to read timestamp on \"{0}\"", path), ex); + Logging.Log.WriteWarningMessage(FILELOGTAG, "TimestampReadFailed", ex, "Failed to read timestamp on \"{0}\"", path); } if ((attributes & FileAttributes.ReparsePoint) == FileAttributes.ReparsePoint) @@ -989,7 +985,7 @@ namespace Duplicati.Library.Main.Operation { if (m_options.SymlinkPolicy == Options.SymlinkStrategy.Ignore) { - m_result.AddVerboseMessage("Ignoring symlink {0}", path); + Logging.Log.WriteVerboseMessage(FILELOGTAG, "IgnoreSymlink", "Ignoring symlink {0}", path); return false; } @@ -1005,14 +1001,14 @@ namespace Duplicati.Library.Main.Operation var metahash = Utility.WrapMetadata(metadata, m_options); AddSymlinkToOutput(backend, path, DateTime.UtcNow, metahash); - m_result.AddVerboseMessage("Stored symlink {0}", path); + Logging.Log.WriteVerboseMessage(FILELOGTAG, "StoreSymlink", "Stored symlink {0}", path); //Do not recurse symlinks return false; } } else { - m_result.AddVerboseMessage("Treating empty symlink as regular path {0}", path); + Logging.Log.WriteVerboseMessage(FILELOGTAG, "FollowingEmptySymlink", "Treating empty symlink as regular path {0}", path); } } @@ -1029,7 +1025,7 @@ namespace Duplicati.Library.Main.Operation metahash = EMPTY_METADATA; } - m_result.AddVerboseMessage("Adding directory {0}", path); + Logging.Log.WriteVerboseMessage(FILELOGTAG, "AddDirectory", "Adding directory {0}", path); AddFolderToOutput(backend, path, lastwrite, metahash); return true; } @@ -1047,7 +1043,7 @@ namespace Duplicati.Library.Main.Operation long filestatsize = -1; try { filestatsize = snapshot.GetFileSize(path); } - catch { } + catch (Exception ex) { Logging.Log.WriteVerboseMessage(FILELOGTAG, "SizeReadFailed", "Failed to read length of file {0}: {1}", path, ex.Message); } IMetahash metahashandsize = m_options.StoreMetadata ? Utility.WrapMetadata(GenerateMetadata(snapshot, path, attributes), m_options) : EMPTY_METADATA; @@ -1070,7 +1066,7 @@ namespace Duplicati.Library.Main.Operation if ((oldId < 0 || m_options.DisableFiletimeCheck || timestampChanged || filesizeChanged || metadatachanged) && !tooLargeFile) { - m_result.AddVerboseMessage("Checking file for changes {0}, new: {1}, timestamp changed: {2}, size changed: {3}, metadatachanged: {4}, {5} vs {6}", path, oldId <= 0, timestampChanged, filesizeChanged, metadatachanged, lastwrite, oldModified); + Logging.Log.WriteVerboseMessage(FILELOGTAG, "CheckFileForChanges", "Checking file for changes {0}, new: {1}, timestamp changed: {2}, size changed: {3}, metadatachanged: {4}, {5} vs {6}", path, oldId <= 0, timestampChanged, filesizeChanged, metadatachanged, lastwrite, oldModified); m_result.OpenedFiles++; @@ -1085,7 +1081,7 @@ namespace Duplicati.Library.Main.Operation using (var fs = snapshot.OpenRead(path)) { try { m_result.OperationProgressUpdater.StartFile(path, fs.Length); } - catch (Exception ex) { m_result.AddWarning(string.Format("Failed to read file length for file {0}", path), ex); } + catch (Exception ex) { Logging.Log.WriteWarningMessage(FILELOGTAG, "FileLengthFailure", ex, "Failed to read file length for file {0}", path); } if ((filesize = ProcessStream(fs, hint, backend, blocklisthashes, hashcollector, false)) < 0) return false; @@ -1097,16 +1093,16 @@ namespace Duplicati.Library.Main.Operation if (oldHash != filekey) { if (oldHash == null) - m_result.AddVerboseMessage("New file {0}", path); + Logging.Log.WriteVerboseMessage(FILELOGTAG, "NewFile", "New file {0}", path); else - m_result.AddVerboseMessage("File has changed {0}", path); + Logging.Log.WriteVerboseMessage(FILELOGTAG, "ChangedFile", "File has changed {0}", path); if (oldId < 0) { m_result.AddedFiles++; m_result.SizeOfAddedFiles += filesize; if (m_options.Dryrun) - m_result.AddDryrunMessage(string.Format("Would add new file {0}, size {1}", path, Library.Utility.Utility.FormatSizeString(filesize))); + Logging.Log.WriteVerboseMessage(FILELOGTAG, "WoudlAddNewFile", "Would add new file {0}, size {1}", path, Library.Utility.Utility.FormatSizeString(filesize)); } else { @@ -1114,7 +1110,7 @@ namespace Duplicati.Library.Main.Operation m_result.SizeOfModifiedFiles += filesize; if (m_options.Dryrun) - m_result.AddDryrunMessage(string.Format("Would add changed file {0}, size {1}", path, Library.Utility.Utility.FormatSizeString(filesize))); + Logging.Log.WriteVerboseMessage(FILELOGTAG, "WoudlAddChangedFile", "Would add changed file {0}, size {1}", path, Library.Utility.Utility.FormatSizeString(filesize)); } AddFileToOutput(backend, path, filesize, lastwrite, metahashandsize, hashcollector, filekey, blocklisthashes); @@ -1122,7 +1118,7 @@ namespace Duplicati.Library.Main.Operation } else if (metadatachanged) { - m_result.AddVerboseMessage("File has only metadata changes {0}", path); + Logging.Log.WriteVerboseMessage(FILELOGTAG, "FileMetadataChanged", "File has only metadata changes {0}", path); AddFileToOutput(backend, path, filesize, lastwrite, metahashandsize, hashcollector, filekey, blocklisthashes); changed = true; } @@ -1130,17 +1126,16 @@ namespace Duplicati.Library.Main.Operation { // When we write the file to output, update the last modified time oldModified = lastwrite; - m_result.AddVerboseMessage("File has not changed {0}", path); + Logging.Log.WriteVerboseMessage(FILELOGTAG, "NoFileChanges", "File has not changed {0}", path); } - } } else { if (tooLargeFile) - m_result.AddVerboseMessage("Excluding file because the size {0} exceeds limit ({1}): {2}", Library.Utility.Utility.FormatSizeString(filestatsize), Library.Utility.Utility.FormatSizeString(m_options.SkipFilesLargerThan), path); + Logging.Log.WriteVerboseMessage(FILELOGTAG, "ExcludeLargeFile", "Excluding file because the size {0} exceeds limit ({1}): {2}", Library.Utility.Utility.FormatSizeString(filestatsize), Library.Utility.Utility.FormatSizeString(m_options.SkipFilesLargerThan), path); else - m_result.AddVerboseMessage("Skipped checking file, because timestamp was not updated {0}", path); + Logging.Log.WriteVerboseMessage(FILELOGTAG, "SkipCheckNoTimestampChange", "Skipped checking file, because timestamp was not updated {0}", path); } // If the file was not previously found, we cannot add it @@ -1156,7 +1151,7 @@ namespace Duplicati.Library.Main.Operation } catch (Exception ex) { - m_result.AddWarning(string.Format("Failed to process path: {0}", path), ex); + Logging.Log.WriteWarningMessage(FILELOGTAG, "PathProcessingFailed", ex, "Failed to process path: {0}", path); m_result.FilesWithError++; } @@ -1272,13 +1267,13 @@ namespace Duplicati.Library.Main.Operation if (m_options.Dryrun) { m_blockvolume.Close(); - m_result.AddDryrunMessage(string.Format("Would upload block volume: {0}, size: {1}", m_blockvolume.RemoteFilename, Library.Utility.Utility.FormatSizeString(new FileInfo(m_blockvolume.LocalFilename).Length))); + Logging.Log.WriteDryrunMessage(LOGTAG, "WouldUploadBlock", "Would upload block volume: {0}, size: {1}", m_blockvolume.RemoteFilename, Library.Utility.Utility.FormatSizeString(new FileInfo(m_blockvolume.LocalFilename).Length)); if (m_indexvolume != null) { UpdateIndexVolume(); m_indexvolume.FinishVolume(Library.Utility.Utility.CalculateHash(m_blockvolume.LocalFilename), new FileInfo(m_blockvolume.LocalFilename).Length); - m_result.AddDryrunMessage(string.Format("Would upload index volume: {0}, size: {1}", m_indexvolume.RemoteFilename, Library.Utility.Utility.FormatSizeString(new FileInfo(m_indexvolume.LocalFilename).Length))); + Logging.Log.WriteDryrunMessage(LOGTAG, "WouldUploadIndex", "Would upload index volume: {0}, size: {1}", m_indexvolume.RemoteFilename, Library.Utility.Utility.FormatSizeString(new FileInfo(m_indexvolume.LocalFilename).Length)); m_indexvolume.Dispose(); m_indexvolume = null; } @@ -1297,7 +1292,7 @@ namespace Duplicati.Library.Main.Operation backend.FlushDbMessages(m_database, m_transaction); m_backendLogFlushTimer = DateTime.Now.Add(FLUSH_TIMESPAN); - using(new Logging.Timer("CommitAddBlockToOutputFlush")) + using(new Logging.Timer(LOGTAG, "CommitAddBlockToOutputFlush", "CommitAddBlockToOutputFlush")) m_transaction.Commit(); m_transaction = m_database.BeginTransaction(); @@ -1305,7 +1300,7 @@ namespace Duplicati.Library.Main.Operation m_blockvolume = null; m_indexvolume = null; - using(new Logging.Timer("CommitAddBlockToOutputFlush")) + using(new Logging.Timer(LOGTAG, "CommitAddBlockToOutputFlush", "CommitAddBlockToOutputFlush")) m_transaction.Commit(); m_transaction = m_database.BeginTransaction(); @@ -1335,7 +1330,7 @@ namespace Duplicati.Library.Main.Operation // This could be done such that an extra query is made if the metadata // spans multiple blocklist hashes, as it is not expected to be common - m_result.AddWarning(string.Format("Metadata size is {0}, but the largest accepted size is {1}, recording empty metadata", meta.Blob.Length, m_maxmetadatasize), null); + Logging.Log.WriteWarningMessage(LOGTAG, "TooLargeMetadata", null, "Metadata size is {0}, but the largest accepted size is {1}, recording empty metadata", meta.Blob.Length, m_maxmetadatasize); meta = EMPTY_METADATA; } @@ -1412,14 +1407,14 @@ namespace Duplicati.Library.Main.Operation if (m_blockvolume != null) { try { m_blockvolume.Dispose(); } - catch (Exception ex) { m_result.AddError("Failed disposing block volume", ex); } + catch (Exception ex) { Logging.Log.WriteWarningMessage(LOGTAG, "BlockDisposeFailed", ex, "Failed disposing block volume", ex); } finally { m_blockvolume = null; } } if (m_indexvolume != null) { try { m_indexvolume.Dispose(); } - catch (Exception ex) { m_result.AddError("Failed disposing index volume", ex); } + catch (Exception ex) { Logging.Log.WriteWarningMessage(LOGTAG, "IndexDisposeFailed", ex, "Failed disposing index volume", ex); } finally { m_indexvolume = null; } } diff --git a/Duplicati/Library/Main/Operation/CompactHandler.cs b/Duplicati/Library/Main/Operation/CompactHandler.cs index e8a99d244..485c6e599 100644 --- a/Duplicati/Library/Main/Operation/CompactHandler.cs +++ b/Duplicati/Library/Main/Operation/CompactHandler.cs @@ -26,6 +26,10 @@ namespace Duplicati.Library.Main.Operation { internal class CompactHandler { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(); protected string m_backendurl; protected Options m_options; protected CompactResults m_result; @@ -58,7 +62,7 @@ namespace Duplicati.Library.Main.Operation if (!m_options.Dryrun) { - using(new Logging.Timer("CommitCompact")) + using(new Logging.Timer(LOGTAG, "CommitCompact", "CommitCompact")) tr.Commit(); if (changed) { @@ -86,7 +90,7 @@ namespace Duplicati.Library.Main.Operation internal bool DoCompact(LocalDeleteDatabase db, bool hasVerifiedBackend, ref System.Data.IDbTransaction transaction, BackendManager sharedBackend) { var report = db.GetCompactReport(m_options.VolumeSize, m_options.Threshold, m_options.SmallFileSize, m_options.SmallFileMaxCount, transaction); - report.ReportCompactData(m_result); + report.ReportCompactData(); if (report.ShouldReclaim || report.ShouldCompact) { @@ -177,7 +181,7 @@ namespace Duplicati.Library.Main.Operation if (!m_options.Dryrun) backend.Put(newvol, newvolindex); else - m_result.AddDryrunMessage(string.Format("Would upload generated blockset of size {0}", Library.Utility.Utility.FormatSizeString(newvol.Filesize))); + Logging.Log.WriteDryrunMessage(LOGTAG, "WouldUploadGeneratedBlockset", "Would upload generated blockset of size {0}", Library.Utility.Utility.FormatSizeString(newvol.Filesize)); newvol = new BlockVolumeWriter(m_options); @@ -217,7 +221,7 @@ namespace Duplicati.Library.Main.Operation if (!m_options.Dryrun) backend.Put(newvol, newvolindex); else - m_result.AddDryrunMessage(string.Format("Would upload generated blockset of size {0}", Library.Utility.Utility.FormatSizeString(newvol.Filesize))); + Logging.Log.WriteDryrunMessage(LOGTAG, "WouldUploadGeneratedBlockset", "Would upload generated blockset of size {0}", Library.Utility.Utility.FormatSizeString(newvol.Filesize)); } else { @@ -248,23 +252,23 @@ namespace Duplicati.Library.Main.Operation if (m_result.Dryrun) { if (downloadedVolumes.Count == 0) - m_result.AddDryrunMessage(string.Format("Would delete {0} files, which would reduce storage by {1}", m_result.DeletedFileCount, Library.Utility.Utility.FormatSizeString(m_result.DeletedFileSize))); + Logging.Log.WriteDryrunMessage(LOGTAG, "CompactResults", "Would delete {0} files, which would reduce storage by {1}", m_result.DeletedFileCount, Library.Utility.Utility.FormatSizeString(m_result.DeletedFileSize)); else - m_result.AddDryrunMessage(string.Format("Would download {0} file(s) with a total size of {1}, delete {2} file(s) with a total size of {3}, and compact to {4} file(s) with a size of {5}, which would reduce storage by {6} file(s) and {7}", + Logging.Log.WriteDryrunMessage(LOGTAG, "CompactResults", "Would download {0} file(s) with a total size of {1}, delete {2} file(s) with a total size of {3}, and compact to {4} file(s) with a size of {5}, which would reduce storage by {6} file(s) and {7}", m_result.DownloadedFileCount, Library.Utility.Utility.FormatSizeString(m_result.DownloadedFileSize), m_result.DeletedFileCount, Library.Utility.Utility.FormatSizeString(m_result.DeletedFileSize), m_result.UploadedFileCount, Library.Utility.Utility.FormatSizeString(m_result.UploadedFileSize), m_result.DeletedFileCount - m_result.UploadedFileCount, - Library.Utility.Utility.FormatSizeString(m_result.DeletedFileSize - m_result.UploadedFileSize))); + Library.Utility.Utility.FormatSizeString(m_result.DeletedFileSize - m_result.UploadedFileSize)); } else { if (m_result.DownloadedFileCount == 0) - m_result.AddMessage(string.Format("Deleted {0} files, which reduced storage by {1}", m_result.DeletedFileCount, Library.Utility.Utility.FormatSizeString(m_result.DeletedFileSize))); + Logging.Log.WriteInformationMessage(LOGTAG, "CompactResults", "Deleted {0} files, which reduced storage by {1}", m_result.DeletedFileCount, Library.Utility.Utility.FormatSizeString(m_result.DeletedFileSize)); else - m_result.AddMessage(string.Format("Downloaded {0} file(s) with a total size of {1}, deleted {2} file(s) with a total size of {3}, and compacted to {4} file(s) with a size of {5}, which reduced storage by {6} file(s) and {7}", + Logging.Log.WriteInformationMessage(LOGTAG, "CompactResults", "Downloaded {0} file(s) with a total size of {1}, deleted {2} file(s) with a total size of {3}, and compacted to {4} file(s) with a size of {5}, which reduced storage by {6} file(s) and {7}", m_result.DownloadedFileCount, Library.Utility.Utility.FormatSizeString(downloadSize), m_result.DeletedFileCount, @@ -272,7 +276,7 @@ namespace Duplicati.Library.Main.Operation m_result.UploadedFileCount, Library.Utility.Utility.FormatSizeString(m_result.UploadedFileSize), m_result.DeletedFileCount - m_result.UploadedFileCount, - Library.Utility.Utility.FormatSizeString(m_result.DeletedFileSize - m_result.UploadedFileSize))); + Library.Utility.Utility.FormatSizeString(m_result.DeletedFileSize - m_result.UploadedFileSize)); } backend.WaitForComplete(db, transaction); @@ -314,7 +318,7 @@ namespace Duplicati.Library.Main.Operation if (!m_options.Dryrun) backend.Delete(f.Name, f.Size); else - m_result.AddDryrunMessage(string.Format("Would delete remote file: {0}, size: {1}", f.Name, Library.Utility.Utility.FormatSizeString(f.Size))); + Logging.Log.WriteDryrunMessage(LOGTAG, "WouldDeleteRemoteFile", "Would delete remote file: {0}, size: {1}", f.Name, Library.Utility.Utility.FormatSizeString(f.Size)); yield return new KeyValuePair(f.Name, f.Size); } diff --git a/Duplicati/Library/Main/Operation/CreateBugReportHandler.cs b/Duplicati/Library/Main/Operation/CreateBugReportHandler.cs index 5586f99df..4f88627e8 100644 --- a/Duplicati/Library/Main/Operation/CreateBugReportHandler.cs +++ b/Duplicati/Library/Main/Operation/CreateBugReportHandler.cs @@ -24,6 +24,10 @@ namespace Duplicati.Library.Main.Operation { internal class CreateBugReportHandler { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(); private string m_targetpath; private Options m_options; private CreateLogDatabaseResults m_result; @@ -44,15 +48,15 @@ namespace Duplicati.Library.Main.Operation m_targetpath = m_targetpath + "." + module; if (System.IO.File.Exists(m_targetpath)) - throw new UserInformationException(string.Format("Output file already exists, not overwriting: {0}", m_targetpath)); + throw new UserInformationException(string.Format("Output file already exists, not overwriting: {0}", m_targetpath), "BugReportTargetAlreadyExists"); if (!System.IO.File.Exists(m_options.Dbpath)) - throw new UserInformationException(string.Format("Database file does not exist: {0}", m_options.Dbpath)); + throw new UserInformationException(string.Format("Database file does not exist: {0}", m_options.Dbpath), "BugReportSourceDatabaseNotFound"); m_result.OperationProgressUpdater.UpdatePhase(OperationPhase.BugReport_Running); m_result.OperationProgressUpdater.UpdateProgress(0); - m_result.AddMessage("Scrubbing filenames from database, this may take a while, please wait"); + Logging.Log.WriteInformationMessage(LOGTAG, "ScrubbingFilenames", "Scrubbing filenames from database, this may take a while, please wait"); using (var tmp = new Library.Utility.TempFile()) { diff --git a/Duplicati/Library/Main/Operation/DeleteHandler.cs b/Duplicati/Library/Main/Operation/DeleteHandler.cs index 84539b4f6..dacc9b5fd 100644 --- a/Duplicati/Library/Main/Operation/DeleteHandler.cs +++ b/Duplicati/Library/Main/Operation/DeleteHandler.cs @@ -25,6 +25,15 @@ namespace Duplicati.Library.Main.Operation { internal class DeleteHandler { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(); + /// + /// The tag used for logging retention policy messages + /// + private static readonly string LOGTAG_RETENTION = LOGTAG + ":RetentionPolicy"; + private DeleteResults m_result; protected string m_backendurl; protected Options m_options; @@ -39,7 +48,7 @@ namespace Duplicati.Library.Main.Operation public void Run() { if (!System.IO.File.Exists(m_options.Dbpath)) - throw new UserInformationException(string.Format("Database file does not exist: {0}", m_options.Dbpath)); + throw new UserInformationException(string.Format("Database file does not exist: {0}", m_options.Dbpath), "DatabaseFileMissing"); using(var db = new Database.LocalDeleteDatabase(m_options.Dbpath, "Delete")) { @@ -54,7 +63,7 @@ namespace Duplicati.Library.Main.Operation if (!m_options.Dryrun) { - using(new Logging.Timer("CommitDelete")) + using(new Logging.Timer(LOGTAG, "CommitDelete", "CommitDelete")) tr.Commit(); db.WriteResults(); @@ -89,12 +98,12 @@ namespace Duplicati.Library.Main.Operation if (!m_options.AllowFullRemoval && sets.Length == toDelete.Length) { - m_result.AddMessage(string.Format("Preventing removal of last fileset, use --{0} to allow removal ...", "allow-full-removal")); + Logging.Log.WriteInformationMessage(LOGTAG, "PreventingLastFilesetRemoval", "Preventing removal of last fileset, use --{0} to allow removal ...", "allow-full-removal"); toDelete = toDelete.Skip(1).ToArray(); } if (toDelete != null && toDelete.Length > 0) - m_result.AddMessage(string.Format("Deleting {0} remote fileset(s) ...", toDelete.Length)); + Logging.Log.WriteInformationMessage(LOGTAG, "DeleteRemoteFileset", "Deleting {0} remote fileset(s) ...", toDelete.Length); var lst = db.DropFilesetsFromTable(toDelete, transaction).ToArray(); foreach(var f in lst) @@ -117,7 +126,7 @@ namespace Duplicati.Library.Main.Operation if (!m_options.Dryrun) backend.Delete(f.Key, f.Value); else - m_result.AddDryrunMessage(string.Format("Would delete remote fileset: {0}", f.Key)); + Logging.Log.WriteDryrunMessage(LOGTAG, "WouldDeleteRemoteFileset", "Would delete remote fileset: {0}", f.Key); } if (sharedManager == null) @@ -129,20 +138,20 @@ namespace Duplicati.Library.Main.Operation if (!m_options.Dryrun) { if (count == 0) - m_result.AddMessage("No remote filesets were deleted"); + Logging.Log.WriteInformationMessage(LOGTAG, "DeleteResults", "No remote filesets were deleted"); else - m_result.AddMessage(string.Format("Deleted {0} remote fileset(s)", count)); + Logging.Log.WriteInformationMessage(LOGTAG, "DeleteResults", "Deleted {0} remote fileset(s)", count); } else { if (count == 0) - m_result.AddDryrunMessage("No remote filesets would be deleted"); + Logging.Log.WriteDryrunMessage(LOGTAG, "WouldDeleteResults", "No remote filesets would be deleted"); else - m_result.AddDryrunMessage(string.Format("{0} remote fileset(s) would be deleted", count)); + Logging.Log.WriteDryrunMessage(LOGTAG, "WouldDeleteResults", "{0} remote fileset(s) would be deleted", count); if (count > 0 && m_options.Dryrun) - m_result.AddDryrunMessage("Remove --dry-run to actually delete files"); + Logging.Log.WriteDryrunMessage(LOGTAG, "WouldDeleteHelp", "Remove --dry-run to actually delete files"); } if (!m_options.NoAutoCompact && (forceCompact || (toDelete != null && toDelete.Length > 0))) @@ -214,13 +223,13 @@ namespace Duplicati.Library.Main.Operation private List ApplyRetentionPolicy(DateTime[] backups) { // Any work to do? - Dictionary retentionPolicyOptionValue = m_options.RetentionPolicy; - if (retentionPolicyOptionValue.Count == 0 || backups.Length == 0) + var retentionPolicyOptionValues = m_options.RetentionPolicy; + if (retentionPolicyOptionValues.Count == 0 || backups.Length == 0) { return new List(); // don't delete any backups } - Logging.Log.WriteMessage("[Retention Policy]: Start checking if backups can be removed", Logging.LogMessageType.Information); + Logging.Log.WriteInformationMessage(LOGTAG_RETENTION, "StartCheck", "Start checking if backups can be removed"); // Work with a copy to not modify the enumeration that the caller passed List clonedBackupList = new List(backups); @@ -234,25 +243,23 @@ namespace Duplicati.Library.Main.Operation clonedBackupList.RemoveAt(0); var deleteMostRecentBackup = m_options.AllowFullRemoval; - Logging.Log.WriteMessage(string.Format("[Retention Policy]: Time frames and intervals pairs: {0}", - string.Join(", ", retentionPolicyOptionValue.Select(x => x.Key + " / " + x.Value))), Logging.LogMessageType.Information); + Logging.Log.WriteInformationMessage(LOGTAG_RETENTION, "FramesAndIntervals", "Time frames and intervals pairs: {0}", + string.Join(", ", retentionPolicyOptionValues)); - Logging.Log.WriteMessage(string.Format("[Retention Policy]: Backups to consider: {0}", - string.Join(", ", clonedBackupList)), Logging.LogMessageType.Information); + Logging.Log.WriteInformationMessage(LOGTAG_RETENTION, "BackupList", "Backups to consider: {0}", + string.Join(", ", clonedBackupList)); // Collect all potential backups in each time frame and thin out according to the specified interval, // starting with the oldest backup in that time frame. // The order in which the time frames values are checked has to be from the smallest to the largest. List backupsToDelete = new List(); var now = DateTime.Now; - foreach (var singleRetentionPolicyOptionValue in retentionPolicyOptionValue.OrderBy(x => x.Key)) + foreach (var singleRetentionPolicyOptionValue in retentionPolicyOptionValues.OrderBy(x => x.Timeframe)) { - var period = singleRetentionPolicyOptionValue.Key; - var interval = singleRetentionPolicyOptionValue.Value; + // The timeframe in the retention policy option is only a timespan which has to be applied to the current DateTime to get the actual lower bound + DateTime timeFrame = (singleRetentionPolicyOptionValue.IsUnlimtedTimeframe()) ? DateTime.MinValue : (now - singleRetentionPolicyOptionValue.Timeframe); - DateTime timeFrame = (period > TimeSpan.Zero) ? (now - period) : DateTime.MinValue; // period equal or below 0 means "biggest time frame possible" - - Logging.Log.WriteMessage(string.Format("[Retention Policy]: Next time frame and interval pair: {0} / {1}", timeFrame, interval), Logging.LogMessageType.Profiling); + Logging.Log.WriteProfilingMessage(LOGTAG_RETENTION, "NextTimeAndFrame", "Next time frame and interval pair: {0}", singleRetentionPolicyOptionValue.ToString()); List backupsInTimeFrame = new List(); while (clonedBackupList.Count > 0 && clonedBackupList[0] >= timeFrame) @@ -261,8 +268,8 @@ namespace Duplicati.Library.Main.Operation clonedBackupList.RemoveAt(0); // remove from here to not handle the same backup in two time frames } - Logging.Log.WriteMessage(string.Format("[Retention Policy]: Backups in this time frame: {0}", - string.Join(", ", backupsInTimeFrame)), Logging.LogMessageType.Profiling); + Logging.Log.WriteProfilingMessage(LOGTAG_RETENTION, "BackupsInFrame", "Backups in this time frame: {0}", + string.Join(", ", backupsInTimeFrame)); // Run through backups in this time frame DateTime? lastKept = null; @@ -271,14 +278,14 @@ namespace Duplicati.Library.Main.Operation // Keep this backup if // - no backup has yet been added to the time frame (keeps at least the oldest backup in a time frame) // - difference between last added backup and this backup is bigger than the specified interval - if (lastKept == null || (backup - lastKept.Value) >= interval) + if (lastKept == null || singleRetentionPolicyOptionValue.IsKeepAllVersions() || (backup - lastKept.Value) >= singleRetentionPolicyOptionValue.Interval) { - Logging.Log.WriteMessage(string.Format("[Retention Policy]: Keeping backup: {0}", backup), Logging.LogMessageType.Profiling); + Logging.Log.WriteProfilingMessage(LOGTAG_RETENTION, "KeepBackups", string.Format("Keeping backup: {0}", backup), Logging.LogMessageType.Profiling); lastKept = backup; } else { - Logging.Log.WriteMessage(string.Format("[Retention Policy]: Deleting backup: {0}", backup), Logging.LogMessageType.Profiling); + Logging.Log.WriteProfilingMessage(LOGTAG_RETENTION, "DeletingBackups", "Deleting backup: {0}", backup); backupsToDelete.Add(backup); } } @@ -289,19 +296,19 @@ namespace Duplicati.Library.Main.Operation // Delete all remaining backups backupsToDelete.AddRange(clonedBackupList); - Logging.Log.WriteMessage(string.Format("[Retention Policy]: Backups outside of all time frames and thus getting deleted: {0}", - string.Join(", ", clonedBackupList)), Logging.LogMessageType.Information); + Logging.Log.WriteInformationMessage(LOGTAG_RETENTION, "BackupsToDelete", "Backups outside of all time frames and thus getting deleted: {0}", + string.Join(", ", clonedBackupList)); // Delete most recent backup if allow-full-removal is set and the most current backup is outside of any time frame if (deleteMostRecentBackup) { backupsToDelete.Add(mostRecentBackup); - Logging.Log.WriteMessage(string.Format("[Retention Policy]: Deleting most recent backup: {0}", - mostRecentBackup), Logging.LogMessageType.Information); + Logging.Log.WriteInformationMessage(LOGTAG_RETENTION, "DeleteMostRecent", "Deleting most recent backup: {0}", + mostRecentBackup); } - Logging.Log.WriteMessage(string.Format("[Retention Policy]: All backups to delete: {0}", - string.Join(", ", backupsToDelete.OrderByDescending(x => x))), Logging.LogMessageType.Information); + Logging.Log.WriteInformationMessage(LOGTAG_RETENTION, "AllBackupsToDelete", "All backups to delete: {0}", + string.Join(", ", backupsToDelete.OrderByDescending(x => x))); return backupsToDelete; } diff --git a/Duplicati/Library/Main/Operation/FilelistProcessor.cs b/Duplicati/Library/Main/Operation/FilelistProcessor.cs index 3a8d8e09b..c364362d1 100644 --- a/Duplicati/Library/Main/Operation/FilelistProcessor.cs +++ b/Duplicati/Library/Main/Operation/FilelistProcessor.cs @@ -24,6 +24,11 @@ namespace Duplicati.Library.Main.Operation { internal static class FilelistProcessor { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(typeof(FilelistProcessor)); + /// /// Helper method that verifies uploaded volumes and updates their state in the database. /// Throws an error if there are issues with the remote storage @@ -46,20 +51,20 @@ namespace Duplicati.Library.Main.Operation case RemoteVolumeState.Temporary: case RemoteVolumeState.Deleting: case RemoteVolumeState.Uploading: - log.AddMessage(string.Format("removing remote file listed as {0}: {1}", i.State, i.Name)); + Logging.Log.WriteInformationMessage(LOGTAG, "RemovingStaleFile", "Removing remote file listed as {0}: {1}", i.State, i.Name); try { backend.Delete(i.Name, i.Size, true); } catch (Exception ex) { - log.AddWarning(string.Format("Failed to erase file {0}, treating as deleted: {1}", i.Name, ex.Message), ex); + Logging.Log.WriteWarningMessage(LOGTAG, "DeleteFileFailed", ex, "Failed to erase file {0}, treating as deleted: {1}", i.Name, ex.Message); } break; default: - log.AddWarning(string.Format("unknown state for remote file listed as {0}: {1}", i.State, i.Name), null); + Logging.Log.WriteWarningMessage(LOGTAG, "UnknownFileState", null, "Unknown state for remote file listed as {0}: {1}", i.State, i.Name); break; } @@ -84,21 +89,21 @@ namespace Duplicati.Library.Main.Operation foreach(var n in tp.ExtraVolumes) { - log.AddWarning(string.Format("Extra unknown file: {0}", n.File.Name), null); + Logging.Log.WriteWarningMessage(LOGTAG, "ExtraUnknownFile", null, "Extra unknown file: {0}", n.File.Name); extraCount++; } foreach(var n in tp.MissingVolumes) { - log.AddWarning(string.Format("Missing file: {0}", n.Name), null); + Logging.Log.WriteWarningMessage(LOGTAG, "MissingFile", null, "Missing file: {0}", n.Name); missingCount++; } if (extraCount > 0) { var s = string.Format("Found {0} remote files that are not recorded in local storage, please run repair", extraCount); - log.AddError(s, null); - throw new Duplicati.Library.Interface.UserInformationException(s); + Logging.Log.WriteErrorMessage(LOGTAG, "ExtraRemoteFiles", null, s); + throw new Duplicati.Library.Interface.UserInformationException(s, "ExtraRemoteFiles"); } ISet doubles; @@ -107,8 +112,8 @@ namespace Duplicati.Library.Main.Operation if (doubles.Count > 0) { var s = string.Format("Found remote files reported as duplicates, either the backend module is broken or you need to manually remove the extra copies.\nThe following files were found multiple times: {0}", string.Join(", ", doubles)); - log.AddError(s, null); - throw new Duplicati.Library.Interface.UserInformationException(s); + Logging.Log.WriteErrorMessage(LOGTAG, "DuplicateRemoteFiles", null, s); + throw new Duplicati.Library.Interface.UserInformationException(s, "DuplicateRemoteFiles"); } if (missingCount > 0) @@ -119,8 +124,8 @@ namespace Duplicati.Library.Main.Operation else s = string.Format("Found {0} files that are missing from the remote storage, please run repair", missingCount); - log.AddError(s, null); - throw new Duplicati.Library.Interface.UserInformationException(s); + Logging.Log.WriteErrorMessage(LOGTAG, "MissingRemoteFiles", null, s); + throw new Duplicati.Library.Interface.UserInformationException(s, "MissingRemoteFiles"); } } @@ -166,7 +171,7 @@ namespace Duplicati.Library.Main.Operation if (options.Dryrun) { - result.AddDryrunMessage(string.Format("Would upload verification file: {0}, size: {1}", remotename, Library.Utility.Utility.FormatSizeString(new System.IO.FileInfo(tempfile).Length))); + Logging.Log.WriteDryrunMessage(LOGTAG, "WouldUploadVerificationFile", "Would upload verification file: {0}, size: {1}", remotename, Library.Utility.Utility.FormatSizeString(new System.IO.FileInfo(tempfile).Length)); } else { @@ -235,7 +240,7 @@ namespace Duplicati.Library.Main.Operation if (!log.ReportedQuotaError && quota.FreeQuotaSpace == 0) { log.ReportedQuotaError = true; - log.AddError(string.Format("Backend quota has been exceeded: Using {0} of {1} ({2} available)", Library.Utility.Utility.FormatSizeString(knownFileSize), Library.Utility.Utility.FormatSizeString(quota.TotalQuotaSpace), Library.Utility.Utility.FormatSizeString(quota.FreeQuotaSpace)), null); + Logging.Log.WriteErrorMessage(LOGTAG, "BackendQuotaExceeded", null, "Backend quota has been exceeded: Using {0} of {1} ({2} available)", Library.Utility.Utility.FormatSizeString(knownFileSize), Library.Utility.Utility.FormatSizeString(quota.TotalQuotaSpace), Library.Utility.Utility.FormatSizeString(quota.FreeQuotaSpace)); } else if (!log.ReportedQuotaWarning && !log.ReportedQuotaError && quota.FreeQuotaSpace >= 0) // Negative value means the backend didn't return the quota info { @@ -244,7 +249,7 @@ namespace Duplicati.Library.Main.Operation if (quota.FreeQuotaSpace < warningThreshold * knownFileSize) { log.ReportedQuotaWarning = true; - log.AddWarning(string.Format("Backend quota is close to being exceeded: Using {0} of {1} ({2} available)", Library.Utility.Utility.FormatSizeString(knownFileSize), Library.Utility.Utility.FormatSizeString(quota.TotalQuotaSpace), Library.Utility.Utility.FormatSizeString(quota.FreeQuotaSpace)), null); + Logging.Log.WriteWarningMessage(LOGTAG, "BackendQuotaNear" , null, "Backend quota is close to being exceeded: Using {0} of {1} ({2} available)", Library.Utility.Utility.FormatSizeString(knownFileSize), Library.Utility.Utility.FormatSizeString(quota.TotalQuotaSpace), Library.Utility.Utility.FormatSizeString(quota.FreeQuotaSpace)); } } } @@ -280,7 +285,7 @@ namespace Duplicati.Library.Main.Operation { case RemoteVolumeState.Deleted: if (remoteFound) - log.AddMessage(string.Format("ignoring remote file listed as {0}: {1}", i.State, i.Name)); + Logging.Log.WriteInformationMessage(LOGTAG, "IgnoreRemoteDeletedFile", "ignoring remote file listed as {0}: {1}", i.State, i.Name); break; @@ -288,24 +293,24 @@ namespace Duplicati.Library.Main.Operation case RemoteVolumeState.Deleting: if (remoteFound) { - log.AddMessage(string.Format("removing remote file listed as {0}: {1}", i.State, i.Name)); + Logging.Log.WriteInformationMessage(LOGTAG, "RemoveUnwantedRemoteFile", "removing remote file listed as {0}: {1}", i.State, i.Name); backend.Delete(i.Name, i.Size, true); } else { if (i.deleteGracePeriod > DateTime.UtcNow) { - log.AddMessage(string.Format("keeping delete request for {0} until {1}", i.Name, i.deleteGracePeriod.ToLocalTime())); + Logging.Log.WriteInformationMessage(LOGTAG, "KeepDeleteRequest", "keeping delete request for {0} until {1}", i.Name, i.deleteGracePeriod.ToLocalTime()); } else { if (string.Equals(i.Name, protectedfile) && i.State == RemoteVolumeState.Temporary) { - log.AddMessage(string.Format("keeping protected incomplete remote file listed as {0}: {1}", i.State, i.Name)); + Logging.Log.WriteInformationMessage(LOGTAG, "KeepIncompleteFile", "keeping protected incomplete remote file listed as {0}: {1}", i.State, i.Name); } else { - log.AddMessage(string.Format("removing file listed as {0}: {1}", i.State, i.Name)); + Logging.Log.WriteInformationMessage(LOGTAG, "RemoteUnwantedMissingFile", "removing file listed as {0}: {1}", i.State, i.Name); cleanupRemovedRemoteVolumes.Add(i.Name); } } @@ -314,7 +319,7 @@ namespace Duplicati.Library.Main.Operation case RemoteVolumeState.Uploading: if (remoteFound && correctSize && r.File.Size >= 0) { - log.AddMessage(string.Format("promoting uploaded complete file from {0} to {2}: {1}", i.State, i.Name, RemoteVolumeState.Uploaded)); + Logging.Log.WriteInformationMessage(LOGTAG, "PromotingCompleteFile", "promoting uploaded complete file from {0} to {2}: {1}", i.State, i.Name, RemoteVolumeState.Uploaded); database.UpdateRemoteVolume(i.Name, RemoteVolumeState.Uploaded, i.Size, i.Hash); } else if (!remoteFound) @@ -322,12 +327,12 @@ namespace Duplicati.Library.Main.Operation if (string.Equals(i.Name, protectedfile)) { - log.AddMessage(string.Format("keeping protected incomplete remote file listed as {0}: {1}", i.State, i.Name)); + Logging.Log.WriteInformationMessage(LOGTAG, "KeepIncompleteFile", "keeping protected incomplete remote file listed as {0}: {1}", i.State, i.Name); database.UpdateRemoteVolume(i.Name, RemoteVolumeState.Temporary, i.Size, i.Hash, false, new TimeSpan(0), null); } else { - log.AddMessage(string.Format("scheduling missing file for deletion, currently listed as {0}: {1}", i.State, i.Name)); + Logging.Log.WriteInformationMessage(LOGTAG, "SchedulingMissingFileForDelete", "scheduling missing file for deletion, currently listed as {0}: {1}", i.State, i.Name); cleanupRemovedRemoteVolumes.Add(i.Name); database.UpdateRemoteVolume(i.Name, RemoteVolumeState.Deleting, i.Size, i.Hash, false, TimeSpan.FromHours(2), null); } @@ -336,11 +341,11 @@ namespace Duplicati.Library.Main.Operation { if (string.Equals(i.Name, protectedfile)) { - log.AddMessage(string.Format("keeping protected incomplete remote file listed as {0}: {1}", i.State, i.Name)); + Logging.Log.WriteInformationMessage(LOGTAG, "KeepIncompleteFile", "keeping protected incomplete remote file listed as {0}: {1}", i.State, i.Name); } else { - log.AddMessage(string.Format("removing incomplete remote file listed as {0}: {1}", i.State, i.Name)); + Logging.Log.WriteInformationMessage(LOGTAG, "Remove incomplete file", "removing incomplete remote file listed as {0}: {1}", i.State, i.Name); backend.Delete(i.Name, i.Size, true); } } @@ -365,7 +370,7 @@ namespace Duplicati.Library.Main.Operation break; default: - log.AddWarning(string.Format("unknown state for remote file listed as {0}: {1}", i.State, i.Name), null); + Logging.Log.WriteWarningMessage(LOGTAG, "UnknownFileState", null, "unknown state for remote file listed as {0}: {1}", i.State, i.Name); break; } @@ -376,7 +381,7 @@ namespace Duplicati.Library.Main.Operation database.RemoveRemoteVolumes(cleanupRemovedRemoteVolumes, null); foreach(var i in missingHash) - log.AddWarning(string.Format("remote file {1} is listed as {0} with size {2} but should be {3}, please verify the sha256 hash \"{4}\"", i.Item2.State, i.Item2.Name, i.Item1, i.Item2.Size, i.Item2.Hash), null); + Logging.Log.WriteWarningMessage(LOGTAG, "MissingRemoteHash", null, "remote file {1} is listed as {0} with size {2} but should be {3}, please verify the sha256 hash \"{4}\"", i.Item2.State, i.Item2.Name, i.Item1, i.Item2.Size, i.Item2.Hash); return new RemoteAnalysisResult() { ParsedVolumes = remotelist, diff --git a/Duplicati/Library/Main/Operation/ListAffected.cs b/Duplicati/Library/Main/Operation/ListAffected.cs index aee7c2bec..f5bc643aa 100644 --- a/Duplicati/Library/Main/Operation/ListAffected.cs +++ b/Duplicati/Library/Main/Operation/ListAffected.cs @@ -36,7 +36,7 @@ namespace Duplicati.Library.Main.Operation public void Run(List args, Action callback = null) { if (!System.IO.File.Exists(m_options.Dbpath)) - throw new UserInformationException(string.Format("Database file does not exist: {0}", m_options.Dbpath)); + throw new UserInformationException(string.Format("Database file does not exist: {0}", m_options.Dbpath), "DatabaseDoesNotExist"); using(var db = new Database.LocalListAffectedDatabase(m_options.Dbpath)) { diff --git a/Duplicati/Library/Main/Operation/ListBrokenFilesHandler.cs b/Duplicati/Library/Main/Operation/ListBrokenFilesHandler.cs index 1083f6165..63b27be3f 100644 --- a/Duplicati/Library/Main/Operation/ListBrokenFilesHandler.cs +++ b/Duplicati/Library/Main/Operation/ListBrokenFilesHandler.cs @@ -24,6 +24,10 @@ namespace Duplicati.Library.Main.Operation { internal class ListBrokenFilesHandler { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(typeof(ListBrokenFilesHandler)); protected string m_backendurl; protected Options m_options; protected ListBrokenFilesResults m_result; @@ -38,7 +42,7 @@ namespace Duplicati.Library.Main.Operation public void Run(Library.Utility.IFilter filter, Func callbackhandler = null) { if (!System.IO.File.Exists(m_options.Dbpath)) - throw new UserInformationException(string.Format("Database file does not exist: {0}", m_options.Dbpath)); + throw new UserInformationException(string.Format("Database file does not exist: {0}", m_options.Dbpath), "DatabaseDoesNotExist"); using (var db = new Database.LocalListBrokenFilesDatabase(m_options.Dbpath)) using (var tr = db.BeginTransaction()) @@ -53,20 +57,20 @@ namespace Duplicati.Library.Main.Operation if (brokensets.Length == 0) { if (db.RepairInProgress) - throw new UserInformationException("Cannot continue because the database is marked as being under repair, but does not have broken files."); + throw new UserInformationException("Cannot continue because the database is marked as being under repair, but does not have broken files.", "CannotListOnDatabaseInRepair"); - result.AddMessage("No broken filesets found in database, checking for missing remote files"); + Logging.Log.WriteInformationMessage(LOGTAG, "NoBrokenFilesetsInDatabase", "No broken filesets found in database, checking for missing remote files"); using (var backend = new BackendManager(backendurl, options, result.BackendWriter, db)) { var remotestate = FilelistProcessor.RemoteListAnalysis(backend, options, db, result.BackendWriter, null); if (!remotestate.ParsedVolumes.Any()) - throw new UserInformationException("No remote volumes were found, refusing purge"); + throw new UserInformationException("No remote volumes were found, refusing purge", "CannotPurgeWithNoRemoteVolumes"); missing = remotestate.MissingVolumes.ToList(); if (missing.Count == 0) { - result.AddMessage("Skipping operation because no files were found to be missing, and no filesets were recorded as broken."); + Logging.Log.WriteInformationMessage(LOGTAG, "NoMissingFilesFound", "Skipping operation because no files were found to be missing, and no filesets were recorded as broken."); return null; } @@ -74,7 +78,7 @@ namespace Duplicati.Library.Main.Operation foreach (var f in missing) db.UpdateRemoteVolume(f.Name, RemoteVolumeState.Deleting, f.Size, f.Hash, transaction); - result.AddMessage(string.Format("Marked {0} remote files for deletion", missing.Count)); + Logging.Log.WriteInformationMessage(LOGTAG, "MarkedRemoteFilesForDeletion", "Marked {0} remote files for deletion", missing.Count); // Drop all content from tables db.RemoveMissingBlocks(missing.Select(x => x.Name), transaction); @@ -88,10 +92,10 @@ namespace Duplicati.Library.Main.Operation private void DoRun(Database.LocalListBrokenFilesDatabase db, System.Data.IDbTransaction transaction, Library.Utility.IFilter filter, Func callbackhandler) { if (filter != null && !filter.Empty) - throw new UserInformationException("Filters are not supported for this operation"); + throw new UserInformationException("Filters are not supported for this operation", "FiltersAreNotSupportedForListBrokenFiles"); if (db.PartiallyRecreated) - throw new UserInformationException("The command does not work on partially recreated databases"); + throw new UserInformationException("The command does not work on partially recreated databases", "ListBrokenFilesDoesNotWorkOnPartialDatabase"); List missing; var brokensets = GetBrokenFilesetsFromRemote(m_backendurl, m_result, db, transaction, m_options, out missing); @@ -101,7 +105,7 @@ namespace Duplicati.Library.Main.Operation if (brokensets.Length == 0) { m_result.BrokenFiles = new Tuple>>[0]; - m_result.AddMessage("No broken filesets found"); + Logging.Log.WriteInformationMessage(LOGTAG, "NoMissingFilesFound", "No broken filesets found"); return; } diff --git a/Duplicati/Library/Main/Operation/ListChangesHandler.cs b/Duplicati/Library/Main/Operation/ListChangesHandler.cs index 13bbb3f9c..66b5d50ea 100644 --- a/Duplicati/Library/Main/Operation/ListChangesHandler.cs +++ b/Duplicati/Library/Main/Operation/ListChangesHandler.cs @@ -24,6 +24,11 @@ namespace Duplicati.Library.Main.Operation { internal class ListChangesHandler { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(typeof(ListChangesHandler)); + private string m_backendurl; private Options m_options; private ListChangesResults m_result; @@ -80,7 +85,7 @@ namespace Duplicati.Library.Main.Operation { var dbtimes = db.FilesetTimes.ToList(); if (dbtimes.Count < 2) - throw new UserInformationException(string.Format("Need at least two backups to show differences, database contains {0} backups", dbtimes.Count)); + throw new UserInformationException(string.Format("Need at least two backups to show differences, database contains {0} backups", dbtimes.Count), "NeedTwoBackupsToStartDiff"); long baseVersionId; long compareVersionId; @@ -95,7 +100,7 @@ namespace Duplicati.Library.Main.Operation } else { - m_result.AddMessage("No local database, accessing remote store"); + Logging.Log.WriteInformationMessage(LOGTAG, "NoLocalDatabase", "No local database, accessing remote store"); var parsedlist = (from n in backend.List() let p = Volumes.VolumeBase.ParseFilename(n) @@ -105,7 +110,7 @@ namespace Duplicati.Library.Main.Operation var numberedList = parsedlist.Zip(Enumerable.Range(0, parsedlist.Length), (a, b) => new Tuple(b, a.Time, a)).ToList(); if (numberedList.Count < 2) - throw new UserInformationException(string.Format("Need at least two backups to show differences, database contains {0} backups", numberedList.Count)); + throw new UserInformationException(string.Format("Need at least two backups to show differences, database contains {0} backups", numberedList.Count), "NeedTwoBackupsToStartDiff"); Volumes.IParsedVolume baseFile; Volumes.IParsedVolume compareFile; @@ -150,7 +155,7 @@ namespace Duplicati.Library.Main.Operation var changes = storageKeeper.CreateChangeCountReport(); var sizes = storageKeeper.CreateChangeSizeReport(); - var lst = (m_options.Verbose || m_options.FullResult || callback != null) ? + var lst = (m_options.FullResult || callback != null) ? (from n in storageKeeper.CreateChangedFileReport() select n) : null; diff --git a/Duplicati/Library/Main/Operation/ListFilesHandler.cs b/Duplicati/Library/Main/Operation/ListFilesHandler.cs index 78524ccaf..10e91fba6 100644 --- a/Duplicati/Library/Main/Operation/ListFilesHandler.cs +++ b/Duplicati/Library/Main/Operation/ListFilesHandler.cs @@ -8,6 +8,11 @@ namespace Duplicati.Library.Main.Operation { internal class ListFilesHandler { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(); + private string m_backendurl; private Options m_options; private ListResults m_result; @@ -67,13 +72,13 @@ namespace Duplicati.Library.Main.Operation } } - m_result.AddMessage("No local database, accessing remote store"); + Logging.Log.WriteInformationMessage(LOGTAG, "NoLocalDatabase", "No local database, accessing remote store"); //TODO: Add prefix and foldercontents if (m_options.ListFolderContents) - throw new UserInformationException("Listing folder contents is not supported without a local database, consider using the \"repair\" option to rebuild the database."); + throw new UserInformationException("Listing folder contents is not supported without a local database, consider using the \"repair\" option to rebuild the database.", "FolderContentListingRequiresLocalDatabase"); else if (m_options.ListPrefixOnly) - throw new UserInformationException("Listing prefixes is not supported without a local database, consider using the \"repair\" option to rebuild the database."); + throw new UserInformationException("Listing prefixes is not supported without a local database, consider using the \"repair\" option to rebuild the database.", "PrefixListingRequiresLocalDatabase"); // Otherwise, grab info from remote location using (var tmpdb = new Library.Utility.TempFile()) @@ -84,7 +89,7 @@ namespace Duplicati.Library.Main.Operation var filteredList = ParseAndFilterFilesets(backend.List(), m_options); if (filteredList.Count == 0) - throw new UserInformationException("No filesets found on remote target"); + throw new UserInformationException("No filesets found on remote target", "EmptyRemoteFolder"); var numberSeq = CreateResultSequence(filteredList); if (filter.Empty) diff --git a/Duplicati/Library/Main/Operation/PurgeBrokenFilesHandler.cs b/Duplicati/Library/Main/Operation/PurgeBrokenFilesHandler.cs index 6c2755610..4fe806c10 100644 --- a/Duplicati/Library/Main/Operation/PurgeBrokenFilesHandler.cs +++ b/Duplicati/Library/Main/Operation/PurgeBrokenFilesHandler.cs @@ -23,6 +23,10 @@ namespace Duplicati.Library.Main.Operation { internal class PurgeBrokenFilesHandler { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(typeof(PurgeBrokenFilesHandler)); protected string m_backendurl; protected Options m_options; protected PurgeBrokenFilesResults m_result; @@ -37,10 +41,10 @@ namespace Duplicati.Library.Main.Operation public void Run(Library.Utility.IFilter filter) { if (!System.IO.File.Exists(m_options.Dbpath)) - throw new UserInformationException(string.Format("Database file does not exist: {0}", m_options.Dbpath)); + throw new UserInformationException(string.Format("Database file does not exist: {0}", m_options.Dbpath), "DatabaseDoesNotExist"); if (filter != null && !filter.Empty) - throw new UserInformationException("Filters are not supported for this operation"); + throw new UserInformationException("Filters are not supported for this operation", "FiltersNotAllowedOnPurgeBrokenFiles"); List missing = null; @@ -48,7 +52,7 @@ namespace Duplicati.Library.Main.Operation using (var tr = db.BeginTransaction()) { if (db.PartiallyRecreated) - throw new UserInformationException("The command does not work on partially recreated databases"); + throw new UserInformationException("The command does not work on partially recreated databases", "CannotPurgeOnPartialDatabase"); var sets = ListBrokenFilesHandler.GetBrokenFilesetsFromRemote(m_backendurl, m_result, db, tr, m_options, out missing); if (sets == null) @@ -57,14 +61,14 @@ namespace Duplicati.Library.Main.Operation if (sets.Length == 0) { if (missing == null) - m_result.AddMessage("Found no broken filesets"); + Logging.Log.WriteInformationMessage(LOGTAG, "NoBrokenFilesets", "Found no broken filesets"); else if (missing.Count == 0) - m_result.AddMessage("Found no broken filesets and no missing remote files"); + Logging.Log.WriteInformationMessage(LOGTAG, "NoBrokenFilesetsOrMissingFiles", "Found no broken filesets and no missing remote files"); else - throw new UserInformationException(string.Format("Found no broken filesets, but {0} missing remote files", sets.Length)); + throw new UserInformationException(string.Format("Found no broken filesets, but {0} missing remote files", sets.Length), "NoBrokenSetsButMissingRemoteFiles"); } - m_result.AddMessage(string.Format("Found {0} broken filesets with {1} affected files, purging files", sets.Length, sets.Sum(x => x.Item3))); + Logging.Log.WriteInformationMessage(LOGTAG, "FoundBrokenFilesets", "Found {0} broken filesets with {1} affected files, purging files", sets.Length, sets.Sum(x => x.Item3)); var pgoffset = 0.0f; var pgspan = 0.95f / sets.Length; @@ -86,9 +90,9 @@ namespace Duplicati.Library.Main.Operation if (fully_emptied.Length != 0) { if (fully_emptied.Length == 1) - m_result.AddMessage(string.Format("Removing entire fileset {1} as all {0} file(s) are broken", fully_emptied.First().Timestamp, fully_emptied.First().RemoveCount)); + Logging.Log.WriteInformationMessage(LOGTAG, "RemovingFilesets", "Removing entire fileset {1} as all {0} file(s) are broken", fully_emptied.First().Timestamp, fully_emptied.First().RemoveCount); else - m_result.AddMessage(string.Format("Removing {0} filesets where all file(s) are broken: {1}", fully_emptied.Length, string.Join(", ", fully_emptied.Select(x => x.Timestamp.ToLocalTime().ToString())))); + Logging.Log.WriteInformationMessage(LOGTAG, "RemovingFilesets", "Removing {0} filesets where all file(s) are broken: {1}", fully_emptied.Length, string.Join(", ", fully_emptied.Select(x => x.Timestamp.ToLocalTime().ToString()))); m_result.DeleteResults = new DeleteResults(m_result); using (var rmdb = new Database.LocalDeleteDatabase(db)) @@ -106,7 +110,7 @@ namespace Duplicati.Library.Main.Operation if (!m_options.Dryrun) { - using (new Logging.Timer("CommitDelete")) + using (new Logging.Timer(LOGTAG, "CommitDelete", "CommitDelete")) deltr.Commit(); rmdb.WriteResults(); @@ -133,7 +137,7 @@ namespace Duplicati.Library.Main.Operation foreach (var bs in to_purge) { - m_result.AddMessage(string.Format("Purging {0} file(s) from fileset {1}", bs.RemoveCount, bs.Timestamp.ToLocalTime())); + Logging.Log.WriteInformationMessage(LOGTAG, "PurgingFiles", "Purging {0} file(s) from fileset {1}", bs.RemoveCount, bs.Timestamp.ToLocalTime()); var opts = new Options(new Dictionary(m_options.RawOptions)); using (var pgdb = new Database.LocalPurgeDatabase(db)) @@ -174,7 +178,7 @@ namespace Duplicati.Library.Main.Operation { foreach (var f in missing) if (m_options.Dryrun) - m_result.AddDryrunMessage(string.Format("Would delete remote file: {0}, size: {1}", f.Name, Library.Utility.Utility.FormatSizeString(f.Size))); + Logging.Log.WriteDryrunMessage(LOGTAG, "WouldDeleteRemoteFile", "Would delete remote file: {0}, size: {1}", f.Name, Library.Utility.Utility.FormatSizeString(f.Size)); else backend.Delete(f.Name, f.Size); } @@ -182,9 +186,9 @@ namespace Duplicati.Library.Main.Operation if (!m_options.Dryrun && db.RepairInProgress) { - m_result.AddMessage("Database was previously marked as in-progress, checking if it is valid after purging files"); + Logging.Log.WriteInformationMessage(LOGTAG, "ValidatingDatabase", "Database was previously marked as in-progress, checking if it is valid after purging files"); db.VerifyConsistency(null, m_options.Blocksize, m_options.BlockhashSize, true); - m_result.AddMessage("Purge completed, and consistency checks completed, marking database as complete"); + Logging.Log.WriteInformationMessage(LOGTAG, "UpdatingDatabase", "Purge completed, and consistency checks completed, marking database as complete"); db.RepairInProgress = false; } diff --git a/Duplicati/Library/Main/Operation/PurgeFilesHandler.cs b/Duplicati/Library/Main/Operation/PurgeFilesHandler.cs index 6d56073af..8d5afb117 100644 --- a/Duplicati/Library/Main/Operation/PurgeFilesHandler.cs +++ b/Duplicati/Library/Main/Operation/PurgeFilesHandler.cs @@ -22,6 +22,10 @@ namespace Duplicati.Library.Main.Operation { internal class PurgeFilesHandler { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(); protected string m_backendurl; protected Options m_options; protected PurgeFilesResults m_result; @@ -36,10 +40,10 @@ namespace Duplicati.Library.Main.Operation public void Run(Library.Utility.IFilter filter) { if (filter == null || filter.Empty) - throw new UserInformationException("Cannot purge with an empty filter, as that would cause all files to be removed.\nTo remove an entire backup set, use the \"delete\" command."); + throw new UserInformationException("Cannot purge with an empty filter, as that would cause all files to be removed.\nTo remove an entire backup set, use the \"delete\" command.", "EmptyFilterPurgeNotAllowed"); if (!System.IO.File.Exists(m_options.Dbpath)) - throw new UserInformationException(string.Format("Database file does not exist: {0}", m_options.Dbpath)); + throw new UserInformationException(string.Format("Database file does not exist: {0}", m_options.Dbpath), "DatabaseDoesNotExist"); using (var db = new Database.LocalPurgeDatabase(m_options.Dbpath)) DoRun(db, filter, null, 0, 1); @@ -53,25 +57,25 @@ namespace Duplicati.Library.Main.Operation private void DoRun(Database.LocalPurgeDatabase db, Library.Utility.IFilter filter, Action filtercommand, float pgoffset, float pgspan) { m_result.OperationProgressUpdater.UpdatePhase(OperationPhase.PurgeFiles_Begin); - m_result.AddMessage("Starting purge operation"); + Logging.Log.WriteInformationMessage(LOGTAG, "StartingPurge", "Starting purge operation"); var doCompactStep = !m_options.NoAutoCompact && filtercommand == null; using (var backend = new BackendManager(m_backendurl, m_options, m_result.BackendWriter, db)) { if (db.PartiallyRecreated) - throw new UserInformationException("The purge command does not work on partially recreated databases"); + throw new UserInformationException("The purge command does not work on partially recreated databases", "PurgeNotAllowedOnPartialDatabase"); if (db.RepairInProgress && filtercommand == null) - throw new UserInformationException(string.Format("The purge command does not work on an incomplete database, try the {0} operation.", "purge-broken-files")); + throw new UserInformationException(string.Format("The purge command does not work on an incomplete database, try the {0} operation.", "purge-broken-files"), "PurgeNotAllowedOnIncompleteDatabase"); var versions = db.GetFilesetIDs(m_options.Time, m_options.Version).ToArray(); if (versions.Length <= 0) - throw new UserInformationException("No filesets matched the supplied time or versions"); + throw new UserInformationException("No filesets matched the supplied time or versions", "NoFilesetFoundForTimeOrVersion"); var orphans = db.CountOrphanFiles(null); if (orphans != 0) - throw new UserInformationException(string.Format("Unable to start the purge process as there are {0} orphan file(s)", orphans)); + throw new UserInformationException(string.Format("Unable to start the purge process as there are {0} orphan file(s)", orphans), "CannotPurgeWithOrphans"); Utility.UpdateOptionsFromDb(db, m_options); Utility.VerifyParameters(db, m_options); @@ -137,7 +141,7 @@ namespace Duplicati.Library.Main.Operation if (tempset.RemovedFileCount == 0) { - m_result.AddMessage(string.Format("Not writing a new fileset for {0} as it was not changed", prevfilename)); + Logging.Log.WriteInformationMessage(LOGTAG, "NotWritingNewFileset", "Not writing a new fileset for {0} as it was not changed", prevfilename); currentprogress += versionprogress; tr.Rollback(); continue; @@ -150,7 +154,7 @@ namespace Duplicati.Library.Main.Operation var newids = tempset.ConvertToPermanentFileset(vol.RemoteFilename, ts); vol.VolumeID = newids.Item1; - m_result.AddMessage(string.Format("Replacing fileset {0} with {1} which has with {2} fewer file(s) ({3} reduction)", prevfilename, vol.RemoteFilename, tempset.RemovedFileCount, Library.Utility.Utility.FormatSizeString(tempset.RemovedFileSize))); + Logging.Log.WriteInformationMessage(LOGTAG, "ReplacingFileset", "Replacing fileset {0} with {1} which has with {2} fewer file(s) ({3} reduction)", prevfilename, vol.RemoteFilename, tempset.RemovedFileCount, Library.Utility.Utility.FormatSizeString(tempset.RemovedFileSize)); db.WriteFileset(vol, tr, newids.Item2); @@ -161,30 +165,28 @@ namespace Duplicati.Library.Main.Operation currentprogress += (versionprogress / 2); m_result.OperationProgressUpdater.UpdateProgress(currentprogress); - if (m_options.Dryrun || m_options.Verbose || Logging.Log.LogLevel == Logging.LogMessageType.Profiling) + if (m_options.Dryrun || m_options.FullResult) { foreach (var fe in tempset.ListAllDeletedFiles()) { var msg = string.Format(" Purging file {0} ({1})", fe.Key, Library.Utility.Utility.FormatSizeString(fe.Value)); - if (Logging.Log.LogLevel == Logging.LogMessageType.Profiling) - Logging.Log.WriteMessage(msg, Logging.LogMessageType.Profiling); + Logging.Log.WriteProfilingMessage(LOGTAG, "PurgeFile", msg); + Logging.Log.WriteVerboseMessage(LOGTAG, "PurgeFile", msg); if (m_options.Dryrun) - m_result.AddDryrunMessage(msg); - else if (m_options.Verbose) - m_result.AddVerboseMessage(msg); + Logging.Log.WriteDryrunMessage(LOGTAG, "WouldPurgeFile", msg); } if (m_options.Dryrun) - m_result.AddDryrunMessage("Writing files to remote storage"); - else if (m_options.Verbose) - m_result.AddVerboseMessage("Writing files to remote storage"); + Logging.Log.WriteDryrunMessage(LOGTAG, "WouldWriteRemoteFiles", "Would write files to remote storage"); + + Logging.Log.WriteVerboseMessage(LOGTAG, "WritingRemoteFiles", "Writing files to remote storage"); } if (m_options.Dryrun) { - m_result.AddDryrunMessage(string.Format("Would upload file {0} ({1}) and delete file {2}, removing {3} files", vol.RemoteFilename, Library.Utility.Utility.FormatSizeString(vol.Filesize), prevfilename, tempset.RemovedFileCount)); + Logging.Log.WriteDryrunMessage(LOGTAG, "WouldUploadAndDelete", "Would upload file {0} ({1}) and delete file {2}, removing {3} files", vol.RemoteFilename, Library.Utility.Utility.FormatSizeString(vol.Filesize), prevfilename, tempset.RemovedFileCount); tr.Rollback(); } else @@ -212,7 +214,7 @@ namespace Duplicati.Library.Main.Operation { if (m_result.RewrittenFileLists == 0) { - m_result.AddMessage("Skipping compacting as no new volumes were written"); + Logging.Log.WriteInformationMessage(LOGTAG, "SkippingCompacting", "Skipping compacting as no new volumes were written"); } else { diff --git a/Duplicati/Library/Main/Operation/RecreateDatabaseHandler.cs b/Duplicati/Library/Main/Operation/RecreateDatabaseHandler.cs index cffa779ef..272838b4b 100644 --- a/Duplicati/Library/Main/Operation/RecreateDatabaseHandler.cs +++ b/Duplicati/Library/Main/Operation/RecreateDatabaseHandler.cs @@ -9,6 +9,11 @@ namespace Duplicati.Library.Main.Operation { internal class RecreateDatabaseHandler : IDisposable { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(); + private string m_backendurl; private Options m_options; private RecreateDatabaseResults m_result; @@ -33,7 +38,7 @@ namespace Duplicati.Library.Main.Operation public void Run(string path, Library.Utility.IFilter filter = null, NumberedFilterFilelistDelegate filelistfilter = null, BlockVolumePostProcessor blockprocessor = null) { if (System.IO.File.Exists(path)) - throw new UserInformationException(string.Format("Cannot recreate database because file already exists: {0}", path)); + throw new UserInformationException(string.Format("Cannot recreate database because file already exists: {0}", path), "RecreateTargetDatabaseExists"); using(var db = new LocalDatabase(path, "Recreate", true)) { @@ -52,14 +57,14 @@ namespace Duplicati.Library.Main.Operation public void RunUpdate(Library.Utility.IFilter filter = null, NumberedFilterFilelistDelegate filelistfilter = null, BlockVolumePostProcessor blockprocessor = null) { if (!m_options.RepairOnlyPaths) - throw new UserInformationException(string.Format("Can only update with paths, try setting {0}", "--repair-only-paths")); + throw new UserInformationException(string.Format("Can only update with paths, try setting {0}", "--repair-only-paths"), "RepairUpdateRequiresPathsOnly"); using(var db = new LocalDatabase(m_options.Dbpath, "Recreate", true)) { m_result.SetDatabase(db); if (db.FindMatchingFilesets(m_options.Time, m_options.Version).Any()) - throw new UserInformationException(string.Format("The version(s) being updated to, already exists")); + throw new UserInformationException(string.Format("The version(s) being updated to, already exists"), "UpdateVersionAlreadyExists"); // Mark as incomplete db.PartiallyRecreated = true; @@ -106,7 +111,7 @@ namespace Duplicati.Library.Main.Operation if (remotefiles.Length == 0) { if (rawlist.Count == 0) - throw new UserInformationException("No files were found at the remote location, perhaps the target url is incorrect?"); + throw new UserInformationException("No files were found at the remote location, perhaps the target url is incorrect?", "EmptyRemoteLocation"); else { var tmp = @@ -118,11 +123,11 @@ namespace Duplicati.Library.Main.Operation var types = tmp.Distinct().ToArray(); if (tmp.Length == 0) - throw new UserInformationException(string.Format("Found {0} files at the remote storage, but none that could be parsed", rawlist.Count)); + throw new UserInformationException(string.Format("Found {0} files at the remote storage, but none that could be parsed", rawlist.Count), "EmptyRemoteLocation"); else if (types.Length == 1) - throw new UserInformationException(string.Format("Found {0} parse-able files with the prefix {1}, did you forget to set the backup prefix?", tmp.Length, types[0])); + throw new UserInformationException(string.Format("Found {0} parse-able files with the prefix {1}, did you forget to set the backup prefix?", tmp.Length, types[0]), "EmptyRemoteLocationWithPrefix"); else - throw new UserInformationException(string.Format("Found {0} parse-able files (of {1} files) with different prefixes: {2}, did you forget to set the backup prefix?", tmp.Length, rawlist.Count, string.Join(", ", types))); + throw new UserInformationException(string.Format("Found {0} parse-able files (of {1} files) with different prefixes: {2}, did you forget to set the backup prefix?", tmp.Length, rawlist.Count, string.Join(", ", types)), "EmptyRemoteLocationWithPrefix"); } } @@ -135,13 +140,13 @@ namespace Duplicati.Library.Main.Operation select n; if (filelists.Count() <= 0) - throw new UserInformationException(string.Format("No filelists found on the remote destination")); + throw new UserInformationException(string.Format("No filelists found on the remote destination"), "EmptyRemoteLocation"); if (filelistfilter != null) filelists = filelistfilter(filelists).Select(x => x.Value).ToArray(); if (filelists.Count() <= 0) - throw new UserInformationException(string.Format("No filelists")); + throw new UserInformationException(string.Format("No filelists"), "NoMatchingRemoteFilelists"); // If we are updating, all files should be accounted for foreach(var fl in remotefiles) @@ -159,7 +164,7 @@ namespace Duplicati.Library.Main.Operation using(var tr = restoredb.BeginTransaction()) { var filelistWork = (from n in filelists orderby n.Time select new RemoteVolume(n.File) as IRemoteVolume).ToList(); - m_result.AddMessage(string.Format("Rebuild database started, downloading {0} filelists", filelistWork.Count)); + Logging.Log.WriteInformationMessage(LOGTAG, "RebuildStarted", "Rebuild database started, downloading {0} filelists", filelistWork.Count); var progress = 0; @@ -244,7 +249,7 @@ namespace Duplicati.Library.Main.Operation else if (m_options.BlockHashAlgorithm == m_options.FileHashAlgorithm) restoredb.AddSmallBlocksetLink(fe.Hash, fe.Hash, fe.Size, tr); else - m_result.AddWarning(string.Format("No block hash found for file: {0}", fe.Path), null); + Logging.Log.WriteWarningMessage(LOGTAG, "MissingBlockHash", null, "No block hash found for file: {0}", fe.Path); } break; @@ -253,7 +258,7 @@ namespace Duplicati.Library.Main.Operation restoredb.AddSymlinkEntry(filesetid, fe.Path, fe.Time, metadataid, tr); break; default: - m_result.AddWarning(string.Format("Skipping file-entry with unknown type {0}: {1} ", fe.Type, fe.Path), null); + Logging.Log.WriteWarningMessage(LOGTAG, "SkippingUnknownFileEntry", null, "Skipping file-entry with unknown type {0}: {1} ", fe.Type, fe.Path); break; } @@ -264,19 +269,19 @@ namespace Duplicati.Library.Main.Operation else if (m_options.BlockHashAlgorithm == m_options.FileHashAlgorithm) restoredb.AddSmallBlocksetLink(fe.Metahash, fe.Metahash, fe.Metasize, tr); else - m_result.AddWarning(string.Format("No block hash found for file metadata: {0}", fe.Path), null); + Logging.Log.WriteWarningMessage(LOGTAG, "MissingMetadataBlockHash", null, "No block hash found for file metadata: {0}", fe.Path); } } catch (Exception ex) { - m_result.AddWarning(string.Format("Failed to process file-entry: {0}", fe.Path), ex); + Logging.Log.WriteWarningMessage(LOGTAG, "FileEntryProcessingFailed", ex, "Failed to process file-entry: {0}", fe.Path); } } } } catch (Exception ex) { - m_result.AddWarning(string.Format("Failed to process file: {0}", entry.Name), ex); + Logging.Log.WriteWarningMessage(LOGTAG, "FileProcessingFailed", ex, "Failed to process file: {0}", entry.Name); if (ex is System.Threading.ThreadAbortException) { m_result.EndTime = DateTime.UtcNow; @@ -294,7 +299,7 @@ namespace Duplicati.Library.Main.Operation if (!updating) Utility.VerifyParameters(restoredb, m_options, tr); - using(new Logging.Timer("CommitUpdateFilesetFromRemote")) + using(new Logging.Timer(LOGTAG, "CommitUpdateFilesetFromRemote", "CommitUpdateFilesetFromRemote")) tr.Commit(); } @@ -302,7 +307,7 @@ namespace Duplicati.Library.Main.Operation { var hashalg = Library.Utility.HashAlgorithmHelper.Create(m_options.BlockHashAlgorithm); if (hashalg == null) - throw new UserInformationException(Strings.Common.InvalidHashAlgorithm(m_options.BlockHashAlgorithm)); + throw new UserInformationException(Strings.Common.InvalidHashAlgorithm(m_options.BlockHashAlgorithm), "BlockHashAlgorithmNotSupported"); var hashsize = hashalg.HashSize / 8; //Grab all index files, and update the block table @@ -313,7 +318,7 @@ namespace Duplicati.Library.Main.Operation where n.FileType == RemoteVolumeType.Index select new RemoteVolume(n.File) as IRemoteVolume).ToList(); - m_result.AddMessage(string.Format("Filelists restored, downloading {0} index files", indexfiles.Count)); + Logging.Log.WriteInformationMessage(LOGTAG, "FilelistsRestored", "Filelists restored, downloading {0} index files", indexfiles.Count); var progress = 0; @@ -352,7 +357,7 @@ namespace Duplicati.Library.Main.Operation var p = VolumeBase.ParseFilename(filename); if (p == null) throw new Exception(string.Format("Unable to parse filename: {0}", filename)); - m_result.AddError(string.Format("Remote file referenced as {0}, but not found in list, registering a missing remote file", filename), null); + Logging.Log.WriteErrorMessage(LOGTAG, "MissingFileDetected", null, "Remote file referenced as {0}, but not found in list, registering a missing remote file", filename); volumeID = restoredb.RegisterRemoteVolume(filename, p.FileType, RemoteVolumeState.Verified, tr); } @@ -373,7 +378,7 @@ namespace Duplicati.Library.Main.Operation catch (Exception ex) { //Not fatal - m_result.AddWarning(string.Format("Failed to process index file: {0}", sf.Name), ex); + Logging.Log.WriteErrorMessage(LOGTAG, "IndexFileProcessingFailed", ex, "Failed to process index file: {0}", sf.Name); if (ex is System.Threading.ThreadAbortException) { m_result.EndTime = DateTime.UtcNow; @@ -381,7 +386,7 @@ namespace Duplicati.Library.Main.Operation } } - using(new Logging.Timer("CommitRecreatedDb")) + using(new Logging.Timer(LOGTAG, "CommitRecreateDb", "CommitRecreatedDb")) tr.Commit(); // TODO: In some cases, we can avoid downloading all index files, @@ -399,25 +404,21 @@ namespace Duplicati.Library.Main.Operation var lst = restoredb.GetMissingBlockListVolumes(i, m_options.Blocksize, hashsize).ToList(); if (lst.Count > 0) { + var fullist = ": " + string.Join(", ", lst.Select(x => x.Name)); switch (i) { + case 0: - if (m_options.Verbose) - m_result.AddVerboseMessage("Processing required {0} blocklist volumes: {1}", lst.Count, string.Join(", ", lst.Select(x => x.Name))); - else - m_result.AddMessage(string.Format("Processing required {0} blocklist volumes", lst.Count)); + Logging.Log.WriteVerboseMessage(LOGTAG, "ProcessingRequiredBlocklistVolumes", "Processing required {0} blocklist volumes{1}", lst.Count, fullist); + Logging.Log.WriteInformationMessage(LOGTAG, "ProcessingRequiredBlocklistVolumes", "Processing required {0} blocklist volumes{1}", lst.Count, m_options.FullResult ? fullist : string.Empty); break; case 1: - if (m_options.Verbose) - m_result.AddVerboseMessage("Probing {0} candidate blocklist volumes: {1}", lst.Count, string.Join(", ", lst.Select(x => x.Name))); - else - m_result.AddMessage(string.Format("Probing {0} candidate blocklist volumes", lst.Count)); + Logging.Log.WriteVerboseMessage(LOGTAG, "ProbingCandicateBlocklistVolumes", "Probing {0} candidate blocklist volumes{1}", lst.Count, fullist); + Logging.Log.WriteInformationMessage(LOGTAG, "ProbingCandicateBlocklistVolumes", "Probing {0} candidate blocklist volumes{1}", lst.Count, m_options.FullResult ? fullist : string.Empty); break; default: - if (m_options.Verbose) - m_result.AddVerboseMessage("Processing all of the {0} volumes for blocklists: {1}", lst.Count, string.Join(", ", lst.Select(x => x.Name))); - else - m_result.AddMessage(string.Format("Processing all of the {0} volumes for blocklists", lst.Count)); + Logging.Log.WriteVerboseMessage(LOGTAG, "ProcessingAllBlocklistVolumes", "Processing all of the {0} volumes for blocklists{1}", lst.Count, fullist); + Logging.Log.WriteVerboseMessage(LOGTAG, "ProcessingAllBlocklistVolumes", "Processing all of the {0} volumes for blocklists{1}", lst.Count, m_options.FullResult ? fullist : string.Empty); break; } } @@ -453,7 +454,7 @@ namespace Duplicati.Library.Main.Operation // Update tables so we know if we are done restoredb.FindMissingBlocklistHashes(hashsize, m_options.Blocksize, tr); - using(new Logging.Timer("CommitRestoredBlocklist")) + using(new Logging.Timer(LOGTAG, "CommitRestoredBlocklist", "CommitRestoredBlocklist")) tr.Commit(); //At this point we can patch files with data from the block volume @@ -467,11 +468,11 @@ namespace Duplicati.Library.Main.Operation if (m_options.RepairOnlyPaths) { - m_result.AddMessage("Recreate/path-update completed, not running consistency checks"); + Logging.Log.WriteInformationMessage(LOGTAG, "RecreateOrUpdateOnly", "Recreate/path-update completed, not running consistency checks"); } else { - m_result.AddMessage("Recreate completed, verifying the database consistency"); + Logging.Log.WriteInformationMessage(LOGTAG, "RecreateCompletedCheckingDatabase", "Recreate completed, verifying the database consistency"); //All done, we must verify that we have all blocklist fully intact // if this fails, the db will not be deleted, so it can be used, @@ -482,12 +483,12 @@ namespace Duplicati.Library.Main.Operation { var broken = lbfdb.GetBrokenFilesets(new DateTime(0), null, null).Count(); if (broken != 0) - throw new UserInformationException(string.Format("Recreated database has missing blocks and {0} broken filelists. Consider using \"{1}\" and \"{2}\" to purge broken data from the remote store and the database.", broken, "list-broken-files", "purge-broken-files")); + throw new UserInformationException(string.Format("Recreated database has missing blocks and {0} broken filelists. Consider using \"{1}\" and \"{2}\" to purge broken data from the remote store and the database.", broken, "list-broken-files", "purge-broken-files"), "DatabaseIsBrokenConsiderPurge"); } restoredb.VerifyConsistency(null, m_options.Blocksize, m_options.BlockhashSize, true); - m_result.AddMessage("Recreate completed, and consistency checks completed, marking database as complete"); + Logging.Log.WriteInformationMessage(LOGTAG, "RecreateCompleted", "Recreate completed, and consistency checks completed, marking database as complete"); restoredb.RepairInProgress = false; } @@ -514,7 +515,7 @@ namespace Duplicati.Library.Main.Operation var tvid = restoredb.GetRemoteVolumeID(testfilename); if (tvid >= 0) { - m_result.AddWarning(string.Format("Unable to find volume {0}, but mapping to matching file {1}", filename, testfilename), null); + Logging.Log.WriteWarningMessage(LOGTAG, "RewritingFilenameMapping", null, "Unable to find volume {0}, but mapping to matching file {1}", filename, testfilename); filename = testfilename; return tvid; } diff --git a/Duplicati/Library/Main/Operation/RepairHandler.cs b/Duplicati/Library/Main/Operation/RepairHandler.cs index 27b8bd564..b6e6ac064 100644 --- a/Duplicati/Library/Main/Operation/RepairHandler.cs +++ b/Duplicati/Library/Main/Operation/RepairHandler.cs @@ -10,6 +10,10 @@ namespace Duplicati.Library.Main.Operation { internal class RepairHandler { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(); private string m_backendurl; private Options m_options; private RepairResults m_result; @@ -21,7 +25,7 @@ namespace Duplicati.Library.Main.Operation m_result = result; if (options.AllowPassphraseChange) - throw new UserInformationException(Strings.Common.PassphraseChangeUnsupported); + throw new UserInformationException(Strings.Common.PassphraseChangeUnsupported, "PassphraseChangeUnsupported"); } public void Run(Library.Utility.IFilter filter = null) @@ -42,14 +46,14 @@ namespace Duplicati.Library.Main.Operation } catch (Exception ex) { - m_result.AddWarning(string.Format("Failed to read local db {0}, error: {1}", m_options.Dbpath, ex.Message), ex); + Logging.Log.WriteWarningMessage(LOGTAG, "FailedToReadLocalDatabase", ex, "Failed to read local db {0}, error: {1}", m_options.Dbpath, ex.Message); } if (knownRemotes <= 0) { if (m_options.Dryrun) { - m_result.AddDryrunMessage("Performing dryrun recreate"); + Logging.Log.WriteDryrunMessage(LOGTAG, "PerformingDryrunRecreate", "Performing dryrun recreate"); } else { @@ -58,7 +62,7 @@ namespace Duplicati.Library.Main.Operation while (System.IO.File.Exists(baseName) && i++ < 1000) baseName = System.IO.Path.ChangeExtension(m_options.Dbpath, "backup-" + i.ToString()); - m_result.AddMessage(string.Format("Renaming existing db from {0} to {1}", m_options.Dbpath, baseName)); + Logging.Log.WriteInformationMessage(LOGTAG, "RenamingDatabase", "Renaming existing db from {0} to {1}", m_options.Dbpath, baseName); System.IO.File.Move(m_options.Dbpath, baseName); } @@ -78,7 +82,7 @@ namespace Duplicati.Library.Main.Operation public void RunRepairLocal(Library.Utility.IFilter filter = null) { m_result.RecreateDatabaseResults = new RecreateDatabaseResults(m_result); - using(new Logging.Timer("Recreate database for repair")) + using(new Logging.Timer(LOGTAG, "RecreateDbForRepair", "Recreate database for repair")) using(var f = m_options.Dryrun ? new Library.Utility.TempFile() : null) { if (f != null && System.IO.File.Exists(f)) @@ -94,7 +98,7 @@ namespace Duplicati.Library.Main.Operation public void RunRepairRemote() { if (!System.IO.File.Exists(m_options.Dbpath)) - throw new UserInformationException(string.Format("Database file does not exist: {0}", m_options.Dbpath)); + throw new UserInformationException(string.Format("Database file does not exist: {0}", m_options.Dbpath), "RepairDatabaseFileDoesNotExist"); m_result.OperationProgressUpdater.UpdateProgress(0); @@ -106,10 +110,10 @@ namespace Duplicati.Library.Main.Operation Utility.VerifyParameters(db, m_options); if (db.PartiallyRecreated) - throw new UserInformationException("The database was only partially recreated. This database may be incomplete and the repair process is not allowed to alter remote files as that could result in data loss."); + throw new UserInformationException("The database was only partially recreated. This database may be incomplete and the repair process is not allowed to alter remote files as that could result in data loss.", "DatabaseIsPartiallyRecreated"); if (db.RepairInProgress) - throw new UserInformationException("The database was attempted repaired, but the repair did not complete. This database may be incomplete and the repair process is not allowed to alter remote files as that could result in data loss."); + throw new UserInformationException("The database was attempted repaired, but the repair did not complete. This database may be incomplete and the repair process is not allowed to alter remote files as that could result in data loss.", "DatabaseIsInRepairState"); var tp = FilelistProcessor.RemoteListAnalysis(backend, m_options, db, m_result.BackendWriter, null); var buffer = new byte[m_options.Blocksize]; @@ -117,9 +121,9 @@ namespace Duplicati.Library.Main.Operation var hashsize = blockhasher.HashSize / 8; if (blockhasher == null) - throw new UserInformationException(Strings.Common.InvalidHashAlgorithm(m_options.BlockHashAlgorithm)); + throw new UserInformationException(Strings.Common.InvalidHashAlgorithm(m_options.BlockHashAlgorithm), "BlockHashAlgorithmNotSupported"); if (!blockhasher.CanReuseTransform) - throw new UserInformationException(Strings.Common.InvalidCryptoSystem(m_options.BlockHashAlgorithm)); + throw new UserInformationException(Strings.Common.InvalidCryptoSystem(m_options.BlockHashAlgorithm), "BlockHashAlgorithmNotSupported"); var progress = 0; var targetProgess = tp.ExtraVolumes.Count() + tp.MissingVolumes.Count() + tp.VerificationRequiredVolumes.Count(); @@ -129,13 +133,13 @@ namespace Duplicati.Library.Main.Operation if (tp.ParsedVolumes.Count() == 0 && tp.OtherVolumes.Count() > 0) { if (tp.BackupPrefixes.Length == 1) - throw new UserInformationException(string.Format("Found no backup files with prefix {0}, but files with prefix {1}, did you forget to set the backup prefix?", m_options.Prefix, tp.BackupPrefixes[0])); + throw new UserInformationException(string.Format("Found no backup files with prefix {0}, but files with prefix {1}, did you forget to set the backup prefix?", m_options.Prefix, tp.BackupPrefixes[0]), "RemoteFolderEmptyWithPrefix"); else - throw new UserInformationException(string.Format("Found no backup files with prefix {0}, but files with prefixes {1}, did you forget to set the backup prefix?", m_options.Prefix, string.Join(", ", tp.BackupPrefixes))); + throw new UserInformationException(string.Format("Found no backup files with prefix {0}, but files with prefixes {1}, did you forget to set the backup prefix?", m_options.Prefix, string.Join(", ", tp.BackupPrefixes)), "RemoteFolderEmptyWithPrefix"); } else if (tp.ParsedVolumes.Count() == 0 && tp.ExtraVolumes.Count() > 0) { - throw new UserInformationException(string.Format("No files were missing, but {0} remote files were, found, did you mean to run recreate-database?", tp.ExtraVolumes.Count())); + throw new UserInformationException(string.Format("No files were missing, but {0} remote files were, found, did you mean to run recreate-database?", tp.ExtraVolumes.Count()), "NoRemoteFilesMissing"); } } @@ -162,21 +166,21 @@ namespace Duplicati.Library.Main.Operation KeyValuePair>> res; using (var tf = backend.GetWithInfo(n.Name, out size, out hash)) - res = TestHandler.TestVolumeInternals(testdb, n, tf, m_options, m_result, 1); + res = TestHandler.TestVolumeInternals(testdb, n, tf, m_options, 1); if (res.Value.Any()) throw new Exception(string.Format("Remote verification failure: {0}", res.Value.First())); if (!m_options.Dryrun) { - m_result.AddMessage(string.Format("Sucessfully captured hash for {0}, updating database", n.Name)); + Logging.Log.WriteInformationMessage(LOGTAG, "CapturedRemoteFileHash", "Sucessfully captured hash for {0}, updating database", n.Name); db.UpdateRemoteVolume(n.Name, RemoteVolumeState.Verified, size, hash); } } catch (Exception ex) { - m_result.AddError(string.Format("Failed to perform verification for file: {0}, please run verify; message: {1}", n.Name, ex.Message), ex); + Logging.Log.WriteErrorMessage(LOGTAG, "RemoteFileVerificationError", ex, "Failed to perform verification for file: {0}, please run verify; message: {1}", n.Name, ex.Message); if (ex is System.Threading.ThreadAbortException) throw; } @@ -235,14 +239,14 @@ namespace Duplicati.Library.Main.Operation } // All checks fine, we accept the new index file - m_result.AddMessage(string.Format("Accepting new index file {0}", n.File.Name)); + Logging.Log.WriteInformationMessage(LOGTAG, "AcceptNewIndexFile", "Accepting new index file {0}", n.File.Name); db.RegisterRemoteVolume(n.File.Name, RemoteVolumeType.Index, size, RemoteVolumeState.Uploading); db.UpdateRemoteVolume(n.File.Name, RemoteVolumeState.Verified, size, hash); continue; } catch (Exception rex) { - m_result.AddError(string.Format("Failed to accept new index file: {0}, message: {1}", n.File.Name, rex.Message), rex); + Logging.Log.WriteErrorMessage(LOGTAG, "FailedNewIndexFile", rex, "Failed to accept new index file: {0}, message: {1}", n.File.Name, rex.Message); } } @@ -252,11 +256,11 @@ namespace Duplicati.Library.Main.Operation backend.Delete(n.File.Name, n.File.Size); } else - m_result.AddDryrunMessage(string.Format("would delete file {0}", n.File.Name)); + Logging.Log.WriteDryrunMessage(LOGTAG, "WouldDeleteFile", "would delete file {0}", n.File.Name); } catch (Exception ex) { - m_result.AddError(string.Format("Failed to perform cleanup for extra file: {0}, message: {1}", n.File.Name, ex.Message), ex); + Logging.Log.WriteErrorMessage(LOGTAG, "FailedExtraFileCleanup", ex, "Failed to perform cleanup for extra file: {0}, message: {1}", n.File.Name, ex.Message); if (ex is System.Threading.ThreadAbortException) throw; } @@ -287,7 +291,7 @@ namespace Duplicati.Library.Main.Operation w.Close(); if (m_options.Dryrun) - m_result.AddDryrunMessage(string.Format("would re-upload fileset {0}, with size {1}, previous size {2}", n.Name, Library.Utility.Utility.FormatSizeString(new System.IO.FileInfo(w.LocalFilename).Length), Library.Utility.Utility.FormatSizeString(n.Size))); + Logging.Log.WriteDryrunMessage(LOGTAG, "WouldReUploadFileset", "would re-upload fileset {0}, with size {1}, previous size {2}", n.Name, Library.Utility.Utility.FormatSizeString(new System.IO.FileInfo(w.LocalFilename).Length), Library.Utility.Utility.FormatSizeString(n.Size)); else { db.UpdateRemoteVolume(w.RemoteFilename, RemoteVolumeState.Uploading, -1, null, null); @@ -326,7 +330,7 @@ namespace Duplicati.Library.Main.Operation w.Close(); if (m_options.Dryrun) - m_result.AddDryrunMessage(string.Format("would re-upload index file {0}, with size {1}, previous size {2}", n.Name, Library.Utility.Utility.FormatSizeString(new System.IO.FileInfo(w.LocalFilename).Length), Library.Utility.Utility.FormatSizeString(n.Size))); + Logging.Log.WriteDryrunMessage(LOGTAG, "WouldReUploadIndexFile", "would re-upload index file {0}, with size {1}, previous size {2}", n.Name, Library.Utility.Utility.FormatSizeString(new System.IO.FileInfo(w.LocalFilename).Length), Library.Utility.Utility.FormatSizeString(n.Size)); else { db.UpdateRemoteVolume(w.RemoteFilename, RemoteVolumeState.Uploading, -1, null, null); @@ -372,7 +376,7 @@ namespace Duplicati.Library.Main.Operation } catch (Exception ex) { - m_result.AddError(string.Format("Failed to access file: {0}", file), ex); + Logging.Log.WriteErrorMessage(LOGTAG, "FileAccessError", ex, "Failed to access file: {0}", file); } } } @@ -391,7 +395,7 @@ namespace Duplicati.Library.Main.Operation } catch (Exception ex) { - m_result.AddError(string.Format("Failed to access remote file: {0}", vol.Name), ex); + Logging.Log.WriteErrorMessage(LOGTAG, "RemoteFileAccessError", ex, "Failed to access remote file: {0}", vol.Name); } } @@ -399,27 +403,27 @@ namespace Duplicati.Library.Main.Operation var missingBlocks = mbl.GetMissingBlocks().Count(); if (missingBlocks > 0) { - m_result.AddMessage(string.Format("Repair cannot acquire {0} required blocks for volume {1}, which are required by the following filesets: ", missingBlocks, n.Name)); + Logging.Log.WriteInformationMessage(LOGTAG, "RepairMissingBlocks", "Repair cannot acquire {0} required blocks for volume {1}, which are required by the following filesets: ", missingBlocks, n.Name); foreach(var f in mbl.GetFilesetsUsingMissingBlocks()) - m_result.AddMessage(f.Name); + Logging.Log.WriteInformationMessage(LOGTAG, "AffectedFilesetName", f.Name); var recoverymsg = string.Format("If you want to continue working with the database, you can use the \"{0}\" and \"{1}\" commands to purge the missing data from the database and the remote storage.", "list-broken-files", "purge-broken-files"); if (!m_options.Dryrun) { - m_result.AddMessage("This may be fixed by deleting the filesets and running repair again"); + Logging.Log.WriteInformationMessage(LOGTAG, "RecoverySuggestion", "This may be fixed by deleting the filesets and running repair again"); - throw new UserInformationException(string.Format("Repair not possible, missing {0} blocks.\n" + recoverymsg, missingBlocks)); + throw new UserInformationException(string.Format("Repair not possible, missing {0} blocks.\n" + recoverymsg, missingBlocks), "RepairIsNotPossible"); } else { - m_result.AddMessage(recoverymsg); + Logging.Log.WriteInformationMessage(LOGTAG, "RecoverySuggestion", recoverymsg); } } else { if (m_options.Dryrun) - m_result.AddDryrunMessage(string.Format("would re-upload block file {0}, with size {1}, previous size {2}", n.Name, Library.Utility.Utility.FormatSizeString(new System.IO.FileInfo(w.LocalFilename).Length), Library.Utility.Utility.FormatSizeString(n.Size))); + Logging.Log.WriteDryrunMessage(LOGTAG, "WouldReUploadBlockFile", "would re-upload block file {0}, with size {1}, previous size {2}", n.Name, Library.Utility.Utility.FormatSizeString(new System.IO.FileInfo(w.LocalFilename).Length), Library.Utility.Utility.FormatSizeString(n.Size)); else { db.UpdateRemoteVolume(w.RemoteFilename, RemoteVolumeState.Uploading, -1, null, null); @@ -436,7 +440,7 @@ namespace Duplicati.Library.Main.Operation catch { } finally { newEntry = null; } - m_result.AddError(string.Format("Failed to perform cleanup for missing file: {0}, message: {1}", n.Name, ex.Message), ex); + Logging.Log.WriteErrorMessage(LOGTAG, "CleanupMissingFileError", ex, "Failed to perform cleanup for missing file: {0}, message: {1}", n.Name, ex.Message); if (ex is System.Threading.ThreadAbortException) throw; @@ -445,7 +449,7 @@ namespace Duplicati.Library.Main.Operation } else { - m_result.AddMessage("Destination and database are synchronized, not making any changes"); + Logging.Log.WriteInformationMessage(LOGTAG, "DatabaseIsSynchronized", "Destination and database are synchronized, not making any changes"); } m_result.OperationProgressUpdater.UpdateProgress(1); @@ -457,7 +461,7 @@ namespace Duplicati.Library.Main.Operation public void RunRepairCommon() { if (!System.IO.File.Exists(m_options.Dbpath)) - throw new UserInformationException(string.Format("Database file does not exist: {0}", m_options.Dbpath)); + throw new UserInformationException(string.Format("Database file does not exist: {0}", m_options.Dbpath), "DatabaseDoesNotExist"); m_result.OperationProgressUpdater.UpdateProgress(0); @@ -468,7 +472,7 @@ namespace Duplicati.Library.Main.Operation Utility.UpdateOptionsFromDb(db, m_options); if (db.RepairInProgress || db.PartiallyRecreated) - m_result.AddWarning("The database is marked as \"in-progress\" and may be incomplete.", null); + Logging.Log.WriteWarningMessage(LOGTAG, "InProgressDatabase", null, "The database is marked as \"in-progress\" and may be incomplete."); db.FixDuplicateMetahash(); db.FixDuplicateFileentries(); diff --git a/Duplicati/Library/Main/Operation/RestoreHandler.cs b/Duplicati/Library/Main/Operation/RestoreHandler.cs index 724fcc76f..1ebdc9e6d 100644 --- a/Duplicati/Library/Main/Operation/RestoreHandler.cs +++ b/Duplicati/Library/Main/Operation/RestoreHandler.cs @@ -10,6 +10,11 @@ namespace Duplicati.Library.Main.Operation { internal class RestoreHandler { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(); + private string m_backendurl; private Options m_options; private byte[] m_blockbuffer; @@ -33,7 +38,7 @@ namespace Duplicati.Library.Main.Operation { var tmp = VolumeBase.ParseFilename(filename); if (tmp == null) - throw new UserInformationException(string.Format("Unable to parse filename to valid entry: {0}", filename)); + throw new UserInformationException(string.Format("Unable to parse filename to valid entry: {0}", filename), "FailedToParseRemoteName"); return tmp.CompressionModule; } @@ -95,7 +100,7 @@ namespace Duplicati.Library.Main.Operation } - m_result.AddMessage("No local database, building a temporary database"); + Logging.Log.WriteInformationMessage(LOGTAG, "NoLocalDatabase", "No local database, building a temporary database"); m_result.OperationProgressUpdater.UpdatePhase(OperationPhase.Restore_RecreateDatabase); using(var tmpdb = new Library.Utility.TempFile()) @@ -127,14 +132,14 @@ namespace Duplicati.Library.Main.Operation blockhasher = Library.Utility.HashAlgorithmHelper.Create(m_options.BlockHashAlgorithm); filehasher = Library.Utility.HashAlgorithmHelper.Create(m_options.FileHashAlgorithm); if (blockhasher == null) - throw new UserInformationException(Strings.Common.InvalidHashAlgorithm(m_options.BlockHashAlgorithm)); + throw new UserInformationException(Strings.Common.InvalidHashAlgorithm(m_options.BlockHashAlgorithm), "BlockHashAlgorithmNotSupported"); if (!blockhasher.CanReuseTransform) - throw new UserInformationException(Strings.Common.InvalidCryptoSystem(m_options.BlockHashAlgorithm)); + throw new UserInformationException(Strings.Common.InvalidCryptoSystem(m_options.BlockHashAlgorithm), "BlockHashAlgorithmNotSupported"); if (filehasher == null) - throw new UserInformationException(Strings.Common.InvalidHashAlgorithm(m_options.FileHashAlgorithm)); + throw new UserInformationException(Strings.Common.InvalidHashAlgorithm(m_options.FileHashAlgorithm), "FileHashAlgorithmNotSupported"); if (!filehasher.CanReuseTransform) - throw new UserInformationException(Strings.Common.InvalidCryptoSystem(m_options.FileHashAlgorithm)); + throw new UserInformationException(Strings.Common.InvalidCryptoSystem(m_options.FileHashAlgorithm), "FileHashAlgorithmNotSupported"); // Don't run this again first = false; @@ -171,7 +176,7 @@ namespace Duplicati.Library.Main.Operation // and this will reduce the need for multiple downloads of the same volume // TODO: This will need some work to preserve the missing block list for use with --fh-dryrun m_result.RecreateDatabaseResults = new RecreateDatabaseResults(m_result); - using(new Logging.Timer("Recreate temporary database for restore")) + using(new Logging.Timer(LOGTAG, "RecreateTempDbForRestore", "Recreate temporary database for restore")) new RecreateDatabaseHandler(m_backendurl, m_options, (RecreateDatabaseResults)m_result.RecreateDatabaseResults) .DoRun(database, false, filter, filelistfilter, /*localpatcher*/null); @@ -202,20 +207,21 @@ namespace Duplicati.Library.Main.Operation foreach(var restorelist in volumekeeper.FilesWithMissingBlocks) { var targetpath = restorelist.Path; - result.AddVerboseMessage("Patching file with remote data: {0}", targetpath); - + if (options.Dryrun) { - result.AddDryrunMessage(string.Format("Would patch file with remote data: {0}", targetpath)); + Logging.Log.WriteDryrunMessage(LOGTAG, "WouldPatchFile", "Would patch file with remote data: {0}", targetpath); } else { + Logging.Log.WriteVerboseMessage(LOGTAG, "PatchingFile", "Patching file with remote data: {0}", targetpath); + try { var folderpath = m_systemIO.PathGetDirectoryName(targetpath); if (!options.Dryrun && !m_systemIO.DirectoryExists(folderpath)) { - result.AddWarning(string.Format("Creating missing folder {0} for file {1}", folderpath, targetpath), null); + Logging.Log.WriteWarningMessage(LOGTAG, "CreateMissingFolder", null, "Creating missing folder {0} for file {1}", folderpath, targetpath); m_systemIO.DirectoryCreate(folderpath); } @@ -236,7 +242,7 @@ namespace Duplicati.Library.Main.Operation if (targetblock.Key == key) valid = true; else - result.AddWarning(string.Format("Invalid block detected for {0}, expected hash: {1}, actual hash: {2}", targetpath, targetblock.Key, key), null); + Logging.Log.WriteWarningMessage(LOGTAG, "InvalidBlock", null, "Invalid block detected for {0}, expected hash: {1}, actual hash: {2}", targetpath, targetblock.Key, key); } if (valid) @@ -247,7 +253,7 @@ namespace Duplicati.Library.Main.Operation } else { - result.AddWarning(string.Format("Block with hash {0} should have size {1} but has size {2}", targetblock.Key, targetblock.Size, size), null); + Logging.Log.WriteWarningMessage(LOGTAG, "WrongBlockSize", null, "Block with hash {0} should have size {1} but has size {2}", targetblock.Key, targetblock.Size, size); } } @@ -256,7 +262,7 @@ namespace Duplicati.Library.Main.Operation } catch (Exception ex) { - result.AddWarning(string.Format("Failed to patch file: \"{0}\", message: {1}, message: {1}", targetpath, ex.Message), ex); + Logging.Log.WriteWarningMessage(LOGTAG, "PatchFailed", ex, "Failed to patch file: \"{0}\", message: {1}, message: {1}", targetpath, ex.Message); } } } @@ -266,7 +272,7 @@ namespace Duplicati.Library.Main.Operation foreach(var restoremetadata in volumekeeper.MetadataWithMissingBlocks) { var targetpath = restoremetadata.Path; - result.AddVerboseMessage("Recording metadata from remote data: {0}", targetpath); + Logging.Log.WriteVerboseMessage(LOGTAG, "RecordingMetadata", "Recording metadata from remote data: {0}", targetpath); try { @@ -291,12 +297,12 @@ namespace Duplicati.Library.Main.Operation } catch (Exception ex) { - result.AddWarning(string.Format("Failed to record metadata for file: \"{0}\", message: {1}", targetpath, ex.Message), ex); + Logging.Log.WriteWarningMessage(LOGTAG, "MetatdataRecordFailed", ex, "Failed to record metadata for file: \"{0}\", message: {1}", targetpath, ex.Message); } } } blockmarker.UpdateProcessed(result.OperationProgressUpdater); - blockmarker.Commit(result); + blockmarker.Commit(); } } @@ -305,20 +311,20 @@ namespace Duplicati.Library.Main.Operation foreach(var metainfo in metadatastorage.Records) { var targetpath = metainfo.Key; - result.AddVerboseMessage("Patching metadata with remote data: {0}", targetpath); if (options.Dryrun) { - result.AddDryrunMessage(string.Format("Would patch metadata with remote data: {0}", targetpath)); + Logging.Log.WriteDryrunMessage(LOGTAG, "WouldPatchMetadata", "Would patch metadata with remote data: {0}", targetpath); } else { + Logging.Log.WriteVerboseMessage(LOGTAG, "PatchingMetadata", "Patching metadata with remote data: {0}", targetpath); try { var folderpath = m_systemIO.PathGetDirectoryName(targetpath); if (!options.Dryrun && !m_systemIO.DirectoryExists(folderpath)) { - result.AddWarning(string.Format("Creating missing folder {0} for target {1}", folderpath, targetpath), null); + Logging.Log.WriteWarningMessage(LOGTAG, "CreateMissingFolder", null, "Creating missing folder {0} for target {1}", folderpath, targetpath); m_systemIO.DirectoryCreate(folderpath); } @@ -326,7 +332,7 @@ namespace Duplicati.Library.Main.Operation } catch (Exception ex) { - result.AddWarning(string.Format("Failed to apply metadata to file: \"{0}\", message: {1}", targetpath, ex.Message), ex); + Logging.Log.WriteWarningMessage(LOGTAG, "MetadataWriteFailed", ex, "Failed to apply metadata to file: \"{0}\", message: {1}", targetpath, ex.Message); } } } @@ -348,14 +354,14 @@ namespace Duplicati.Library.Main.Operation var blockhasher = Library.Utility.HashAlgorithmHelper.Create(m_options.BlockHashAlgorithm); var filehasher = Library.Utility.HashAlgorithmHelper.Create(m_options.FileHashAlgorithm); if (blockhasher == null) - throw new UserInformationException(Strings.Common.InvalidHashAlgorithm(m_options.BlockHashAlgorithm)); + throw new UserInformationException(Strings.Common.InvalidHashAlgorithm(m_options.BlockHashAlgorithm), "BlockHashAlgorithmNotSupported"); if (!blockhasher.CanReuseTransform) - throw new UserInformationException(Strings.Common.InvalidCryptoSystem(m_options.BlockHashAlgorithm)); + throw new UserInformationException(Strings.Common.InvalidCryptoSystem(m_options.BlockHashAlgorithm), "BlockHashAlgorithmNotSupported"); if (filehasher == null) - throw new UserInformationException(Strings.Common.InvalidHashAlgorithm(m_options.FileHashAlgorithm)); + throw new UserInformationException(Strings.Common.InvalidHashAlgorithm(m_options.FileHashAlgorithm), "FileHashAlgorithmNotSupported"); if (!filehasher.CanReuseTransform) - throw new UserInformationException(Strings.Common.InvalidCryptoSystem(m_options.FileHashAlgorithm)); + throw new UserInformationException(Strings.Common.InvalidCryptoSystem(m_options.FileHashAlgorithm), "FileHashAlgorithmNotSupported"); if (!m_options.NoBackendverification) { @@ -365,21 +371,21 @@ namespace Duplicati.Library.Main.Operation //Figure out what files are to be patched, and what blocks are needed m_result.OperationProgressUpdater.UpdatePhase(OperationPhase.Restore_CreateFileList); - using(new Logging.Timer("PrepareBlockList")) + using(new Logging.Timer(LOGTAG, "PrepareBlockList", "PrepareBlockList")) PrepareBlockAndFileList(database, m_options, filter, result); //Make the entire output setup m_result.OperationProgressUpdater.UpdatePhase(OperationPhase.Restore_CreateTargetFolders); - using(new Logging.Timer("CreateDirectory")) + using(new Logging.Timer(LOGTAG, "CreateDirectory", "CreateDirectory")) CreateDirectoryStructure(database, m_options, result); //If we are patching an existing target folder, do not touch stuff that is already updated m_result.OperationProgressUpdater.UpdatePhase(OperationPhase.Restore_ScanForExistingFiles); - using(new Logging.Timer("ScanForexistingTargetBlocks")) + using(new Logging.Timer(LOGTAG, "ScanForExistingTargetBlocks", "ScanForExistingTargetBlocks")) ScanForExistingTargetBlocks(database, m_blockbuffer, blockhasher, filehasher, m_options, result); //Look for existing blocks in the original source files only - using(new Logging.Timer("ScanForExistingSourceBlocksFast")) + using(new Logging.Timer(LOGTAG, "ScanForExistingSourceBlocksFast", "ScanForExistingSourceBlocksFast")) if (!m_options.NoLocalBlocks && !string.IsNullOrEmpty(m_options.Restorepath)) { m_result.OperationProgressUpdater.UpdatePhase(OperationPhase.Restore_ScanForLocalBlocks); @@ -396,7 +402,7 @@ namespace Duplicati.Library.Main.Operation if (m_options.PatchWithLocalBlocks) { m_result.OperationProgressUpdater.UpdatePhase(OperationPhase.Restore_PatchWithLocalBlocks); - using(new Logging.Timer("PatchWithLocalBlocks")) + using(new Logging.Timer(LOGTAG, "PatchWithLocalBlocks", "PatchWithLocalBlocks")) ScanForExistingSourceBlocks(database, m_options, m_blockbuffer, blockhasher, result, metadatastorage); } @@ -408,12 +414,12 @@ namespace Duplicati.Library.Main.Operation // Fill BLOCKS with remote sources List volumes; - using (new Logging.Timer("GetMissingVolumes")) + using (new Logging.Timer(LOGTAG, "GetMissingVolumes", "GetMissingVolumes")) volumes = database.GetMissingVolumes().ToList(); if (volumes.Count > 0) { - m_result.AddMessage(string.Format("{0} remote files are required to restore", volumes.Count)); + Logging.Log.WriteInformationMessage(LOGTAG, "RemoteFileCount", "{0} remote files are required to restore", volumes.Count); m_result.OperationProgressUpdater.UpdatePhase(OperationPhase.Restore_DownloadingRemoteFiles); } @@ -434,7 +440,7 @@ namespace Duplicati.Library.Main.Operation catch (Exception ex) { brokenFiles.Add(blockvolume.Name); - result.AddError(string.Format("Failed to patch with remote file: \"{0}\", message: {1}", blockvolume.Name, ex.Message), ex); + Logging.Log.WriteErrorMessage(LOGTAG, "PatchingFailed", ex, "Failed to patch with remote file: \"{0}\", message: {1}", blockvolume.Name, ex.Message); if (ex is System.Threading.ThreadAbortException) throw; } @@ -459,7 +465,7 @@ namespace Duplicati.Library.Main.Operation if (m_options.PerformRestoredFileVerification) { // After all blocks in the files are restored, verify the file hash - using(new Logging.Timer("RestoreVerification")) + using(new Logging.Timer(LOGTAG, "RestoreVerification", "RestoreVerification")) foreach(var file in database.GetFilesToRestore(true)) { try @@ -470,7 +476,7 @@ namespace Duplicati.Library.Main.Operation return; } - result.AddVerboseMessage("Testing restored file integrity: {0}", file.Path); + Logging.Log.WriteVerboseMessage(LOGTAG, "TestFileIntegrity", "Testing restored file integrity: {0}", file.Path); string key; long size; @@ -488,7 +494,7 @@ namespace Duplicati.Library.Main.Operation catch (Exception ex) { fileErrors++; - result.AddWarning(ex.Message, ex); + Logging.Log.WriteErrorMessage(LOGTAG, "RestoreFileFailed", ex, ex.Message); if (ex is System.Threading.ThreadAbortException) throw; } @@ -496,9 +502,9 @@ namespace Duplicati.Library.Main.Operation } if (fileErrors > 0 && brokenFiles.Count > 0) - m_result.AddMessage(string.Format("Failed to restore {0} files, additionally the following files failed to download, which may be the cause:{1}{2}", fileErrors, Environment.NewLine, string.Join(Environment.NewLine, brokenFiles))); + Logging.Log.WriteInformationMessage(LOGTAG, "RestoreFailures", "Failed to restore {0} files, additionally the following files failed to download, which may be the cause:{1}{2}", fileErrors, Environment.NewLine, string.Join(Environment.NewLine, brokenFiles)); else if (fileErrors > 0) - m_result.AddMessage(string.Format("Failed to restore {0} files", fileErrors)); + Logging.Log.WriteInformationMessage(LOGTAG, "RestoreFailures", "Failed to restore {0} files", fileErrors); // Drop the temp tables database.DropRestoreTable(); @@ -576,7 +582,7 @@ namespace Duplicati.Library.Main.Operation var folderpath = m_systemIO.PathGetDirectoryName(targetpath); if (!options.Dryrun && !m_systemIO.DirectoryExists(folderpath)) { - result.AddWarning(string.Format("Creating missing folder {0} for file {1}", folderpath, targetpath), null); + Logging.Log.WriteWarningMessage(LOGTAG, "CreateMissingFolder", null, "Creating missing folder {0} for file {1}", folderpath, targetpath); m_systemIO.DirectoryCreate(folderpath); } @@ -619,7 +625,7 @@ namespace Duplicati.Library.Main.Operation } catch (Exception ex) { - result.AddWarning(string.Format("Failed to patch file: \"{0}\" with data from local file \"{1}\", message: {2}", targetpath, sourcepath, ex.Message), ex); + Logging.Log.WriteWarningMessage(LOGTAG, "PatchingFileLocalFailed", ex, "Failed to patch file: \"{0}\" with data from local file \"{1}\", message: {2}", targetpath, sourcepath, ex.Message); if (ex is System.Threading.ThreadAbortException) throw; } @@ -635,27 +641,27 @@ namespace Duplicati.Library.Main.Operation } else { - result.AddVerboseMessage("Local source file not found: {0}", sourcepath); + Logging.Log.WriteVerboseMessage(LOGTAG, "LocalSourceMissing", "Local source file not found: {0}", sourcepath); } } catch (Exception ex) { - result.AddWarning(string.Format("Failed to patch file: \"{0}\" with local data, message: {1}", targetpath, ex.Message), ex); + Logging.Log.WriteWarningMessage(LOGTAG, "PatchingFileLocalFailed", ex, "Failed to patch file: \"{0}\" with local data, message: {1}", targetpath, ex.Message); if (ex is System.Threading.ThreadAbortException) throw; } if (patched) - result.AddVerboseMessage("Target file is patched with some local data: {0}", targetpath); + Logging.Log.WriteVerboseMessage(LOGTAG, "FilePatchedWithLocal", "Target file is patched with some local data: {0}", targetpath); else - result.AddVerboseMessage("Target file is not patched any local data: {0}", targetpath); + Logging.Log.WriteVerboseMessage(LOGTAG, "FilePatchedWithLocal", "Target file is not patched any local data: {0}", targetpath); if (patched && options.Dryrun) - result.AddDryrunMessage(string.Format("Would patch file with local data: {0}", targetpath)); + Logging.Log.WriteDryrunMessage(LOGTAG, "WouldPatchWithLocal", "Would patch file with local data: {0}", targetpath); } blockmarker.UpdateProcessed(result.OperationProgressUpdater); - blockmarker.Commit(result); + blockmarker.Commit(); } } @@ -678,7 +684,7 @@ namespace Duplicati.Library.Main.Operation var folderpath = m_systemIO.PathGetDirectoryName(targetpath); if (!options.Dryrun && !m_systemIO.DirectoryExists(folderpath)) { - result.AddWarning(string.Format("Creating missing folder {0} for file {1}", folderpath, targetpath), null); + Logging.Log.WriteWarningMessage(LOGTAG, "CreateMissingFolder", null, "Creating missing folder {0} for file {1}", folderpath, targetpath); m_systemIO.DirectoryCreate(folderpath); } @@ -734,7 +740,7 @@ namespace Duplicati.Library.Main.Operation } catch (Exception ex) { - result.AddWarning(string.Format("Failed to patch file: \"{0}\" with data from local file \"{1}\", message: {2}", targetpath, source.Path, ex.Message), ex); + Logging.Log.WriteWarningMessage(LOGTAG, "PatchingFileLocalFailed", ex, "Failed to patch file: \"{0}\" with data from local file \"{1}\", message: {2}", targetpath, source.Path, ex.Message); if (ex is System.Threading.ThreadAbortException) throw; } @@ -746,20 +752,20 @@ namespace Duplicati.Library.Main.Operation } catch (Exception ex) { - result.AddWarning(string.Format("Failed to patch file: \"{0}\" with local data, message: {1}", targetpath, ex.Message), ex); + Logging.Log.WriteWarningMessage(LOGTAG, "PatchingFileLocalFailed", ex, "Failed to patch file: \"{0}\" with local data, message: {1}", targetpath, ex.Message); } if (patched) - result.AddVerboseMessage("Target file is patched with some local data: {0}", targetpath); + Logging.Log.WriteVerboseMessage(LOGTAG, "FilePatchedWithLocal", "Target file is patched with some local data: {0}", targetpath); else - result.AddVerboseMessage("Target file is not patched any local data: {0}", targetpath); + Logging.Log.WriteVerboseMessage(LOGTAG, "FilePatchedWithLocal", "Target file is not patched any local data: {0}", targetpath); if (patched && options.Dryrun) - result.AddDryrunMessage(string.Format("Would patch file with local data: {0}", targetpath)); + Logging.Log.WriteDryrunMessage(LOGTAG, "WouldPatchWithLocal", string.Format("Would patch file with local data: {0}", targetpath)); } blockmarker.UpdateProcessed(result.OperationProgressUpdater); - blockmarker.Commit(result); + blockmarker.Commit(); } } @@ -767,13 +773,13 @@ namespace Duplicati.Library.Main.Operation { // Create a temporary table FILES by selecting the files from fileset that matches a specific operation id // Delete all entries from the temp table that are excluded by the filter(s) - using(new Logging.Timer("PrepareRestoreFileList")) + using(new Logging.Timer(LOGTAG, "PrepareRestoreFileList", "PrepareRestoreFileList")) { - var c = database.PrepareRestoreFilelist(options.Time, options.Version, filter, result); + var c = database.PrepareRestoreFilelist(options.Time, options.Version, filter); result.OperationProgressUpdater.UpdatefileCount(c.Item1, c.Item2, true); } - using(new Logging.Timer("SetTargetPaths")) + using(new Logging.Timer(LOGTAG, "SetTargetPaths", "SetTargetPaths")) if (!string.IsNullOrEmpty(options.Restorepath)) { // Find the largest common prefix @@ -781,7 +787,7 @@ namespace Duplicati.Library.Main.Operation if (options.DontCompressRestorePaths) largest_prefix = ""; - result.AddVerboseMessage("Mapping restore path prefix to \"{0}\" to \"{1}\"", largest_prefix, Library.Utility.Utility.AppendDirSeparator(options.Restorepath)); + Logging.Log.WriteVerboseMessage(LOGTAG, "MappingRestorePath", "Mapping restore path prefix to \"{0}\" to \"{1}\"", largest_prefix, Library.Utility.Utility.AppendDirSeparator(options.Restorepath)); // Set the target paths, special care with C:\ and / database.SetTargetPaths(largest_prefix, Library.Utility.Utility.AppendDirSeparator(options.Restorepath)); @@ -792,11 +798,11 @@ namespace Duplicati.Library.Main.Operation } // Create a temporary table BLOCKS that lists all blocks that needs to be recovered - using(new Logging.Timer("FindMissingBlocks")) - database.FindMissingBlocks(result, options.SkipMetadata); + using(new Logging.Timer(LOGTAG, "FindMissingBlocks", "FindMissingBlocks")) + database.FindMissingBlocks(options.SkipMetadata); // Create temporary tables and triggers that automatically track progress - using (new Logging.Timer("CreateProgressTracker")) + using (new Logging.Timer(LOGTAG, "CreateProgressTracker", "CreateProgressTracker")) database.CreateProgressTracker(false); } @@ -807,11 +813,10 @@ namespace Duplicati.Library.Main.Operation if (!string.IsNullOrEmpty(options.Restorepath)) if (!m_systemIO.DirectoryExists(options.Restorepath)) { - if (options.Verbose) - result.AddVerboseMessage("Creating folder: {0}", options.Restorepath); + Logging.Log.WriteVerboseMessage(LOGTAG, "CreateFolder", "Creating folder: {0}", options.Restorepath); if (options.Dryrun) - result.AddDryrunMessage(string.Format("Would create folder: {0}", options.Restorepath)); + Logging.Log.WriteDryrunMessage(LOGTAG, "WouldCreateFolder", "Would create folder: {0}", options.Restorepath); else m_systemIO.DirectoryCreate(options.Restorepath); } @@ -827,18 +832,17 @@ namespace Duplicati.Library.Main.Operation { result.FoldersRestored++; - if (options.Verbose) - result.AddVerboseMessage("Creating folder: {0}", folder); + Logging.Log.WriteVerboseMessage(LOGTAG, "CreateFolder", "Creating folder: {0}", folder); if (options.Dryrun) - result.AddDryrunMessage(string.Format("Would create folder: {0}", folder)); + Logging.Log.WriteDryrunMessage(LOGTAG, "WouldCreateFolder", "Would create folder: {0}", folder); else m_systemIO.DirectoryCreate(folder); } } catch (Exception ex) { - result.AddWarning(string.Format("Failed to create folder: \"{0}\", message: {1}", folder, ex.Message), ex); + Logging.Log.WriteWarningMessage(LOGTAG, "FolderCreateFailed", ex, "Failed to create folder: \"{0}\", message: {1}", folder, ex.Message); } } } @@ -874,11 +878,12 @@ namespace Duplicati.Library.Main.Operation var currentAttr = m_systemIO.GetFileAttributes(targetpath); if ((currentAttr & System.IO.FileAttributes.ReadOnly) != 0) // clear readonly attribute { - if (options.Dryrun) result.AddDryrunMessage(string.Format("Would reset read-only attribute on file: {0}", targetpath)); + if (options.Dryrun) + Logging.Log.WriteDryrunMessage(LOGTAG, "WouldResetReadOnlyAttribyte", "Would reset read-only attribute on file: {0}", targetpath); else m_systemIO.SetFileAttributes(targetpath, currentAttr & ~System.IO.FileAttributes.ReadOnly); } if (options.Dryrun) - result.AddDryrunMessage(string.Format("Would truncate file '{0}' to length of {1:N0} bytes", targetpath, targetfilelength)); + Logging.Log.WriteDryrunMessage(LOGTAG, "WouldTruncateFile", "Would truncate file '{0}' to length of {1:N0} bytes", targetpath, targetfilelength); else { using (var file = m_systemIO.FileOpenWrite(targetpath)) @@ -952,7 +957,8 @@ namespace Duplicati.Library.Main.Operation var currentAttr = m_systemIO.GetFileAttributes(targetpath); if ((currentAttr & System.IO.FileAttributes.ReadOnly) != 0) { - if (options.Dryrun) result.AddDryrunMessage(string.Format("Would reset read-only attribute on file: {0}", targetpath)); + if (options.Dryrun) + Logging.Log.WriteDryrunMessage(LOGTAG, "WouldResetReadOnlyAttribyte", "Would reset read-only attribute on file: {0}", targetpath); else m_systemIO.SetFileAttributes(targetpath, currentAttr & ~System.IO.FileAttributes.ReadOnly); } } @@ -961,7 +967,7 @@ namespace Duplicati.Library.Main.Operation { //TODO: Check metadata to trigger rename? If metadata changed, it will still be restored for the file in-place. blockmarker.SetFileDataVerified(targetfileid); - result.AddVerboseMessage("Target file exists{1} and is correct version: {0}", targetpath, wasTruncated ? " (but was truncated)" : ""); + Logging.Log.WriteVerboseMessage(LOGTAG, "TargetExistsInCorrectVersion", "Target file exists{1} and is correct version: {0}", targetpath, wasTruncated ? " (but was truncated)" : ""); rename = false; } else if (rename) @@ -981,14 +987,14 @@ namespace Duplicati.Library.Main.Operation } catch (Exception ex) { - result.AddWarning(string.Format("Failed to read target file: \"{0}\", message: {1}", targetpath, ex.Message), ex); + Logging.Log.WriteWarningMessage(LOGTAG, "TargetFileReadError", ex, "Failed to read target file: \"{0}\", message: {1}", targetpath, ex.Message); if (ex is System.Threading.ThreadAbortException) throw; } } else { - result.AddVerboseMessage("Target file does not exist: {0}", targetpath); + Logging.Log.WriteVerboseMessage(LOGTAG, "MissingTargetFile", "Target file does not exist: {0}", targetpath); rename = false; } @@ -1026,21 +1032,21 @@ namespace Duplicati.Library.Main.Operation } catch(Exception ex) { - result.AddWarning(string.Format("Failed to read candidate restore target {0}", tr), ex); + Logging.Log.WriteWarningMessage(LOGTAG, "FailedToReadRestoreTarget", ex, "Failed to read candidate restore target {0}", tr); } tr = newname + " (" + (c++).ToString() + ")" + ext; } newname = tr; - result.AddVerboseMessage("Target file exists and will be restored to: {0}", newname); + Logging.Log.WriteVerboseMessage(LOGTAG, "TargetFileRetargeted", "Target file exists and will be restored to: {0}", newname); database.UpdateTargetPath(targetfileid, newname); } } blockmarker.UpdateProcessed(result.OperationProgressUpdater); - blockmarker.Commit(result); + blockmarker.Commit(); } } } diff --git a/Duplicati/Library/Main/Operation/RestoreHandlerMetadataStorage.cs b/Duplicati/Library/Main/Operation/RestoreHandlerMetadataStorage.cs index 32803c19b..ee5a513a7 100644 --- a/Duplicati/Library/Main/Operation/RestoreHandlerMetadataStorage.cs +++ b/Duplicati/Library/Main/Operation/RestoreHandlerMetadataStorage.cs @@ -22,6 +22,10 @@ namespace Duplicati.Library.Main.Operation { public class RestoreHandlerMetadataStorage : IDisposable { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(); private TempFile m_temp; private FileStream m_stream; private long m_entries; @@ -81,9 +85,9 @@ namespace Duplicati.Library.Main.Operation var bf = BitConverter.GetBytes(0L); var buf = new byte[8 * 1024]; - Logging.Log.WriteMessage(string.Format("The metadata storage file has {0} entries and takes up {1}", m_entries, Library.Utility.Utility.FormatSizeString(m_stream.Length)), Duplicati.Library.Logging.LogMessageType.Profiling); + Logging.Log.WriteProfilingMessage(LOGTAG, "MetadataStorageSize", "The metadata storage file has {0} entries and takes up {1}", m_entries, Library.Utility.Utility.FormatSizeString(m_stream.Length)); - using(new Logging.Timer("Read metadata from file")) + using(new Logging.Timer(LOGTAG, "ReadMetadata", "Read metadata from file")) for(var e = 0L; e < m_entries; e++) { m_stream.Position = pos; @@ -116,12 +120,12 @@ namespace Duplicati.Library.Main.Operation { if (m_stream != null) try { m_stream.Dispose(); } - catch { } + catch (Exception ex) { Logging.Log.WriteWarningMessage(LOGTAG, "DisposeError", ex, "Failed to dispose stream"); } finally { m_stream = null; } if (m_temp != null) try { m_temp.Dispose(); } - catch { } + catch (Exception ex) { Logging.Log.WriteWarningMessage(LOGTAG, "DisposeError", ex, "Failed to temp file stream"); } finally { m_temp = null; } } diff --git a/Duplicati/Library/Main/Operation/TestFilterHandler.cs b/Duplicati/Library/Main/Operation/TestFilterHandler.cs index 7b4b4775b..82d204563 100644 --- a/Duplicati/Library/Main/Operation/TestFilterHandler.cs +++ b/Duplicati/Library/Main/Operation/TestFilterHandler.cs @@ -23,6 +23,11 @@ namespace Duplicati.Library.Main.Operation { internal class TestFilterHandler : IDisposable { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(); + private readonly Options m_options; private TestFilterResults m_result; @@ -37,21 +42,21 @@ namespace Duplicati.Library.Main.Operation var storeSymlinks = m_options.SymlinkPolicy == Duplicati.Library.Main.Options.SymlinkStrategy.Store; var sourcefilter = new Library.Utility.FilterExpression(sources, true); - using(var snapshot = BackupHandler.GetSnapshot(sources, m_options, m_result)) + using(var snapshot = BackupHandler.GetSnapshot(sources, m_options)) { - foreach(var path in new BackupHandler.FilterHandler(snapshot, m_options.FileAttributeFilter, sourcefilter, filter, m_options.SymlinkPolicy, m_options.HardlinkPolicy, m_result).EnumerateFilesAndFolders()) + foreach(var path in new BackupHandler.FilterHandler(snapshot, m_options.FileAttributeFilter, sourcefilter, filter, m_options.SymlinkPolicy, m_options.HardlinkPolicy).EnumerateFilesAndFolders()) { var fa = FileAttributes.Normal; try { fa = snapshot.GetAttributes(path); } - catch { } - + catch (Exception ex) { Logging.Log.WriteVerboseMessage(LOGTAG, "FailedAttributeRead", "Failed to read attributes from {0}: {1}", path, ex.Message); } + if (storeSymlinks && snapshot.IsSymlink(path, fa)) { - m_result.AddVerboseMessage("Storing symlink: {0}", path); + Logging.Log.WriteVerboseMessage(LOGTAG, "StoreSymlink", "Storing symlink: {0}", path); } else if ((fa & FileAttributes.Directory) == FileAttributes.Directory) { - m_result.AddVerboseMessage("Including folder: {0}", path); + Logging.Log.WriteVerboseMessage(LOGTAG, "AddDirectory", "Including folder {0}", path); } else { @@ -63,15 +68,16 @@ namespace Duplicati.Library.Main.Operation size = snapshot.GetFileSize(path); m_result.FileSize += size; } - catch - { + catch (Exception ex) + { + Logging.Log.WriteVerboseMessage(LOGTAG, "SizeReadFailed", "Failed to read length of file {0}: {1}", path, ex.Message); } if (m_options.SkipFilesLargerThan == long.MaxValue || m_options.SkipFilesLargerThan == 0 || size < m_options.SkipFilesLargerThan) - m_result.AddVerboseMessage("Including file: {0} ({1})", path, size < 0 ? "unknown" : Duplicati.Library.Utility.Utility.FormatSizeString(size)); + Logging.Log.WriteVerboseMessage(LOGTAG, "IncludeFile", "Including file: {0} ({1})", path, size < 0 ? "unknown" : Duplicati.Library.Utility.Utility.FormatSizeString(size)); else - m_result.AddVerboseMessage("Excluding file due to size: {0} ({1})", path, size < 0 ? "unknown" : Duplicati.Library.Utility.Utility.FormatSizeString(size)); + Logging.Log.WriteVerboseMessage(LOGTAG, "ExcludeLargeFile", "Excluding file due to size: {0} ({1})", path, size < 0 ? "unknown" : Duplicati.Library.Utility.Utility.FormatSizeString(size)); } } diff --git a/Duplicati/Library/Main/Operation/TestHandler.cs b/Duplicati/Library/Main/Operation/TestHandler.cs index b0dd5617e..7d5a0fc25 100644 --- a/Duplicati/Library/Main/Operation/TestHandler.cs +++ b/Duplicati/Library/Main/Operation/TestHandler.cs @@ -25,6 +25,11 @@ namespace Duplicati.Library.Main.Operation { internal class TestHandler { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(); + private readonly Options m_options; private string m_backendurl; private TestResults m_results; @@ -39,7 +44,7 @@ namespace Duplicati.Library.Main.Operation public void Run(long samples) { if (!System.IO.File.Exists(m_options.Dbpath)) - throw new UserInformationException(string.Format("Database file does not exist: {0}", m_options.Dbpath)); + throw new UserInformationException(string.Format("Database file does not exist: {0}", m_options.Dbpath), "DatabaseDoesNotExist"); using(var db = new LocalTestDatabase(m_options.Dbpath)) using(var backend = new BackendManager(m_backendurl, m_options, m_results.BackendWriter, db)) @@ -82,7 +87,7 @@ namespace Duplicati.Library.Main.Operation KeyValuePair>> res; using(var tf = vol.TempFile) - res = TestVolumeInternals(db, vol, tf, m_options, m_results, m_options.FullBlockVerification ? 1.0 : 0.2); + res = TestVolumeInternals(db, vol, tf, m_options, m_options.FullBlockVerification ? 1.0 : 0.2); m_results.AddResult(res.Key, res.Value); if (!string.IsNullOrWhiteSpace(vol.Hash) && vol.Size > 0) @@ -100,11 +105,11 @@ namespace Duplicati.Library.Main.Operation { if (m_options.Dryrun) { - m_results.AddDryrunMessage(string.Format("Sucessfully captured hash and size for {0}, would update database", vol.Name)); + Logging.Log.WriteDryrunMessage(LOGTAG, "CaptureHashAndSize", "Sucessfully captured hash and size for {0}, would update database", vol.Name); } else { - m_results.AddMessage(string.Format("Sucessfully captured hash and size for {0}, updating database", vol.Name)); + Logging.Log.WriteInformationMessage(LOGTAG, "CaptureHashAndSize", "Sucessfully captured hash and size for {0}, updating database", vol.Name); db.UpdateRemoteVolume(vol.Name, RemoteVolumeState.Verified, vol.Size, vol.Hash); } } @@ -117,7 +122,7 @@ namespace Duplicati.Library.Main.Operation catch (Exception ex) { m_results.AddResult(vol.Name, new KeyValuePair[] { new KeyValuePair(Duplicati.Library.Interface.TestEntryStatus.Error, ex.Message) }); - m_results.AddError(string.Format("Failed to process file {0}", vol.Name), ex); + Logging.Log.WriteErrorMessage(LOGTAG, "RemoteFileProcessingFailed", ex, "Failed to process file {0}", vol.Name); if (ex is System.Threading.ThreadAbortException) { m_results.EndTime = DateTime.UtcNow; @@ -143,13 +148,13 @@ namespace Duplicati.Library.Main.Operation if (f.Size <= 0 || string.IsNullOrWhiteSpace(f.Hash)) { - m_results.AddMessage(string.Format("No hash or size recorded for {0}, performing full verification", f.Name)); + Logging.Log.WriteInformationMessage(LOGTAG, "MissingRemoteHash", "No hash or size recorded for {0}, performing full verification", f.Name); KeyValuePair>> res; string hash; long size; using (var tf = backend.GetWithInfo(f.Name, out size, out hash)) - res = TestVolumeInternals(db, f, tf, m_options, m_results, 1); + res = TestVolumeInternals(db, f, tf, m_options, 1); m_results.AddResult(res.Key, res.Value); if (!string.IsNullOrWhiteSpace(hash) && size > 0) @@ -158,11 +163,11 @@ namespace Duplicati.Library.Main.Operation { if (m_options.Dryrun) { - m_results.AddDryrunMessage(string.Format("Sucessfully captured hash and size for {0}, would update database", f.Name)); + Logging.Log.WriteDryrunMessage(LOGTAG, "CapturedHashAndSize", "Sucessfully captured hash and size for {0}, would update database", f.Name); } else { - m_results.AddMessage(string.Format("Sucessfully captured hash and size for {0}, updating database", f.Name)); + Logging.Log.WriteInformationMessage(LOGTAG, "CapturedHashAndSize", "Sucessfully captured hash and size for {0}, updating database", f.Name); db.UpdateRemoteVolume(f.Name, RemoteVolumeState.Verified, size, hash); } } @@ -177,7 +182,7 @@ namespace Duplicati.Library.Main.Operation catch (Exception ex) { m_results.AddResult(f.Name, new KeyValuePair[] { new KeyValuePair(Duplicati.Library.Interface.TestEntryStatus.Error, ex.Message) }); - m_results.AddError(string.Format("Failed to process file {0}", f.Name), ex); + Logging.Log.WriteErrorMessage(LOGTAG, "FailedToProcessFile", ex, "Failed to process file {0}", f.Name); if (ex is System.Threading.ThreadAbortException) { m_results.EndTime = DateTime.UtcNow; @@ -196,14 +201,14 @@ namespace Duplicati.Library.Main.Operation /// The remote volume being examined /// The path to the downloaded copy of the file /// A value between 0 and 1 that indicates how many blocks are tested in a dblock file - public static KeyValuePair>> TestVolumeInternals(LocalTestDatabase db, IRemoteVolume vol, string tf, Options options, ILogWriter log, double sample_percent) + public static KeyValuePair>> TestVolumeInternals(LocalTestDatabase db, IRemoteVolume vol, string tf, Options options, double sample_percent) { var blockhasher = Library.Utility.HashAlgorithmHelper.Create(options.BlockHashAlgorithm); if (blockhasher == null) - throw new UserInformationException(Strings.Common.InvalidHashAlgorithm(options.BlockHashAlgorithm)); + throw new UserInformationException(Strings.Common.InvalidHashAlgorithm(options.BlockHashAlgorithm), "BlockHashAlgorithmInvalid"); if (!blockhasher.CanReuseTransform) - throw new UserInformationException(Strings.Common.InvalidCryptoSystem(options.BlockHashAlgorithm)); + throw new UserInformationException(Strings.Common.InvalidCryptoSystem(options.BlockHashAlgorithm), "BlockHashAlgorithmInvalid"); var hashsize = blockhasher.HashSize / 8; var parsedInfo = Volumes.VolumeBase.ParseFilename(vol.Name); @@ -285,7 +290,7 @@ namespace Duplicati.Library.Main.Operation } } - log.AddWarning(string.Format("Unexpected file type {0} for {1}", parsedInfo.FileType, vol.Name), null); + Logging.Log.WriteWarningMessage(LOGTAG, "UnexpectedFileType", null, "Unexpected file type {0} for {1}", parsedInfo.FileType, vol.Name); return new KeyValuePair>>(vol.Name, null); } } diff --git a/Duplicati/Library/Main/Options.cs b/Duplicati/Library/Main/Options.cs index 465dfcbf7..d28ac6161 100644 --- a/Duplicati/Library/Main/Options.cs +++ b/Duplicati/Library/Main/Options.cs @@ -188,7 +188,7 @@ namespace Duplicati.Library.Main /// /// Lock that protects the options collection /// - protected object m_lock = new object(); + protected readonly object m_lock = new object(); protected Dictionary m_options; @@ -257,7 +257,8 @@ namespace Duplicati.Library.Main "compression-extension-file", "full-remote-verification", "disable-synthetic-filelist", - "disable-file-scanner" + "disable-file-scanner", + "disable-on-battery" }; } } @@ -280,7 +281,8 @@ namespace Duplicati.Library.Main "max-upload-pr-second", "max-download-pr-second", "no-connection-reuse", - "allow-sleep" + "allow-sleep", + "use-background-io-priority" }; } } @@ -310,7 +312,10 @@ namespace Duplicati.Library.Main "debug-output", "debug-retry-errors", "log-file", - "log-level", + "log-file-log-level", + "log-file-log-filter", + "console-log-level", + "console-log-filter", }; } } @@ -460,11 +465,18 @@ namespace Duplicati.Library.Main new CommandLineArgument("debug-output", CommandLineArgument.ArgumentType.Boolean, Strings.Options.DebugoutputShort, Strings.Options.DebugoutputLong, "false"), new CommandLineArgument("debug-retry-errors", CommandLineArgument.ArgumentType.Boolean, Strings.Options.DebugretryerrorsShort, Strings.Options.DebugretryerrorsLong, "false"), - new CommandLineArgument("log-file", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Path, Strings.Options.LogfileShort, Strings.Options.LogfileShort), - new CommandLineArgument("log-level", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Enumeration, Strings.Options.LoglevelShort, Strings.Options.LoglevelLong, "Warning", null, Enum.GetNames(typeof(Duplicati.Library.Logging.LogMessageType))), + new CommandLineArgument("log-file", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Path, Strings.Options.LogfileShort, Strings.Options.LogfileLong), + new CommandLineArgument("log-file-log-level", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Enumeration, Strings.Options.LogfileloglevelShort, Strings.Options.LogfileloglevelShort, "Warning", null, Enum.GetNames(typeof(Duplicati.Library.Logging.LogMessageType))), + new CommandLineArgument("log-file-log-filter", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.String, Strings.Options.LogfilelogfiltersShort, Strings.Options.LogfilelogfiltersLong(System.IO.Path.PathSeparator.ToString()), null), + + new CommandLineArgument("console-log-level", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Enumeration, Strings.Options.ConsoleloglevelShort, Strings.Options.ConsoleloglevelShort, "Warning", null, Enum.GetNames(typeof(Duplicati.Library.Logging.LogMessageType))), + new CommandLineArgument("console-log-filter", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.String, Strings.Options.ConsolelogfiltersShort, Strings.Options.ConsolelogfiltersLong(System.IO.Path.PathSeparator.ToString()), null), + + new CommandLineArgument("log-level", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Enumeration, Strings.Options.LoglevelShort, Strings.Options.LoglevelLong, "Warning", null, Enum.GetNames(typeof(Duplicati.Library.Logging.LogMessageType)), Strings.Options.LogLevelDeprecated("log-file-log-level", "console-log-level")), new CommandLineArgument("list-verify-uploads", CommandLineArgument.ArgumentType.Boolean, Strings.Options.ListverifyuploadsShort, Strings.Options.ListverifyuploadsShort, "false"), new CommandLineArgument("allow-sleep", CommandLineArgument.ArgumentType.Boolean, Strings.Options.AllowsleepShort, Strings.Options.AllowsleepLong, "false"), + new CommandLineArgument("use-background-io-priority", CommandLineArgument.ArgumentType.Boolean, Strings.Options.UsebackgroundiopriorityShort, Strings.Options.UsebackgroundiopriorityLong, "false"), new CommandLineArgument("no-connection-reuse", CommandLineArgument.ArgumentType.Boolean, Strings.Options.NoconnectionreuseShort, Strings.Options.NoconnectionreuseLong, "false"), new CommandLineArgument("quota-size", CommandLineArgument.ArgumentType.Size, Strings.Options.QuotasizeShort, Strings.Options.QuotasizeLong), @@ -478,7 +490,7 @@ namespace Duplicati.Library.Main new CommandLineArgument("backup-name", CommandLineArgument.ArgumentType.String, Strings.Options.BackupnameShort, Strings.Options.BackupnameLong, DefaultBackupName), new CommandLineArgument("compression-extension-file", CommandLineArgument.ArgumentType.Path, Strings.Options.CompressionextensionfileShort, Strings.Options.CompressionextensionfileLong(DEFAULT_COMPRESSED_EXTENSION_FILE), DEFAULT_COMPRESSED_EXTENSION_FILE), - new CommandLineArgument("verbose", CommandLineArgument.ArgumentType.Boolean, Strings.Options.VerboseShort, Strings.Options.VerboseLong, "false"), + new CommandLineArgument("verbose", CommandLineArgument.ArgumentType.Boolean, Strings.Options.VerboseShort, Strings.Options.VerboseLong, "false", null, null, Strings.Options.VerboseDeprecated), new CommandLineArgument("full-result", CommandLineArgument.ArgumentType.Boolean, Strings.Options.FullresultShort, Strings.Options.FullresultLong, "false"), new CommandLineArgument("overwrite", CommandLineArgument.ArgumentType.Boolean, Strings.Options.OverwriteShort, Strings.Options.OverwriteLong, "false"), @@ -532,6 +544,7 @@ namespace Duplicati.Library.Main new CommandLineArgument("auto-vacuum", CommandLineArgument.ArgumentType.Boolean, Strings.Options.AutoVacuumShort, Strings.Options.AutoVacuumLong, "false"), new CommandLineArgument("disable-file-scanner", CommandLineArgument.ArgumentType.Boolean, Strings.Options.DisablefilescannerShort, Strings.Options.DisablefilescannerLong, "false"), + new CommandLineArgument("disable-on-battery", CommandLineArgument.ArgumentType.Boolean, Strings.Options.DisableOnBatteryShort, Strings.Options.DisableOnBatteryLong, "false"), }); return lst; @@ -816,10 +829,10 @@ namespace Duplicati.Library.Main /// /// Gets the time frames and intervals for the retention policy /// - public Dictionary RetentionPolicy + public List RetentionPolicy { get { - var retentionPolicyConfig = new Dictionary(); + var retentionPolicyConfig = new List(); string v; m_options.TryGetValue("retention-policy", out v); @@ -831,11 +844,7 @@ namespace Duplicati.Library.Main foreach (var periodIntervalString in periodIntervalStrings) { - var periodInterval = periodIntervalString.Split(':'); - var period = Library.Utility.Timeparser.ParseTimeSpan(periodInterval[0]); - var interval = Library.Utility.Timeparser.ParseTimeSpan(periodInterval[1]); - - retentionPolicyConfig.Add(period, interval); + retentionPolicyConfig.Add(RetentionPolicyValue.CreateFromString(periodIntervalString)); } return retentionPolicyConfig; @@ -937,7 +946,7 @@ namespace Duplicati.Library.Main { int x = int.Parse(m_options["number-of-retries"]); if (x < 0) - throw new UserInformationException("Invalid count for number-of-retries"); + throw new UserInformationException("Invalid count for number-of-retries", "NumberOfRetriesInvalid"); return x; } @@ -950,10 +959,15 @@ namespace Duplicati.Library.Main public bool SynchronousUpload { get { return Library.Utility.Utility.ParseBoolOption(m_options, "synchronous-upload"); } } /// - /// A value indicating if system is allowed to enter sleep power states during backup/restore ops (win32 only) + /// A value indicating if system is allowed to enter sleep power states during backup/restore /// public bool AllowSleep { get { return GetBool("allow-sleep"); } } + /// + /// A value indicating if system should use the low-priority IO during backup/restore + /// + public bool UseBackgroundIOPriority { get { return GetBool("use-background-io-priority"); } } + /// /// A value indicating if use of the streaming interface is disallowed /// @@ -1212,34 +1226,19 @@ namespace Duplicati.Library.Main } /// - /// Gets a value indicating if the log level has been set + /// Gets the log-file detail level /// - public bool HasLoglevel + public Duplicati.Library.Logging.LogMessageType LogFileLoglevel { get { string value; - if (!m_options.TryGetValue("log-level", out value)) + if (!m_options.TryGetValue("log-file-log-level", out value)) value = null; - foreach (string s in Enum.GetNames(typeof(Duplicati.Library.Logging.LogMessageType))) - if (s.Equals(value, StringComparison.OrdinalIgnoreCase)) - return true; - - return false; - } - } - - /// - /// Gets the log detail level - /// - public Duplicati.Library.Logging.LogMessageType Loglevel - { - get - { - string value; - if (!m_options.TryGetValue("log-level", out value)) - value = null; + if (string.IsNullOrWhiteSpace(value)) + if (!m_options.TryGetValue("log-level", out value)) + value = null; foreach (string s in Enum.GetNames(typeof(Duplicati.Library.Logging.LogMessageType))) if (s.Equals(value, StringComparison.OrdinalIgnoreCase)) @@ -1249,6 +1248,102 @@ namespace Duplicati.Library.Main } } + /// + /// Helper method to support filters with either a + or - prefix + /// + /// The IFilter instance. + /// The filter string to parse. + private static IFilter StringToIFilter(string msg) + { + if (string.IsNullOrWhiteSpace(msg)) + return new FilterExpression(); + if (msg[0] == '+') + return new FilterExpression(msg.Substring(1), true); + if (msg[0] == '-') + return new FilterExpression(msg.Substring(1), false); + return new FilterExpression(msg, true); + } + + /// + /// Parses a log filter string, and returns the filter instance + /// + /// The log filter. + /// The filter string to parse. + public static IFilter ParseLogFilter(string value) + { + if (string.IsNullOrWhiteSpace(value)) + return new FilterExpression(); + + return value + .Split(new char[] { System.IO.Path.PathSeparator, ':', ';', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries) + .Select(StringToIFilter) + .Aggregate(FilterExpression.Combine); + } + + /// + /// Parses a log level string + /// + /// The log level enumeration value. + /// The string value to parse. + /// An optional fallback parsing value. + public static Logging.LogMessageType ParseLogLevel(string value, string backupvalue) + { + value = string.IsNullOrWhiteSpace(value) ? backupvalue : value; + foreach (string s in Enum.GetNames(typeof(Duplicati.Library.Logging.LogMessageType))) + if (s.Equals(value, StringComparison.OrdinalIgnoreCase)) + return (Duplicati.Library.Logging.LogMessageType)Enum.Parse(typeof(Duplicati.Library.Logging.LogMessageType), s); + + return Duplicati.Library.Logging.LogMessageType.Warning; + } + + /// + /// Gets the filter used for log-file messages. + /// + /// The log file filter. + public IFilter LogFileLogFilter + { + get + { + m_options.TryGetValue("log-file-log-filter", out var value); + return ParseLogFilter(value); + } + } + + /// + /// Gets the filter used for console messages. + /// + /// The log file filter. + public IFilter ConsoleLogFilter + { + get + { + m_options.TryGetValue("console-log-filter", out var value); + return ParseLogFilter(value); + } + } + + /// + /// Gets the console log detail level + /// + public Duplicati.Library.Logging.LogMessageType ConsoleLoglevel + { + get + { + string value; + if (!m_options.TryGetValue("console-log-level", out value)) + value = null; + + if (string.IsNullOrWhiteSpace(value)) + if (!m_options.TryGetValue("log-level", out value)) + value = null; + + foreach (string s in Enum.GetNames(typeof(Duplicati.Library.Logging.LogMessageType))) + if (s.Equals(value, StringComparison.OrdinalIgnoreCase)) + return (Duplicati.Library.Logging.LogMessageType)Enum.Parse(typeof(Duplicati.Library.Logging.LogMessageType), s); + + return Duplicati.Library.Logging.LogMessageType.Warning; + } + } /// /// Gets the attribute filter used to exclude files and folders. /// @@ -1282,11 +1377,6 @@ namespace Duplicati.Library.Main /// public bool NoConnectionReuse { get { return GetBool("no-connection-reuse"); } } - /// - /// A value indicating if the output should be verbose - /// - public bool Verbose { get { return GetBool("verbose"); } } - /// /// A value indicating if the returned value should not be truncated /// @@ -1802,6 +1892,15 @@ namespace Duplicati.Library.Main get { return Library.Utility.Utility.ParseBoolOption(m_options, "disable-file-scanner"); } } + /// + /// Gets a flag indicating whether the backup should be disabled when on battery power. + /// + /// true if the backup should be disabled when on battery power; otherwise, false. + public bool DisableOnBattery + { + get { return Library.Utility.Utility.ParseBoolOption(m_options, "disable-on-battery"); } + } + /// /// Gets the threshold for when log data should be cleaned /// @@ -1878,5 +1977,89 @@ namespace Duplicati.Library.Main return Library.Utility.Utility.ParseBoolOption(m_options, name); } + /// + /// Class for handling a single RententionPolicy timeframe-interval-pair + /// + public class RetentionPolicyValue + { + public readonly TimeSpan Timeframe; + public readonly TimeSpan Interval; + + public RetentionPolicyValue(TimeSpan timeframe, TimeSpan interval) + { + if (timeframe < TimeSpan.Zero) + { + throw new ArgumentOutOfRangeException(nameof(timeframe), string.Format("The timeframe cannot be negative: '{0}'", timeframe)); + } + if (interval < TimeSpan.Zero) + { + throw new ArgumentOutOfRangeException(nameof(interval), string.Format("The interval cannot be negative: '{0}'", interval)); + } + + this.Timeframe = timeframe; + this.Interval = interval; + } + + /// + /// Returns whether this is an unlimited timeframe or not + /// + /// + public Boolean IsUnlimtedTimeframe() + { + // Timeframes equal or bigger than the maximum TimeSpan effectivly represent an unlimited timeframe + return Timeframe >= TimeSpan.MaxValue; + } + + /// + /// Returns whether all versions in this timeframe should be kept or not + /// + /// + public Boolean IsKeepAllVersions() + { + /// Intervals between two versions that are equal or smaller than zero effectivly result in + /// all versions in that timeframe being kept. + return Interval <= TimeSpan.Zero; + } + + public override string ToString() + { + return (IsUnlimtedTimeframe() ? "Unlimited" : Timeframe.ToString()) + " / " + (IsKeepAllVersions() ? "Keep all" : Interval.ToString()); + } + + /// + /// Parses a string representation of a timeframe-interval-pair and returns a RentionPolicyValue object + /// + /// + public static RetentionPolicyValue CreateFromString(string rententionPolicyValueString) + { + var periodInterval = rententionPolicyValueString.Split(':'); + + TimeSpan timeframe; + // Timeframe "U" (= Unlimited) means: For unlimted time keep one version every X interval. + // So the timeframe has to span the maximum time possible. + if (String.Equals(periodInterval[0], "U", StringComparison.OrdinalIgnoreCase)) + { + timeframe = TimeSpan.MaxValue; + } + else + { + timeframe = Library.Utility.Timeparser.ParseTimeSpan(periodInterval[0]); + } + + TimeSpan interval; + // Interval "U" (= Unlimited) means: For period X keep all versions. + // So the interval between two versions has to be zero. + if (String.Equals(periodInterval[1], "U", StringComparison.OrdinalIgnoreCase)) + { + interval = TimeSpan.Zero; + } + else + { + interval = Library.Utility.Timeparser.ParseTimeSpan(periodInterval[1]); + } + + return new RetentionPolicyValue(timeframe, interval); + } + } } } diff --git a/Duplicati/Library/Main/ProcessController.cs b/Duplicati/Library/Main/ProcessController.cs new file mode 100755 index 000000000..e56850e3c --- /dev/null +++ b/Duplicati/Library/Main/ProcessController.cs @@ -0,0 +1,403 @@ +// Copyright (C) 2018, The Duplicati Team +// http://www.duplicati.com, info@duplicati.com +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +using System; +using System.Linq; +using Duplicati.Library.Utility; + +namespace Duplicati.Library.Main +{ + /// + /// This class provides various process control tasks, + /// such as preventing sleep and setting the IO priority of + /// the running process + /// + public class ProcessController : IDisposable + { + /// + /// The log tag to use + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(); + + /// + /// A flag used to control the stop invocation + /// + private bool m_disposed = true; + + /// + /// A flag indicating if the sleep prevention has been started + /// + private bool m_runningSleepPrevention; + + /// + /// A flag indicating if the background IO priority has been started + /// + private bool m_hasEnabledBackgroundIOPriority; + + /// + /// The caffeinate process runner + /// + private System.Diagnostics.Process m_caffeinate; + + /// + /// The nice level to restore the process to + /// + private int m_originalNiceLevel; + + /// + /// The nice class to restore the process to + /// + private int m_originalNiceClass; + + /// + /// The priority class to restore the process to + /// + private Win32.IO_PRIORITY_HINT m_originalWinPriorityClass; + + /// + /// A flag indicating if the Windows background mode is started + /// + private bool m_hasStartedBackgroundMode = false; + + /// + /// Initializes a new instance of the class. + /// + /// The options to use. + public ProcessController(Options options) + { + if (options == null) + return; + + try + { + Start(options); + m_disposed = false; + } + catch (Exception ex) + { + Logging.Log.WriteWarningMessage(LOGTAG, "ProcessControllerStartError", ex, "Failed to start the process controller: {0}", ex.Message); + } + + } + + /// + /// Starts the sleep prevention + /// + private void StartSleepPrevention() + { + if (Duplicati.Library.Utility.Utility.IsClientWindows) + { + try + { + Win32.SetThreadExecutionState(Win32.EXECUTION_STATE.ES_CONTINUOUS | Win32.EXECUTION_STATE.ES_SYSTEM_REQUIRED); + m_runningSleepPrevention = true; + } + catch (Exception ex) + { + Logging.Log.WriteWarningMessage(LOGTAG, "SleepPrevetionError", ex, "Failed to set sleep prevention"); + } + } + else if (Duplicati.Library.Utility.Utility.IsClientOSX) + { + try + { + // -s prevents sleep on AC, -i prevents sleep generally + var psi = new System.Diagnostics.ProcessStartInfo("caffeinate", "-s"); + psi.RedirectStandardInput = true; + psi.UseShellExecute = false; + m_caffeinate = System.Diagnostics.Process.Start(psi); + m_runningSleepPrevention = true; + } + catch (Exception ex) + { + Logging.Log.WriteWarningMessage(LOGTAG, "SleepPreventionError", ex, "Failed to set sleep prevention"); + } + } + else + { + + + } + } + + /// + /// Activates the process bacground IO priority + /// + private void ActivateBackgroundIOPriority() + { + var pid = System.Diagnostics.Process.GetCurrentProcess().Id; + + if (Duplicati.Library.Utility.Utility.IsClientWindows) + { + var handle = System.Diagnostics.Process.GetCurrentProcess().Handle; + + try + { + var mode = Win32.IO_PRIORITY_HINT.IoPriorityLow; + var res = Win32.NtQueryInformationProcess(handle, Win32.PROCESS_INFORMATION_CLASS.ProcessIoPriority, ref mode, sizeof(Win32.IO_PRIORITY_HINT), IntPtr.Zero); + if (res != 0) + throw new Library.Interface.UserInformationException($"Failed to read process priority {res:x}", "BackgroundPriorityEnableError", new System.ComponentModel.Win32Exception()); + + m_originalWinPriorityClass = mode; + mode = Win32.IO_PRIORITY_HINT.IoPriorityVeryLow; + res = Win32.NtSetInformationProcess(handle, Win32.PROCESS_INFORMATION_CLASS.ProcessIoPriority, ref mode, sizeof(Win32.IO_PRIORITY_HINT)); + if (res != 0) + throw new Library.Interface.UserInformationException($"Failed to set process priority {res:x}", "BackgroundPriorityEnableError", new System.ComponentModel.Win32Exception()); + + m_hasEnabledBackgroundIOPriority = true; + } + catch (Exception ex) + { + Logging.Log.WriteWarningMessage(LOGTAG, "BackgroundPriorityError", ex, "Failed to set background IO priority"); + } + + try + { + if (!Win32.SetPriorityClass(handle, Win32.PROCESS_PRIORITY_CLASS.PROCESS_MODE_BACKGROUND_BEGIN)) + throw new Library.Interface.UserInformationException($"Failed to start process background mode", "BackgroundPriorityEnableError", new System.ComponentModel.Win32Exception()); + m_hasStartedBackgroundMode = true; + } + catch (Exception ex) + { + Logging.Log.WriteWarningMessage(LOGTAG, "BackgroundPriorityError", ex, "Failed to set start background processing mode"); + } + } + else + { + if (Duplicati.Library.Utility.Utility.IsClientOSX) + { + var data = RunProcessAndGetResult("ps", $"-onice -p {pid}"); + m_originalNiceLevel = int.Parse(data.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).Last()); + + data = RunProcessAndGetResult("renice", $"20 {pid}"); + m_hasEnabledBackgroundIOPriority = true; + } + else + { + var data = RunProcessAndGetResult("ionice", $"-p {pid}"); + var results = data.Split(new char[] { ':', ' ', '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); + var ioclass = results[0]; + if (string.Equals(ioclass, "idle", StringComparison.OrdinalIgnoreCase)) + { + m_originalNiceClass = 3; + m_originalNiceLevel = -1; + } + else if (string.Equals(ioclass, "none", StringComparison.OrdinalIgnoreCase)) + { + m_originalNiceClass = 0; + m_originalNiceLevel = int.Parse(results.Last()); + } + else if (string.Equals(ioclass, "best-effort", StringComparison.OrdinalIgnoreCase)) + { + m_originalNiceClass = 2; + m_originalNiceLevel = int.Parse(results.Last()); + } + else if (string.Equals(ioclass, "realtime", StringComparison.OrdinalIgnoreCase)) + { + m_originalNiceClass = 1; + m_originalNiceLevel = int.Parse(results.Last()); + } + else + throw new Library.Interface.UserInformationException($"Unable to parse priority class {ioclass}", "UnableToParseIONicePriorityClass"); + + data = RunProcessAndGetResult("ionice", $"-c 3 -p {pid}"); + m_hasEnabledBackgroundIOPriority = true; + } + } + } + + /// + /// Starts the process controller + /// + /// The options to use + private void Start(Options options) + { + if (!options.AllowSleep) + StartSleepPrevention(); + + if (options.UseBackgroundIOPriority) + ActivateBackgroundIOPriority(); + } + + /// + /// Stops the sleep prevention, if it was enabled + /// + private void StopSleepPrevention() + { + if (Duplicati.Library.Utility.Utility.IsClientWindows) + { + try + { + if (m_runningSleepPrevention) + { + m_runningSleepPrevention = false; + Win32.SetThreadExecutionState(Win32.EXECUTION_STATE.ES_CONTINUOUS); + } + } + catch (Exception ex) + { + Logging.Log.WriteWarningMessage(LOGTAG, "SleepPrevetionError", ex, "Failed to set sleep prevention"); + } + } + else if (Duplicati.Library.Utility.Utility.IsClientOSX) + { + try + { + m_runningSleepPrevention = false; + if (m_caffeinate != null && !m_caffeinate.HasExited) + { + // Send CTRL+C + m_caffeinate.StandardInput.Write("\x3"); + m_caffeinate.StandardInput.Flush(); + m_caffeinate.WaitForExit(500); + + if (!m_caffeinate.HasExited) + { + m_caffeinate.Kill(); + m_caffeinate.WaitForExit(500); + if (!m_caffeinate.HasExited) + throw new Exception("Failed to kill the caffeinate process"); + } + } + } + catch (Exception ex) + { + Logging.Log.WriteWarningMessage(LOGTAG, "SleepPreventionDisableError", ex, "Failed to unset sleep prevention"); + } + } + } + + /// + /// Deactivates the background IO Priority, if set. + /// + private void DeactivateBackgroundIOPriority() + { + if (Duplicati.Library.Utility.Utility.IsClientWindows) + { + try + { + if (m_hasStartedBackgroundMode) + { + m_hasStartedBackgroundMode = false; + var handle = System.Diagnostics.Process.GetCurrentProcess().Handle; + if (!Win32.SetPriorityClass(handle, Win32.PROCESS_PRIORITY_CLASS.PROCESS_MODE_BACKGROUND_END)) + throw new Library.Interface.UserInformationException($"Failed to stop process background mode", "BackgroundPriorityEnableError", new System.ComponentModel.Win32Exception()); + } + } + catch (Exception ex) + { + Logging.Log.WriteWarningMessage(LOGTAG, "BackgroundPriorityError", ex, "Failed to stop start background processing mode"); + } + + try + { + if (m_hasEnabledBackgroundIOPriority) + { + m_hasEnabledBackgroundIOPriority = false; + + var handle = System.Diagnostics.Process.GetCurrentProcess().Handle; + var mode = m_originalWinPriorityClass; + var res = Win32.NtSetInformationProcess(handle, Win32.PROCESS_INFORMATION_CLASS.ProcessIoPriority, ref mode, sizeof(Win32.IO_PRIORITY_HINT)); + if (res != 0) + Logging.Log.WriteWarningMessage(LOGTAG, "BackgroundPriorityDisableError", new System.ComponentModel.Win32Exception(), "Failed to reset background IO priority, status code {0}", res); + } + } + catch (Exception ex) + { + Logging.Log.WriteWarningMessage(LOGTAG, "BackgroundPriorityError", ex, "Failed to reset background IO priority"); + } + } + else + { + if (m_hasEnabledBackgroundIOPriority) + { + m_hasEnabledBackgroundIOPriority = false; + var pid = System.Diagnostics.Process.GetCurrentProcess().Id; + if (Duplicati.Library.Utility.Utility.IsClientOSX) + { + var data = RunProcessAndGetResult($"renice", $"{m_originalNiceLevel} {pid}"); + } + else + { + string data; + if (m_originalNiceLevel < 0) + data = RunProcessAndGetResult($"ionice", $"-c {m_originalNiceClass} -p {pid}"); + else + data = RunProcessAndGetResult($"ionice", $"-c {m_originalNiceClass} -n {m_originalNiceLevel} -p {pid}"); + } + } + } + } + + /// + /// Stops the process controller + /// + private void Stop() + { + + StopSleepPrevention(); + DeactivateBackgroundIOPriority(); + } + + /// + /// Runs a process and returns the stdout data + /// + /// The stdout data. + /// The executable to invoke. + /// The commandline arguments. + private static string RunProcessAndGetResult(string filename, string arguments) + { + var psi = new System.Diagnostics.ProcessStartInfo(filename, arguments); + psi.RedirectStandardOutput = true; + psi.UseShellExecute = false; + + Logging.Log.WriteExplicitMessage(LOGTAG, "RunningCommand", null, "Running: {0} {1}", filename, arguments); + + var pi = System.Diagnostics.Process.Start(psi); + pi.WaitForExit(5000); + if (pi.HasExited) + return pi.StandardOutput.ReadToEnd().Trim(); + pi.Kill(); + + throw new Library.Interface.UserInformationException($"The process {filename} with arguments {arguments} failed to stop", "LaunchProcessFailed"); + } + + /// + /// Releases all resource used by the object. + /// + /// Call when you are finished using the + /// . The method leaves the + /// in an unusable state. After calling + /// , you must release all references to the + /// so the garbage collector can reclaim the memory + /// that the was occupying. + public void Dispose() + { + if (!m_disposed) + { + m_disposed = true; + try + { + Stop(); + } + catch(Exception ex) + { + Logging.Log.WriteWarningMessage(LOGTAG, "ProcessControllerStopError", ex, "Failed to stop the process controller: {0}", ex.Message); + } + } + } + } +} diff --git a/Duplicati/Library/Main/ProgressClasses.cs b/Duplicati/Library/Main/ProgressClasses.cs index 15cd8fb01..7261ff312 100644 --- a/Duplicati/Library/Main/ProgressClasses.cs +++ b/Duplicati/Library/Main/ProgressClasses.cs @@ -1,38 +1,40 @@ -// Copyright (C) 2013, Duplicati Team - -// http://www.duplicati.com, info@duplicati.com -// -// This library is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation; either version 2.1 of the -// License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// Copyright (C) 2013, Duplicati Team + +// http://www.duplicati.com, info@duplicati.com +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA using System; using System.Linq; - +using Duplicati.Library.Logging; + namespace Duplicati.Library.Main { /// /// Interface for recieving messages from the Duplicati operations /// - public interface IMessageSink - { + public interface IMessageSink : Logging.ILogDestination + { + /// + /// Handles an event from the backend + /// + /// The backend action. + /// The event type. + /// The target path. + /// The size of the element. void BackendEvent(BackendActionType action, BackendEventType type, string path, long size); - void VerboseEvent(string message, object[] args); - void MessageEvent(string message); - void RetryEvent(string message, Exception ex); - void WarningEvent(string message, Exception ex); - void ErrorEvent(string message, Exception ex); - void DryrunEvent(string message); - + /// /// Sets the backend progress update object /// @@ -104,40 +106,10 @@ namespace Duplicati.Library.Main s.BackendEvent(action, type, path, size); } - public void DryrunEvent(string message) + public void WriteMessage(LogEntry entry) { - foreach (var s in m_sinks) - s.DryrunEvent(message); - } - - public void ErrorEvent(string message, Exception ex) - { - foreach (var s in m_sinks) - s.ErrorEvent(message, ex); - } - - public void MessageEvent(string message) - { - foreach (var s in m_sinks) - s.MessageEvent(message); - } - - public void RetryEvent(string message, Exception ex) - { - foreach (var s in m_sinks) - s.RetryEvent(message, ex); - } - - public void VerboseEvent(string message, object[] args) - { - foreach (var s in m_sinks) - s.VerboseEvent(message, args); - } - - public void WarningEvent(string message, Exception ex) - { - foreach (var s in m_sinks) - s.WarningEvent(message, ex); + foreach (var s in m_sinks) + s.WriteMessage(entry); } } diff --git a/Duplicati/Library/Main/ResultClasses.cs b/Duplicati/Library/Main/ResultClasses.cs index eb3ea0cbb..06ab3f9ac 100644 --- a/Duplicati/Library/Main/ResultClasses.cs +++ b/Duplicati/Library/Main/ResultClasses.cs @@ -24,21 +24,8 @@ using System.Linq; namespace Duplicati.Library.Main { - public interface ILogWriter + internal interface IBackendWriter { - bool VerboseOutput { get; } - void AddVerboseMessage(string message, params object[] args); - void AddMessage(string message); - void AddWarning(string message, Exception ex); - void AddError(string message, Exception ex); - void AddDryrunMessage(string message); - void WriteLogMessageDirect(string message, LogMessageType type, Exception ex); - } - - internal interface IBackendWriter : ILogWriter - { - void AddRetryAttempt(string message, Exception ex); - long UnknownFileSize { set; } long UnknownFileCount { set; } long KnownFileCount { set; } @@ -68,11 +55,8 @@ namespace Duplicati.Library.Main IBackendProgressUpdater BackendProgressUpdater { get; } } - internal interface ISetCommonOptions : ILogWriter + internal interface ISetCommonOptions { - new bool VerboseOutput { set; } - bool VerboseErrors { set; } - DateTime EndTime { get; set; } DateTime BeginTime { set; } @@ -189,8 +173,13 @@ namespace Duplicati.Library.Main Abort } - internal abstract class BasicResults : IBasicResults, ILogWriter, ISetCommonOptions, ITaskControl, Logging.ILog + internal abstract class BasicResults : IBasicResults, ISetCommonOptions, ITaskControl, Logging.ILogDestination { + /// + /// The tag used for logging + /// + protected static readonly string LOGTAG = Logging.Log.LogTagFromType(typeof(BasicResults)); + protected class DbMessage { public readonly string Type; @@ -214,45 +203,6 @@ namespace Duplicati.Library.Main private TaskControlState m_controlState = TaskControlState.Run; private System.Threading.ManualResetEvent m_pauseEvent = new System.Threading.ManualResetEvent(true); - private bool m_verboseOutput; - private bool m_verboseErrors; - - public bool VerboseOutput - { - get - { - if (m_parent != null) - return m_parent.VerboseOutput; - else - return m_verboseOutput; - } - set - { - if (m_parent != null) - m_parent.VerboseOutput = value; - else - m_verboseOutput = value; - } - } - - public bool VerboseErrors - { - get - { - if (m_parent != null) - return m_parent.VerboseErrors; - else - return m_verboseErrors; - } - set - { - if (m_parent != null) - m_parent.VerboseErrors = value; - else - m_verboseErrors = value; - } - } - public virtual ParsedResultType ParsedResult { get @@ -384,7 +334,7 @@ namespace Duplicati.Library.Main if (type == BackendEventType.Started) this.BackendProgressUpdater.StartAction(action, path, size); - Logging.Log.WriteMessage(string.Format("Backend event: {0} - {1}: {2} ({3})", action, type, path, size <= 0 ? "" : Library.Utility.Utility.FormatSizeString(size)), Duplicati.Library.Logging.LogMessageType.Information, null); + Logging.Log.WriteInformationMessage(LOGTAG, "BackendEvent", "Backend event: {0} - {1}: {2} ({3})", action, type, path, size <= 0 ? "" : Library.Utility.Utility.FormatSizeString(size)); if (MessageSink != null) MessageSink.BackendEvent(action, type, path, size); @@ -398,203 +348,9 @@ namespace Duplicati.Library.Main } - public void AddDryrunMessage(string message) - { - if (m_parent != null) - m_parent.AddDryrunMessage(message); - else - { - lock (Logging.Log.Lock) - { - if (m_is_reporting) - return; - - try - { - m_is_reporting = true; - Logging.Log.WriteMessage(message, Duplicati.Library.Logging.LogMessageType.Information, null); - if (MessageSink != null) - MessageSink.DryrunEvent(message); - } - finally - { - m_is_reporting = false; - } - } - } - } - - public void AddVerboseMessage(string message, params object[] args) - { - if (m_parent != null) - { - if ((args != null) && (args.Length > 0)) m_parent.AddVerboseMessage(message, args); - else m_parent.AddMessage(message); - } - else - { - lock (Logging.Log.Lock) - { - if (m_is_reporting) - return; - - try - { - m_is_reporting = true; - Logging.Log.WriteMessage((((args != null) && (args.Length > 0)) ? string.Format(message, args) : message), Duplicati.Library.Logging.LogMessageType.Profiling, null); - - if (MessageSink != null) - { - if ((args != null) && (args.Length > 0)) MessageSink.VerboseEvent(message, args); - else MessageSink.MessageEvent(message); - } - } - finally - { - m_is_reporting = false; - } - } - } - } - - public void AddMessage(string message) - { - if (m_parent != null) - m_parent.AddMessage(message); - else - { - lock (Logging.Log.Lock) - { - if (m_is_reporting) - return; - - try - { - m_is_reporting = true; - Logging.Log.WriteMessage(message, Duplicati.Library.Logging.LogMessageType.Information, null); - - m_messages.Add(message); - - if (MessageSink != null) - MessageSink.MessageEvent(message); - - lock (m_lock) - if (m_db != null && !m_db.IsDisposed) - LogDbMessage("Message", message, null); - } - finally - { - m_is_reporting = false; - } - } - } - } - - public void AddWarning(string message, Exception ex) - { - if (m_parent != null) - m_parent.AddWarning(message, ex); - else - { - lock (Logging.Log.Lock) - { - if (m_is_reporting) - return; - - try - { - m_is_reporting = true; - Logging.Log.WriteMessage(message, Duplicati.Library.Logging.LogMessageType.Warning, ex); - - var s = ex == null ? message : string.Format("{0} => {1}", message, VerboseErrors ? ex.ToString() : ex.Message); - m_warnings.Add(s); - - if (MessageSink != null) - MessageSink.WarningEvent(message, ex); - - lock (m_lock) - if (m_db != null && !m_db.IsDisposed) - LogDbMessage("Warning", message, ex); - } - finally - { - m_is_reporting = false; - } - } - } - } - - public void AddRetryAttempt(string message, Exception ex) - { - if (m_parent != null) - m_parent.AddRetryAttempt(message, ex); - else - { - lock (Logging.Log.Lock) - { - if (m_is_reporting) - return; - - try - { - m_is_reporting = true; - Logging.Log.WriteMessage(message, Duplicati.Library.Logging.LogMessageType.Warning, ex); - - var s = ex == null ? message : string.Format("{0} => {1}", message, VerboseErrors ? ex.ToString() : ex.Message); - m_retryAttempts.Add(s); - - if (MessageSink != null) - MessageSink.RetryEvent(message, ex); - - lock (m_lock) - if (m_db != null && !m_db.IsDisposed) - LogDbMessage("Retry", message, ex); - } - finally - { - m_is_reporting = false; - } - } - } - } - - public void AddError(string message, Exception ex) - { - if (m_parent != null) - m_parent.AddError(message, ex); - else - { - lock (Logging.Log.Lock) - { - if (m_is_reporting) - return; - - try - { - m_is_reporting = true; - Logging.Log.WriteMessage(message, Duplicati.Library.Logging.LogMessageType.Error, ex); - - var s = ex == null ? message : string.Format("{0} => {1}", message, VerboseErrors ? ex.ToString() : ex.Message); - m_errors.Add(s); - - if (MessageSink != null) - MessageSink.ErrorEvent(message, ex); - - lock (m_lock) - if (m_db != null && !m_db.IsDisposed) - LogDbMessage("Error", message, ex); - } - finally - { - m_is_reporting = false; - } - } - } - } - - public IEnumerable Messages { get { return m_messages; } } - public IEnumerable Warnings { get { return m_warnings; } } - public IEnumerable Errors { get { return m_errors; } } + public IEnumerable Messages { get { return m_parent == null ? m_messages : m_parent.Messages; } } + public IEnumerable Warnings { get { return m_parent == null ? m_warnings : m_parent.Warnings; } } + public IEnumerable Errors { get { return m_parent == null ? m_errors : m_parent.Errors; } } public BasicResults() { @@ -763,9 +519,6 @@ namespace Duplicati.Library.Main filter: (prop, item) => !typeof(IBackendProgressUpdater).IsAssignableFrom(prop.PropertyType) && !typeof(IMessageSink).IsAssignableFrom(prop.PropertyType) && - !typeof(ILogWriter).IsAssignableFrom(prop.PropertyType) && - prop.Name != "VerboseOutput" && - prop.Name != "VerboseErrors" && !(prop.Name == "MainOperation" && item is BackendWriter) && !(prop.Name == "EndTime" && item is BackendWriter) && !(prop.Name == "Duration" && item is BackendWriter) && @@ -774,53 +527,26 @@ namespace Duplicati.Library.Main ).ToString(); } - public void WriteMessage(string message, LogMessageType type, Exception exception) - { - switch (type) - { - case LogMessageType.Error: - AddError(message, exception); - break; - case LogMessageType.Warning: - AddWarning(message, exception); - break; - case LogMessageType.Profiling: - if (Log.LogLevel == LogMessageType.Profiling && VerboseOutput) - AddVerboseMessage(message, new object[0]); - break; - default: - AddMessage(message); - break; - } - } - - /// - /// Writes a message to the log, bypassing injection as normal messages - /// - /// The message to write to the log. - /// Type. - /// Exception. - public void WriteLogMessageDirect(string message, LogMessageType type, Exception exception) + public void WriteMessage(LogEntry entry) { if (m_parent != null) - m_parent.WriteLogMessageDirect(message, type, exception); + m_parent.WriteMessage(entry); else { - lock (Logging.Log.Lock) + switch (entry.Level) { - try - { - m_is_reporting = true; - WriteMessage(message, type, exception); - } - finally - { - m_is_reporting = false; - } + case LogMessageType.Error: + m_errors.Add(entry.AsString(false)); + break; + case LogMessageType.Warning: + m_warnings.Add(entry.AsString(false)); + break; + case LogMessageType.Information: + m_messages.Add(entry.AsString(false)); + break; } } } - } internal class BackupResults : BasicResults, IBackupResults diff --git a/Duplicati/Library/Main/Strings.cs b/Duplicati/Library/Main/Strings.cs index 274b7b6c4..c3f0562cd 100644 --- a/Duplicati/Library/Main/Strings.cs +++ b/Duplicati/Library/Main/Strings.cs @@ -95,9 +95,11 @@ namespace Duplicati.Library.Main.Strings public static string AsynchronousuploadlimitShort { get { return LC.L(@"The number of volumes to create ahead of time"); } } public static string DebugoutputLong { get { return LC.L(@"Activating this option will make some error messages more verbose, which may help you track down a particular issue"); } } public static string DebugoutputShort { get { return LC.L(@"Enables debugging output"); } } - public static string LogfileShort { get { return LC.L(@"Log internal information"); } } + public static string LogfileShort { get { return LC.L(@"Log internal information to a file"); } } + public static string LogfileLong { get { return LC.L(@"Logs information to the file specified"); } } public static string LoglevelLong { get { return LC.L(@"Specifies the amount of log information to write into the file specified by --log-file"); } } public static string LoglevelShort { get { return LC.L(@"Log information level"); } } + public static string LogLevelDeprecated(string option1, string option2) { return LC.L("Use the {0} and {1} options instead", option1, option2); } public static string DisableautocreatefolderLong { get { return LC.L(@"If Duplicati detects that the target folder is missing, it will create it automatically. Activate this option to prevent automatic folder creation."); } } public static string DisableautocreatefolderShort { get { return LC.L(@"Disables automatic folder creation"); } } public static string VssexcludewritersLong { get { return LC.L(@"Use this option to exclude faulty writers from a snapshot. This is equivalent to the -wx flag of the vshadow.exe tool, except that it only accepts writer class GUIDs, and not component names or instance GUIDs. Multiple GUIDs must be separated with a semicolon, and most forms of GUIDs are allowed, including with and without curly braces."); } } @@ -183,13 +185,14 @@ namespace Duplicati.Library.Main.Strings public static string KeeptimeShort { get { return LC.L(@"Keep all versions within a timespan"); } } public static string KeeptimeLong { get { return LC.L(@"Use this option to set the timespan in which backups are kept."); } } public static string RetentionPolicyShort { get { return LC.L(@"Reduce number of versions by deleting old intermediate backups"); } } - public static string RetentionPolicyLong { get { return LC.L(@"Use this option to reduce the number of versions that are kept with increasing version age by deleting most of the old backups. The expected format is a comma separated list of colon separated time frame and interval pairs. For example the value ""7D:0s,3M:1D,10Y:2M"" means ""For 7 day keep all backups, for 3 months keep one backup every day, for 10 years one backup every 2nd month and delete every backup older than this."""); } } + public static string RetentionPolicyLong { get { return LC.L(@"Use this option to reduce the number of versions that are kept with increasing version age by deleting most of the old backups. The expected format is a comma separated list of colon separated time frame and interval pairs. For example the value ""7D:0s,3M:1D,10Y:2M"" means ""For 7 day keep all backups, for 3 months keep one backup every day, for 10 years one backup every 2nd month and delete every backup older than this."". This option also supports using the specifier ""U"" to indicate an unlimited time interval."); } } public static string AllowmissingsourceShort { get { return LC.L(@"Ignore missing source elements"); } } public static string AllowmissingsourceLong { get { return LC.L(@"Use this option to continue even if some source entries are missing."); } } public static string OverwriteShort { get { return LC.L(@"Overwrite files when restoring"); } } public static string OverwriteLong { get { return LC.L(@"Use this option to overwrite target files when restoring, if this option is not set the files will be restored with a timestamp and a number appended."); } } public static string VerboseShort { get { return LC.L(@"Output more progress information"); } } public static string VerboseLong { get { return LC.L(@"Use this option to increase the amount of output generated when running an option. Generally this option will produce a line for each file processed."); } } + public static string VerboseDeprecated { get { return LC.L(@"Set a log-level for the desired output method instead"); } } public static string FullresultShort { get { return LC.L(@"Output full results"); } } public static string FullresultLong { get { return LC.L(@"Use this option to increase the amount of output generated as the result of the operation, including all filenames."); } } public static string UploadverificationfileShort { get { return LC.L(@"Determine if verification files are uploaded"); } } @@ -239,6 +242,20 @@ namespace Duplicati.Library.Main.Strings public static string AutoVacuumLong { get { return LC.L(@"Some operations that manipulate the local database leave unused entries behind. These entries are not deleted from a hard drive until a VACUUM operation is run. This operation saves disk space in the long run but needs to temporarily create a copy of all valid entries in the database. Setting this to true will allow Duplicati to perform VACUUM operations at its discretion."); } } public static string DisablefilescannerShort { get { return LC.L(@"Disable the read-ahead scanner"); } } public static string DisablefilescannerLong { get { return LC.L(@"When this flag is enabled, the scanner that computes the size of source files is disabled, and instead the reported size is read from the database. Using this flag can speed up the backup by reducing disk access, but will give a less accurate progress indicator."); } } + public static string DisableOnBatteryShort { get { return LC.L("Disable the backup when on battery power"); } } + public static string DisableOnBatteryLong { get { return LC.L("When this flag is enabled, a scheduled backup will not run if the system is detected to be running on battery power (manual or command line backups will still be run). If the detected power source is mains (i.e., AC) or unknown, then scheduled backups will proceed as normal."); } } + + public static string LogfileloglevelLong { get { return LC.L(@"Specifies the amount of log information to write into the file specified by --log-file"); } } + public static string LogfileloglevelShort { get { return LC.L(@"Log file information level"); } } + public static string LogfilelogfiltersShort { get { return LC.L(@"Applies filters to the file log data"); } } + public static string LogfilelogfiltersLong(string delimiter) { return LC.L(@"This option accepts filters that removes or includes messages regardless of their log level. Multiple filters are supported by separating with {0}. Filters are matched against the log tag and assumed to be including, unless they start with '-'. Regular expressions are supported within hard braces. Example: ""+Path*{0}+*Mail*{0}-[.*DNS]"" "); } + public static string ConsoleloglevelLong { get { return LC.L(@"Specifies the amount of log information to write as console output"); } } + public static string ConsoleloglevelShort { get { return LC.L(@"Console information level"); } } + public static string ConsolelogfiltersShort { get { return LC.L(@"Applies filters to the console log data"); } } + public static string ConsolelogfiltersLong(string delimiter) { return LogfilelogfiltersLong(delimiter); } + + public static string UsebackgroundiopriorityShort { get { return LC.L("Sets the processe to use low IO priority"); } } + public static string UsebackgroundiopriorityLong { get { return LC.L("This option instructions the operating system to set the current process to use the lowest IO priority level, which can make operations run slower but will interfere less with other operations running at the same time"); } } } internal static class Common diff --git a/Duplicati/Library/Main/Utility.cs b/Duplicati/Library/Main/Utility.cs index cb287f670..a523030b2 100644 --- a/Duplicati/Library/Main/Utility.cs +++ b/Duplicati/Library/Main/Utility.cs @@ -53,7 +53,7 @@ namespace Duplicati.Library.Main using(var filehasher = Library.Utility.HashAlgorithmHelper.Create(options.FileHashAlgorithm)) { if (filehasher == null) - throw new Duplicati.Library.Interface.UserInformationException(Strings.Common.InvalidHashAlgorithm(options.FileHashAlgorithm)); + throw new Duplicati.Library.Interface.UserInformationException(Strings.Common.InvalidHashAlgorithm(options.FileHashAlgorithm), "FileHashAlgorithmNotSupported"); w.Write(JsonConvert.SerializeObject(values)); w.Flush(); @@ -153,21 +153,21 @@ namespace Duplicati.Library.Main if (!options.AllowPassphraseChange) { if (newDict[k.Key] == "no-encryption") - throw new Duplicati.Library.Interface.UserInformationException("You have attempted to remove the passphrase on an existing backup, which is not supported. Please configure a new clean backup if you want to remove the passphrase."); + throw new Duplicati.Library.Interface.UserInformationException("You have attempted to remove the passphrase on an existing backup, which is not supported. Please configure a new clean backup if you want to remove the passphrase.", "PassphraseRemovalNotSupported"); else if (opts[k.Key] == "no-encryption") - throw new Duplicati.Library.Interface.UserInformationException("You have attempted to add a passphrase to an existing backup, which is not supported. Please configure a new clean backup if you want to add a passphrase."); + throw new Duplicati.Library.Interface.UserInformationException("You have attempted to add a passphrase to an existing backup, which is not supported. Please configure a new clean backup if you want to add a passphrase.", "PassphraseAdditionNotSupported"); else - throw new Duplicati.Library.Interface.UserInformationException("You have attempted to change a passphrase to an existing backup, which is not supported. Please configure a new clean backup if you want to change the passphrase."); + throw new Duplicati.Library.Interface.UserInformationException("You have attempted to change a passphrase to an existing backup, which is not supported. Please configure a new clean backup if you want to change the passphrase.", "PassphraseChangeNotSupported"); } } else - throw new Duplicati.Library.Interface.UserInformationException(string.Format("You have attempted to change the parameter \"{0}\" from \"{1}\" to \"{2}\", which is not supported. Please configure a new clean backup if you want to change the parameter.", k.Key, opts[k.Key], k.Value)); + throw new Duplicati.Library.Interface.UserInformationException(string.Format("You have attempted to change the parameter \"{0}\" from \"{1}\" to \"{2}\", which is not supported. Please configure a new clean backup if you want to change the parameter.", k.Key, opts[k.Key], k.Value), "ParameterChangeNotSupported"); } //Extra sanity check if (db.GetBlocksLargerThan(options.Blocksize) > 0) - throw new Duplicati.Library.Interface.UserInformationException("You have attempted to change the block-size on an existing backup, which is not supported. Please configure a new clean backup if you want to change the block-size."); + throw new Duplicati.Library.Interface.UserInformationException("You have attempted to change the block-size on an existing backup, which is not supported. Please configure a new clean backup if you want to change the block-size.", "BlockSizeChangeNotSupported"); if (needsUpdate) { diff --git a/Duplicati/Library/Main/Volumes/VolumeWriterBase.cs b/Duplicati/Library/Main/Volumes/VolumeWriterBase.cs index ea43043a1..d6af23a06 100644 --- a/Duplicati/Library/Main/Volumes/VolumeWriterBase.cs +++ b/Duplicati/Library/Main/Volumes/VolumeWriterBase.cs @@ -58,7 +58,7 @@ namespace Duplicati.Library.Main.Volumes m_compression = DynamicLoader.CompressionLoader.GetModule(options.CompressionModule, m_localFileStream, ArchiveMode.Write, options.RawOptions); if (m_compression == null) - throw new UserInformationException(string.Format("Unsupported compression module: {0}", options.CompressionModule)); + throw new UserInformationException(string.Format("Unsupported compression module: {0}", options.CompressionModule), "UnsupportedCompressionModule"); if ((this is IndexVolumeWriter || this is FilesetVolumeWriter) && m_compression is Library.Interface.ICompressionHinting) ((Library.Interface.ICompressionHinting)m_compression).LowOverheadMode = true; diff --git a/Duplicati/Library/Modules/Builtin/ConsolePasswordInput.cs b/Duplicati/Library/Modules/Builtin/ConsolePasswordInput.cs index 7b7bb9302..f520b6dd7 100644 --- a/Duplicati/Library/Modules/Builtin/ConsolePasswordInput.cs +++ b/Duplicati/Library/Modules/Builtin/ConsolePasswordInput.cs @@ -107,11 +107,11 @@ namespace Duplicati.Library.Modules.Builtin Console.WriteLine(); if (passphrase.ToString() != password2.ToString()) - throw new Duplicati.Library.Interface.UserInformationException(Strings.ConsolePasswordInput.PassphraseMismatchError); + throw new Duplicati.Library.Interface.UserInformationException(Strings.ConsolePasswordInput.PassphraseMismatchError, "PassphraseMismatch"); } if (passphrase.ToString().Length == 0) - throw new Duplicati.Library.Interface.UserInformationException(Strings.ConsolePasswordInput.EmptyPassphraseError); + throw new Duplicati.Library.Interface.UserInformationException(Strings.ConsolePasswordInput.EmptyPassphraseError, "EmptyPassphrase"); return passphrase.ToString(); } diff --git a/Duplicati/Library/Modules/Builtin/HyperVOptions.cs b/Duplicati/Library/Modules/Builtin/HyperVOptions.cs index d33ebdbbf..cbf0e4a20 100644 --- a/Duplicati/Library/Modules/Builtin/HyperVOptions.cs +++ b/Duplicati/Library/Modules/Builtin/HyperVOptions.cs @@ -27,6 +27,10 @@ namespace Duplicati.Library.Modules.Builtin { public class HyperVOptions : Interface.IGenericSourceModule { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(); private const string m_HyperVPathGuidRegExp = @"\%HYPERV\%\\([0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12})"; private const string m_HyperVPathAllRegExp = @"%HYPERV%"; @@ -69,7 +73,7 @@ namespace Duplicati.Library.Modules.Builtin // Early exit in case we are non-windows to prevent attempting to load Windows-only components if (!Utility.Utility.IsClientWindows) { - Logging.Log.WriteMessage("Hyper-V backup works only on Windows OS", Logging.LogMessageType.Warning); + Logging.Log.WriteWarningMessage(LOGTAG, "HyperVWindowsOnly", null, "Hyper-V backup works only on Windows OS"); if (paths != null) paths = paths.Where(x => !x.Equals(m_HyperVPathAllRegExp, StringComparison.OrdinalIgnoreCase) && !Regex.IsMatch(x, m_HyperVPathGuidRegExp, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)).ToArray(); @@ -121,26 +125,26 @@ namespace Duplicati.Library.Modules.Builtin if (excludedWriters.Contains(HyperVUtility.HyperVWriterGuid)) { - Logging.Log.WriteMessage(string.Format("Excluded writers for VSS cannot contain Hyper-V writer when backuping Hyper-V virtual machines. Removing \"{0}\" to continue", HyperVUtility.HyperVWriterGuid.ToString()), Logging.LogMessageType.Warning); + Logging.Log.WriteWarningMessage(LOGTAG, "CannotExcludeHyperVVSSWriter", null, "Excluded writers for VSS cannot contain Hyper-V writer when backuping Hyper-V virtual machines. Removing \"{0}\" to continue", HyperVUtility.HyperVWriterGuid.ToString()); changedOptions["vss-exclude-writers"] = string.Join(";", excludedWriters.Where(x => x != HyperVUtility.HyperVWriterGuid)); } } if (!commandlineOptions.Keys.Contains("snapshot-policy") || !commandlineOptions["snapshot-policy"].Equals("required", StringComparison.OrdinalIgnoreCase)) { - Logging.Log.WriteMessage("Snapshot strategy have to be set to \"required\" when backuping Hyper-V virtual machines. Changing to \"required\" to continue", Logging.LogMessageType.Warning); + Logging.Log.WriteWarningMessage(LOGTAG, "MustSetSnapshotPolicy", null, "Snapshot policy have to be set to \"required\" when backuping Hyper-V virtual machines. Changing to \"required\" to continue", Logging.LogMessageType.Warning); changedOptions["snapshot-policy"] = "required"; } if (!hypervUtility.IsVSSWriterSupported) - Logging.Log.WriteMessage("This is client version of Windows. Hyper-V VSS writer is present only on Server version. Backup will continue, but will be crash consistent only in opposite to application consistent in Server version", Logging.LogMessageType.Warning); + Logging.Log.WriteWarningMessage(LOGTAG, "HyperVOnServerOnly", null, "This is client version of Windows. Hyper-V VSS writer is present only on Server version. Backup will continue, but will be crash consistent only in opposite to application consistent in Server version"); - Logging.Log.WriteMessage("Starting to gather Hyper-V information", Logging.LogMessageType.Information); + Logging.Log.WriteInformationMessage(LOGTAG, "StartingHyperVQuery", "Starting to gather Hyper-V information"); hypervUtility.QueryHyperVGuestsInfo(true); - Logging.Log.WriteMessage(string.Format("Found {0} virtual machines on Hyper-V", hypervUtility.Guests.Count), Logging.LogMessageType.Information); + Logging.Log.WriteInformationMessage(LOGTAG, "HyperVMachineCount", "Found {0} virtual machines on Hyper-V", hypervUtility.Guests.Count); foreach (var guest in hypervUtility.Guests) - Logging.Log.WriteMessage(string.Format("Found VM name {0}, ID {1}, files {2}", guest.Name, guest.ID, string.Join(";", guest.DataPaths)), Logging.LogMessageType.Profiling); + Logging.Log.WriteProfilingMessage(LOGTAG, "FoundHyperVMachine", "Found VM name {0}, ID {1}, files {2}", guest.Name, guest.ID, string.Join(";", guest.DataPaths)); List guestsForBackup = new List(); @@ -153,7 +157,7 @@ namespace Duplicati.Library.Modules.Builtin var foundGuest = hypervUtility.Guests.Where(x => x.ID == new Guid(guestID)); if (foundGuest.Count() != 1) - throw new Duplicati.Library.Interface.UserInformationException(string.Format("Hyper-V guest specified in source with ID {0} cannot be found", guestID)); + throw new Duplicati.Library.Interface.UserInformationException(string.Format("Hyper-V guest specified in source with ID {0} cannot be found", guestID), "HyperVGuestNotFound"); guestsForBackup.Add(foundGuest.First()); } @@ -164,10 +168,10 @@ namespace Duplicati.Library.Modules.Builtin var foundGuest = hypervUtility.Guests.Where(x => x.ID == new Guid(guestID)); if (foundGuest.Count() != 1) - throw new Duplicati.Library.Interface.UserInformationException(string.Format("Hyper-V guest specified in include filter with ID {0} cannot be found", guestID)); + throw new Duplicati.Library.Interface.UserInformationException(string.Format("Hyper-V guest specified in include filter with ID {0} cannot be found", guestID), "HyperVGuestNotFound"); guestsForBackup.Add(foundGuest.First()); - Logging.Log.WriteMessage(string.Format("Including {0} based on including filters", guestID), Logging.LogMessageType.Information); + Logging.Log.WriteInformationMessage(LOGTAG, "IncludeByFilter", "Including {0} based on including filters", guestID); } guestsForBackup = guestsForBackup.Distinct().ToList(); @@ -178,10 +182,10 @@ namespace Duplicati.Library.Modules.Builtin var foundGuest = guestsForBackup.Where(x => x.ID == new Guid(guestID)); if (foundGuest.Count() != 1) - throw new Duplicati.Library.Interface.UserInformationException(string.Format("Hyper-V guest specified in exclude filter with ID {0} cannot be found", guestID)); + throw new Duplicati.Library.Interface.UserInformationException(string.Format("Hyper-V guest specified in exclude filter with ID {0} cannot be found", guestID), "HyperVGuestNotFound"); guestsForBackup.Remove(foundGuest.First()); - Logging.Log.WriteMessage(string.Format("Excluding {0} based on excluding filters", guestID), Logging.LogMessageType.Information); + Logging.Log.WriteInformationMessage(LOGTAG, "ExcludeByFilter", "Excluding {0} based on excluding filters", guestID); } var pathsForBackup = new List(paths); @@ -196,11 +200,11 @@ namespace Duplicati.Library.Modules.Builtin if (!filterhandler.Matches(pathForBackup, out bResult, out matchFilter)) { - Logging.Log.WriteMessage(string.Format("For VM {0} - adding {1}", guestForBackup.Name, pathForBackup), Logging.LogMessageType.Information); + Logging.Log.WriteInformationMessage(LOGTAG, "IncludeHyperV", "For VM {0} - adding {1}", guestForBackup.Name, pathForBackup); pathsForBackup.Add(pathForBackup); } else - Logging.Log.WriteMessage(string.Format("Excluding {0} based on excluding filters", pathForBackup), Logging.LogMessageType.Information); + Logging.Log.WriteInformationMessage(LOGTAG, "ExcludeByFilter", "Excluding {0} based on excluding filters", pathForBackup); } paths = pathsForBackup.Where(x => !x.Equals(m_HyperVPathAllRegExp, StringComparison.OrdinalIgnoreCase) && !Regex.IsMatch(x, m_HyperVPathGuidRegExp, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)) diff --git a/Duplicati/Library/Modules/Builtin/MSSQLOptions.cs b/Duplicati/Library/Modules/Builtin/MSSQLOptions.cs index 4c3c42136..f9458f298 100644 --- a/Duplicati/Library/Modules/Builtin/MSSQLOptions.cs +++ b/Duplicati/Library/Modules/Builtin/MSSQLOptions.cs @@ -27,6 +27,11 @@ namespace Duplicati.Library.Modules.Builtin { public class MSSQLOptions : Interface.IGenericSourceModule { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(); + private const string m_MSSQLPathDBRegExp = @"\%MSSQL\%\\(.+)"; private const string m_MSSQLPathAllRegExp = @"%MSSQL%"; @@ -69,7 +74,7 @@ namespace Duplicati.Library.Modules.Builtin // Early exit in case we are non-windows to prevent attempting to load Windows-only components if (!Utility.Utility.IsClientWindows) { - Logging.Log.WriteMessage("Microsoft SQL Server databases backup works only on Windows OS", Logging.LogMessageType.Warning); + Logging.Log.WriteWarningMessage(LOGTAG, "MSSqlWindowsOnly", null, "Microsoft SQL Server databases backup works only on Windows OS"); if (paths != null) paths = paths.Where(x => !x.Equals(m_MSSQLPathAllRegExp, StringComparison.OrdinalIgnoreCase) && !Regex.IsMatch(x, m_MSSQLPathDBRegExp, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)).ToArray(); @@ -121,23 +126,23 @@ namespace Duplicati.Library.Modules.Builtin if (excludedWriters.Contains(MSSQLUtility.MSSQLWriterGuid)) { - Logging.Log.WriteMessage(string.Format("Excluded writers for VSS cannot contain MS SQL writer when backuping Microsoft SQL Server databases. Removing \"{0}\" to continue", MSSQLUtility.MSSQLWriterGuid.ToString()), Logging.LogMessageType.Warning); + Logging.Log.WriteWarningMessage(LOGTAG, "CannotExcludeMsSqlVSSWriter", null, "Excluded writers for VSS cannot contain MS SQL writer when backuping Microsoft SQL Server databases. Removing \"{0}\" to continue", MSSQLUtility.MSSQLWriterGuid.ToString()); changedOptions["vss-exclude-writers"] = string.Join(";", excludedWriters.Where(x => x != MSSQLUtility.MSSQLWriterGuid)); } } if (!commandlineOptions.Keys.Contains("snapshot-policy") || !commandlineOptions["snapshot-policy"].Equals("required", StringComparison.OrdinalIgnoreCase)) { - Logging.Log.WriteMessage("Snapshot strategy have to be set to \"required\" when backuping Microsoft SQL Server databases. Changing to \"required\" to continue", Logging.LogMessageType.Warning); + Logging.Log.WriteWarningMessage(LOGTAG, "MustSetSnapshotPolicy", null, "Snapshot policy have to be set to \"required\" when backuping Microsoft SQL Server databases. Changing to \"required\" to continue"); changedOptions["snapshot-policy"] = "required"; } - Logging.Log.WriteMessage("Starting to gather Microsoft SQL Server information", Logging.LogMessageType.Information); + Logging.Log.WriteInformationMessage(LOGTAG, "StartingMsSqlQuery", "Starting to gather Microsoft SQL Server information", Logging.LogMessageType.Information); mssqlUtility.QueryDBsInfo(); - Logging.Log.WriteMessage(string.Format("Found {0} databases on Microsoft SQL Server", mssqlUtility.DBs.Count), Logging.LogMessageType.Information); + Logging.Log.WriteInformationMessage(LOGTAG, "MsSqlDatabaseCount", "Found {0} databases on Microsoft SQL Server", mssqlUtility.DBs.Count); foreach(var db in mssqlUtility.DBs) - Logging.Log.WriteMessage(string.Format("Found DB name {0}, ID {1}, files {2}", db.Name, db.ID, string.Join(";", db.DataPaths)), Logging.LogMessageType.Profiling); + Logging.Log.WriteProfilingMessage(LOGTAG, "MsSqlDatabaseName", "Found DB name {0}, ID {1}, files {2}", db.Name, db.ID, string.Join(";", db.DataPaths)); List dbsForBackup = new List(); @@ -150,7 +155,7 @@ namespace Duplicati.Library.Modules.Builtin var foundDB = mssqlUtility.DBs.Where(x => x.ID.Equals(dbID, StringComparison.OrdinalIgnoreCase)); if (foundDB.Count() != 1) - throw new Duplicati.Library.Interface.UserInformationException(string.Format("DB name specified in source with ID {0} cannot be found", dbID)); + throw new Duplicati.Library.Interface.UserInformationException(string.Format("DB name specified in source with ID {0} cannot be found", dbID), "MsSqlDatabaseNotFound"); dbsForBackup.Add(foundDB.First()); } @@ -161,10 +166,10 @@ namespace Duplicati.Library.Modules.Builtin var foundDB = mssqlUtility.DBs.Where(x => x.ID.Equals(dbID, StringComparison.OrdinalIgnoreCase)); if (foundDB.Count() != 1) - throw new Duplicati.Library.Interface.UserInformationException(string.Format("DB name specified in include filter with ID {0} cannot be found", dbID)); + throw new Duplicati.Library.Interface.UserInformationException(string.Format("DB name specified in include filter with ID {0} cannot be found", dbID), "MsSqlDatabaseNotFound"); dbsForBackup.Add(foundDB.First()); - Logging.Log.WriteMessage(string.Format("Including {0} based on including filters", dbID), Logging.LogMessageType.Information); + Logging.Log.WriteInformationMessage(LOGTAG, "IncludeByFilter", "Including {0} based on including filters", dbID); } dbsForBackup = dbsForBackup.Distinct().ToList(); @@ -175,10 +180,10 @@ namespace Duplicati.Library.Modules.Builtin var foundDB = dbsForBackup.Where(x => x.ID.Equals(dbID, StringComparison.OrdinalIgnoreCase)); if (foundDB.Count() != 1) - throw new Duplicati.Library.Interface.UserInformationException(string.Format("DB name specified in exclude filter with ID {0} cannot be found", dbID)); + throw new Duplicati.Library.Interface.UserInformationException(string.Format("DB name specified in exclude filter with ID {0} cannot be found", dbID), "MsSqlDatabaseNotFound"); dbsForBackup.Remove(foundDB.First()); - Logging.Log.WriteMessage(string.Format("Excluding {0} based on excluding filters", dbID), Logging.LogMessageType.Information); + Logging.Log.WriteInformationMessage(LOGTAG, "ExcludeByFilter", "Excluding {0} based on excluding filters", dbID); } var pathsForBackup = new List(paths); @@ -193,11 +198,11 @@ namespace Duplicati.Library.Modules.Builtin if (!filterhandler.Matches(pathForBackup, out bResult, out matchFilter)) { - Logging.Log.WriteMessage(string.Format("For DB {0} - adding {1}", dbForBackup.Name, pathForBackup), Logging.LogMessageType.Information); + Logging.Log.WriteInformationMessage(LOGTAG, "IncludeDatabase", "For DB {0} - adding {1}", dbForBackup.Name, pathForBackup); pathsForBackup.Add(pathForBackup); } else - Logging.Log.WriteMessage(string.Format("Excluding {0} based on excluding filters", pathForBackup), Logging.LogMessageType.Information); + Logging.Log.WriteInformationMessage(LOGTAG, "ExcludeByFilter", "Excluding {0} based on excluding filters", pathForBackup); } paths = pathsForBackup.Where(x => !x.Equals(m_MSSQLPathAllRegExp, StringComparison.OrdinalIgnoreCase) && !Regex.IsMatch(x, m_MSSQLPathDBRegExp, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)) diff --git a/Duplicati/Library/Modules/Builtin/RunScript.cs b/Duplicati/Library/Modules/Builtin/RunScript.cs index d624dad76..d900c0362 100644 --- a/Duplicati/Library/Modules/Builtin/RunScript.cs +++ b/Duplicati/Library/Modules/Builtin/RunScript.cs @@ -27,6 +27,11 @@ namespace Duplicati.Library.Modules.Builtin { public class RunScript : Duplicati.Library.Interface.IGenericCallbackModule { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(); + private const string STARTUP_OPTION = "run-script-before"; private const string FINISH_OPTION = "run-script-after"; private const string REQUIRED_OPTION = "run-script-before-required"; @@ -225,9 +230,9 @@ namespace Duplicati.Library.Modules.Builtin if (requiredScript) { if (!p.HasExited) - throw new Duplicati.Library.Interface.UserInformationException(Strings.RunScript.ScriptTimeoutError(scriptpath)); + throw new Duplicati.Library.Interface.UserInformationException(Strings.RunScript.ScriptTimeoutError(scriptpath), "RunScriptTimeout"); else if (p.ExitCode != 0) - throw new Duplicati.Library.Interface.UserInformationException(Strings.RunScript.InvalidExitCodeError(scriptpath, p.ExitCode)); + throw new Duplicati.Library.Interface.UserInformationException(Strings.RunScript.InvalidExitCodeError(scriptpath, p.ExitCode), "RunScriptInvalidExitCode"); } if (p.HasExited) @@ -235,16 +240,16 @@ namespace Duplicati.Library.Modules.Builtin stderr = cs.StandardError; stdout = cs.StandardOutput; if (p.ExitCode != 0) - Logging.Log.WriteMessage(Strings.RunScript.InvalidExitCodeError(scriptpath, p.ExitCode), Duplicati.Library.Logging.LogMessageType.Warning); + Logging.Log.WriteWarningMessage(LOGTAG, "InvalidExitCode", null, Strings.RunScript.InvalidExitCodeError(scriptpath, p.ExitCode)); } else { - Logging.Log.WriteMessage(Strings.RunScript.ScriptTimeoutError(scriptpath), Duplicati.Library.Logging.LogMessageType.Warning); + Logging.Log.WriteWarningMessage(LOGTAG, "ScriptTimeout", null, Strings.RunScript.ScriptTimeoutError(scriptpath)); } } if (!string.IsNullOrEmpty(stderr)) - Logging.Log.WriteMessage(Strings.RunScript.StdErrorReport(scriptpath, stderr), Duplicati.Library.Logging.LogMessageType.Warning); + Logging.Log.WriteWarningMessage(LOGTAG, "StdErrorNotEmpty", null, Strings.RunScript.StdErrorReport(scriptpath, stderr)); //We only allow setting parameters on startup if (eventname == "BEFORE" && stdout != null) @@ -302,7 +307,7 @@ namespace Duplicati.Library.Modules.Builtin } catch (Exception ex) { - Logging.Log.WriteMessage(Strings.RunScript.ScriptExecuteError(scriptpath, ex.Message), Duplicati.Library.Logging.LogMessageType.Warning, ex); + Logging.Log.WriteWarningMessage(LOGTAG, "ScriptExecuteError", ex, Strings.RunScript.ScriptExecuteError(scriptpath, ex.Message)); if (requiredScript) throw; } diff --git a/Duplicati/Library/Modules/Builtin/SendHttpMessage.cs b/Duplicati/Library/Modules/Builtin/SendHttpMessage.cs index fa78ea256..662eacd2d 100644 --- a/Duplicati/Library/Modules/Builtin/SendHttpMessage.cs +++ b/Duplicati/Library/Modules/Builtin/SendHttpMessage.cs @@ -12,6 +12,11 @@ using System.Text.RegularExpressions; namespace Duplicati.Library.Modules.Builtin { public class SendHttpMessage : Interface.IGenericCallbackModule { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(); + #region Option names /// @@ -266,7 +271,7 @@ namespace Duplicati.Library.Modules.Builtin { top = top.InnerException; } - Logging.Log.WriteMessage(Strings.SendHttpMessage.SendMessageError(sb.ToString()), LogMessageType.Warning, ex); + Logging.Log.WriteWarningMessage(LOGTAG, "SendMessageError", ex, Strings.SendHttpMessage.SendMessageError(sb.ToString())); } } diff --git a/Duplicati/Library/Modules/Builtin/SendJabberMessage.cs b/Duplicati/Library/Modules/Builtin/SendJabberMessage.cs index 586b40c00..2f4481666 100644 --- a/Duplicati/Library/Modules/Builtin/SendJabberMessage.cs +++ b/Duplicati/Library/Modules/Builtin/SendJabberMessage.cs @@ -18,6 +18,11 @@ namespace Duplicati.Library.Modules.Builtin { public class SendJabberMessage : Interface.IGenericCallbackModule { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(); + #region Option names /// @@ -264,7 +269,7 @@ namespace Duplicati.Library.Modules.Builtin top = top.InnerException; } - Logging.Log.WriteMessage(Strings.SendJabberMessage.SendMessageError(sb.ToString()), LogMessageType.Warning, ex); + Logging.Log.WriteWarningMessage(LOGTAG, "SendFailed", ex, Strings.SendJabberMessage.SendMessageError(sb.ToString())); } } diff --git a/Duplicati/Library/Modules/Builtin/SendMail.cs b/Duplicati/Library/Modules/Builtin/SendMail.cs index 2afb0a733..bc5ca49da 100644 --- a/Duplicati/Library/Modules/Builtin/SendMail.cs +++ b/Duplicati/Library/Modules/Builtin/SendMail.cs @@ -19,6 +19,11 @@ namespace Duplicati.Library.Modules.Builtin { public class SendMail : Interface.IGenericCallbackModule { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(); + #region Option names /// @@ -374,7 +379,7 @@ namespace Duplicati.Library.Modules.Builtin foreach(var server in servers) { if (lastEx != null) - Logging.Log.WriteMessage(Strings.SendMail.SendMailFailedRetryError(lastServer, lastEx.Message, server), LogMessageType.Warning, lastEx); + Logging.Log.WriteWarningMessage(LOGTAG, "SendMailFailedWillRetry", lastEx, Strings.SendMail.SendMailFailedRetryError(lastServer, lastEx.Message, server)); lastServer = server; try @@ -405,12 +410,12 @@ namespace Duplicati.Library.Modules.Builtin { var log = Encoding.UTF8.GetString(ms.GetBuffer()); if (!string.IsNullOrWhiteSpace(log)) - Logging.Log.WriteMessage(Strings.SendMail.SendMailLog(log), LogMessageType.Profiling); + Logging.Log.WriteProfilingMessage(LOGTAG, "SendMailResult", Strings.SendMail.SendMailLog(log)); } } lastEx = null; - Logging.Log.WriteMessage(Strings.SendMail.SendMailSuccess(server), LogMessageType.Information); + Logging.Log.WriteInformationMessage(LOGTAG, "SendMailComplete", Strings.SendMail.SendMailSuccess(server)); break; } catch (Exception ex) @@ -434,7 +439,7 @@ namespace Duplicati.Library.Modules.Builtin top = top.InnerException; } - Logging.Log.WriteMessage(Strings.SendMail.SendMailFailedError(sb.ToString()), LogMessageType.Warning, ex); + Logging.Log.WriteWarningMessage(LOGTAG, "SendMailError", ex, Strings.SendMail.SendMailFailedError(sb.ToString())); } } diff --git a/Duplicati/Library/SQLiteHelper/DatabaseUpgrader.cs b/Duplicati/Library/SQLiteHelper/DatabaseUpgrader.cs index 994d7ed95..cda18b622 100644 --- a/Duplicati/Library/SQLiteHelper/DatabaseUpgrader.cs +++ b/Duplicati/Library/SQLiteHelper/DatabaseUpgrader.cs @@ -217,13 +217,13 @@ namespace Duplicati.Library.SQLiteHelper catch (Exception ex) { //Hopefully a more explanatory error message - throw new Duplicati.Library.Interface.UserInformationException(Strings.DatabaseUpgrader.DatabaseFormatError(ex.Message), ex); + throw new Duplicati.Library.Interface.UserInformationException(Strings.DatabaseUpgrader.DatabaseFormatError(ex.Message), "DatabaseFormatError", ex); } Dictionary preparserVars = null; if (dbversion > versions.Count) - throw new Duplicati.Library.Interface.UserInformationException(Strings.DatabaseUpgrader.InvalidVersionError(dbversion, versions.Count, System.IO.Path.GetDirectoryName(sourcefile))); + throw new Duplicati.Library.Interface.UserInformationException(Strings.DatabaseUpgrader.InvalidVersionError(dbversion, versions.Count, System.IO.Path.GetDirectoryName(sourcefile)), "DatabaseVersionNotSupportedError"); else if (dbversion < versions.Count) // will need action, collect vars for preparser { preparserVars = new Dictionary(StringComparer.OrdinalIgnoreCase); diff --git a/Duplicati/Library/Snapshots/HyperVUtility.cs b/Duplicati/Library/Snapshots/HyperVUtility.cs index 215a60d27..ea6bcb416 100644 --- a/Duplicati/Library/Snapshots/HyperVUtility.cs +++ b/Duplicati/Library/Snapshots/HyperVUtility.cs @@ -64,6 +64,11 @@ namespace Duplicati.Library.Snapshots public class HyperVUtility { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(); + private readonly ManagementScope _wmiScope; private readonly string _vmIdField; private readonly string _wmiHost = "localhost"; @@ -107,7 +112,7 @@ namespace Duplicati.Library.Snapshots //Set the VM ID Selector Field for the WMI Query _vmIdField = _wmiv2Namespace ? "VirtualSystemIdentifier" : "SystemName"; - Logging.Log.WriteMessage(string.Format("Using WMI provider {0}", _wmiScope.Path), Logging.LogMessageType.Profiling); + Logging.Log.WriteProfilingMessage(LOGTAG, "WMISelect", "Using WMI provider {0}", _wmiScope.Path); IsVSSWriterSupported = new ManagementObjectSearcher("SELECT * FROM Win32_OperatingSystem") .Get().OfType() @@ -123,7 +128,7 @@ namespace Duplicati.Library.Snapshots catch { IsHyperVInstalled = false; } if (!IsHyperVInstalled) - Logging.Log.WriteMessage(string.Format("Cannot open WMI provider {0}. Hyper-V is probably not installed.", _wmiScope.Path), Logging.LogMessageType.Information); + Logging.Log.WriteInformationMessage(LOGTAG, "NoHyperVFound", "Cannot open WMI provider {0}. Hyper-V is probably not installed.", _wmiScope.Path); } /// @@ -181,7 +186,7 @@ namespace Duplicati.Library.Snapshots var writerMetaData = m_backup.WriterMetadata.FirstOrDefault(o => o.WriterId.Equals(HyperVWriterGuid)); if (writerMetaData == null) - throw new Duplicati.Library.Interface.UserInformationException("Microsoft Hyper-V VSS Writer not found - cannot backup Hyper-V machines."); + throw new Duplicati.Library.Interface.UserInformationException("Microsoft Hyper-V VSS Writer not found - cannot backup Hyper-V machines.", "NoHyperVVssWriter"); foreach (var component in writerMetaData.Components) { diff --git a/Duplicati/Library/Snapshots/LinuxSnapshot.cs b/Duplicati/Library/Snapshots/LinuxSnapshot.cs index f0723bee9..ef9632dc3 100644 --- a/Duplicati/Library/Snapshots/LinuxSnapshot.cs +++ b/Duplicati/Library/Snapshots/LinuxSnapshot.cs @@ -148,7 +148,7 @@ namespace Duplicati.Library.Snapshots p.Kill(); p.WaitForExit(5 * 1000); //This should work, and if it does, prevents a race with any cleanup invocations - throw new Duplicati.Library.Interface.UserInformationException(Strings.LinuxSnapshot.ExternalProgramTimeoutError(program, commandline)); + throw new Duplicati.Library.Interface.UserInformationException(Strings.LinuxSnapshot.ExternalProgramTimeoutError(program, commandline), "LvmScriptTimeout"); } //Build the output string. Since the process has exited, these cannot block @@ -156,7 +156,7 @@ namespace Duplicati.Library.Snapshots //Throw an exception if something went wrong if (p.ExitCode != expectedExitCode) - throw new Duplicati.Library.Interface.UserInformationException(Strings.LinuxSnapshot.ScriptExitCodeError(p.ExitCode, expectedExitCode, output)); + throw new Duplicati.Library.Interface.UserInformationException(Strings.LinuxSnapshot.ScriptExitCodeError(p.ExitCode, expectedExitCode, output), "LvmScriptWrongExitCode"); return output; } diff --git a/Duplicati/Library/Snapshots/MSSQLUtility.cs b/Duplicati/Library/Snapshots/MSSQLUtility.cs index 1c0de4844..0f8f03e54 100644 --- a/Duplicati/Library/Snapshots/MSSQLUtility.cs +++ b/Duplicati/Library/Snapshots/MSSQLUtility.cs @@ -63,6 +63,10 @@ namespace Duplicati.Library.Snapshots public class MSSQLUtility { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(); /// /// The MS SQL VSS Writer Guid /// @@ -119,7 +123,7 @@ namespace Duplicati.Library.Snapshots IsMSSQLInstalled = arrInstalledInstances == null ? false : arrInstalledInstances.Length > 0; if (!IsMSSQLInstalled) - Logging.Log.WriteMessage("Cannot find any MS SQL Server instance. MS SQL Server is probably not installed.", Logging.LogMessageType.Information); + Logging.Log.WriteInformationMessage(LOGTAG, "NoMSSQLInstance", "Cannot find any MS SQL Server instance. MS SQL Server is probably not installed."); } /// @@ -151,7 +155,7 @@ namespace Duplicati.Library.Snapshots var writerMetaData = m_backup.WriterMetadata.FirstOrDefault(o => o.WriterId.Equals(MSSQLWriterGuid)); if (writerMetaData == null) - throw new Duplicati.Library.Interface.UserInformationException("Microsoft SQL Server VSS Writer not found - cannot backup SQL databases."); + throw new Duplicati.Library.Interface.UserInformationException("Microsoft SQL Server VSS Writer not found - cannot backup SQL databases.", "NoMsSqlVssWriter"); foreach (var component in writerMetaData.Components) { diff --git a/Duplicati/Library/Snapshots/USNHelper.cs b/Duplicati/Library/Snapshots/USNHelper.cs index 4099e73ad..d21703af4 100644 --- a/Duplicati/Library/Snapshots/USNHelper.cs +++ b/Duplicati/Library/Snapshots/USNHelper.cs @@ -74,7 +74,7 @@ namespace Duplicati.Library.Snapshots internal USNHelper(string path, string volumeRoot) { if (Utility.Utility.IsClientLinux) - throw new Duplicati.Library.Interface.UserInformationException(Strings.USNHelper.LinuxNotSupportedError); + throw new Duplicati.Library.Interface.UserInformationException(Strings.USNHelper.LinuxNotSupportedError, "UsnOnLinuxNotSupported"); if (!System.IO.Path.IsPathRooted(path)) throw new Exception(string.Format("Path {0} is not rooted", path)); diff --git a/Duplicati/Library/Snapshots/WinNativeMethods.cs b/Duplicati/Library/Snapshots/WinNativeMethods.cs index bd2af622b..b7b1ac1c1 100644 --- a/Duplicati/Library/Snapshots/WinNativeMethods.cs +++ b/Duplicati/Library/Snapshots/WinNativeMethods.cs @@ -235,14 +235,14 @@ namespace Duplicati.Library.Snapshots GetBackupPrivilege(out hasPrivilege, out isEnabled); if (!hasPrivilege) - throw new Duplicati.Library.Interface.UserInformationException(Strings.WinNativeMethod.MissingBackupPrivilegeError); + throw new Duplicati.Library.Interface.UserInformationException(Strings.WinNativeMethod.MissingBackupPrivilegeError, "MissingBackupPrivilege"); return isEnabled; } set { if (!CanEnableBackupPrivilege) - throw new Duplicati.Library.Interface.UserInformationException(Strings.WinNativeMethod.MissingBackupPrivilegeError); + throw new Duplicati.Library.Interface.UserInformationException(Strings.WinNativeMethod.MissingBackupPrivilegeError, "MissingBackupPrivilege"); int token = 0; int outsize = 0; diff --git a/Duplicati/Library/Snapshots/WindowsSnapshot.cs b/Duplicati/Library/Snapshots/WindowsSnapshot.cs index 075784ce9..4f256367c 100644 --- a/Duplicati/Library/Snapshots/WindowsSnapshot.cs +++ b/Duplicati/Library/Snapshots/WindowsSnapshot.cs @@ -38,6 +38,10 @@ namespace Duplicati.Library.Snapshots /// public class WindowsSnapshot : ISnapshotService { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(); /// /// The main reference to the backup controller /// @@ -114,13 +118,13 @@ namespace Duplicati.Library.Snapshots m_sourcepaths = Utility.Utility.GetUniqueItems(m_sourcepaths, Utility.Utility.ClientFilenameStringComparer, out pathDuplicates).ToList(); foreach(var pathDuplicate in pathDuplicates) - Logging.Log.WriteMessage(string.Format("Removing duplicate source: {0}", pathDuplicate), Logging.LogMessageType.Information); + Logging.Log.WriteInformationMessage(LOGTAG, "VSSDuplicates", "Removing duplicate source: {0}", pathDuplicate); //Sanity check for multiple inclusions of the same files/folders var pathIncludedPaths = m_sourcepaths.Where(x => m_sourcepaths.Where(y => y != x).Any(z => x.StartsWith(z, Utility.Utility.ClientFilenameStringComparision))).ToList(); foreach (var pathIncluded in pathIncludedPaths) - Logging.Log.WriteMessage(string.Format("Removing already included source: {0}", pathIncluded), Logging.LogMessageType.Information); + Logging.Log.WriteInformationMessage(LOGTAG, "VSSMultiInclude", "Removing already included source: {0}", pathIncluded); if (pathIncludedPaths.Count > 0) m_sourcepaths = m_sourcepaths.Except(pathIncludedPaths, Utility.Utility.ClientFilenameStringComparer).ToList(); diff --git a/Duplicati/Library/UsageReporter/ReportSetUploader.cs b/Duplicati/Library/UsageReporter/ReportSetUploader.cs index a2e9f7600..1ac9ac3a6 100644 --- a/Duplicati/Library/UsageReporter/ReportSetUploader.cs +++ b/Duplicati/Library/UsageReporter/ReportSetUploader.cs @@ -26,6 +26,11 @@ namespace Duplicati.Library.UsageReporter { public static class ReportSetUploader { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(typeof(ReportSetUploader)); + /// /// The maximum number of pending uploads /// @@ -88,7 +93,7 @@ namespace Duplicati.Library.UsageReporter } catch (Exception ex) { - Logging.Log.WriteMessage("UsageReporter failed", Duplicati.Library.Logging.LogMessageType.Error, ex); + Logging.Log.WriteErrorMessage(LOGTAG, "UploadFailed", ex, "UsageReporter failed"); } } } diff --git a/Duplicati/Library/UsageReporter/Reporter.cs b/Duplicati/Library/UsageReporter/Reporter.cs index e89a154ed..7ef020e9f 100644 --- a/Duplicati/Library/UsageReporter/Reporter.cs +++ b/Duplicati/Library/UsageReporter/Reporter.cs @@ -25,6 +25,11 @@ namespace Duplicati.Library.UsageReporter /// public static class Reporter { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Logging.Log.LogTagFromType(typeof(Reporter)); + /// /// The primary input channel for new report messages /// @@ -122,7 +127,7 @@ namespace Duplicati.Library.UsageReporter { ShutdownTask.Wait(TimeSpan.FromSeconds(30)); if (!ShutdownTask.IsCompleted) - Logging.Log.WriteMessage("Failed to shut down usage reporter after 30 seconds, leaving hanging ...", Logging.LogMessageType.Warning); + Logging.Log.WriteWarningMessage(LOGTAG, "ReporterShutdownFailuer", null, "Failed to shut down usage reporter after 30 seconds, leaving hanging ..."); } AppDomain.CurrentDomain.UnhandledException -= HandleUncaughtException; diff --git a/Duplicati/Library/Utility/AsyncHttpRequest.cs b/Duplicati/Library/Utility/AsyncHttpRequest.cs index 87aa8ef99..d8eff7bfb 100644 --- a/Duplicati/Library/Utility/AsyncHttpRequest.cs +++ b/Duplicati/Library/Utility/AsyncHttpRequest.cs @@ -79,7 +79,7 @@ namespace Duplicati.Library.Utility public AsyncHttpRequest(WebRequest request) { if (request == null) - throw new ArgumentNullException("request"); + throw new ArgumentNullException(nameof(request)); m_request = request; m_timeout = m_request.Timeout; if (m_timeout != System.Threading.Timeout.Infinite) diff --git a/Duplicati/Library/Utility/BlockingQueue.cs b/Duplicati/Library/Utility/BlockingQueue.cs index 0709434b9..5a057f489 100644 --- a/Duplicati/Library/Utility/BlockingQueue.cs +++ b/Duplicati/Library/Utility/BlockingQueue.cs @@ -24,7 +24,7 @@ using System.Text; namespace Duplicati.Library.Utility { /// - /// Class for wrapping a as an + /// Class for wrapping a as an /// public class BlockingQueueAsEnumerable : IEnumerable { @@ -115,7 +115,7 @@ namespace Duplicati.Library.Utility /// /// The lock that protects the data structures /// - private object m_lock = new object(); + private readonly object m_lock = new object(); /// /// The queue storing the elements produced /// @@ -138,19 +138,19 @@ namespace Duplicati.Library.Utility private long m_maxCapacity = 100; /// - /// Initializes a new instance of the class with the default capacity + /// Initializes a new instance of the class with the default capacity /// public BlockingQueue() { } /// - /// Gets a value indicating whether this is completed + /// Gets a value indicating whether this is completed /// public bool Completed { get { return m_completed; } } /// - /// Initializes a new instance of the class + /// Initializes a new instance of the class /// /// The maximum capacity of the queue, the producers will be blocked if more elements are put into the queue public BlockingQueue(long maxCapacity) diff --git a/Duplicati/Library/Utility/DefaultFilters.cs b/Duplicati/Library/Utility/DefaultFilters.cs index 7c04ac378..18900177d 100644 --- a/Duplicati/Library/Utility/DefaultFilters.cs +++ b/Duplicati/Library/Utility/DefaultFilters.cs @@ -34,6 +34,8 @@ namespace Duplicati.Library.Utility /// This class defines a set of common filters for files that don't typically need to be backed up. /// These filters are largely based on the filters described here: /// https://superuser.com/questions/443890/what-files-file-types-and-folders-to-exclude-from-user-folder-backup + /// which are in turn based on the filters defined by Crashplan: + /// https://support.code42.com/CrashPlan/4/Troubleshooting/What_is_not_backing_up#Admin_Excludes /// public static class DefaultFilters { @@ -114,6 +116,10 @@ namespace Duplicati.Library.Utility // If no filter sets are specified, we use the default for the platform we're on if (!anyOptions) { + // Until we agree on how default filters should be applied, + // we do not apply default filters + + /* if (Utility.IsClientWindows) { filterSets |= DefaultFilterSet.Windows; @@ -127,7 +133,8 @@ namespace Duplicati.Library.Utility if (Utility.IsClientLinux) { filterSets |= DefaultFilterSet.Linux; - } + }*/ + } if (filterSets == DefaultFilterSet.None) @@ -180,7 +187,6 @@ namespace Duplicati.Library.Utility { var filters = new[] { - DefaultFilters.CreateWildcardFilter(@"*/config.msi/*.rbf"), // https://github.com/duplicati/duplicati/issues/2886 DefaultFilters.CreateWildcardFilter(@"*.tmp"), DefaultFilters.CreateWildcardFilter(@"*.tmp/*"), DefaultFilters.CreateWildcardFilter(@"*/$RECYCLE.BIN/*"), @@ -188,48 +194,32 @@ namespace Duplicati.Library.Utility DefaultFilters.CreateWildcardFilter(@"*/AppData/Local/Microsoft/Windows Store/*"), DefaultFilters.CreateWildcardFilter(@"*/AppData/Local/Packages/*"), // https://superuser.com/questions/490925/explain-windows-8-windows-store-appdata-packages-and-what-to-backup DefaultFilters.CreateWildcardFilter(@"*/AppData/Local/Temp*"), - DefaultFilters.CreateWildcardFilter(@"*/AppData/LocalLow/*"), DefaultFilters.CreateWildcardFilter(@"*/AppData/Temp*"), DefaultFilters.CreateWildcardFilter(@"*/Application Data/Apple Computer/Mobile Sync/*"), DefaultFilters.CreateWildcardFilter(@"*/Application Data/Application Data*"), - DefaultFilters.CreateWildcardFilter(@"*/Cookies/*"), DefaultFilters.CreateWildcardFilter(@"*/Google/Chrome/User Data/Default/Cookies"), DefaultFilters.CreateWildcardFilter(@"*/Google/Chrome/User Data/Default/Cookies-journal"), DefaultFilters.CreateWildcardFilter(@"*/I386*"), DefaultFilters.CreateWildcardFilter(@"*/Internet Explorer/*"), - DefaultFilters.CreateWildcardFilter(@"*/Local Settings/History/*"), DefaultFilters.CreateWildcardFilter(@"*/Local Settings/Temp*"), - DefaultFilters.CreateWildcardFilter(@"*/LocalService/*"), DefaultFilters.CreateWildcardFilter(@"*/Microsoft*/RecoveryStore*"), DefaultFilters.CreateWildcardFilter(@"*/Microsoft*/Windows/*.edb"), DefaultFilters.CreateWildcardFilter(@"*/Microsoft*/Windows/*.log"), DefaultFilters.CreateWildcardFilter(@"*/Microsoft*/Windows/Cookies*"), DefaultFilters.CreateWildcardFilter(@"*/MSOCache*"), - DefaultFilters.CreateWildcardFilter(@"*/NetHood/*"), - DefaultFilters.CreateWildcardFilter(@"*/NetworkService/*"), DefaultFilters.CreateWildcardFilter(@"*/NTUSER*"), - DefaultFilters.CreateWildcardFilter(@"*/ntuser.dat*"), - DefaultFilters.CreateWildcardFilter(@"*/PrintHood/*"), DefaultFilters.CreateWildcardFilter(@"*/Recent/*"), DefaultFilters.CreateWildcardFilter(@"*/RECYCLER/*"), DefaultFilters.CreateWildcardFilter(@"*/Safari/Library/Caches/*"), - DefaultFilters.CreateWildcardFilter(@"*/SendTo/*"), - DefaultFilters.CreateWildcardFilter(@"*/Start Menu/*"), DefaultFilters.CreateWildcardFilter(@"*/Temporary Internet Files/*"), DefaultFilters.CreateWildcardFilter(@"*/Thumbs.db"), DefaultFilters.CreateWildcardFilter(@"*UsrClass.dat"), DefaultFilters.CreateWildcardFilter(@"*UsrClass.dat.LOG"), - DefaultFilters.CreateWildcardFilter(@"?:/autoexec.bat"), - DefaultFilters.CreateWildcardFilter(@"?:/Config.Msi*"), + DefaultFilters.CreateWildcardFilter(@"?:/Config.Msi*"), // https://github.com/duplicati/duplicati/issues/2886 DefaultFilters.CreateWildcardFilter(@"?:/hiberfil.sys"), DefaultFilters.CreateWildcardFilter(@"?:/pagefile.sys"), - DefaultFilters.CreateWildcardFilter(@"?:/Program Files (x86)/*"), - DefaultFilters.CreateWildcardFilter(@"?:/Program Files/*"), - DefaultFilters.CreateWildcardFilter(@"?:/ProgramData/*"), DefaultFilters.CreateWildcardFilter(@"?:/swapfile.sys"), DefaultFilters.CreateWildcardFilter(@"?:/System Volume Information/*"), - DefaultFilters.CreateWildcardFilter(@"?:/Windows.old/*"), - DefaultFilters.CreateWildcardFilter(@"?:/Windows/*"), DefaultFilters.CreateWildcardFilter(@"?:/Windows/Installer*"), DefaultFilters.CreateWildcardFilter(@"?:/Windows/Temp*"), }; @@ -282,23 +272,20 @@ namespace Duplicati.Library.Utility DefaultFilters.CreateWildcardFilter(@"*/Network Trash Folder/*"), DefaultFilters.CreateWildcardFilter(@"*/Trash/*"), DefaultFilters.CreateWildcardFilter(@"*/VM Storage"), - DefaultFilters.CreateWildcardFilter(@"*Mobile.*Backups/*"), + DefaultFilters.CreateWildcardFilter(@"*MobileBackups/*"), DefaultFilters.CreateWildcardFilter(@"/.vol/*"), DefaultFilters.CreateWildcardFilter(@"/afs/*"), DefaultFilters.CreateWildcardFilter(@"/automount/*"), - DefaultFilters.CreateWildcardFilter(@"/bin/*"), DefaultFilters.CreateWildcardFilter(@"/cores/*"), DefaultFilters.CreateWildcardFilter(@"/Desktop DB"), DefaultFilters.CreateWildcardFilter(@"/Desktop DF"), DefaultFilters.CreateWildcardFilter(@"/dev/.*"), - DefaultFilters.CreateWildcardFilter(@"/etc/*"), DefaultFilters.CreateWildcardFilter(@"/mach.sym"), DefaultFilters.CreateWildcardFilter(@"/mach_kernel"), DefaultFilters.CreateWildcardFilter(@"/net/*"), DefaultFilters.CreateWildcardFilter(@"/Network/*"), DefaultFilters.CreateWildcardFilter(@"/Network/Servers*"), DefaultFilters.CreateWildcardFilter(@"/Previous Systems*"), - DefaultFilters.CreateWildcardFilter(@"/private/*"), DefaultFilters.CreateWildcardFilter(@"/private/Network/*"), DefaultFilters.CreateWildcardFilter(@"/private/tmp/*"), DefaultFilters.CreateWildcardFilter(@"/private/var/automount/*"), @@ -309,13 +296,9 @@ namespace Duplicati.Library.Utility DefaultFilters.CreateWildcardFilter(@"/private/var/spool/postfix/*"), DefaultFilters.CreateWildcardFilter(@"/private/var/tmp/*"), DefaultFilters.CreateWildcardFilter(@"/private/var/vm/*"), - DefaultFilters.CreateWildcardFilter(@"/sbin/*"), - DefaultFilters.CreateWildcardFilter(@"/sw/*"), - DefaultFilters.CreateWildcardFilter(@"/System/*"), DefaultFilters.CreateWildcardFilter(@"/System/Library/Extensions/Caches/*"), DefaultFilters.CreateWildcardFilter(@"/tmp/*"), DefaultFilters.CreateWildcardFilter(@"/Users/Shared/SC Info*"), - DefaultFilters.CreateWildcardFilter(@"/usr/*"), }; } @@ -331,21 +314,11 @@ namespace Duplicati.Library.Utility DefaultFilters.CreateWildcardFilter(@"*/.config/google-chrome/Default/Cookies-journal"), DefaultFilters.CreateWildcardFilter(@"*/lost+found/*"), DefaultFilters.CreateWildcardFilter(@"*~"), - DefaultFilters.CreateWildcardFilter(@"/bin/*"), - DefaultFilters.CreateWildcardFilter(@"/boot/*"), DefaultFilters.CreateWildcardFilter(@"/dev/*"), - DefaultFilters.CreateWildcardFilter(@"/etc/*"), - DefaultFilters.CreateWildcardFilter(@"/initrd/*"), - DefaultFilters.CreateWildcardFilter(@"/lib/*"), - DefaultFilters.CreateWildcardFilter(@"/opt/*"), DefaultFilters.CreateWildcardFilter(@"/proc/*"), - DefaultFilters.CreateWildcardFilter(@"/sbin/*"), DefaultFilters.CreateWildcardFilter(@"/selinux/*"), - DefaultFilters.CreateWildcardFilter(@"/srv/*"), DefaultFilters.CreateWildcardFilter(@"/sys/*"), DefaultFilters.CreateWildcardFilter(@"/tmp/*"), - DefaultFilters.CreateWildcardFilter(@"/usr/*"), - DefaultFilters.CreateWildcardFilter(@"/var/*"), }; } diff --git a/Duplicati/Library/Utility/DirectStreamLink.cs b/Duplicati/Library/Utility/DirectStreamLink.cs index e0fe8c1c6..32dbb63a2 100644 --- a/Duplicati/Library/Utility/DirectStreamLink.cs +++ b/Duplicati/Library/Utility/DirectStreamLink.cs @@ -41,7 +41,7 @@ namespace Duplicati.Library.Utility /// Used to protect accesses to all state vars and making decisions /// on blocking thereon. /// - private object m_lock = new object(); + private readonly object m_lock = new object(); /// An event to wake reader. private ManualResetEventSlim m_signalDataAvailable = new ManualResetEventSlim(false); diff --git a/Duplicati/Library/Utility/FilterExpression.cs b/Duplicati/Library/Utility/FilterExpression.cs index a9ab54409..e03139b93 100644 --- a/Duplicati/Library/Utility/FilterExpression.cs +++ b/Duplicati/Library/Utility/FilterExpression.cs @@ -288,7 +288,7 @@ namespace Duplicati.Library.Utility } /// - /// Creates a new instance. + /// Creates a new instance. /// /// The filter string that represents the filter public FilterExpression(IEnumerable filter, bool result = true) @@ -375,7 +375,7 @@ namespace Duplicati.Library.Utility /// /// The lock object for protecting access to the lookup table /// - private static object _matchLock = new object(); + private readonly static object _matchLock = new object(); /// /// Utility function to match a filter with a default fall-through value diff --git a/Duplicati/Library/Utility/OverrideableStream.cs b/Duplicati/Library/Utility/OverrideableStream.cs index 5bce21c36..94c35c2b7 100644 --- a/Duplicati/Library/Utility/OverrideableStream.cs +++ b/Duplicati/Library/Utility/OverrideableStream.cs @@ -36,7 +36,7 @@ namespace Duplicati.Library.Utility public OverrideableStream(Stream basestream) { if (basestream == null) - throw new ArgumentNullException("basestream"); + throw new ArgumentNullException(nameof(basestream)); m_basestream = basestream; } diff --git a/Duplicati/Library/Utility/ShaderStream.cs b/Duplicati/Library/Utility/ShaderStream.cs index 7fc970ca0..71ccd1b2c 100644 --- a/Duplicati/Library/Utility/ShaderStream.cs +++ b/Duplicati/Library/Utility/ShaderStream.cs @@ -22,7 +22,7 @@ using System; namespace Duplicati.Library.Utility { /// - /// A small utility stream that allows to keep streams open and counts the bytes sent through. + /// A small utility stream that allows to keep streams open and counts the bytes sent through. /// public class ShaderStream : System.IO.Stream { diff --git a/Duplicati/Library/Utility/TempFile.cs b/Duplicati/Library/Utility/TempFile.cs index a1750833a..ba7a49706 100644 --- a/Duplicati/Library/Utility/TempFile.cs +++ b/Duplicati/Library/Utility/TempFile.cs @@ -38,7 +38,7 @@ namespace Duplicati.Library.Utility #if DEBUG //In debug mode, we track the creation of temporary files, and encode the generating method into the name - private static object m_lock = new object(); + private static readonly object m_lock = new object(); private static Dictionary m_fileTrace = new Dictionary(); public static System.Diagnostics.StackTrace GetStackTraceForTempFile(string filename) diff --git a/Duplicati/Library/Utility/Uri.cs b/Duplicati/Library/Utility/Uri.cs index 8b5a6baf3..7e42f025c 100644 --- a/Duplicati/Library/Utility/Uri.cs +++ b/Duplicati/Library/Utility/Uri.cs @@ -124,13 +124,13 @@ namespace Duplicati.Library.Utility } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The URL to parse public Uri(string url) { if (string.IsNullOrEmpty(url)) - throw new ArgumentNullException("url"); + throw new ArgumentNullException(nameof(url)); m_queryParams = null; this.OriginalUri = url; @@ -356,7 +356,7 @@ namespace Duplicati.Library.Utility public static string UrlEncode(string value, System.Text.Encoding encoding = null, string spacevalue = "+") { if (value == null) - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); encoding = encoding ?? System.Text.Encoding.UTF8; @@ -399,7 +399,7 @@ namespace Duplicati.Library.Utility public static string UrlDecode(string value, System.Text.Encoding encoding = null) { if (value == null) - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); encoding = encoding ?? System.Text.Encoding.UTF8; @@ -443,7 +443,7 @@ namespace Duplicati.Library.Utility public static NameValueCollection ParseQueryString(string query) { if (query == null) - throw new ArgumentNullException("query"); + throw new ArgumentNullException(nameof(query)); if (query.StartsWith("?", StringComparison.Ordinal)) query = query.Substring(1); if (string.IsNullOrEmpty(query)) diff --git a/Duplicati/Library/Utility/Win32.cs b/Duplicati/Library/Utility/Win32.cs index d830a09ed..1f57f0c24 100644 --- a/Duplicati/Library/Utility/Win32.cs +++ b/Duplicati/Library/Utility/Win32.cs @@ -51,6 +51,125 @@ namespace Duplicati.Library.Utility // ES_USER_PRESENT = 0x00000004 } + + [Flags] + public enum PROCESS_PRIORITY_CLASS : int + { + /// + /// Process that has priority above but below . + /// + ABOVE_NORMAL_PRIORITY_CLASS = 0x00008000, + /// + /// Process that has priority above but below . + /// + BELOW_NORMAL_PRIORITY_CLASS = 0x00004000, + /// + /// Process that performs time-critical tasks that must be executed immediately. The threads of the process preempt the threads of normal or idle priority class processes. An example is the Task List, which must respond quickly when called by the user, regardless of the load on the operating system. Use extreme care when using the high-priority class, because a high-priority class application can use nearly all available CPU time. + /// + HIGH_PRIORITY_CLASS = 0x00000080, + /// + /// Process whose threads run only when the system is idle. The threads of the process are preempted by the threads of any process running in a higher priority class. An example is a screen saver. The idle-priority class is inherited by child processes. + /// + IDLE_PRIORITY_CLASS = 0x00000040, + /// + /// Process with no special scheduling needs. + /// + NORMAL_PRIORITY_CLASS = 0x00000020, + /// + /// Begin background processing mode. The system lowers the resource scheduling priorities of the process (and its threads) so that it can perform background work without significantly affecting activity in the foreground. + /// + PROCESS_MODE_BACKGROUND_BEGIN = 0x00100000, + /// + /// End background processing mode. The system restores the resource scheduling priorities of the process (and its threads) as they were before the process entered background processing mode. + /// + PROCESS_MODE_BACKGROUND_END = 0x00200000, + /// + /// Process that has the highest possible priority. The threads of the process preempt the threads of all other processes, including operating system processes performing important tasks. For example, a real-time process that executes for more than a very brief interval can cause disk caches not to flush or cause the mouse to be unresponsive. + /// + REALTIME_PRIORITY_CLASS = 0x00000100 + } + + + /// + /// The IO priority settings + /// + public enum IO_PRIORITY_HINT : int + { + /// + /// Defragging, content indexing and other background I/Os. + /// + IoPriorityVeryLow = 0, + /// + /// Prefetching for applications. + /// + IoPriorityLow, + /// + /// Normal I/Os. + /// + IoPriorityNormal, + /// + /// Used by filesystems for checkpoint I/O. + /// + IoPriorityHigh, + /// + /// Used by memory manager. Not available for applications. + /// + IoPriorityCritical, + } + + + public enum PROCESS_INFORMATION_CLASS : int + { + ProcessBasicInformation = 0, + ProcessQuotaLimits, + ProcessIoCounters, + ProcessVmCounters, + ProcessTimes, + ProcessBasePriority, + ProcessRaisePriority, + ProcessDebugPort, + ProcessExceptionPort, + ProcessAccessToken, + ProcessLdtInformation, + ProcessLdtSize, + ProcessDefaultHardErrorMode, + ProcessIoPortHandlers, + ProcessPooledUsageAndLimits, + ProcessWorkingSetWatch, + ProcessUserModeIOPL, + ProcessEnableAlignmentFaultFixup, + ProcessPriorityClass, + ProcessWx86Information, + ProcessHandleCount, + ProcessAffinityMask, + ProcessPriorityBoost, + ProcessDeviceMap, + ProcessSessionInformation, + ProcessForegroundInformation, + ProcessWow64Information, + ProcessImageFileName, + ProcessLUIDDeviceMapsEnabled, + ProcessBreakOnTermination, + ProcessDebugObjectHandle, + ProcessDebugFlags, + ProcessHandleTracing, + ProcessIoPriority, + ProcessExecuteFlags, + ProcessResourceManagement, + ProcessCookie, + ProcessImageInformation, + ProcessCycleTime, + ProcessPagePriority, + ProcessInstrumentationCallback, + ProcessThreadStackAllocation, + ProcessWorkingSetWatchEx, + ProcessImageFileNameWin32, + ProcessImageFileMapping, + ProcessAffinityUpdateMode, + ProcessMemoryAllocationMode, + MaxProcessInfoClass + } + #endregion #region Function calls @@ -68,6 +187,46 @@ namespace Duplicati.Library.Utility [DllImport("kernel32.dll", SetLastError = true)] public static extern bool AttachConsole(int dwProcessId); + /// + /// Sets the process information parameters + /// + /// The set information process. + /// The process to use. + /// The process information class. + /// The process information. + /// The process information length. + [DllImport("ntdll.dll", SetLastError = true)] + public static extern int NtSetInformationProcess(IntPtr hProcess, PROCESS_INFORMATION_CLASS processInformationClass, ref IO_PRIORITY_HINT processInformation, int processInformationLength); + + + /// + /// Sets the process information parameters + /// + /// The query information. + /// The process to use. + /// The process information class. + /// The process information. + /// Process information length. + /// The size of the result. + [DllImport("ntdll.dll", SetLastError = true)] + public static extern int NtQueryInformationProcess(IntPtr hProcess, PROCESS_INFORMATION_CLASS processInformationClass, ref IO_PRIORITY_HINT processInformation, int processInformationLength, IntPtr returnlen); + + /// + /// Sets the priority class for the specified process. This value together with the priority value of each thread of the process determines each thread's base priority level. + /// + /// true, if priority class was set, false otherwise. + /// A handle to the process. The handle must have the PROCESS_SET_INFORMATION access right. + /// The priority class for the process. + [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern bool SetPriorityClass(IntPtr handle, PROCESS_PRIORITY_CLASS priorityClass); + + /// + /// Gets the priority class for the specified process. This value together with the priority value of each thread of the process determines each thread's base priority level. + /// + /// The value. + /// A handle to the process. The handle must have the PROCESS_SET_INFORMATION access right. + [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern PROCESS_PRIORITY_CLASS GetPriorityClass(IntPtr handle); #endregion } } diff --git a/Duplicati/Library/Utility/WorkerThread.cs b/Duplicati/Library/Utility/WorkerThread.cs index ee4bd9b2e..cff4219fc 100644 --- a/Duplicati/Library/Utility/WorkerThread.cs +++ b/Duplicati/Library/Utility/WorkerThread.cs @@ -33,7 +33,7 @@ namespace Duplicati.Library.Utility /// /// Locking object for shared data /// - private object m_lock = new object(); + private readonly object m_lock = new object(); /// /// The wait event /// diff --git a/Duplicati/Server/Database/Connection.cs b/Duplicati/Server/Database/Connection.cs index 3a085574c..fbefec2e9 100644 --- a/Duplicati/Server/Database/Connection.cs +++ b/Duplicati/Server/Database/Connection.cs @@ -81,7 +81,7 @@ namespace Duplicati.Server.Database lock(m_lock) { if (backup == null) - throw new ArgumentNullException("backup"); + throw new ArgumentNullException(nameof(backup)); if (backup.ID != null) throw new ArgumentException("Backup is already active, cannot make temporary"); @@ -276,7 +276,7 @@ namespace Duplicati.Server.Database internal IBackup GetBackup(string id) { if (string.IsNullOrWhiteSpace(id)) - throw new ArgumentNullException("id"); + throw new ArgumentNullException(nameof(id)); long lid; if (long.TryParse(id, out lid)) @@ -759,11 +759,12 @@ namespace Duplicati.Server.Database return true; } - public void RegisterNotification(Serialization.NotificationType type, string title, string message, Exception ex, string backupid, string action, Func conflicthandler) + public void RegisterNotification(Serialization.NotificationType type, string title, string message, Exception ex, string backupid, string action, string logid, string messageid, string logtag, Func conflicthandler) { lock(m_lock) { - var notification = new Notification() { + var notification = new Notification() + { ID = -1, Type = type, Title = title, @@ -771,7 +772,10 @@ namespace Duplicati.Server.Database Exception = ex == null ? "" : ex.ToString(), BackupID = backupid, Action = action ?? "", - Timestamp = DateTime.UtcNow + Timestamp = DateTime.UtcNow, + LogEntryID = logid, + MessageID = messageid, + MessageLogTag = logtag }; var conflictResult = conflicthandler(notification, GetNotifications()); diff --git a/Duplicati/Server/Database/Database schema/5. Extend notification table.sql b/Duplicati/Server/Database/Database schema/5. Extend notification table.sql new file mode 100644 index 000000000..35506e9d3 --- /dev/null +++ b/Duplicati/Server/Database/Database schema/5. Extend notification table.sql @@ -0,0 +1,3 @@ +ALTER TABLE "Notification" ADD COLUMN "LogEntryID" TEXT NULL; +ALTER TABLE "Notification" ADD COLUMN "MessageID" TEXT NULL; +ALTER TABLE "Notification" ADD COLUMN "MessageLogTag" TEXT NULL; diff --git a/Duplicati/Server/Database/Database schema/Schema.sql b/Duplicati/Server/Database/Database schema/Schema.sql index 6cc17ae73..6ebd58082 100644 --- a/Duplicati/Server/Database/Database schema/Schema.sql +++ b/Duplicati/Server/Database/Database schema/Schema.sql @@ -127,7 +127,10 @@ CREATE TABLE "Notification" ( "Exception" TEXT NOT NULL, "BackupID" TEXT NULL, "Action" TEXT NOT NULL, - "Timestamp" INTEGER NOT NULL + "Timestamp" INTEGER NOT NULL, + "LogEntryID" TEXT NULL, + "MessageID" TEXT NULL, + "MessageLogTag" TEXT NULL ); /* @@ -150,5 +153,5 @@ CREATE TABLE "TempFile" ( "Expires" INTEGER NOT NULL ); -INSERT INTO "Version" ("Version") VALUES (4); +INSERT INTO "Version" ("Version") VALUES (5); diff --git a/Duplicati/Server/Database/Notification.cs b/Duplicati/Server/Database/Notification.cs index 1490911ca..22b507701 100644 --- a/Duplicati/Server/Database/Notification.cs +++ b/Duplicati/Server/Database/Notification.cs @@ -30,6 +30,9 @@ namespace Duplicati.Server.Database public string BackupID { get; set; } public string Action { get; set; } public DateTime Timestamp { get; set; } + public string LogEntryID { get; set; } + public string MessageID { get; set; } + public string MessageLogTag { get; set; } #endregion } } diff --git a/Duplicati/Server/Duplicati.Server.Serialization/Implementations/Notification.cs b/Duplicati/Server/Duplicati.Server.Serialization/Implementations/Notification.cs index 12433ac47..e18ed9c22 100644 --- a/Duplicati/Server/Duplicati.Server.Serialization/Implementations/Notification.cs +++ b/Duplicati/Server/Duplicati.Server.Serialization/Implementations/Notification.cs @@ -29,6 +29,9 @@ namespace Duplicati.Server.Serialization.Implementations public string BackupID { get; set; } public string Action { get; set; } public DateTime Timestamp { get; set; } + public string LogEntryID { get; set; } + public string MessageID { get; set; } + public string MessageLogTag { get; set; } } } diff --git a/Duplicati/Server/Duplicati.Server.Serialization/Interface/INotification.cs b/Duplicati/Server/Duplicati.Server.Serialization/Interface/INotification.cs index e2410551c..3d251c11d 100644 --- a/Duplicati/Server/Duplicati.Server.Serialization/Interface/INotification.cs +++ b/Duplicati/Server/Duplicati.Server.Serialization/Interface/INotification.cs @@ -19,16 +19,56 @@ using System; namespace Duplicati.Server.Serialization.Interface { + /// + /// Describes a notification + /// public interface INotification { + /// + /// The notification unique ID + /// long ID { get; set; } + /// + /// The notification type + /// NotificationType Type { get; set; } + /// + /// The notification title + /// string Title { get; set; } + /// + /// The notification message + /// string Message { get; set; } + /// + /// The serialized exception data, if any + /// string Exception { get; set; } + /// + /// The ID of the backup that the notification belongs to + /// string BackupID { get; set; } + /// + /// The action for the notification + /// string Action { get; set; } + /// + /// When the notification was emitted + /// DateTime Timestamp { get; set; } + /// + /// The ID of the log entry that relates to this message, if any + /// + /// The log entry identifier. + string LogEntryID { get; set; } + /// + /// The ID of the event that triggered this notification + /// + string MessageID { get; set; } + /// + /// The logtag of the error or event that triggered this notification + /// + string MessageLogTag { get; set; } } } diff --git a/Duplicati/Server/Duplicati.Server.csproj b/Duplicati/Server/Duplicati.Server.csproj index f970e65a6..d956775a8 100644 --- a/Duplicati/Server/Duplicati.Server.csproj +++ b/Duplicati/Server/Duplicati.Server.csproj @@ -136,6 +136,7 @@ + diff --git a/Duplicati/Server/EventPollNotify.cs b/Duplicati/Server/EventPollNotify.cs index 2004aa00a..83e853252 100644 --- a/Duplicati/Server/EventPollNotify.cs +++ b/Duplicati/Server/EventPollNotify.cs @@ -13,7 +13,7 @@ namespace Duplicati.Server /// /// The lock that grants exclusive access to control structures /// - private object m_lock = new object(); + private readonly object m_lock = new object(); /// /// The current eventID /// diff --git a/Duplicati/Server/LiveControls.cs b/Duplicati/Server/LiveControls.cs index cafbfa6de..cfb835e3f 100644 --- a/Duplicati/Server/LiveControls.cs +++ b/Duplicati/Server/LiveControls.cs @@ -29,6 +29,11 @@ namespace Duplicati.Server /// public class LiveControls { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Duplicati.Library.Logging.Log.LogTagFromType(); + /// /// An event that is activated when the pause state changes /// @@ -97,7 +102,7 @@ namespace Duplicati.Server /// /// The object that ensures concurrent operations /// - private object m_lock = new object(); + private readonly object m_lock = new object(); /// /// Gets the current overridden thread priority @@ -190,7 +195,7 @@ namespace Duplicati.Server } catch (Exception ex) { - Library.Logging.Log.WriteMessage(string.Format("Failed to parse download limit: {0}", settings.DownloadSpeedLimit), Library.Logging.LogMessageType.Error, ex); + Library.Logging.Log.WriteErrorMessage(LOGTAG, "ParseDownloadLimitError", ex, "Failed to parse download limit: {0}", settings.DownloadSpeedLimit); } if (!string.IsNullOrEmpty(settings.UploadSpeedLimit)) @@ -200,7 +205,7 @@ namespace Duplicati.Server } catch (Exception ex) { - Library.Logging.Log.WriteMessage(string.Format("Failed to parse upload limit: {0}", settings.UploadSpeedLimit), Library.Logging.LogMessageType.Error, ex); + Library.Logging.Log.WriteErrorMessage(LOGTAG, "ParseUploadLimitError", ex, "Failed to parse upload limit: {0}", settings.UploadSpeedLimit); } try diff --git a/Duplicati/Server/LogWriteHandler.cs b/Duplicati/Server/LogWriteHandler.cs index e37857dfd..c4519c96e 100644 --- a/Duplicati/Server/LogWriteHandler.cs +++ b/Duplicati/Server/LogWriteHandler.cs @@ -27,7 +27,7 @@ namespace Duplicati.Server /// and provides an entry point for the runner /// to redirect log output to a file /// - public class LogWriteHandler : ILog, IDisposable + public class LogWriteHandler : ILogDestination, IDisposable { /// /// The number of messages to keep when inactive @@ -38,6 +38,15 @@ namespace Duplicati.Server /// private const int ACTIVE_SIZE = 5000; + /// + /// The context key used for conveying the backup ID + /// + public const string LOG_EXTRA_BACKUPID = "BackupID"; + /// + /// The context key used for conveying the task ID + /// + public const string LOG_EXTRA_TASKID = "TaskID"; + /// /// Represents a single log event /// @@ -51,41 +60,76 @@ namespace Duplicati.Server /// /// The time the message was logged /// - public DateTime When; + public readonly DateTime When; /// /// The ID assigned to the message /// - public long ID; + public readonly long ID; /// /// The logged message /// - public string Message; + public readonly string Message; + + /// + /// The log tag + /// + public readonly string Tag; + + /// + /// The message ID + /// + public readonly string MessageID; + + /// + /// The message ID + /// + public readonly string ExceptionID; /// /// The message type /// - public LogMessageType Type; + public readonly LogMessageType Type; /// /// Exception data attached to the message /// - public Exception Exception; + public readonly Exception Exception; + + /// + /// The backup ID, if any + /// + public readonly string BackupID; + + /// + /// The task ID, if any + /// + public readonly string TaskID; /// /// Initializes a new instance of the struct. /// - /// Message. - /// Type. - /// Exception. - public LogEntry(string message, LogMessageType type, Exception exception) + /// The log entry to store + public LogEntry(Duplicati.Library.Logging.LogEntry entry) { this.ID = System.Threading.Interlocked.Increment(ref _id); - this.When = DateTime.UtcNow; - this.Message = message; - this.Type = type; - this.Exception = exception; + this.When = entry.When; + this.Message = entry.FormattedMessage; + this.Type = entry.Level; + this.Exception = entry.Exception; + this.Tag = entry.Tag; + this.MessageID = entry.Id; + this.BackupID = entry[LOG_EXTRA_BACKUPID]; + this.TaskID = entry[LOG_EXTRA_TASKID]; + + if (entry.Exception == null) + this.ExceptionID = null; + else if (entry.Exception is Library.Interface.UserInformationException) + this.ExceptionID = ((Library.Interface.UserInformationException)entry.Exception).HelpID; + else + this.ExceptionID = entry.Exception.GetType().FullName; + } } @@ -99,7 +143,7 @@ namespace Duplicati.Server private int m_tail; private int m_length; private int m_key; - private object m_lock = new object(); + private readonly object m_lock = new object(); public RingBuffer(int size, IEnumerable initial = null) { @@ -183,12 +227,13 @@ namespace Duplicati.Server } private DateTime[] m_timeouts; - private object m_lock = new object(); + private readonly object m_lock = new object(); private volatile bool m_anytimeouts = false; private RingBuffer m_buffer; - private ILog m_serverfile; + private ILogDestination m_serverfile; private LogMessageType m_serverloglevel; + private LogMessageType m_logLevel; public LogWriteHandler() { @@ -214,7 +259,7 @@ namespace Duplicati.Server if (!System.IO.Directory.Exists(dir)) System.IO.Directory.CreateDirectory(dir); - m_serverfile = new StreamLog(path); + m_serverfile = new StreamLogDestination(path); m_serverloglevel = level; UpdateLogLevel(); @@ -267,20 +312,23 @@ namespace Duplicati.Server } private void UpdateLogLevel() - { - Duplicati.Library.Logging.Log.LogLevel = + { + m_logLevel = (LogMessageType)(GetActiveTimeouts().Union(new int[] { (int)m_serverloglevel }).Min()); } #region ILog implementation - public void WriteMessage(string message, LogMessageType type, Exception exception) + public void WriteMessage(Duplicati.Library.Logging.LogEntry entry) { - if (m_serverfile != null && type >= m_serverloglevel) + if (entry.Level < m_logLevel) + return; + + if (m_serverfile != null && entry.Level >= m_serverloglevel) try { - m_serverfile.WriteMessage(message, type, exception); + m_serverfile.WriteMessage(entry); } catch { @@ -303,7 +351,7 @@ namespace Duplicati.Server } if (m_buffer != null) - m_buffer.Enqueue(new LogEntry(message, type, exception)); + m_buffer.Enqueue(new LogEntry(entry)); } } diff --git a/Duplicati/Server/Program.cs b/Duplicati/Server/Program.cs index 131b496ba..177d6fd4e 100644 --- a/Duplicati/Server/Program.cs +++ b/Duplicati/Server/Program.cs @@ -7,6 +7,10 @@ namespace Duplicati.Server { public class Program { + /// + /// The log tag for messages from this class + /// + public static readonly string LOGTAG = Library.Logging.Log.LogTagFromType(); /// /// The path to the directory that contains the main executable /// @@ -40,7 +44,7 @@ namespace Duplicati.Server /// /// This is the lock to be used before manipulating the shared resources /// - public static object MainLock = new object(); + public static readonly object MainLock = new object(); /// /// This is the scheduling thread @@ -122,6 +126,11 @@ namespace Duplicati.Server /// public static LogWriteHandler LogHandler = new LogWriteHandler(); + /// + /// Used to check the origin of the web server (e.g. Tray icon or a stand alone Server) + /// + public static string Origin = "Server"; + private static System.Threading.Timer PurgeTempFilesTimer = null; public static int ServerPort @@ -138,6 +147,12 @@ namespace Duplicati.Server set { DataConnection.ApplicationSettings.IsFirstRun = value; } } + public static string StartedBy + { + get { return Origin; } + set { Origin = value; } + } + public static bool ServerPortChanged { get { return DataConnection.ApplicationSettings.ServerPortChanged; } @@ -243,7 +258,7 @@ namespace Duplicati.Server try { // Setup the log redirect - Duplicati.Library.Logging.Log.CurrentLog = Program.LogHandler; + var logscope = Library.Logging.Log.StartScope(Program.LogHandler, null); if (commandlineOptions.ContainsKey("log-file")) { @@ -859,7 +874,7 @@ namespace Duplicati.Server // If the user specifies parameters-file, all filters must be in the file. // Allowing to specify some filters on the command line could result in wrong filter ordering if (!filter.Empty && !newfilter.Empty) - throw new Duplicati.Library.Interface.UserInformationException(Strings.Program.FiltersCannotBeUsedWithFileError2); + throw new Duplicati.Library.Interface.UserInformationException(Strings.Program.FiltersCannotBeUsedWithFileError2, "FiltersCannotBeUsedOnCommandLineAndInParameterFile"); if (!newfilter.Empty) filter = newfilter; @@ -886,8 +901,8 @@ namespace Duplicati.Server if (cargs.Count >= 1 && cargs[0].Equals("backup", StringComparison.OrdinalIgnoreCase)) cargs.AddRange(newsource); - else if (newsource.Count > 0 && Library.Utility.Utility.ParseBoolOption(options, "verbose")) - Console.WriteLine(Strings.Program.SkippingSourceArgumentsOnNonBackupOperation); + else if (newsource.Count > 0) + Library.Logging.Log.WriteVerboseMessage(LOGTAG, "NotUsingBackupSources", Strings.Program.SkippingSourceArgumentsOnNonBackupOperation); return true; } diff --git a/Duplicati/Server/Runner.cs b/Duplicati/Server/Runner.cs index 3bf12e1f9..a6f5605f4 100644 --- a/Duplicati/Server/Runner.cs +++ b/Duplicati/Server/Runner.cs @@ -142,7 +142,7 @@ namespace Duplicati.Server : base() { if (runner == null) - throw new ArgumentNullException("runner"); + throw new ArgumentNullException(nameof(runner)); Run = runner; Operation = DuplicatiOperation.CustomRunner; Backup = new Database.Backup(); @@ -264,7 +264,7 @@ namespace Duplicati.Server private ProgressState m_state; private Duplicati.Library.Main.IBackendProgress m_backendProgress; private Duplicati.Library.Main.IOperationProgress m_operationProgress; - private object m_lock = new object(); + private readonly object m_lock = new object(); public MessageSink(long taskId, string backupId) { @@ -306,24 +306,10 @@ namespace Duplicati.Server } } } - public void VerboseEvent(string message, object[] args) - { - } - public void MessageEvent(string message) - { - } - public void RetryEvent(string message, Exception ex) - { - } - public void WarningEvent(string message, Exception ex) - { - } - public void ErrorEvent(string message, Exception ex) - { - } - public void DryrunEvent(string message) + public void WriteMessage(Library.Logging.LogEntry entry) { } + public Duplicati.Library.Main.IBackendProgress BackendProgress { set @@ -512,6 +498,11 @@ namespace Duplicati.Server } } + // Attach a log scope that tags all messages to relay the TaskID and BackupID + using (Library.Logging.Log.StartScope(log => { + log[LogWriteHandler.LOG_EXTRA_TASKID] = data.TaskID.ToString(); + log[LogWriteHandler.LOG_EXTRA_BACKUPID] = data.BackupID; + })) using (tempfolder) using(var controller = new Duplicati.Library.Main.Controller(backup.TargetURL, options, sink)) { @@ -615,6 +606,9 @@ namespace Duplicati.Server null, null, "bug-report:created:" + tempid, + null, + "BugreportCreatedReady", + "", (n, a) => n ); @@ -683,6 +677,10 @@ namespace Duplicati.Server if (!backup.IsTemporary) Program.DataConnection.SetMetadata(backup.Metadata, long.Parse(backup.ID), null); + string messageid = null; + if (ex is Library.Interface.UserInformationException) + messageid = ((Library.Interface.UserInformationException)ex).HelpID; + System.Threading.Interlocked.Increment(ref Program.LastDataUpdateID); Program.DataConnection.RegisterNotification( NotificationType.Error, @@ -692,6 +690,9 @@ namespace Duplicati.Server ex, backup.ID, "backup:show-log", + null, + messageid, + null, (n, a) => { return a.Where(x => x.BackupID == backup.ID).FirstOrDefault() ?? n; } @@ -762,6 +763,9 @@ namespace Duplicati.Server null, backup.ID, "backup:show-log", + null, + null, + null, (n, a) => { var existing = (a.Where(x => x.BackupID == backup.ID)).FirstOrDefault(); @@ -801,6 +805,9 @@ namespace Duplicati.Server message, null, backup.ID, + null, + null, + null, "backup:show-log", (n, a) => n ); @@ -836,7 +843,7 @@ namespace Duplicati.Server options["disable-module"] = string.Join(",", mods.Union(new string[] { module }).Distinct(StringComparer.OrdinalIgnoreCase)); } - private static Dictionary ApplyOptions(Duplicati.Server.Serialization.Interface.IBackup backup, DuplicatiOperation mode, Dictionary options) + internal static Dictionary ApplyOptions(Duplicati.Server.Serialization.Interface.IBackup backup, DuplicatiOperation mode, Dictionary options) { options["backup-name"] = backup.Name; options["dbpath"] = backup.DBPath; @@ -884,7 +891,7 @@ namespace Duplicati.Server return filter; } - private static Dictionary GetCommonOptions(Duplicati.Server.Serialization.Interface.IBackup backup, DuplicatiOperation mode) + internal static Dictionary GetCommonOptions(Duplicati.Server.Serialization.Interface.IBackup backup, DuplicatiOperation mode) { return (from n in Program.DataConnection.Settings diff --git a/Duplicati/Server/Scheduler.cs b/Duplicati/Server/Scheduler.cs index 41325f70a..fb01df458 100644 --- a/Duplicati/Server/Scheduler.cs +++ b/Duplicati/Server/Scheduler.cs @@ -34,6 +34,8 @@ namespace Duplicati.Server /// public class Scheduler { + private static readonly string LOGTAG = Duplicati.Library.Logging.Log.LogTagFromType(); + /// /// The thread that runs the scheduler /// @@ -53,7 +55,7 @@ namespace Duplicati.Server /// /// The data syncronization lock /// - private object m_lock = new object(); + private readonly object m_lock = new object(); /// /// An event that is raised when the schedule changes @@ -278,7 +280,18 @@ namespace Duplicati.Server { var entry = Program.DataConnection.GetBackup(id); if (entry != null) - jobsToRun.Add(Server.Runner.CreateTask(Duplicati.Server.Serialization.DuplicatiOperation.Backup, entry)); + { + Dictionary options = Duplicati.Server.Runner.GetCommonOptions(entry, Duplicati.Server.Serialization.DuplicatiOperation.Backup); + Duplicati.Server.Runner.ApplyOptions(entry, Duplicati.Server.Serialization.DuplicatiOperation.Backup, options); + if ((new Duplicati.Library.Main.Options(options)).DisableOnBattery && (Duplicati.Library.Utility.Power.PowerSupply.GetSource() == Duplicati.Library.Utility.Power.PowerSupply.Source.Battery)) + { + Duplicati.Library.Logging.Log.WriteInformationMessage(LOGTAG, "BackupDisabledOnBattery", "Scheduled backup disabled while on battery power."); + } + else + { + jobsToRun.Add(Server.Runner.CreateTask(Duplicati.Server.Serialization.DuplicatiOperation.Backup, entry)); + } + } } } diff --git a/Duplicati/Server/UpdatePollThread.cs b/Duplicati/Server/UpdatePollThread.cs index 0c741aff5..f913a60a6 100644 --- a/Duplicati/Server/UpdatePollThread.cs +++ b/Duplicati/Server/UpdatePollThread.cs @@ -31,7 +31,7 @@ namespace Duplicati.Server private volatile bool m_terminated = false; private volatile bool m_download = false; private volatile bool m_forceCheck = false; - private object m_lock = new object(); + private readonly object m_lock = new object(); private AutoResetEvent m_waitSignal; private double m_downloadProgress; @@ -183,6 +183,9 @@ namespace Duplicati.Server null, null, "update:new", + null, + "NewUpdateFound", + null, (self, all) => { return all.Where(x => x.Action == "update:new").FirstOrDefault() ?? self; } diff --git a/Duplicati/Server/WebServer/RESTMethods/Backup.cs b/Duplicati/Server/WebServer/RESTMethods/Backup.cs index 64d76c08a..5079b4637 100644 --- a/Duplicati/Server/WebServer/RESTMethods/Backup.cs +++ b/Duplicati/Server/WebServer/RESTMethods/Backup.cs @@ -47,7 +47,7 @@ namespace Duplicati.Server.WebServer.RESTMethods if (string.IsNullOrWhiteSpace(timestring) && !allversion) { - info.ReportClientError("Invalid or missing time"); + info.ReportClientError("Invalid or missing time", System.Net.HttpStatusCode.BadRequest); return; } @@ -329,13 +329,13 @@ namespace Duplicati.Server.WebServer.RESTMethods { var np = info.Request.Form["path"].Value; if (string.IsNullOrWhiteSpace(np)) - info.ReportClientError("No target path supplied"); + info.ReportClientError("No target path supplied", System.Net.HttpStatusCode.BadRequest); else if (!Path.IsPathRooted(np)) - info.ReportClientError("Target path is relative, please supply a fully qualified path"); + info.ReportClientError("Target path is relative, please supply a fully qualified path", System.Net.HttpStatusCode.BadRequest); else { if (move && (File.Exists(np) || Directory.Exists(np))) - info.ReportClientError("A file already exists at the new location"); + info.ReportClientError("A file already exists at the new location", System.Net.HttpStatusCode.Conflict); else { if (move) @@ -387,7 +387,7 @@ namespace Duplicati.Server.WebServer.RESTMethods IsActive(bk, info); return; default: - info.ReportClientError(string.Format("Invalid component: {0}", operation)); + info.ReportClientError(string.Format("Invalid component: {0}", operation), System.Net.HttpStatusCode.BadRequest); return; } @@ -416,7 +416,7 @@ namespace Duplicati.Server.WebServer.RESTMethods var parts = (key ?? "").Split(new char[] { '/' }, 2); var bk = Program.DataConnection.GetBackup(parts.First()); if (bk == null) - info.ReportClientError("Invalid or missing backup id"); + info.ReportClientError("Invalid or missing backup id", System.Net.HttpStatusCode.NotFound); else { if (parts.Length > 1) @@ -483,7 +483,7 @@ namespace Duplicati.Server.WebServer.RESTMethods } } - info.ReportClientError("Invalid request"); + info.ReportClientError("Invalid request", System.Net.HttpStatusCode.BadRequest); } } @@ -495,7 +495,7 @@ namespace Duplicati.Server.WebServer.RESTMethods if (string.IsNullOrWhiteSpace(str)) { - info.ReportClientError("Missing backup object"); + info.ReportClientError("Missing backup object", System.Net.HttpStatusCode.BadRequest); return; } @@ -505,7 +505,7 @@ namespace Duplicati.Server.WebServer.RESTMethods data = Serializer.Deserialize(new StringReader(str)); if (data.Backup == null) { - info.ReportClientError("Data object had no backup entry"); + info.ReportClientError("Data object had no backup entry", System.Net.HttpStatusCode.BadRequest); return; } @@ -514,7 +514,7 @@ namespace Duplicati.Server.WebServer.RESTMethods if (string.IsNullOrEmpty(data.Backup.ID)) { - info.ReportClientError("Invalid or missing backup id"); + info.ReportClientError("Invalid or missing backup id", System.Net.HttpStatusCode.BadRequest); return; } @@ -535,20 +535,20 @@ namespace Duplicati.Server.WebServer.RESTMethods var backup = Program.DataConnection.GetBackup(data.Backup.ID); if (backup == null) { - info.ReportClientError("Invalid or missing backup id"); + info.ReportClientError("Invalid or missing backup id", System.Net.HttpStatusCode.NotFound); return; } if (Program.DataConnection.Backups.Where(x => x.Name.Equals(data.Backup.Name, StringComparison.OrdinalIgnoreCase) && x.ID != data.Backup.ID).Any()) { - info.ReportClientError("There already exists a backup with the name: " + data.Backup.Name); + info.ReportClientError("There already exists a backup with the name: " + data.Backup.Name, System.Net.HttpStatusCode.Conflict); return; } var err = Program.DataConnection.ValidateBackup(data.Backup, data.Schedule); if (!string.IsNullOrWhiteSpace(err)) { - info.ReportClientError(err); + info.ReportClientError(err, System.Net.HttpStatusCode.BadRequest); return; } @@ -563,9 +563,9 @@ namespace Duplicati.Server.WebServer.RESTMethods catch (Exception ex) { if (data == null) - info.ReportClientError(string.Format("Unable to parse backup or schedule object: {0}", ex.Message)); + info.ReportClientError(string.Format("Unable to parse backup or schedule object: {0}", ex.Message), System.Net.HttpStatusCode.BadRequest); else - info.ReportClientError(string.Format("Unable to save backup or schedule: {0}", ex.Message)); + info.ReportClientError(string.Format("Unable to save backup or schedule: {0}", ex.Message), System.Net.HttpStatusCode.InternalServerError); } } @@ -586,7 +586,7 @@ namespace Duplicati.Server.WebServer.RESTMethods var captcha_answer = info.Request.Param["captcha-answer"].Value; if (string.IsNullOrWhiteSpace(captcha_token) || string.IsNullOrWhiteSpace(captcha_answer)) { - info.ReportClientError("Missing captcha"); + info.ReportClientError("Missing captcha", System.Net.HttpStatusCode.Unauthorized); return; } diff --git a/Duplicati/Server/WebServer/RESTMethods/Backups.cs b/Duplicati/Server/WebServer/RESTMethods/Backups.cs index 6e7d14f8c..87ca5bbc2 100644 --- a/Duplicati/Server/WebServer/RESTMethods/Backups.cs +++ b/Duplicati/Server/WebServer/RESTMethods/Backups.cs @@ -120,7 +120,7 @@ namespace Duplicati.Server.WebServer.RESTMethods var err = Program.DataConnection.ValidateBackup(ipx.Backup, ipx.Schedule); if (!string.IsNullOrWhiteSpace(err)) { - info.ReportClientError(err); + info.ReportClientError(err, System.Net.HttpStatusCode.BadRequest); return; } @@ -168,7 +168,7 @@ namespace Duplicati.Server.WebServer.RESTMethods data = Serializer.Deserialize(new StringReader(str)); if (data.Backup == null) { - info.ReportClientError("Data object had no backup entry"); + info.ReportClientError("Data object had no backup entry", System.Net.HttpStatusCode.BadRequest); return; } @@ -200,14 +200,14 @@ namespace Duplicati.Server.WebServer.RESTMethods { if (Program.DataConnection.Backups.Where(x => x.Name.Equals(data.Backup.Name, StringComparison.OrdinalIgnoreCase)).Any()) { - info.ReportClientError("There already exists a backup with the name: " + data.Backup.Name); + info.ReportClientError("There already exists a backup with the name: " + data.Backup.Name, System.Net.HttpStatusCode.Conflict); return; } var err = Program.DataConnection.ValidateBackup(data.Backup, data.Schedule); if (!string.IsNullOrWhiteSpace(err)) { - info.ReportClientError(err); + info.ReportClientError(err, System.Net.HttpStatusCode.BadRequest); return; } @@ -220,9 +220,9 @@ namespace Duplicati.Server.WebServer.RESTMethods catch (Exception ex) { if (data == null) - info.ReportClientError(string.Format("Unable to parse backup or schedule object: {0}", ex.Message)); + info.ReportClientError(string.Format("Unable to parse backup or schedule object: {0}", ex.Message), System.Net.HttpStatusCode.BadRequest); else - info.ReportClientError(string.Format("Unable to save schedule or backup object: {0}", ex.Message)); + info.ReportClientError(string.Format("Unable to save schedule or backup object: {0}", ex.Message), System.Net.HttpStatusCode.InternalServerError); } } diff --git a/Duplicati/Server/WebServer/RESTMethods/BugReport.cs b/Duplicati/Server/WebServer/RESTMethods/BugReport.cs index b3c1c9b8f..ac9b8cc95 100644 --- a/Duplicati/Server/WebServer/RESTMethods/BugReport.cs +++ b/Duplicati/Server/WebServer/RESTMethods/BugReport.cs @@ -29,13 +29,13 @@ namespace Duplicati.Server.WebServer.RESTMethods var tf = Program.DataConnection.GetTempFiles().Where(x => x.ID == id).FirstOrDefault(); if (tf == null) { - info.ReportClientError("Invalid or missing bugreport id"); + info.ReportClientError("Invalid or missing bugreport id", System.Net.HttpStatusCode.NotFound); return; } if (!System.IO.File.Exists(tf.Path)) { - info.ReportClientError("File is missing"); + info.ReportClientError("File is missing", System.Net.HttpStatusCode.NotFound); return; } diff --git a/Duplicati/Server/WebServer/RESTMethods/Captcha.cs b/Duplicati/Server/WebServer/RESTMethods/Captcha.cs index 4bf51fb2c..bd7ad5d5d 100644 --- a/Duplicati/Server/WebServer/RESTMethods/Captcha.cs +++ b/Duplicati/Server/WebServer/RESTMethods/Captcha.cs @@ -38,7 +38,7 @@ namespace Duplicati.Server.WebServer.RESTMethods } } - private static object m_lock = new object(); + private static readonly object m_lock = new object(); private static Dictionary m_captchas = new Dictionary(); public static bool SolvedCaptcha(string token, string target, string answer) @@ -61,7 +61,7 @@ namespace Duplicati.Server.WebServer.RESTMethods { if (string.IsNullOrWhiteSpace(key)) { - info.ReportClientError("Missing token value"); + info.ReportClientError("Missing token value", System.Net.HttpStatusCode.Unauthorized); return; } else @@ -105,7 +105,7 @@ namespace Duplicati.Server.WebServer.RESTMethods var target = info.Request.Param["target"].Value; if (string.IsNullOrWhiteSpace(target)) { - info.ReportClientError("Missing target parameter"); + info.ReportClientError("Missing target parameter", System.Net.HttpStatusCode.BadRequest); return; } @@ -147,19 +147,19 @@ namespace Duplicati.Server.WebServer.RESTMethods var target = info.Request.Param["target"].Value; if (string.IsNullOrWhiteSpace(answer)) { - info.ReportClientError("Missing answer parameter"); + info.ReportClientError("Missing answer parameter", System.Net.HttpStatusCode.BadRequest); return; } if (string.IsNullOrWhiteSpace(target)) { - info.ReportClientError("Missing target parameter"); + info.ReportClientError("Missing target parameter", System.Net.HttpStatusCode.BadRequest); return; } if (SolvedCaptcha(key, target, answer)) info.OutputOK(); else - info.ReportClientError("Incorrect"); + info.ReportClientError("Incorrect", System.Net.HttpStatusCode.Forbidden); } } } diff --git a/Duplicati/Server/WebServer/RESTMethods/Changelog.cs b/Duplicati/Server/WebServer/RESTMethods/Changelog.cs index 0fda33ebc..6adb73f0c 100644 --- a/Duplicati/Server/WebServer/RESTMethods/Changelog.cs +++ b/Duplicati/Server/WebServer/RESTMethods/Changelog.cs @@ -45,7 +45,7 @@ namespace Duplicati.Server.WebServer.RESTMethods var updateInfo = Program.DataConnection.ApplicationSettings.UpdatedVersion; if (updateInfo == null) { - info.ReportClientError("No update found"); + info.ReportClientError("No update found", System.Net.HttpStatusCode.NotFound); } else { diff --git a/Duplicati/Server/WebServer/RESTMethods/CommandLine.cs b/Duplicati/Server/WebServer/RESTMethods/CommandLine.cs index addeed592..fcc8c8499 100644 --- a/Duplicati/Server/WebServer/RESTMethods/CommandLine.cs +++ b/Duplicati/Server/WebServer/RESTMethods/CommandLine.cs @@ -148,14 +148,14 @@ namespace Duplicati.Server.WebServer.RESTMethods { if (!key.EndsWith("/abort", StringComparison.OrdinalIgnoreCase)) { - info.ReportClientError("Only abort commands are allowed"); + info.ReportClientError("Only abort commands are allowed", System.Net.HttpStatusCode.BadRequest); return; } key = key.Substring(0, key.Length - "/abort".Length); if (string.IsNullOrWhiteSpace(key)) { - info.ReportClientError("No task key found"); + info.ReportClientError("No task key found", System.Net.HttpStatusCode.BadRequest); return; } diff --git a/Duplicati/Server/WebServer/RESTMethods/Filesystem.cs b/Duplicati/Server/WebServer/RESTMethods/Filesystem.cs index a6553a527..a54e394e3 100644 --- a/Duplicati/Server/WebServer/RESTMethods/Filesystem.cs +++ b/Duplicati/Server/WebServer/RESTMethods/Filesystem.cs @@ -39,7 +39,7 @@ namespace Duplicati.Server.WebServer.RESTMethods { if (string.IsNullOrEmpty(path)) { - info.ReportClientError("No path parameter was found"); + info.ReportClientError("No path parameter was found", System.Net.HttpStatusCode.BadRequest); return; } @@ -68,7 +68,7 @@ namespace Duplicati.Server.WebServer.RESTMethods if (Duplicati.Library.Utility.Utility.IsClientLinux && !path.StartsWith("/", StringComparison.Ordinal)) { - info.ReportClientError("The path parameter must start with a forward-slash"); + info.ReportClientError("The path parameter must start with a forward-slash", System.Net.HttpStatusCode.BadRequest); return; } @@ -88,12 +88,12 @@ namespace Duplicati.Server.WebServer.RESTMethods { } - info.ReportServerError("File or folder not found"); + info.ReportServerError("File or folder not found", System.Net.HttpStatusCode.NotFound); return; } else { - info.ReportClientError(string.Format("No such operation found: {0}", command)); + info.ReportClientError(string.Format("No such operation found: {0}", command), System.Net.HttpStatusCode.NotFound); return; } } @@ -144,7 +144,7 @@ namespace Duplicati.Server.WebServer.RESTMethods } catch (Exception ex) { - info.ReportClientError("Failed to process the path: " + ex.Message); + info.ReportClientError("Failed to process the path: " + ex.Message, System.Net.HttpStatusCode.InternalServerError); } } @@ -159,7 +159,7 @@ namespace Duplicati.Server.WebServer.RESTMethods /// A new TreeNode instance on success; null if an exception occurred during creation. private static Serializable.TreeNode TryCreateTreeNodeForDrive(DriveInfo driveInfo) { - if (driveInfo == null) throw new ArgumentNullException("driveInfo"); + if (driveInfo == null) throw new ArgumentNullException(nameof(driveInfo)); try { diff --git a/Duplicati/Server/WebServer/RESTMethods/HyperV.cs b/Duplicati/Server/WebServer/RESTMethods/HyperV.cs index 497ee99fb..79640ff60 100644 --- a/Duplicati/Server/WebServer/RESTMethods/HyperV.cs +++ b/Duplicati/Server/WebServer/RESTMethods/HyperV.cs @@ -62,7 +62,7 @@ namespace Duplicati.Server.WebServer.RESTMethods if (foundVMs.Count == 1) info.OutputOK(foundVMs[0].DataPaths.Select(x => new { text = x, id = x, cls = "folder", iconCls = "x-tree-icon-leaf", check = "false", leaf = "true" }).ToList()); else - info.ReportClientError(string.Format("Cannot find VM with ID {0}.", key)); + info.ReportClientError(string.Format("Cannot find VM with ID {0}.", key), System.Net.HttpStatusCode.NotFound); } } catch (Exception ex) diff --git a/Duplicati/Server/WebServer/RESTMethods/MSSQL.cs b/Duplicati/Server/WebServer/RESTMethods/MSSQL.cs index 15ddf1923..910aa467e 100644 --- a/Duplicati/Server/WebServer/RESTMethods/MSSQL.cs +++ b/Duplicati/Server/WebServer/RESTMethods/MSSQL.cs @@ -60,7 +60,7 @@ namespace Duplicati.Server.WebServer.RESTMethods if (foundDBs.Count == 1) info.OutputOK(foundDBs[0].DataPaths.Select(x => new { text = x, id = x, cls = "folder", iconCls = "x-tree-icon-leaf", check = "false", leaf = "true" }).ToList()); else - info.ReportClientError(string.Format("Cannot find DB with ID {0}.", key)); + info.ReportClientError(string.Format("Cannot find DB with ID {0}.", key), System.Net.HttpStatusCode.NotFound); } } catch (Exception ex) diff --git a/Duplicati/Server/WebServer/RESTMethods/Notification.cs b/Duplicati/Server/WebServer/RESTMethods/Notification.cs index 24be2c1da..e5043aa8e 100644 --- a/Duplicati/Server/WebServer/RESTMethods/Notification.cs +++ b/Duplicati/Server/WebServer/RESTMethods/Notification.cs @@ -20,6 +20,6 @@ namespace Duplicati.Server.WebServer.RESTMethods { public class Notification : IRESTMethodGET, IRESTMethodDELETE { - public void GET(string key, RequestInfo info) { long id; if (!long.TryParse(key, out id)) { info.ReportClientError("Invalid ID"); return; } var el = Program.DataConnection.GetNotifications().Where(x => x.ID == id).FirstOrDefault(); if (el == null) info.ReportClientError("No such notification", System.Net.HttpStatusCode.NotFound); else info.OutputOK(el); } public void DELETE(string key, RequestInfo info) { long id; if (!long.TryParse(key, out id)) { info.ReportClientError("Invalid ID"); return; } var el = Program.DataConnection.GetNotifications().Where(x => x.ID == id).FirstOrDefault(); if (el == null) info.ReportClientError("No such notification", System.Net.HttpStatusCode.NotFound); else { Program.DataConnection.DismissNotification(id); info.OutputOK(); } } } + public void GET(string key, RequestInfo info) { long id; if (!long.TryParse(key, out id)) { info.ReportClientError("Invalid ID", System.Net.HttpStatusCode.BadRequest); return; } var el = Program.DataConnection.GetNotifications().Where(x => x.ID == id).FirstOrDefault(); if (el == null) info.ReportClientError("No such notification", System.Net.HttpStatusCode.NotFound); else info.OutputOK(el); } public void DELETE(string key, RequestInfo info) { long id; if (!long.TryParse(key, out id)) { info.ReportClientError("Invalid ID", System.Net.HttpStatusCode.BadRequest); return; } var el = Program.DataConnection.GetNotifications().Where(x => x.ID == id).FirstOrDefault(); if (el == null) info.ReportClientError("No such notification", System.Net.HttpStatusCode.NotFound); else { Program.DataConnection.DismissNotification(id); info.OutputOK(); } } } } diff --git a/Duplicati/Server/WebServer/RESTMethods/ProgressState.cs b/Duplicati/Server/WebServer/RESTMethods/ProgressState.cs index b21ead7c6..ebe06090b 100644 --- a/Duplicati/Server/WebServer/RESTMethods/ProgressState.cs +++ b/Duplicati/Server/WebServer/RESTMethods/ProgressState.cs @@ -20,6 +20,6 @@ namespace Duplicati.Server.WebServer.RESTMethods { public class ProgressState : IRESTMethodGET, IRESTMethodDocumented { - public void GET(string key, RequestInfo info) { if (Program.GenerateProgressState == null) info.ReportClientError("No active backup"); else info.OutputOK(Program.GenerateProgressState()); } public string Description { get { return "Return the progress of the currently running operation."; } } public IEnumerable> Types { get { return new KeyValuePair[] { new KeyValuePair(HttpServer.Method.Get, typeof(Serialization.Interface.IProgressEventData)) }; } } } + public void GET(string key, RequestInfo info) { if (Program.GenerateProgressState == null) info.ReportClientError("No active backup", System.Net.HttpStatusCode.NotFound); else info.OutputOK(Program.GenerateProgressState()); } public string Description { get { return "Return the progress of the currently running operation."; } } public IEnumerable> Types { get { return new KeyValuePair[] { new KeyValuePair(HttpServer.Method.Get, typeof(Serialization.Interface.IProgressEventData)) }; } } } } diff --git a/Duplicati/Server/WebServer/RESTMethods/RemoteOperation.cs b/Duplicati/Server/WebServer/RESTMethods/RemoteOperation.cs index bbaa6f6a5..f57dce0f2 100644 --- a/Duplicati/Server/WebServer/RESTMethods/RemoteOperation.cs +++ b/Duplicati/Server/WebServer/RESTMethods/RemoteOperation.cs @@ -125,7 +125,7 @@ namespace Duplicati.Server.WebServer.RESTMethods if (parts.Length <= 1) { - info.ReportClientError("No url or operation supplied"); + info.ReportClientError("No url or operation supplied", System.Net.HttpStatusCode.BadRequest); return; } @@ -147,7 +147,7 @@ namespace Duplicati.Server.WebServer.RESTMethods TestConnection(url, info); return; default: - info.ReportClientError("No such method"); + info.ReportClientError("No such method", System.Net.HttpStatusCode.BadRequest); return; } } @@ -177,7 +177,7 @@ namespace Duplicati.Server.WebServer.RESTMethods TestConnection(url, info); return; default: - info.ReportClientError("No such method"); + info.ReportClientError("No such method", System.Net.HttpStatusCode.BadRequest); return; } } diff --git a/Duplicati/Server/WebServer/RESTMethods/RequestInfo.cs b/Duplicati/Server/WebServer/RESTMethods/RequestInfo.cs index b4a532f60..50d10a24c 100644 --- a/Duplicati/Server/WebServer/RESTMethods/RequestInfo.cs +++ b/Duplicati/Server/WebServer/RESTMethods/RequestInfo.cs @@ -22,6 +22,6 @@ namespace Duplicati.Server.WebServer.RESTMethods { public HttpServer.IHttpRequest Request { get; private set; } public HttpServer.IHttpResponse Response { get; private set; } public HttpServer.Sessions.IHttpSession Session { get; private set; } public BodyWriter BodyWriter { get; private set; } public RequestInfo(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session) { Request = request; Response = response; Session = session; BodyWriter = new BodyWriter(response, request); - } public void ReportServerError(string message, System.Net.HttpStatusCode code = System.Net.HttpStatusCode.InternalServerError) { Response.Status = code; Response.Reason = message; BodyWriter.WriteJsonObject(new { Error = message }); } public void ReportClientError(string message, System.Net.HttpStatusCode code = System.Net.HttpStatusCode.BadRequest) { ReportServerError(message, code); } public bool LongPollCheck(EventPollNotify poller, ref long id, out bool isError) { HttpServer.HttpInput input = Request.Method.ToUpper() == "POST" ? Request.Form : Request.QueryString; if (Library.Utility.Utility.ParseBool(input["longpoll"].Value, false)) { long lastEventId; if (!long.TryParse(input["lasteventid"].Value, out lastEventId)) { ReportClientError("When activating long poll, the request must include the last event id"); isError = true; return false; } TimeSpan ts; try { ts = Library.Utility.Timeparser.ParseTimeSpan(input["duration"].Value); } catch (Exception ex) { ReportClientError("Invalid duration: " + ex.Message); isError = true; return false; } if (ts <= TimeSpan.FromSeconds(10) || ts.TotalMilliseconds > int.MaxValue) { ReportClientError("Invalid duration, must be at least 10 seconds, and less than " + int.MaxValue + " milliseconds"); isError = true; return false; } isError = false; id = poller.Wait(lastEventId, (int)ts.TotalMilliseconds); return true; } isError = false; return false; } public void OutputOK(object item = null) { BodyWriter.OutputOK(item); } public void OutputError(object item = null, System.Net.HttpStatusCode code = System.Net.HttpStatusCode.InternalServerError, string reason = null) { Response.Status = code; Response.Reason = reason ?? "Error"; BodyWriter.WriteJsonObject(item); } public void Dispose() { if (BodyWriter != null) { var bw = BodyWriter; BodyWriter = null; bw.Dispose(); } } } + } public void ReportServerError(string message, System.Net.HttpStatusCode code = System.Net.HttpStatusCode.InternalServerError) { Response.Status = code; Response.Reason = message; BodyWriter.WriteJsonObject(new { Error = message }); } public void ReportClientError(string message, System.Net.HttpStatusCode code = System.Net.HttpStatusCode.BadRequest) { ReportServerError(message, code); } public bool LongPollCheck(EventPollNotify poller, ref long id, out bool isError) { HttpServer.HttpInput input = Request.Method.ToUpper() == "POST" ? Request.Form : Request.QueryString; if (Library.Utility.Utility.ParseBool(input["longpoll"].Value, false)) { long lastEventId; if (!long.TryParse(input["lasteventid"].Value, out lastEventId)) { ReportClientError("When activating long poll, the request must include the last event id", System.Net.HttpStatusCode.BadRequest); isError = true; return false; } TimeSpan ts; try { ts = Library.Utility.Timeparser.ParseTimeSpan(input["duration"].Value); } catch (Exception ex) { ReportClientError("Invalid duration: " + ex.Message, System.Net.HttpStatusCode.BadRequest); isError = true; return false; } if (ts <= TimeSpan.FromSeconds(10) || ts.TotalMilliseconds > int.MaxValue) { ReportClientError("Invalid duration, must be at least 10 seconds, and less than " + int.MaxValue + " milliseconds", System.Net.HttpStatusCode.BadRequest); isError = true; return false; } isError = false; id = poller.Wait(lastEventId, (int)ts.TotalMilliseconds); return true; } isError = false; return false; } public void OutputOK(object item = null) { BodyWriter.OutputOK(item); } public void OutputError(object item = null, System.Net.HttpStatusCode code = System.Net.HttpStatusCode.InternalServerError, string reason = null) { Response.Status = code; Response.Reason = reason ?? "Error"; BodyWriter.WriteJsonObject(item); } public void Dispose() { if (BodyWriter != null) { var bw = BodyWriter; BodyWriter = null; bw.Dispose(); } } } } diff --git a/Duplicati/Server/WebServer/RESTMethods/ServerSettings.cs b/Duplicati/Server/WebServer/RESTMethods/ServerSettings.cs index 222f0e5e9..1df9d13cf 100644 --- a/Duplicati/Server/WebServer/RESTMethods/ServerSettings.cs +++ b/Duplicati/Server/WebServer/RESTMethods/ServerSettings.cs @@ -56,7 +56,7 @@ namespace Duplicati.Server.WebServer.RESTMethods if (string.IsNullOrWhiteSpace(str)) { - info.ReportClientError("Missing data object"); + info.ReportClientError("Missing data object", System.Net.HttpStatusCode.BadRequest); return; } @@ -66,7 +66,7 @@ namespace Duplicati.Server.WebServer.RESTMethods data = Serializer.Deserialize>(new StringReader(str)); if (data == null) { - info.ReportClientError("Data object had no entry"); + info.ReportClientError("Data object had no entry", System.Net.HttpStatusCode.BadRequest); return; } @@ -104,9 +104,9 @@ namespace Duplicati.Server.WebServer.RESTMethods catch (Exception ex) { if (data == null) - info.ReportClientError(string.Format("Unable to parse data object: {0}", ex.Message)); + info.ReportClientError(string.Format("Unable to parse data object: {0}", ex.Message), System.Net.HttpStatusCode.BadRequest); else - info.ReportClientError(string.Format("Unable to save settings: {0}", ex.Message)); + info.ReportClientError(string.Format("Unable to save settings: {0}", ex.Message), System.Net.HttpStatusCode.InternalServerError); } } diff --git a/Duplicati/Server/WebServer/RESTMethods/ServerState.cs b/Duplicati/Server/WebServer/RESTMethods/ServerState.cs index 586f23647..d1f7d02de 100644 --- a/Duplicati/Server/WebServer/RESTMethods/ServerState.cs +++ b/Duplicati/Server/WebServer/RESTMethods/ServerState.cs @@ -55,7 +55,7 @@ namespace Duplicati.Server.WebServer.RESTMethods } catch (Exception ex) { - info.ReportClientError(ex.Message); + info.ReportClientError(ex.Message, System.Net.HttpStatusCode.BadRequest); return; } if (ts.TotalMilliseconds > 0) diff --git a/Duplicati/Server/WebServer/RESTMethods/SystemInfo.cs b/Duplicati/Server/WebServer/RESTMethods/SystemInfo.cs index 07eb83339..22e7b942a 100644 --- a/Duplicati/Server/WebServer/RESTMethods/SystemInfo.cs +++ b/Duplicati/Server/WebServer/RESTMethods/SystemInfo.cs @@ -71,6 +71,7 @@ namespace Duplicati.Server.WebServer.RESTMethods ServerVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(), ServerVersionName = Duplicati.License.VersionNumbers.Version, ServerVersionType = Duplicati.Library.AutoUpdater.UpdaterManager.SelfVersion.ReleaseType, + StartedBy = Duplicati.Server.Program.Origin, BaseVersionName = Duplicati.Library.AutoUpdater.UpdaterManager.BaseVersion.Displayname, DefaultUpdateChannel = Duplicati.Library.AutoUpdater.AutoUpdateSettings.DefaultUpdateChannel, DefaultUsageReportLevel = Duplicati.Library.UsageReporter.Reporter.DefaultReportLevel, @@ -81,6 +82,7 @@ namespace Duplicati.Server.WebServer.RESTMethods CaseSensitiveFilesystem = Duplicati.Library.Utility.Utility.IsFSCaseSensitive, MonoVersion = Duplicati.Library.Utility.Utility.IsMono ? Duplicati.Library.Utility.Utility.MonoVersion.ToString() : null, MachineName = System.Environment.MachineName, + UserName = System.Environment.UserName, NewLine = System.Environment.NewLine, CLRVersion = System.Environment.Version.ToString(), CLROSInfo = new diff --git a/Duplicati/Server/WebServer/RESTMethods/Task.cs b/Duplicati/Server/WebServer/RESTMethods/Task.cs index d8f01c889..8a216b6c8 100644 --- a/Duplicati/Server/WebServer/RESTMethods/Task.cs +++ b/Duplicati/Server/WebServer/RESTMethods/Task.cs @@ -60,7 +60,7 @@ namespace Duplicati.Server.WebServer.RESTMethods } else { - info.ReportClientError("Invalid request"); + info.ReportClientError("Invalid request", System.Net.HttpStatusCode.BadRequest); } } @@ -97,7 +97,7 @@ namespace Duplicati.Server.WebServer.RESTMethods } } - info.ReportClientError("Invalid or missing task id"); + info.ReportClientError("Invalid or missing task id", System.Net.HttpStatusCode.NotFound); } } } diff --git a/Duplicati/Server/WebServer/RESTMethods/UISettings.cs b/Duplicati/Server/WebServer/RESTMethods/UISettings.cs index ff8e300f5..e760a8b17 100644 --- a/Duplicati/Server/WebServer/RESTMethods/UISettings.cs +++ b/Duplicati/Server/WebServer/RESTMethods/UISettings.cs @@ -30,7 +30,7 @@ namespace Duplicati.Server.WebServer.RESTMethods { if (string.IsNullOrWhiteSpace(key)) { - info.ReportClientError("Scheme is missing"); + info.ReportClientError("Scheme is missing", System.Net.HttpStatusCode.BadRequest); return; } @@ -41,13 +41,13 @@ namespace Duplicati.Server.WebServer.RESTMethods } catch (Exception ex) { - info.ReportClientError(string.Format("Unable to parse settings object: {0}", ex.Message)); + info.ReportClientError(string.Format("Unable to parse settings object: {0}", ex.Message), System.Net.HttpStatusCode.BadRequest); return; } if (data == null) { - info.ReportClientError(string.Format("Unable to parse settings object")); + info.ReportClientError(string.Format("Unable to parse settings object"), System.Net.HttpStatusCode.BadRequest); return; } diff --git a/Duplicati/Server/WebServer/Server.cs b/Duplicati/Server/WebServer/Server.cs index ead1e596a..5351482b9 100644 --- a/Duplicati/Server/WebServer/Server.cs +++ b/Duplicati/Server/WebServer/Server.cs @@ -11,6 +11,11 @@ namespace Duplicati.Server.WebServer { public class Server { + /// + /// The tag used for logging + /// + private static readonly string LOGTAG = Duplicati.Library.Logging.Log.LogTagFromType(); + /// /// Option for changing the webroot folder /// @@ -66,19 +71,6 @@ namespace Duplicati.Server.WebServer /// public const string PASSWORD_PLACEHOLDER = "**********"; - /// - /// Writes a log message to Console, Service-hook and normal log - /// - /// The message to write. - /// The message type. - /// The exception, if any. - public static void WriteLogMessage(string message, Library.Logging.LogMessageType type, Exception ex) - { - System.Console.WriteLine(message); - Library.Logging.Log.WriteMessage(message, type, ex); - Program.LogHandler.WriteMessage(message, type, ex); - } - /// /// Sets up the webserver and starts it /// @@ -134,7 +126,7 @@ namespace Duplicati.Server.WebServer } catch (Exception ex) { - WriteLogMessage(Strings.Server.DefectSSLCertInDatabase, Duplicati.Library.Logging.LogMessageType.Warning, ex); + Duplicati.Library.Logging.Log.WriteWarningMessage(LOGTAG, "DefectStoredSSLCert", ex, Strings.Server.DefectSSLCertInDatabase); } } else if (certificateFile.Length == 0) @@ -184,7 +176,7 @@ namespace Duplicati.Server.WebServer if (certValid && !cert.Equals(Program.DataConnection.ApplicationSettings.ServerSSLCertificate)) Program.DataConnection.ApplicationSettings.ServerSSLCertificate = cert; - WriteLogMessage(Strings.Server.StartedServer(listenInterface.ToString(), p), Library.Logging.LogMessageType.Information, null); + Duplicati.Library.Logging.Log.WriteInformationMessage(LOGTAG, "ServerListening", Strings.Server.StartedServer(listenInterface.ToString(), p)); return; } diff --git a/Duplicati/Server/webroot/ngax/scripts/angular-gettext-cli_compiled_js_output.js b/Duplicati/Server/webroot/ngax/scripts/angular-gettext-cli_compiled_js_output.js index b157a1d3d..7d653d41b 100644 --- a/Duplicati/Server/webroot/ngax/scripts/angular-gettext-cli_compiled_js_output.js +++ b/Duplicati/Server/webroot/ngax/scripts/angular-gettext-cli_compiled_js_output.js @@ -1,15 +1,15 @@ angular.module('backupApp').run(['gettextCatalog', function (gettextCatalog) { /* jshint -W100 */ - gettextCatalog.setStrings('cs', {"- pick an option -":"- vyberte jednu z možností -","...loading...":"…načítání…","API Key":"Klíč k aplikačnímu programovému rozhraní (API)","AWS Access ID":"Přístupový identifikátor ke službe AWS","AWS Access Key":"Přístupový klíč ke službě AWS","AWS IAM Policy":"Zásady IAM služby AWS","About":"O aplikaci","About {{appname}}":"O aplikaci {{appname}}","Access Key":"Přístupový klíč","Access denied":"Přístup odepřen","Access to user interface":"Přístup k uživatelskému rozhraní","Account name":"Název účtu","Activate":"Aktivovat","Activate failed:":"Aktivace se nezdařila:","Add a new backup":"Přidat novou zálohu","Add a path directly":"Přidat popis umístění přímo","Add advanced option":"Přidat pokročilou volbu","Add backup":"Přidat zálohu","Add filter":"Přidat filtr","Add path":"Přidat popis umístění","Adjust bucket name?":"Přizpůsobit název „nádoby“ (bucket)?","Adjust path name?":"Přizpůsobit popis umístění?","Advanced Options":"Pokročilé volby","Advanced options":"Pokročilé volby","Advanced:":"Pokročilé:","All":"Vše","All Hyper-V Machines":"Všechny Hyper-V stroje","All Microsoft SQL Databases":"Všechny Microsoft SQL databáze","All usage reports are sent anonymously and do not contain any personal information. They contain information about hardware and operating system, the type of backend, backup duration, overall size of source data and similar data. They do not contain paths, filenames, usernames, passwords or similar sensitive information.":"Veškerá hlášení o využívání jsou posílána anonymně a neobsahují žádné osobní údaje. Obsahují informace o hardware a operačním systému, typu podpůrné vrstvy (backend), trvání zálohy, celkové velikosti zdrojových dat a podobně.\nNeobsahují popisy umístění, názvy souborů, uživatelská jména, hesla nebo podobné citlivé údaje.","Allow remote access (requires restart)":"Umožnit přístup na dálku (vyžaduje restart)","Allowed days":"Dny, ve které je přístup umožněn","An existing file was found at the new location":"V novém umístění byl nalezen už existující soubor","An existing file was found at the new location\nAre you sure you want the database to point to an existing file?":"V novém umístění byl nalezen už existující soubor\nOpravdu chcete nasměrovat databázi do existujícího souboru?","An existing local database for the storage has been found.\nRe-using the database will allow the command-line and server instances to work on the same remote storage.\n\n Do you wish to use the existing database?":"Byla nalezena existující místní databáze pro ukládání.\nOpětovné využití databáze umožní, aby instance pro příkazový řádek a server fungovaly na stejném vzdáleném úložišti.\n\nChcete použít existující databázi?","Anonymous usage reports":"Anonymní hlášení o použití","As Command-line":"Jako příkazový řádek","AuthID":"AuthID","Authentication password":"Ověřovací heslo","Authentication username":"Ověřovací uživatelské jméno","Autogenerated passphrase":"Automaticky vytvořená heslová fráze","Automatically run backups.":"Spouštět zálohy automaticky.","B2 Account ID":"Identifikátor účtu u služby B2","B2 Application Key":"Aplikační klíč ke službě B2","B2 Cloud Storage Account ID":"Identifikátor účtu u cloudového úložiště B2","B2 Cloud Storage Application Key":"Aplikační klíč ke cloudovému úložišti B2","Back":"Zpět","Backend modules:":"Moduly podpůrných vrstev (backend):","Backup destination":"Cíl zálohy","Backup location":"Umístění zálohy","Backup:":"Záloha:","Beta":"Vývojová testovací (beta)","Broken access":"Nefunkční přístup","Browse":"Procházet","Browser default":"Výchozí nastavení webového prohlížeče","Bucket Name":"Název „nádoby“ (bucket)","Bucket create location":"Umístění ve kterém „nádobu“ (bucket) vytvořit","Bucket create region":"Oblast světa ve které „nádobu“ (bucket) vytvořit","Bucket name":"Název „nádoby“ (bucket)","Bucket storage class":"Třída úložiště nesoucí „nádobu“ (bucket)","Building list of files to restore ...":"Vytváření seznamu souborů k obnovení…","Building partial temporary database ...":"Vytváření částečné dočasné databáze…","Busy ...":"Zaneprázdněno…","Canary":"Kanárek","Cancel":"Storno","Cannot move to existing file":"Nelze přesunout do existujícího souboru","Changelog":"Seznam změn","Changelog for {{appname}} {{version}}":"Seznam změn v {{appname}} {{version}}","Check failed:":"Zjištění se nezdařilo:","Check for updates now":"Zjistit dostupnost případných aktualizací nyní","Checking ...":"Zjišťování…","Checking for updates ...":"Zjišťování dostupnosti případných aktualizací…","Chose a storage type to get started":"Pro začátek vyberte typ úložiště","Click the AuthID link to create an AuthID":"AuthID vytvoříte kliknutím na odkaz AuthID","Click to set throttle options":"Kliknutím nastavte předvolby přiškrcování","Commandline ...":"Příkazový řádek…","Compact now":"Zkompaktnit nyní","Compacting remote data ...":"Zkompaktňování dat na protějšku…","Completing backup ...":"Dokončování zálohy…","Completing previous backup ...":"Dokončování předchozí zálohy…","Compression modules:":"Komprimační moduly:","Computer":"Počítač","Configuration file:":"Soubor s nastaveními:","Configuration:":"Nastavení:","Configure a new backup":"Nastavit novou zálohu","Confirm delete":"Potvrzení smazání","Confirmation required":"Vyžadováno potvrzení","Connect":"Připojit","Connect now":"Připojit nyní","Connecting to server ...":"Připojování k serveru…","Connecting to task ....":"Připojování k úloze…","Connecting...":"Připojování…","Connection lost":"Spojení ztraceno","Connection worked!":"Spojení funguje!","Container name":"Název kontejneru","Container region":"Region umístění kontejneru","Continue":"Pokračovat","Continue without encryption":"Pokračovat bez šifrování","Copied!":"Zkopírováno!","Copy Destination URL to Clipboard":"Zkopírovat URL adresu cíle do schránky","Copy failed. Please manually copy the URL":"Kopie se nezdařila. Zkopírujte URL adresu ručně","Core options":"Core volby","Counting ({{files}} files found, {{size}})":"Počítání ({{files}} souborů nalezeno, {{size}})","Crashes only":"Pouze pády","Create bug report ...":"Vyplnit hlášení chyby…","Create folder?":"Vytvořit složku?","Created new limited user":"Vytvořit nový uživatelský účet s omezenými oprávněními","Creating bug report ...":"Vytváření hlášení chyby…","Creating new user with limited access ...":"Vytváření nového uživatele s omezeným přístupem…","Creating target folders ...":"Vytváření cílových složek…","Creating temporary backup ...":"Vytváření dočasné zálohy…","Creating user...":"Vytváření uživatelského účtu…","Current version is {{versionname}} ({{versionnumber}})":"Stávající verze je {{versionname}} ({{versionnumber}})","Custom S3 endpoint":"Vlastní S3 koncový bod","Custom authentication url":"Vlastní ověřovací URL adresa","Custom location ({{server}})":"Vlastní umístění ({{server}})","Custom region for creating buckets":"Vlastní region pro vytváření „nádob“ (bucket)","Custom region value ({{region}})":"Hodnota pro vlastní region ({{region}})","Custom server url ({{server}})":"Vlastní URL adresa serveru ({{server}})","Custom storage class ({{class}})":"Vlastní třída úložiště ({{class}})","Database ...":"Databáze…","Days":"Dnů","Default":"Výchozí","Default ({{channelname}})":"Výchozí ({{channelname}})","Default Filters":"Výchozí filtry","Default options":"Výchozí volby","Delete":"Smazat","Delete ...":"Smazat…","Delete backup":"Smazat zálohu","Delete local database":"Smazat místní databázi","Delete remote files":"Smazat soubory na protějšku","Delete the local database":"Smazat místní databázi","Delete {{filecount}} files ({{filesize}}) from the remote storage?":"Smazat {{filecount}} souborů ({{filesize}}) ze vzdáleného úložiště?","Deleting remote files ...":"Mazání souborů na protějšku…","Deleting unwanted files ...":"Mazání nepotřebných souborů…","Desktop":"Osobní počítač","Destination":"Cíl","Did we help save your files? If so, please consider supporting Duplicati with a donation. We suggest {{smallamount}} for private use and {{largeamount}} for commercial use.":"Pomohli jsme vám zachránit vaše soubory? Pokud ano, zvažte prosím podpoření Duplicati darem. Doporučujeme {{smallamount}} pro soukromé a {{largeamount}} pro komerční použití.","Direct restore from backup files ...":"Přímé obnovování ze záložních souborů…","Disabled":"Vypnuto","Dismiss":"Odmítnout","Display and color theme":"Motiv vzhledu zobrazení a barev","Do you really want to delete the backup: \"{{name}}\" ?":"Opravdu chcete smazat zálohu: „{{name}}“?","Do you really want to delete the local database for: {{name}}":"Opravdu chcete smazat místní databázi pro: {{name}}","Donate":"Darovat","Donate with PayPal":"Darovat prostřednictvím PayPal","Donate with crypto currency":"Darovat v kryptoměně","Donation messages":"Darovací zprávy","Donation messages are hidden, click to show":"Darovací zprávy jsou skryté, kliknutím je zobrazíte","Donation messages are visible, click to hide":"Darovací zprávy jsou zobrazené, kliknutím je skryjete","Done":"Hotovo","Download":"Stáhnout","Downloading ...":"Stahování…","Downloading files ...":"Stahování souborů…","Downloading update...":"Stahování aktualizace…","Duplicate option {{opt}}":"Volba duplikace {{opt}}","Duplicati Website":"Webové stránky projektu Duplicati","Duplicati forum":"Diskuzní fórum o Duplicati","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\n When deleting a backup, you can also delete the local database without affecting the ability to restore the remote files.\n If you are using the local database for backups from the commandline, you should keep the database.":"Ke každé záloze je přiřazena místní databáze, která uchovává informace o vzdálené záloze na místním stroji.\n Při mazání zálohy je také možné smazat lokální databázi aniž by tím byla postižena schopnost obnovovat vzdálené soubory.\n Pokud používáte místní databáze pro zálohy z příkazového řádku, měli byste databázi ponechat.","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\\nThis makes it faster to perform many operations, and reduces the amount of data that needs to be downloaded for each operation.":"Ke každé záloze je přiřazena místní databáze, která uchovává informace o vzdálené záloze na místním stroji.\\nTo zrychluje provádění mnoha operací a snižuje množství dat které je při každé operaci třeba stahovat.","Edit ...":"Upravit…","Edit as list":"Upravit jako seznam","Edit as text":"Upravit jako text","Encrypt file":"Zašifrovat soubor","Encryption":"Šifrování","Encryption changed":"Šifrování změněno","Encryption modules:":"Šifrovací moduly:","Enter URL":"Zadejte URL adresu","Enter access key":"Zadejte přístupový klíč","Enter account name":"Zadejte název účtu","Enter backup passphrase, if any":"Zadejte záložní heslovou frázi, pokud existuje","Enter configuration details":"Zadejte podrobnosti nastavení","Enter container name":"Zadejte název kontejneru","Enter encryption passphrase":"Zadejte šifrovací heslovou frázi","Enter expression here":"Sem zadejte výraz","Enter folder path name":"Zadejte popis umístění složky","Enter one option per line in command-line format, eg. {0}":"Každou z voleb zadejte zvlášť na samostatný řádek, např. {0}","Enter the destination path":"Zadejte popis cílového umístění ","Error":"Chyba","Error!":"Chyba!","Errors and crashes":"Chyby a pády","Exclude":"Vynechat","Exclude directories whose names contain":"Vynechat složky jejichž názvy obsahují","Exclude expression":"Výraz pro vynechané","Exclude file":"Vynechat soubor","Exclude file extension":"Vynechat soubory s příponami","Exclude files whose names contain":"Vynechat soubory jejichž názvy obsahují","Exclude folder":"Vynechat složku","Exclude regular expression":"Regulární výraz pro vynechávané","Existing file found":"Nalezen existující soubor","Experimental":"Experimentální","Export":"Exportovat","Export ...":"Exportovat…","Export backup configuration":"Exportovat zálohu nastavení","Export configuration":"Exportovat nastavení","Exporting ...":"Exportování…","FTP (Alternative)":"FTP (alternativní)","Failed to build temporary database: {{message}}":"Nepodařilo se vytvořit dočasnou databázi: {{message}}","Failed to connect:":"Nepodařilo se připojit:","Failed to connect: {{message}}":"Nepodařilo se připojit: {{message}}","Failed to delete:":"Nepodařilo se smazat:","Failed to fetch path information: {{message}}":"Nepodařilo se stáhnout informaci o popisu umístění: {{message}}","Failed to import:":"Nepodařilo se importovat:","Failed to read backup defaults:":"Nepodařilo se načíst výchozí parametry zálohy:","Failed to restore files: {{message}}":"Nepodařilo se obnovit soubory: {{message}}","Failed to save:":"Nepodařilo se uložit:","Fetching path information ...":"Získávání informací o popisu umístění…","File":"Soubor","Files larger than:":"Soubory větší než:","Filters":"Filtry","Finished!":"Dokončeno!","First run setup":"Úvodní nastavení při prvním spuštění","Folder":"Složka","Folder path":"Popis umístění složky","Fri":"Pá","GByte":"GB","GByte/s":"GB/s","GCS Project ID":"GCS identifikátor projektu","General":"Obecné","General backup settings":"Obecná nastavení zálohy","General options":"Obecné volby","Generate":"Vytvořit","Generate IAM access policy":"Vytvořit IAM zásady přístupu","Getting file versions ...":"Získávání verzí souboru…","Hidden files":"Skryté soubory","Hide":"Skrýt","Hide hidden folders":"Skrýt skryté složky","Home":"Domovská složka","Hours":"Hodin","How do you want to handle existing files?":"Jak chcete zacházet s existujícími soubory?","Hyper-V Machine":"Hyper-V stroj","Hyper-V Machine:":"Hyper-V stroj:","Hyper-V Machines":"Hyper-V stroje","ID:":"Identifikátor:","If a date was missed, the job will run as soon as possible.":"Pokud chybělo datum, úloha bude spuštěna co možná nejdříve.","If the backup and the remote storage is out of sync, Duplicati will require that you perform a repair operation to synchronize the database.\\nIf the repair is unsuccesful, you can delete the local database and re-generate.":"Pokud záloha a vzdálené úložiště ztratí synchronizaci, Duplicati bude potřebovat abyste provedli operaci opravy a databáze se synchronizovala.\\nPokud oprava nebude úspěšná, je možné smazat místní databázi a nechat ji znovu vytvořit.","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"Pokud soubor se zálohou nebyl stažen automaticky, klikněte pravým tlačítkem a zvolte „Uložit jako…“;","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"Pokud soubor se zálohou nebyl stažen automaticky, klikněte pravým tlačítkem a zvolte „Uložit jako…“;","If you do not enter a path, all files will be stored in the login folder.\nAre you sure this is what you want?":"Pokud nezadáte popis umístění, všechny soubory budou uloženy v přihlašovací složce.\nJe to to, co chcete?","If you do not enter an API Key, the tenant name is required":"Pokud nezadáte klíč k API, je vyžadováno jméno nájemníka (tenant)","If you want to use the backup later, you can export the configuration before deleting it":"Pokud zálohu chcete použít později, můžete exportovat nastavení než jí smažete","If your machine is in a multi-user environment (i.e. the machine has more than one account), you need to set a password to prevent other users from accessing data on your account.\nDo you want to set a password now?":"Pokud je stroj používán vícero uživateli (tj. je na něm více než jeden uživatelský účet), je třeba nastavit heslo, které ostatním uživatelům brání v přístupu k datům ve vašem účtu.\nNastavit heslo nyní?","Import":"Import","Import Destination URL":"Importovat URL adresu cíle","Import backup configuration":"Importovat nastavení zálohy","Import completed, but no certificates were found after the import":"Import dokončen, ale nebyly po něm nalezeny žádné certifikáty","Import failed":"Import se nezdařil","Import from a file":"Importovat ze souboru","Importing ...":"Importování…","Include a file?":"Zahrnout soubor?","Include expression":"Výraz pro zahrnutí","Include regular expression":"Regulární výraz pro zahrnutí","Incorrect answer, try again":"Nesprávná odpověď, zkuste to znovu","Individual builds for developers only.":"Jednotlivá sestavení pouze pro vývojáře.","Information":"Informace","Install":"Nainstalovat","Install failed:":"Instalace se nezdařila:","Invalid characters in path":"Neplatné znaky v popisu umístění","Invalid retention time":"Neplatná doba ponechání","It is possible to connect to some FTP without a password.\nAre you sure your FTP server supports password-less logins?":"K některým FTP serverům je možné se připojit i bez hesla.\nOpravdu to tento FTP server umožňuje?","KByte":"KB","KByte/s":"KB/s","Keep this number of backups":"Ponechat tento počet záloh","Language in user interface":"Jazyk textů v uživatelském rozhraní","Last month":"Minulý měsíc","Last successful run:":"Poslední úspěšný běh:","Latest":"Poslední","Libraries":"Knihovny","Linux":"GNU/Linux","Listing backup dates ...":"Vypisování datumů záloh…","Listing remote files ...":"Vypisování vzdálených souborů…","Live":"Aktuální","Load a configuration from an exported job or a storage provider":"Načíst nastavení z exportované úlohy nebo z poskytovatele úložiště","Load destination from an exported job or a storage provider":"Načíst cíl z exportované úlohy nebo poskytovatele úložiště","Load older data":"Načíst starší data","Loading ...":"Načítání…","Loading remote storage usage ...":"Načítání údajů o využití vzdáleného úložiště…","Local database for":"Místní databáze pro","Local database path:":"Popis umístění místní databáze:","Local storage":"Místní úložiště","Location":"Umístění","Location where buckets are created":"Umístění ve kterém jsou „nádoby“ (bucket) vytvářeny","Log data for {{Backup.Backup.Name}}":"Zaznamenávat (log) údaje pro {{Backup.Backup.Name}}","Log data from the server":"Zaznamenávat data ze serveru","Log out":"Odhlásit se","MByte":"MB","MByte/s":"MB/s","Maintenance":"Údržba","Manually type path":"Zadejte popis umístění ručně","Max download speed":"Nejvyšší rychlost stahování","Max upload speed":"Nejvyšší rychlost odesílání","Menu":"Nabídka","Microsoft SQL Database:":"Databáze Microsoft SQL:","Microsoft SQL Databases":"Databáze Microsoft SQL","Minimum redundancy":"Minimální redundance","Minimum redundancy is 1.0":"Minimální redundance je 1.0","Minutes":"Minut","Missing name":"Chybějící název","Missing passphrase":"Chybějící heslová fráze","Missing sources":"Chybějící zdroje","Mon":"Po","Months":"Měsíců","Move existing database":"Přesunout existující databázi","Move failed:":"Přesun se nezdařil:","My Documents":"Moje dokumenty","My Music":"Hudba","My Photos":"Fotografie","My Pictures":"Obrázky","Name":"Název","Never":"Nikdy","New update found: {{message}}":"Nalezena nová aktualizace: {{message}}","New user name is {{user}}.\nUpdated credentials to use the new limited user":"Nové uživatelské jméno je {{user}}.\nAktualizované přihlašovací údaje které použít pro uživatele s omezenými přístupovými právy","Next":"Další","Next scheduled run:":"Příští naplánované spuštění:","Next scheduled task:":"Příští naplánovaná úloha:","Next task:":"Příští úloha:","Next time":"Příště","No":"Ne","No certificate was specified previously, please verify with the server administrator that the key is correct: {{key}} \n\nDo you want to approve the reported host key?":"Předtím nebyl určen žádný certifikát, ověřte se správcem serveru že klíč je správný: {{key}}\n\nSchvalujete tento klíč stroje?","No editor found for the "{{backend}}" storage type":"Nebyl nalezen žádný editor pro typ úložiště „{{backend}}“","No encryption":"Nešifrovat","No items selected":"Nejsou vybrané žádné položky","No items to restore, please select one or more items":"Žádné položky pro obnovení – vyberte alespoň jednu","No passphrase entered":"Není zadaná žádná heslová fráze","No scheduled tasks":"Žádné naplánované úlohy","No, my machine has only a single account":"Ne, na mém stroji je pouze jediný uživatelský účet","Non-matching passphrase":"Zadání heslové fráze se neshodují","None / disabled":"Žádné / vypnuté","OK":"OK","OSX":"Apple macOS","OpenStack AuthURI":"AuthURI pro OpenStack","OpenStack Object Storage / Swift":"Objektové úložiště OpenStack (Swift)","Operation failed:":"Operace se nezdařila:","Operations:":"Operace:","Optional authentication password":"Volitelné ověřovací heslo","Optional authentication username":"Volitelné uživatelské jméno pro ověření","Options":"Předvolby","Options added here are applied to all backups, but can be overridden in each individual backup":"Zde přidané volby jsou použity na všechny zálohy, ale je možné je přepsat v nastavení jednotlivých záloh","Original location":"Původní umístění","Others":"Ostatní","Overwrite":"Přepsat","Passphrase":"Heslová fráze","Passphrase (if encrypted)":"Heslová fráze (v případě, že je použito šifrování)","Passphrase changed":"Heslová fráze změněna","Passphrases are not matching":"Zadání heslové fráze se neshodují","Password":"Heslo","Passwords do not match":"Zadání hesla se neshodují","Patching files with local blocks ...":"Opravování souborů pomocí místních bloků…","Path not found":"Umístění nenalezeno","Path on server":"Popis umístění na serveru","Path or subfolder in the bucket":"Umístění nebo podsložka v „nádobě“ (bucket)","Pause":"Pozastavit","Pause after startup or hibernation":"Pozastavit po spuštění nebo hibernaci","Pause options":"Předvolby pozastavení","Permissions":"Přístupová práva","Pick location":"Vyberte umístění","Point to your backup files and restore from there":"Nasměrujte na soubory se zálohou a obnovte odsud","Port":"Port","Previous":"Předchozí","ProjectID is optional if the bucket exist":"Pokud „nádoba“ (bucket) existuje, je identifikátor projektu (ProjectID) nepovinný","Proprietary":"Proprietární","Purging files ...":"Trvalé vymazávání souborů…","Rebuilding local database ...":"Znovuvytváření místní databáze…","Recreate (delete and repair)":"Vytvořit znovu (smazat a opravit)","Recreating database ...":"Znovuvytváření databáze…","Registering temporary backup ...":"Registrace dočasné zálohy…","Relative paths not allowed":"Vztažené (relativní) popisy umístění není možné použít","Reload":"Načíst znovu","Remote":"Vzdálené","Remove":"Odebrat","Remove option":"Odebrat volbu","Repair":"Opravit","Reparing ...":"Opravování…","Repeat Passphrase":"Zopakování heslové fráze","Reporting:":"Hlášení:","Reset":"Resetovat","Restore":"Obnovit","Restore files":"Obnovit soubory","Restore files ...":"Obnovit soubory…","Restore files from {{backupname}}":"Obnovit soubory z {{backupname}}","Restore from":"Obnovit z","Restore from backup configuration":"Obnovit nastavení ze zálohy","Restore from configuration ...":"Obnovit z nastavení…","Restore options":"Volby obnovení","Restore read/write permissions":"Obnovit práva pro čtení/zápis","Restoring files ...":"Obnovování souborů…","Resume":"Pokračovat","Run again every":"Spustit znovu každou","Run now":"Spustit nyní","Running ...":"Spuštěné…","Running ....":"Spuštěné…","Running commandline entry":"Spuštěná položka příkazového řádku","Running task:":"Spuštěná úloha:","S3 Compatible":"Kompatibilní s S3","Same as the base install version: {{channelname}}":"Stejné jako základní nainstalovaná verze: {{channelname}}","Sat":"So","Save":"Uložit","Save and repair":"Uložit a opravit","Save different versions with timestamp in file name":"Uložit různé verze odlišené časovou značkou v názvu souboru","Save immediately":"Okamžitě uložit","Scanning existing files ...":"Skenování existujících souborů…","Scanning for local blocks ...":"Skenování místních bloků…","Schedule":"Plán","Search":"Hledat","Search for files":"Hledat soubory","Seconds":"Sekund","Select a log level and see messages as they happen:":"Vyberte úroveň podrobnosti zaznamenávaných událostí a sledujte zprávy:","Select files":"Vybrat soubory","Server":"Server","Server and port":"Server a port","Server hostname or IP":"Název nebo IP adresa serveru","Server is currently paused,":"Server je nyní pozastavený,","Server is currently paused, do you want to resume now?":"Server je nyní pozastavený, chcete ho nyní znovu spustit?","Server password":"Heslo serveru","Server paused":"Server pozastaven","Server state properties":"Vlastnosti stavu serveru","Settings":"Nastavení","Show":"Zobrazit","Show advanced editor":"Zobrazit pokročilý editor","Show hidden folders":"Zobrazit skryté složky","Show log":"Zobrazit záznam událostí (log)","Show log ...":"Zobrazit záznam událostí (log)…","Show treeview":"Zobrazit stromový pohled","Sia server password":"Heslo Sia serveru","Some OpenStack providers allow an API key instead of a password and tenant name":"Někteří poskytovatelé OpenStack umožňují použití klíče k API namísto hesla a jména nájemníka (tenant)","Source Data":"Zdrojová data","Source data":"Zdrojová data","Source folders":"Zdrojové složky","Source:":"Zdroj:","Specific builds for developers only.":"Konkrétní sestavení pouze pro vývojáře.","Standard protocols":"Standardní protokoly","Starting ...":"Spouštění…","Starting the restore process ...":"Spouštění procesu obnovení…","Stop after the current file":"Zastavit po stávajícím souboru","Stop after upload":"Zastavit po nahrání","Stop now":"Zastavit nyní","Stop running backup":"Zastavit probíhající zálohu","Stop running task":"Zastavit probíhající úlohu","Stopping after upload:":"Zastavování po nahrávání:","Stopping task:":"Zastavování úlohy:","Storage Type":"Typ úložiště","Storage class":"Třída úložiště","Storage class for creating a bucket":"Třída úložiště pro vytváření „nádoby“ (bucket)","Stored":"Uloženo","Strong":"Silné","Success":"Úspěch","Sun":"Ne","Symbolic link":"Symbolický odkaz","System default ({{levelname}})":"Systémové výchozí ({{levelname}})","System files":"Systémové soubory","System info":"Informace o systému","System properties":"Vlastnosti systému","TByte":"TB","TByte/s":"TB/s","Target path, ie /backup":"Popis umístění cíle, tj. /zaloha","Task is running":"Úloha je spuštěná","Temporary files":"Dočasné soubory","Tenant Name":"Jméno nájemníka (tenant)","Test connection":"Vyzkoušet spojení","Testing ...":"Testování…","Testing connection ...":"Zkouška spojení…","Testing permissions ...":"Zkouška přístupových práv…","Testing permissions...":"Zkouška přístupových práv…","The bucket name should be all lower-case, convert automatically?":"Název nádoby by měl být malými písmeny, převést automaticky?","The bucket name should start with your username, prepend automatically?":"Název „nádoby“ (bucket) by měl začínat vaším uživatelským jménem – předřadit automaticky?","The connection to the server is lost, attempting again in {{time}} ...":"Spojení se serverem ztraceno, opětovný pokus za {{time}}…","The dark theme (by Michal)":"Tmavé téma vzhledu (od Michala)","The default blue on white theme (by Alex)":"Výchozí téma vzhledu modrá na bílé (od Alexe)","The folder {{folder}} does not exist.\nCreate it now?":"Složka {{folder}} neesxistuje.\nVytvořit nyní?","The host key has changed, please check with the server administrator if this is correct, otherwise you could be the victim of a MAN-IN-THE-MIDDLE attack.\n\nDo you want to REPLACE your CURRENT host key \"{{prev}}\" with the REPORTED host key: {{key}}?":"Klíč stroje se změnil, zkontrolujte se správcem serveru zda je správný, protože byste mohli být obětí útoku typu člověk uprostřed (man-in-the-midle).\n\nChcete NAHRADIT STÁVAJÍCÍ klíč stroje \"{{prev}}\" NAHLÁŠENÝM klíčem stroje: {{key}}?","The path does not appear to exist, do you want to add it anyway?":"Popisované umístění zdá se neexistuje, přejete si ho přidat i tak?","The path does not end with a '{{dirsep}}' character, which means that you include a file, not a folder.\n\nDo you want to include the specified file?":"Dané umístění nekončí na znak „{{dirsep}}“, což znamená, že jste zahrnuli soubor, ne složku.\n\nChcete zahrnout daný soubor?","The path must be an absolute path, i.e. it must start with a forward slash '/'":"Je třeba, aby se jednalo o úplný popis umístění, tj. aby začínal dopředným lomítkem „/“","The path should start with \"{{prefix1}}\" or \"{{prefix2}}\", otherwise you will not be able to see the files in the HubiC web interface.\n\nDo you want to add the prefix to the path automatically?":"Popis umístění by měl začínat na „{{prefix1}}“ nebo „{{prefix2}}“, jinak soubory neuvidíte ve webovém rozhraní HubiC.\n\nChcete přidat předponu k popisu umístění automaticky?","The region parameter is only applied when creating a new bucket":"Parametr region je použit pouze při vytváření nové „nádoby“ (bucket)","The region parameter is only used when creating a bucket":"Parametr region je použit pouze při vytváření „nádoby“ (bucket)","The server certificate could not be validated.\nDo you want to approve the SSL certificate with the hash: {{hash}}?":"Certifikát serveru se nepodařilo ověřit.\nChcete schválit SSL certifikát s otiskem: {{hash}}?","The storage class affects the availability and price for a stored file":"Třída úložiště ovlivňuje dostupnost a cenu za uložení souboru","The target folder contains encrypted files, please supply the passphrase":"Cílová složka obsahuje zašifrované soubory, zadejte heslovou frázi","The user has too many permissions. Do you want to create a new limited user, with only permissions to the selected path?":"Uživatel má příliš vysoká přístupová práva. Chcete vytvořit nového uživatele s právy omezenými pouze na vybraný popis umístění?","This backup was created on another operating system. Restoring files without specifying a destination folder can cause files to be restored in unexpected places. Are you sure you want to continue without choosing a destination folder?":"Tato záloha byla vytvořena na jiném operačním systému. Obnovení souborů bez zadání cílové složky může způsobit, že soubory budou obnoveny do neočekávaných míst. Opravdu chcete pokračovat bez zvolení cílové složky?","This month":"Tento měsíc","This week":"Tento týden","Throttle settings":"Nastavení přiškrcování","Thu":"Čt","To File":"Do soubour","To confirm you want to delete all remote files for \"{{name}}\", please enter the word you see below":"Svůj úmysl smazat všechny vzdálené soubory pro „{{name}}“ potvrďte opsáním níže uvedeného slova ","To export without a passphrase, uncheck the \"Encrypt file\" box":"Pro exportování bez heslové fráze odškrtněte „Šifrovat soubor“","Today":"Út","Trust host certificate?":"Důvěřovat certifikátu stroje?","Trust server certificate?":"Důvěřovat certifikátu serveru?","Try out the new features we are working on. Don't use with important data.":"Vyzkoušejte nové funkce na kterých pracujeme. Nepoužívejte pro důležitá data.","Tue":"Út","Type to highlight files":"Soubory zvýrazňujte psaním","Unknown backup size and versions":"Neznámá velikost a verze databáze","Until resumed":"Dokud není pokračováno","Update channel":"Aktualizační kanál","Update failed:":"Aktualizace se nezdařila:","Updating with existing database":"Aktualizace se stávající databází","Upload volume size":"Velikost nahrávaného svazku","Uploading verification file ...":"Nahrávání ověřovacího souboru…","Usage reports help us improve the user experience and evaluate impact of new features. We use them to generate public usage statistics":"Hlášení využití nám pomáhají zlepšovat pro uživatele dojem z používání aplikace a vyhodnocovat úspěšnost nových funkcí. Používáme je pro vytváření veřejných statistik o používání","Usage statistics":"Statistiky využití","Usage statistics, warnings, errors, and crashes":"Statistiky využití, varování, chyby a pády","Use SSL":"Použít SSL","Use existing database?":"Použít existující databázi?","Use weak passphrase":"Použít slabou heslovou frázi","Useless":"Nepoužitelné","User data":"Uživatelská data","User has too many permissions":"Uživatel má příliš mnoho oprávnění","User interface settings":"Nastavení uživatelského rozhraní","Username":"Uživatelské jméno","Validating ...":"Ověřování…","Verify files":"Ověřit soubory","Verifying ...":"Ověřování…","Verifying answer":"Ověřování odpovědi","Verifying backend data ...":"Ověřování dat podpůrné vrstvy (backend)…","Verifying remote data ...":"Ověřování vzdálených dat…","Verifying restored files ...":"Ověřování obnovených souborů…","Very strong":"Velmi silné","Very weak":"Velmi slabé","Visit us on":"Navštivte nás na","WARNING: The remote database is found to be in use by the commandline library":"VAROVÁNÍ: bylo zjištěno, že vzdálená databáze je používána knihovnou pro příkazový řádek","WARNING: This will prevent you from restoring the data in the future.":"VAROVÁNÍ: toto zabrání v budoucnu obnovovat data!","Waiting for task to begin":"Čekání na zahájení úlohy","Waiting for task to start ....":"Čekání na zahájení úlohy…","Waiting for upload ...":"Čekání na nahrání…","Warnings, errors and crashes":"Varování, chyby a pády","We accept donations via different services, such as OpenCollective, PayPal, BountySource and various crypto currencies.":"Přijímáme dary prostřednictvím různých služeb, jako například OpenCollective, PayPal, BountySource a různé kryptoměny.","We recommend that you encrypt all backups stored outside your system":"Doporučujeme šifrovat všechny zálohy, které jsou ukládány mimo váš stroj","Weak":"Slabé","Weak passphrase":"Slabá heslová fráze","Wed":"St","Weeks":"Týdny","Where do you want to restore from?":"Odkud chcete obnovit?","Where do you want to restore the files to?":"Kam chcete soubory obnovit?","Windows":"MS Windows","Years":"Let","Yes":"Ano","Yes, I have stored the passphrase safely":"Ano, heslovou frázi mám bezpečně uloženou","Yes, I'm brave!":"Ano, mám odvahu!","Yes, please break my backup!":"Ano, chci rozbít své zálohy!","Yesterday":"Včera","You appear to be running Mono with no SSL certificates loaded.\nDo you want to import the list of trusted certificates from Mozilla?":"Zdá se, že provozujete Mono bez načtených SSL certifikátů.\nChcete importovat seznam důvěryhodných certifikátů z Mozilla?","You are changing the database path away from an existing database.\nAre you sure this is what you want?":"Měníte umístění databáze pryč z existující databáze.\nOpravdu je to to, co chcete?","You are currently running {{appname}} {{version}}":"Nyní provozujete {{appname}} {{version}}","You can stop the backup immediately, or stop after the current file has been uploaded.":"Zálohu můžete zastavit buď teď hned, nebo po dokončení probíhajícího nahrávání souboru.","You can stop the task immediately, or allow the process to continue its current file and the stop.":"Úlohu můžete ukončit buď teď hned, nebo procesu umožnit zpracovat stávající soubor a pak zastavit.","You have changed the encryption mode. This may break stuff. You are encouraged to create a new backup instead":"Změnili jste režim šifrování. To může něco rozbít. Doporučujeme namísto toho vytvořit novou zálohu","You have changed the passphrase, which is not supported. You are encouraged to create a new backup instead.":"Změnili jste heslovou frázi, což není podporováno. Doporučujeme namísto toho vytvořit novou zálohu.","You have chosen not to encrypt the backup. Encryption is recommended for all data stored on a remote server.":"Zvolili jste že záloha nebude šifrována. Šifrování je doporučeno pro veškerá data ukládaná na vzdálený server.","You have chosen to restore to a new location, but not entered one":"Zvolili jste obnovu do nového umístění, ale nezadali jste ho","You have generated a strong passphrase. Make sure you have made a safe copy of the passphrase, as the data cannot be recovered if you lose the passphrase.":"Vytvořili jste odolnou heslovou frázi. Tu si dobře uschovejte, protože v případě její ztráty data nebude možné obnovit.","You must choose at least one source folder":"Je třeba zvolit alespoň jednu zdrojovou složku","You must enter a name for the backup":"Je třeba zadat název zálohy","You must enter a passphrase or disable encryption":"Buď je třeba zadat heslovou frázi nebo šifrování vypnout","You must enter a positive number of backups to keep":"Je třeba zadat kladný počet záloh které uchovávat","You must enter a tenant name if you do not provide an API Key":"Pokud nezadáte klíč k API, je třeba zadat jméno nájemníka (tenant)","You must enter a valid duration for the time to keep backups":"Je třeba zadat platnou dobu po kterou ponechávat zálohy","You must enter either a password or an API Key":"Je třeba zadat buď klíč k API nebo heslo","You must enter either a password or an API Key, not both":"Je třeba zadat buď heslo, nebo klíč k API – ne obojí naráz","You must fill in the password":"Je třeba vyplnit heslo","You must fill in the server name or address":"Je třeba vyplnit název nebo adresu serveru","You must fill in the username":"Je třeba vyplnit uživatelské jméno","You must fill in {{field}}":"Je třeba vyplnit kolonku {{field}}","You must select or fill in the AuthURI":"Je třeba vybrat nebo vyplnit AuthURI","You must select or fill in the server":"Je třeba vybrat nebo vyplnit server","You must specify a path":"Je třeba zadat popis umístění","Your files and folders have been restored successfully.":"Soubory a složky byly úspěšně obnoveny.","Your passphrase is easy to guess. Consider changing passphrase.":"Vaše heslová fráze je snadno uhodnutelná. Zvažte volbu jiné.","a specific number":"konkrétní číslo","bucket/folder/subfolder":"nadoba/slozka/podslozka","byte":"B","byte/s":"B/s","custom":"vlastní","resume now":"pokračovat nyní","unlimited":"neomezené","until they are older than":"dokud nejsou starší než","{{appname}} was primarily developed by {{dev1}} and {{dev2}}. {{appname}} can be downloaded from {{websitename}}. {{appname}} is licensed under the {{licensename}}.":"{{appname}} bylo vyvynuto hlavně {{dev1}} a {{dev2}}. {{appname}} je možné si stáhnout z {{websitename}}. {{appname}} je šířeno pod licencí {{licensename}}.","{{files}} files ({{size}}) to go {{speed_txt}}":"{{files}} souborů ({{size}}) zbývá {{speed_txt}}","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Version":["{{item.Backup.Metadata.TargetSizeString}} / {{$count}} verze","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} verze","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} verzí"],"{{number}} Hour":"{{number}} hodin","{{number}} Minutes":"{{number}} minut","{{time}} (took {{duration}})":"{{time}} (trvalo {{duration}})"}); - gettextCatalog.setStrings('da', {"- pick an option -":"- vælg indstilling -","...loading...":"...indlæser...","API Key":"API Key","AWS Access ID":"AWS Access ID","AWS Access Key":"AWS Access Key","AWS IAM Policy":"AWS IAM Policy","About":"Om","About {{appname}}":"Om {{appname}}","Access Key":"Access Key","Access denied":"Adgang nægtet","Access to user interface":"Adgang til brugerinterface","Account name":"Konto navn","Activate":"Aktiver","Activate failed:":"Aktivering fejlede:","Add a new backup":"Tilføj en ny backup","Add a path directly":"Tilføj en sti","Add advanced option":"Tilføj en avanceret indstilling","Add backup":"Tilføj backup","Add filter":"Tilføj filter","Add path":"Tilføj sti","Adjust bucket name?":"Tilpas bucket navnet?","Adjust path name?":"Juster stien?","Advanced Options":"Avancerede indstillinger","Advanced options":"Avancerede indstillinger","Advanced:":"Avanceret:","All":"Alle","All Hyper-V Machines":"Alle Hyper-V maskiner","All Microsoft SQL Databases":"Alle Microsoft SQL databaser","All usage reports are sent anonymously and do not contain any personal information. They contain information about hardware and operating system, the type of backend, backup duration, overall size of source data and similar data. They do not contain paths, filenames, usernames, passwords or similar sensitive information.":"Alle brugs rapporter bliver sendt anonymt og indeholder ikke personlige oplysninger. De indeholder oplysninger om hardware, operativsystem, destinationstype, backup varighed, backup størrelse og lignende information. De indeholder ikke stier, filnavne, brugernavne, kodeord eller lignende følsom information.","Allow remote access (requires restart)":"Tillad fjernadgang (kræver genstart)","Allowed days":"Tilladte dage","An existing file was found at the new location":"En eksisterende fil blev fundet på den nye placering","An existing file was found at the new location\nAre you sure you want the database to point to an existing file?":"En eksisterende fil blev funder på den nye placering.\nEr du sikker på at du vil have databasen til at pege på en eksisterende fil?","An existing local database for the storage has been found.\nRe-using the database will allow the command-line and server instances to work on the same remote storage.\n\n Do you wish to use the existing database?":"En eksisterende lokal database for destinationen er fundet.\nHvis du genbruger databasen, kan du bruge både kommandolinie og serveren til at arbejde på samme destination.\n\nVil du bruge den eksisterende database?","Anonymous usage reports":"Anonyme brugsstatistiker","As Command-line":"Som kommandolinie","AuthID":"AuthID","Authentication password":"Kodeord til godkendelse","Authentication username":"Brugernavn til godkendelse","Autogenerated passphrase":"Autogenereret kodeord","Automatically run backups.":"Kør backups automatisk","B2 Account ID":"B2 Account ID","B2 Application Key":"B2 Application Key","B2 Cloud Storage Account ID":"B2 Cloud Storage Account ID","B2 Cloud Storage Application Key":"B2 Cloud Storage Application Key","Back":"Tilbage","Backend modules:":"Backend moduler:","Backup destination":"Backup destination","Backup location":"Backup placering","Backup:":"Backup:","Beta":"Beta","Broken access":"Adgang defekt","Browse":"Gennemse","Browser default":"Browser standard","Bucket Name":"Bucket navn","Bucket create location":"Bucket placering ved oprettelse","Bucket create region":"Bucket region ved oprettelse","Bucket name":"Bucket navn","Bucket storage class":"Bucket storage class","Building list of files to restore ...":"Bygger liste af filer til gendannelse ...","Building partial temporary database ...":"Bygger en midlertidig database ...","Busy ...":"Optaget ...","Canary":"Canary","Cancel":"Annuller","Cannot move to existing file":"Kan ikke flytte til eksisterende fil","Changelog":"Ændringslog","Changelog for {{appname}} {{version}}":"Ændringslog for {{appname}} {{version}}","Check failed:":"Kontrol fejlede:","Check for updates now":"Tjek for opdateringer nu","Checking ...":"Kontrollerer ...","Checking for updates ...":"Leder efter opdateringer...","Chose a storage type to get started":"Valgte en destinationstype at komme i gang","Click the AuthID link to create an AuthID":"Click på AuthID linket for at oprettet et AuthID","Click to set throttle options":"Klik for at sætte hastigheds begrænsning","Commandline ...":"Kommandolinie ...","Compact now":"Komprimer nu","Compacting remote data ...":"Komprimerer data på destinationen ...","Completing backup ...":"Fuldfører backup ...","Completing previous backup ...":"Fuldfører forrige backup ...","Compression modules:":"Kompressions moduler:","Computer":"Computer","Configuration file:":"Konfigurationsfil:","Configuration:":"Konfiguration:","Configure a new backup":"Indstil en ny backup","Confirm delete":"Bekræft sletning","Confirmation required":"Bekræftelse kræves","Connect":"Forbind","Connect now":"Forbind nu","Connecting to server ...":"Forbinder til server ...","Connecting to task ....":"Forbinder til opgave ...","Connecting...":"Forbinder ...","Connection lost":"Forbindelse mistet","Connection worked!":"Forbindelsen virkede!","Container name":"Container navn","Container region":"Container region","Continue":"Fortsæt","Continue without encryption":"Fortsæt uden kryptering","Copied!":"Kopieret!","Copy Destination URL to Clipboard":"Kopier URL-destinationsadressen til udklipsholder","Copy failed. Please manually copy the URL":"Kopiering mislykkedes. Kopier venligst URL-adressen manuelt","Core options":"Grund indstillinger","Counting ({{files}} files found, {{size}})":"Tæller ({{files}} filer fundet, {{size}})","Crashes only":"Kun nedbrud","Create bug report ...":"Opret fejlrapport ...","Create folder?":"Opret mappe?","Created new limited user":"Opret en ny begrænset bruger","Creating bug report ...":"Opretter fejlrapport ...","Creating new user with limited access ...":"Opretter en ny bruger med begrænset adgang ...","Creating target folders ...":"Opretter destinations mapper ...","Creating temporary backup ...":"Opretter en midlertidig backup ...","Creating user...":"Opretter bruger ...","Current version is {{versionname}} ({{versionnumber}})":"Nuværende version er {{versionname}} ({{versionnumber}})","Custom S3 endpoint":"Brugerdefineret S3 endpoint","Custom authentication url":"Brugerdefineret godkendelses url","Custom location ({{server}})":"Brugerdefineret placering ({{server}})","Custom region for creating buckets":"Brugerdefineret region for at oprette buckets","Custom region value ({{region}})":"Brugerdefineret regions værdi ({{region}})","Custom server url ({{server}})":"Brugerdefineret server url ({{server}})","Custom storage class ({{class}})":"Brugerdefineret storage class ({{klasse}})","Database ...":"Database ...","Days":"Dage","Default":"Standard","Default ({{channelname}})":"Standard ({{channelname}})","Default Filters":"Standard filtre","Default options":"Standardindstillinger","Delete":"Slet","Delete ...":"Slet ...","Delete backup":"Slet backup","Delete local database":"Slet lokal database","Delete remote files":"Slette filer fra destinationen","Delete the local database":"Slet den lokale database","Delete {{filecount}} files ({{filesize}}) from the remote storage?":"Slet {{filecount}} filer ({{filesize}}) fra destinationen?","Deleting remote files ...":"Sletter filer fra destinationen ...","Deleting unwanted files ...":"Sletter uønskede filer ...","Desktop":"Skrivebord","Destination":"Destination","Did we help save your files? If so, please consider supporting Duplicati with a donation. We suggest {{smallamount}} for private use and {{largeamount}} for commercial use.":"Hjalp vi med at redde dine filer? Du kan overveje at støtte Duplicati med en donation. Vi foreslår {{smallamount}} ved privat brug og {{largeamount}} ved kommerciel brug.","Direct restore from backup files ...":"Direkte gendannelse fra backup filer ...","Disabled":"Deaktiveret","Dismiss":"Afvis","Display and color theme":"Visning og farvevalg","Do you really want to delete the backup: \"{{name}}\" ?":"Vil du virkelig slette backupen: \"{{name}}\"?","Do you really want to delete the local database for: {{name}}":"Vil du virkelig slette den lokale database for: {{navn}}","Donate":"Donér","Donation messages":"Donations beskeder","Donation messages are hidden, click to show":"Donations beskeder er skjult, klik for at vise","Donation messages are visible, click to hide":"Donation beskeder er synlige, klik for at skjule","Done":"Færdig","Download":"Download","Downloading ...":"Downloader ...","Downloading files ...":"Downloader filer ...","Downloading update...":"Downloader opdatering ...","Duplicate option {{opt}}":"Dublet af indstilling {{opt}}","Duplicati Website":"Duplicati hjemmeside","Duplicati forum":"Duplicati forum","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\n When deleting a backup, you can also delete the local database without affecting the ability to restore the remote files.\n If you are using the local database for backups from the commandline, you should keep the database.":"Hver backup har en lokal database tilknyttet, som gemmer information om data på fjerndestinationen lokalt på maskinen.\nNår du sletter en backup kan du også slette den lokale database uden at dette påvirker muligheden for at gendanne filer.\nHvis du bruger den lokale database til at køre backup via kommandolinien skal du beholde databasen.","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\\nThis makes it faster to perform many operations, and reduces the amount of data that needs to be downloaded for each operation.":"Hver backup har en lokal database forbundet, som gemmer oplysninger om destinationens filer på den lokale maskine. \\nDette gør det hurtigere at udføre mange operationer, og reducerer mængden af data, der skal hentes for hver operation.","Edit ...":"Rediger ...","Edit as list":"Rediger som liste","Edit as text":"Rediger som tekst","Encrypt file":"Krypter fil","Encryption":"Kryptering","Encryption changed":"Kryptering ændret","Encryption modules:":"Krypterings moduler:","Enter URL":"Indtast URL","Enter access key":"Indtast adgangsnøgle","Enter account name":"Indtast kontonavn","Enter backup passphrase, if any":"Indtast krypteringssætning, hvis krævet","Enter configuration details":"Indtast konfigurationsdetaljer","Enter container name":"Indtast container navn","Enter encryption passphrase":"Indtast krypteringssætning","Enter expression here":"Indtast udtryk her","Enter folder path name":"indtast mappe navn","Enter one option per line in command-line format, eg. {0}":"Indtast én indstilling per linie i kommandolinieformat, f.eks. {0}","Enter the destination path":"Indtast destinations stien","Error":"Fejl","Error!":"Fejl!","Errors and crashes":"Fejl og nedbrud","Exclude":"Eksludér","Exclude directories whose names contain":"Ekskluder mapper hvor navnet indeholder","Exclude expression":"Excluder udtryk","Exclude file":"Excluder fil","Exclude file extension":"Ekskluder filendelse","Exclude files whose names contain":"Ekskluder filer hvor navnet indeholder","Exclude folder":"Ekskluder mappe","Exclude regular expression":"Ekskluder regulært udtryk","Existing file found":"Eksisterende fil fundet","Experimental":"Eksperimental","Export":"Eksporter","Export ...":"Eksporter ...","Export backup configuration":"Eksporter backup konfiguration","Export configuration":"Eksporter konfiguration","Exporting ...":"Eksporterer ...","FTP (Alternative)":"FTP (alternativ)","Failed to build temporary database: {{message}}":"Kunne ikke bygge midlertidig database: {{message}}","Failed to connect:":"Kunne ikke forbinde:","Failed to connect: {{message}}":"Kunne ikke forbinde: {{message}}","Failed to delete:":"Kunne ikke slette:","Failed to fetch path information: {{message}}":"Kunne ikke hente sti-information: {{message}}","Failed to import:":"Kunne ikke importere:","Failed to read backup defaults:":"Kunne ikke læse backup standardværdier:","Failed to restore files: {{message}}":"Kunne ikke gendanne filer: {{message}}","Failed to save:":"Kunne ikke gemme:","Fetching path information ...":"Henter information om stier ...","File":"Fil","Files larger than:":"Filer større end:","Filters":"Filtre","Finished!":"Færdig!","First run setup":"Førstegangsopsætning","Folder":"Mappe","Folder path":"Mappe sti","Fri":"Fre","GByte":"GByte","GByte/s":"GByte/s","GCS Project ID":"GCS Projekt ID","General":"Generelt","General backup settings":"Generelle backup indstillinger","General options":"Generelle indstillinger","Generate":"Generér","Generate IAM access policy":"Generér IAM access policy","Getting file versions ...":"Henter fil versioner ...","Hidden files":"Skjulte filer","Hide":"Skjul","Hide hidden folders":"Skjul skjulte filer","Home":"Hjem","Hours":"Timer","How do you want to handle existing files?":"Hvordan vil du håndtere eksisterende filer?","Hyper-V Machine":"Hyper-V maskine","Hyper-V Machine:":"Hyper-V maskine:","Hyper-V Machines":"Hyper-V maskiner","ID:":"ID:","If a date was missed, the job will run as soon as possible.":"Hvis der ikke blev kørt på det angivne tidspunkt, vil jobbet køre så hurtigt som muligt.","If the backup and the remote storage is out of sync, Duplicati will require that you perform a repair operation to synchronize the database.\\nIf the repair is unsuccesful, you can delete the local database and re-generate.":"Hvis backup og data på destinationen ikke er synkroniseret, vil Duplicati kræve at du kører en reparation for at synkronisere databasen.\\nHvis reparationen ikke lykkes kan du slette den lokale database og gendanne den.","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"Hvis backup filen ikke blev downloaded automatisk, så højreklik og vælg "Gem som... "","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"Hvis backup filen ikke blev downloaded automatisk, så højreklik og vælg "Gem som... "","If you do not enter a path, all files will be stored in the login folder.\nAre you sure this is what you want?":"Hvis du ikke indtaster en sti, vil alle filer blive gemt i login mappen.\nEr du sikke på at det er det du vil gøre?","If you do not enter an API Key, the tenant name is required":"Hvis du ikke indtaster en API key, skal du angive tenant navnet","If you want to use the backup later, you can export the configuration before deleting it":"Hvis du vil bruge din backup senere, kan du eksportere konfigurationen før du sletter den","If your machine is in a multi-user environment (i.e. the machine has more than one account), you need to set a password to prevent other users from accessing data on your account.\nDo you want to set a password now?":"Hvis flere personer bruger denne computer (med forskellig brugerkonti) bør du indstille et kodeord for at forhindre andre i at tilgå din data.\nVil du indstille et kodeord nu?","Import":"Importér","Import Destination URL":"Importer destinations URL","Import backup configuration":"Importer backup konfiguration","Import completed, but no certificates were found after the import":"Importen blev færdig, men der blev ikke funder certifikater efter importen","Import failed":"Importen fejlede","Import from a file":"Importer fra en fil","Importing ...":"Importerer ...","Include a file?":"Inkluder en fil?","Include expression":"Inkluder udtryk","Include regular expression":"Inkluder regulært udtryk","Incorrect answer, try again":"Forkert svar, prøv igen","Individual builds for developers only.":"Individuelle versioner for udviklere","Information":"Information","Install":"Installer","Install failed:":"Installationen fejlede:","Invalid characters in path":"Ugyldige tegn i stien","Invalid retention time":"Ugyldig bevaringstid","It is possible to connect to some FTP without a password.\nAre you sure your FTP server supports password-less logins?":"Det er muligt at oprette forbindelse til nogle FTP servere uden en adgangskode.\nEr du sikker på din FTP-server understøtter password-fri login?","KByte":"KByte","KByte/s":"KByte/s","Language in user interface":"Sprog i brugergrænsefladen","Last month":"Sidste måned","Last successful run:":"Sidste succesfulde kørsel:","Latest":"Nyeste","Libraries":"Biblioteker","Linux":"Linux","Listing backup dates ...":"Henter backup datoer...","Listing remote files ...":"Henter filer fra destinationen ...","Live":"Live","Load a configuration from an exported job or a storage provider":"Indlæs konfiguration fra en eksporteret fil eller en pladsudbyder","Load destination from an exported job or a storage provider":"Indlæs destination fra en eksporteret fil eller en pladsudbyder","Load older data":"Indlæs ældre data","Loading ...":"Indlæser ...","Loading remote storage usage ...":"Indlæser forbrug fra fjerndestinationen ...","Local database for":"Lokal database for","Local database path:":"Lokal database sti:","Local storage":"Local opbevaring","Location":"Placering","Location where buckets are created":"Placering hvor buckets bliver oprettet","Log data for {{Backup.Backup.Name}}":"Logdata for {{Backup.Backup.Name}}","Log data from the server":"Logdata fra serveren","Log out":"Log ud","MByte":"MByte","MByte/s":"MByte/s","Maintenance":"Vedligehold","Manually type path":"Indtast en sti manuelt","Max download speed":"Max downloadhastighed","Max upload speed":"Maks uploadhastighed","Menu":"Menu","Microsoft SQL Database:":"Microsoft SQL Database:","Microsoft SQL Databases":"Microsoft SQL Databaser","Minimum redundancy":"Mindste tilladte redundans","Minimum redundancy is 1.0":"Mindste redundans er 1.0","Minutes":"Minutter","Missing name":"Navn mangler","Missing passphrase":"Kodesætning mangler","Missing sources":"Kilder mangler","Mon":"Man","Months":"Måneder","Move existing database":"Flyt eksisterende database","Move failed:":"Flytning fejlede:","My Documents":"Mine dokumenter","My Music":"Min musik","My Photos":"Mine foto","My Pictures":"Mine billeder","Name":"Navn","Never":"Aldrig","New update found: {{message}}":"Ny opdatering fundet: {{message}}","New user name is {{user}}.\nUpdated credentials to use the new limited user":"Nyt bruger navn er {{user}}.\nLoginoplysninger er opdateret til den nye begrænsede bruger","Next":"Næste","Next scheduled run:":"Næste planlagte kørsel:","Next scheduled task:":"Næste planlagte opgave:","Next task:":"Næste opgave:","Next time":"Næste tidspunkt","No":"Nej","No certificate was specified previously, please verify with the server administrator that the key is correct: {{key}} \n\nDo you want to approve the reported host key?":"Intet certifikat har været anvendt før, kontroller venligst at nøglen er korrekt hos serveradministratoren: {{key}} \n\nVil du godkende den angivne nøgle?","No editor found for the "{{backend}}" storage type":"Ingen editor blev fundet for "{{backend}}" destinationen","No encryption":"Ingen kryptering","No items selected":"Ingen emner valgt","No items to restore, please select one or more items":"Ingen emner er valgt til gendannelse, vælg venligst en eller flere emner","No passphrase entered":"Ingen adgangssætning angivet","No scheduled tasks":"Ingen planlagte opgaver","No, my machine has only a single account":"Nej, min computer har kun en brugerkonto","Non-matching passphrase":"Uoverenstemmelse mellem kodesætninger","None / disabled":"Ingen / deaktiveret","OK":"OK","OSX":"OSX","OpenStack AuthURI":"OpenStack AuthURI","OpenStack Object Storage / Swift":"OpenStack Object Storage / Swift","Operation failed:":"Operation fejlede:","Operations:":"Operationer:","Optional authentication password":"Valgfrit kodeord til godkendelse","Optional authentication username":"Valgfrit brugernavn til godkendelse","Options":"Indstillinger","Options added here are applied to all backups, but can be overridden in each individual backup":"Indstilliger tilføjet here bliver anvendt på alle backups, men kan blive overskrevet individuelt på hver backup","Original location":"Oprindelig placering","Others":"Andre","Overwrite":"Overskriv","Passphrase":"Kodesætning","Passphrase (if encrypted)":"Kodesætning (hvis krypteret)","Passphrase changed":"Kodesætning ændret","Passphrases are not matching":"Kodesætninger er ikke ens","Password":"Kodeord","Passwords do not match":"Kodeord er ikke ens","Patching files with local blocks ...":"Opdaterer filer med lokale blokke ...","Path not found":"Stien blev ikke fundet","Path on server":"Sti på server","Path or subfolder in the bucket":"Sti eller undermappe i bucket","Pause":"Pause","Pause after startup or hibernation":"Pause efter start eller dvale","Pause options":"Pause indstillinger","Permissions":"Tilladelser","Pick location":"Vælg placering","Point to your backup files and restore from there":"Udpeg dine backup-filer og gendan fra dem","Port":"Port","Previous":"Forrige","ProjectID is optional if the bucket exist":"ProjectID er valgfrit hvis bucket eksisterer","Proprietary":"Proprietære","Purging files ...":"Fjerner filer ...","Rebuilding local database ...":"Genopbygger lokal database ...","Recreate (delete and repair)":"Gendan (slet og reparer)","Recreating database ...":"Gendanner database ...","Registering temporary backup ...":"Registrerer midlertidig backup ...","Relative paths not allowed":"Relative stier er ikke tilladt","Reload":"Genindlæs","Remote":"Destination","Remove":"Fjern","Remove option":"Fjern indstilling","Repair":"Reparer","Reparing ...":"Reparerer ...","Repeat Passphrase":"Gentag kodesætning","Reporting:":"Rapporterer:","Reset":"Nulstil","Restore":"Gendan","Restore files":"Gendan filer","Restore files ...":"Gendan filer ...","Restore files from {{backupname}}":"Gendan filer fra {{backupname}}","Restore from":"Gendan fra","Restore from backup configuration":"Gendan fra konfiguration i backup","Restore from configuration ...":"Gendan fra konfiguration ...","Restore options":"Indstillinger til gendannelse","Restore read/write permissions":"Gendan læse/skrive tilladelser","Restoring files ...":"Gendanner filer ...","Resume":"Genoptag","Run again every":"Kør igen hver","Run now":"Kør nu","Running ...":"Kører ...","Running ....":"Kører ...","Running commandline entry":"Kører kommandolinie opgave","Running task:":"Kørende opgave:","S3 Compatible":"S3 kompatibel","Same as the base install version: {{channelname}}":"Samme som grundinstallationsversionen: {{channelname}}","Sat":"Lør","Save":"Gem","Save and repair":"Gem og reparer","Save different versions with timestamp in file name":"Gem forskellige versioner med tidstempel i filnavnet","Save immediately":"Gem med det samme","Scanning existing files ...":"Skanner eksisterende filer ...","Scanning for local blocks ...":"Scanner for lokale blokke ...","Schedule":"Planlagt","Search":"Søg","Search for files":"Søg efter filer","Seconds":"Sekunder","Select a log level and see messages as they happen:":"Vælg et log niveau og se beskeder som de kommer:","Select files":"Vælg filer","Server":"Server","Server and port":"Server og port","Server hostname or IP":"Server navn eller IP","Server is currently paused,":"Serveren er sat på pause.","Server is currently paused, do you want to resume now?":"Serveren er sat på pause, vil du genoptage med det samme?","Server password":"Server kodeord","Server paused":"Server på pause","Server state properties":"Egenskaber for serveren","Settings":"Indstillinger","Show":"Vis","Show advanced editor":"Vis avanceret redigering","Show hidden folders":"Vis skjulte mapper","Show log":"Vis log","Show log ...":"Vis log ...","Show treeview":"Vis træstruktur","Sia server password":"Sia server kodeord","Some OpenStack providers allow an API key instead of a password and tenant name":"Nogle OpenStack udbydere tillader en API nøgle istedet for et kodeord og et tenant navn","Source Data":"Kilde data","Source data":"Kilde data","Source folders":"Kilde mapper","Source:":"Kilde:","Specific builds for developers only.":"Specielle versioner til udviklere.","Standard protocols":"Standard protokoller","Starting ...":"Starter ...","Starting the restore process ...":"Starter gendannelses processen ...","Stop after the current file":"Stop efter den nuværende fil","Stop after upload":"Stop efter upload","Stop now":"Stop nu","Stop running backup":"Stop den kørende backup","Stop running task":"Stop den kørende opgave","Stopping after upload:":"Stopper efter upload:","Stopping task:":"Stopper opgave:","Storage Type":"Opbevaringstype","Storage class":"Opbevaringsklasse","Storage class for creating a bucket":"Opbevaringsklasse når der oprettes en bucket","Stored":"Gemt","Strong":"Stærk","Success":"Succes","Sun":"Søn","Symbolic link":"Symbolsk kæde","System default ({{levelname}})":"System standard ({{levelname}})","System files":"System filer","System info":"System info","System properties":"System egenskaber","TByte":"TByte","TByte/s":"TByte/s","Target path, ie /backup":"Destinationsstien, f.eks. /backup","Task is running":"Opgave kører","Temporary files":"Midlertidige filer","Tenant Name":"Tenant navn","Test connection":"Test forbindelse","Testing ...":"Tester ...","Testing connection ...":"Tester forbindelse ...","Testing permissions ...":"Tester tilladelser ...","Testing permissions...":"Tester tilladelser...","The bucket name should be all lower-case, convert automatically?":"Bucket navnet bør være med små bogstaver, konverter automatisk?","The bucket name should start with your username, prepend automatically?":"Bucket navnet bør starte med dit brugernavn, vil du sætte det foran automatisk?","The connection to the server is lost, attempting again in {{time}} ...":"Forbindelsen til serveren er mistet, forsøger igen om {{time}} ...","The dark theme (by Michal)":"Mørke farver (af Michal)","The default blue on white theme (by Alex)":"Standard blå på hvid (af Alex)","The host key has changed, please check with the server administrator if this is correct, otherwise you could be the victim of a MAN-IN-THE-MIDDLE attack.\n\nDo you want to REPLACE your CURRENT host key \"{{prev}}\" with the REPORTED host key: {{key}}?":"Nøglen fra værten er ændret, kontroller venligst med server administratoren om dette er korrekt, ellers kan du være offer for et MAN-IN-THE-MIDDLE angreb.\n\nVil du ERSTATTE din NUVÆRENDE værtsnøgle \"{{prev}}\" med den RAPPORTEREDE værtsnøgle: {{key}}?","The path does not appear to exist, do you want to add it anyway?":"Stien ser ikke ud til at findes, vil du tilføje den alligevel?","The path does not end with a '{{dirsep}}' character, which means that you include a file, not a folder.\n\nDo you want to include the specified file?":"Stien slutter ikke med '{{dirsep}}' tegnet, hvilket betyder at du inkluderer en file og ikke en mappe.\n\nVil du inkludere den valgte fil?","The path must be an absolute path, i.e. it must start with a forward slash '/'":"Stien skal være en absolut sti, altså skal den starte med '/'","The path should start with \"{{prefix1}}\" or \"{{prefix2}}\", otherwise you will not be able to see the files in the HubiC web interface.\n\nDo you want to add the prefix to the path automatically?":"Stien bør starte med \"{{præfiks1}}\" eller \"{{præfiks2}}\", ellers vil du ikke kunne se andre filer i HubiC web konsollen\n\nVil du tilføje præfikset til stien automatisk?","The region parameter is only applied when creating a new bucket":"Regionsparameteren anvendes kun når der oprettes en ny bucket","The region parameter is only used when creating a bucket":"Regionsparameteren bruges kun når der oprettes en ny bucket","The server certificate could not be validated.\nDo you want to approve the SSL certificate with the hash: {{hash}}?":"Server certifikatet kunne ikke valideres.\nVil du godkende SSL certifikatet med dette hash: {{hash}}?","The storage class affects the availability and price for a stored file":"Opbevaringsklasen påvirker tilgængeligheden og prisen for en opbevaret fil","The target folder contains encrypted files, please supply the passphrase":"Destinationsmappen indeholder krypterede filer, angiv venligst kodesætningen","The user has too many permissions. Do you want to create a new limited user, with only permissions to the selected path?":"Brugeren har for mange tilladelser. Vil du oprette en ny begrænset bruger der kun har adgang til den valgte sti?","This backup was created on another operating system. Restoring files without specifying a destination folder can cause files to be restored in unexpected places. Are you sure you want to continue without choosing a destination folder?":"Denne backup blev oprettet på et andet operativsystem. Når der gendannes filer uden at angive en destination, kan disse blive oprettet på uventede placeringer. Er du sikker på at du vil fortsætte uden at vælge en destinationsmappe?","This month":"Denne måned","This week":"Denne uge","Throttle settings":"Indstillinger for hastighedsbegrænsning","Thu":"Tor","To File":"Til fil","To confirm you want to delete all remote files for \"{{name}}\", please enter the word you see below":"For at bekræfte at du vil slette all fjernfiler til \"{{name}}\", indtast venligst det ord ud ser herunder","To export without a passphrase, uncheck the \"Encrypt file\" box":"For at eksportere uden en adgangsætning, fjern mærket ud for \"Krypter filen\"","Today":"I dag","Trust host certificate?":"Stol på værtscertifikatet?","Trust server certificate?":"Stol på server certifikatet?","Try out the new features we are working on. Don't use with important data.":"Prøv de nye ting vi arbejder på. Undlad at bruge denne med vigtige data.","Tue":"Tir","Type to highlight files":"Skriv for at markere filer","Unknown backup size and versions":"Ukendt backup størrelse og versionsantal","Until resumed":"Indtil genoptaget","Update channel":"Opdateringskanal","Update failed:":"Opdatering fejlede:","Updating with existing database":"Opdaterer med eksisterende database","Upload volume size":"Filstørrelse til upload","Uploading verification file ...":"Uploader verifikationsfil ...","Usage statistics":"Brugsstatistik","Usage statistics, warnings, errors, and crashes":"Brugsstatistik, advarsler, fejl og nedbrud","Use SSL":"Brug SSL","Use existing database?":"Brug eksisterende database?","Use weak passphrase":"Brug svag kodesætning","Useless":"Ubrugelig","User data":"Brugerdata","User has too many permissions":"Brugeren har for mange tilladelser","User interface settings":"Indstillinger til brugergrænseflade","Username":"Brugernavn","Validating ...":"Validerer ...","Verify files":"Verificer filer","Verifying ...":"Verificerer ...","Verifying answer":"Verificerer svar","Verifying backend data ...":"Verificerer destinationsdata ...","Verifying remote data ...":"Verificerer fjerndata ...","Verifying restored files ...":"Verificerer gendannede filer ...","Very strong":"Meget stærk","Very weak":"Meget svag","Visit us on":"Besøg os på","WARNING: The remote database is found to be in use by the commandline library":"ADVARSEL: Databasen benyttes af kommandolinie programmet","WARNING: This will prevent you from restoring the data in the future.":"ADVARSEL: Dette vil forhindre dig i at gendanne data i fremtiden.","Waiting for task to begin":"Venter på at opgaven starter","Waiting for task to start ....":"Venter på at opgaven starter ...","Waiting for upload ...":"Venter på upload ...","Warnings, errors and crashes":"Advarsler, fejl og nedbrud","We recommend that you encrypt all backups stored outside your system":"Vi anbefaler at du krypterer alle backups der er gemt uden for dit system","Weak":"Svag","Weak passphrase":"Svag kodesætning","Wed":"Ons","Weeks":"Uger","Where do you want to restore from?":"Hvor vil du gerne gendanne fra?","Where do you want to restore the files to?":"Hvor vil du gendanne filerne til?","Windows":"Windows","Years":"År","Yes":"Ja","Yes, I have stored the passphrase safely":"Ja, jeg har opbevaret kodesætningen sikkert","Yes, I'm brave!":"Ja, jeg er modig!","Yes, please break my backup!":"Ja, ødelæg venligst min backup!","Yesterday":"I går","You appear to be running Mono with no SSL certificates loaded.\nDo you want to import the list of trusted certificates from Mozilla?":"Det ser ud til at du kører Mono uden nogen SSL certifikater.\nVil du importere listen af certifikater som Mozilla bruger?","You are changing the database path away from an existing database.\nAre you sure this is what you want?":"Du er ved at ændre database stien væk fra en eksisterende database.\nEr du sikker på at det er det du vil?","You are currently running {{appname}} {{version}}":"Du kører med {{appname}} {{version}}","You can stop the backup immediately, or stop after the current file has been uploaded.":"Du kan stoppe backup'en med det samme, eller stoppe efter den nuværende fil er uploaded.","You can stop the task immediately, or allow the process to continue its current file and the stop.":"Du kan stoppe opgaven med det samme, eller lade den afslutte den nuværende fil og så stoppe.","You have changed the encryption mode. This may break stuff. You are encouraged to create a new backup instead":"Du har skiftet krypteringsmetode. Dette kan ødelægge ting. Du opfordres til at oprette en ny backup i stedet.","You have changed the passphrase, which is not supported. You are encouraged to create a new backup instead.":"Du har skiftet kodesætningen, hvilket ikke understøttes. Du opfordres til at oprette en ny backup i stedet.","You have chosen not to encrypt the backup. Encryption is recommended for all data stored on a remote server.":"Du har valgt at undlade at kryptere din backup. Kryptering anbefales for alt data der gemmes på en fjerndestination.","You have chosen to restore to a new location, but not entered one":"Du har valgt at gendanne til en ny placering, men ikke angivet en","You have generated a strong passphrase. Make sure you have made a safe copy of the passphrase, as the data cannot be recovered if you lose the passphrase.":"Du har genereret en stærk adgangskode. Sørg for, at du har en sikker kopi af adgangskoden, da data ikke kan gendannes, hvis du mister adgangskoden.","You must choose at least one source folder":"Du skal vælge mindst en kilde mappe","You must enter a name for the backup":"Du skal angive et navn for denne backup","You must enter a passphrase or disable encryption":"Du skal indtaste en kodesætning eller fravælge kryptering","You must enter a positive number of backups to keep":"Du skal indtaste et positivt antal backups der skal bevares","You must enter a tenant name if you do not provide an API Key":"Du skal angive et tenant navn hvis du ikke angiver en API nøgle","You must enter a valid duration for the time to keep backups":"Du skal angive en gyldig periode som backups gemmes i","You must enter either a password or an API Key":"Du skal angive enten et kodeord eller en API nøgle","You must enter either a password or an API Key, not both":"Du skal angive enten et kodeord eller en API nøgle, men ikke begge","You must fill in the password":"Du skal angive et kodeord","You must fill in the server name or address":"Du skal angive server navnet eller adressen","You must fill in the username":"Du skal angive et brugernavn","You must fill in {{field}}":"Du skal udfylde {{field}}","You must select or fill in the AuthURI":"Du skal vælge eller udfylde AuthURI","You must select or fill in the server":"Du skal vælge eller indtaste server navnet","You must specify a path":"Du skal angive en sti","Your files and folders have been restored successfully.":"Dine filer og mapper blev gendannet korrekt.","Your passphrase is easy to guess. Consider changing passphrase.":"Din kodesætning er let at gætte. Overvej at skifte den.","bucket/folder/subfolder":"buvket/mappe/undermappe","byte":"byte","byte/s":"byte/s","custom":"tilpasset","resume now":"genoptag nu","{{appname}} was primarily developed by {{dev1}} and {{dev2}}. {{appname}} can be downloaded from {{websitename}}. {{appname}} is licensed under the {{licensename}}.":"{{appname}} er primært udviklet af {{dev1}} og {{dev2}}. {{appname}} kan downloades fra {{websitename}}. {{appname}} er licenseret med {{licensename}}.","{{files}} files ({{size}}) to go {{speed_txt}}":"{{files}} filer ({{size}}) tilbage {{speed_txt}}","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Version":["{{item.Backup.Metadata.TargetSizeString}} / {{$count}} version","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} versioner"],"{{number}} Hour":"{{number}} Timer","{{number}} Minutes":"{{number}} Minutter","{{time}} (took {{duration}})":"{{time}} (varighed: {{duration}})"}); + gettextCatalog.setStrings('cs', {"- pick an option -":"- vyberte jednu z možností -","...loading...":"…načítání…","API Key":"Klíč k aplikačnímu programovému rozhraní (API)","AWS Access ID":"Přístupový identifikátor ke službe AWS","AWS Access Key":"Přístupový klíč ke službě AWS","AWS IAM Policy":"Zásady IAM služby AWS","About":"O aplikaci","About {{appname}}":"O aplikaci {{appname}}","Access Key":"Přístupový klíč","Access denied":"Přístup odepřen","Access to user interface":"Přístup k uživatelskému rozhraní","Account name":"Název účtu","Activate":"Aktivovat","Activate failed:":"Aktivace se nezdařila:","Add a new backup":"Přidat novou zálohu","Add a path directly":"Přidat popis umístění přímo","Add advanced option":"Přidat pokročilou volbu","Add backup":"Přidat zálohu","Add filter":"Přidat filtr","Add path":"Přidat popis umístění","Adjust bucket name?":"Přizpůsobit název „nádoby“ (bucket)?","Adjust path name?":"Přizpůsobit popis umístění?","Advanced Options":"Pokročilé volby","Advanced options":"Pokročilé volby","Advanced:":"Pokročilé:","All":"Vše","All Hyper-V Machines":"Všechny Hyper-V stroje","All Microsoft SQL Databases":"Všechny Microsoft SQL databáze","All usage reports are sent anonymously and do not contain any personal information. They contain information about hardware and operating system, the type of backend, backup duration, overall size of source data and similar data. They do not contain paths, filenames, usernames, passwords or similar sensitive information.":"Veškerá hlášení o využívání jsou posílána anonymně a neobsahují žádné osobní údaje. Obsahují informace o hardware a operačním systému, typu podpůrné vrstvy (backend), trvání zálohy, celkové velikosti zdrojových dat a podobně.\nNeobsahují popisy umístění, názvy souborů, uživatelská jména, hesla nebo podobné citlivé údaje.","Allow remote access (requires restart)":"Umožnit přístup na dálku (vyžaduje restart)","Allowed days":"Dny, ve které je přístup umožněn","An existing file was found at the new location":"V novém umístění byl nalezen už existující soubor","An existing file was found at the new location\nAre you sure you want the database to point to an existing file?":"V novém umístění byl nalezen už existující soubor\nOpravdu chcete nasměrovat databázi do existujícího souboru?","An existing local database for the storage has been found.\nRe-using the database will allow the command-line and server instances to work on the same remote storage.\n\n Do you wish to use the existing database?":"Byla nalezena existující místní databáze pro ukládání.\nOpětovné využití databáze umožní, aby instance pro příkazový řádek a server fungovaly na stejném vzdáleném úložišti.\n\nChcete použít existující databázi?","Anonymous usage reports":"Anonymní hlášení o použití","As Command-line":"Jako příkazový řádek","AuthID":"AuthID","Authentication password":"Ověřovací heslo","Authentication username":"Ověřovací uživatelské jméno","Autogenerated passphrase":"Automaticky vytvořená heslová fráze","Automatically run backups.":"Spouštět zálohy automaticky.","B2 Account ID":"Identifikátor účtu u služby B2","B2 Application Key":"Aplikační klíč ke službě B2","B2 Cloud Storage Account ID":"Identifikátor účtu u cloudového úložiště B2","B2 Cloud Storage Application Key":"Aplikační klíč ke cloudovému úložišti B2","Back":"Zpět","Backend modules:":"Moduly podpůrných vrstev (backend):","Backup destination":"Cíl zálohy","Backup location":"Umístění zálohy","Backup retention":"Doba uchovávání záloh","Backup:":"Záloha:","Beta":"Vývojová testovací (beta)","Broken access":"Nefunkční přístup","Browse":"Procházet","Browser default":"Výchozí nastavení webového prohlížeče","Bucket Name":"Název „nádoby“ (bucket)","Bucket create location":"Umístění ve kterém „nádobu“ (bucket) vytvořit","Bucket create region":"Oblast světa ve které „nádobu“ (bucket) vytvořit","Bucket name":"Název „nádoby“ (bucket)","Bucket storage class":"Třída úložiště nesoucí „nádobu“ (bucket)","Building list of files to restore ...":"Vytváření seznamu souborů k obnovení…","Building partial temporary database ...":"Vytváření částečné dočasné databáze…","Busy ...":"Zaneprázdněno…","Canary":"Kanárek","Cancel":"Storno","Cannot move to existing file":"Nelze přesunout do existujícího souboru","Changelog":"Seznam změn","Changelog for {{appname}} {{version}}":"Seznam změn v {{appname}} {{version}}","Check failed:":"Zjištění se nezdařilo:","Check for updates now":"Zjistit dostupnost případných aktualizací nyní","Checking ...":"Zjišťování…","Checking for updates ...":"Zjišťování dostupnosti případných aktualizací…","Chose a storage type to get started":"Pro začátek vyberte typ úložiště","Click the AuthID link to create an AuthID":"AuthID vytvoříte kliknutím na odkaz AuthID","Click to set throttle options":"Kliknutím nastavte předvolby přiškrcování","Commandline ...":"Příkazový řádek…","Compact now":"Zkompaktnit nyní","Compacting remote data ...":"Zkompaktňování dat na protějšku…","Completing backup ...":"Dokončování zálohy…","Completing previous backup ...":"Dokončování předchozí zálohy…","Compression modules:":"Komprimační moduly:","Computer":"Počítač","Configuration file:":"Soubor s nastaveními:","Configuration:":"Nastavení:","Configure a new backup":"Nastavit novou zálohu","Confirm delete":"Potvrzení smazání","Confirmation required":"Vyžadováno potvrzení","Connect":"Připojit","Connect now":"Připojit nyní","Connecting to server ...":"Připojování k serveru…","Connecting to task ....":"Připojování k úloze…","Connecting...":"Připojování…","Connection lost":"Spojení ztraceno","Connection worked!":"Spojení funguje!","Container name":"Název kontejneru","Container region":"Region umístění kontejneru","Continue":"Pokračovat","Continue without encryption":"Pokračovat bez šifrování","Copied!":"Zkopírováno!","Copy":"Kopírovat","Copy Destination URL to Clipboard":"Zkopírovat URL adresu cíle do schránky","Copy failed. Please manually copy the URL":"Kopie se nezdařila. Zkopírujte URL adresu ručně","Core options":"Core volby","Counting ({{files}} files found, {{size}})":"Počítání ({{files}} souborů nalezeno, {{size}})","Crashes only":"Pouze pády","Create bug report ...":"Vyplnit hlášení chyby…","Create folder?":"Vytvořit složku?","Created new limited user":"Vytvořit nový uživatelský účet s omezenými oprávněními","Creating bug report ...":"Vytváření hlášení chyby…","Creating new user with limited access ...":"Vytváření nového uživatele s omezeným přístupem…","Creating target folders ...":"Vytváření cílových složek…","Creating temporary backup ...":"Vytváření dočasné zálohy…","Creating user...":"Vytváření uživatelského účtu…","Current version is {{versionname}} ({{versionnumber}})":"Stávající verze je {{versionname}} ({{versionnumber}})","Custom S3 endpoint":"Vlastní S3 koncový bod","Custom authentication url":"Vlastní ověřovací URL adresa","Custom backup retention":"Uživatelem určená doba uchovávání záloh","Custom location ({{server}})":"Vlastní umístění ({{server}})","Custom region for creating buckets":"Vlastní region pro vytváření „nádob“ (bucket)","Custom region value ({{region}})":"Hodnota pro vlastní region ({{region}})","Custom server url ({{server}})":"Vlastní URL adresa serveru ({{server}})","Custom storage class ({{class}})":"Vlastní třída úložiště ({{class}})","Database ...":"Databáze…","Days":"Dnů","Default":"Výchozí","Default ({{channelname}})":"Výchozí ({{channelname}})","Default Filters":"Výchozí filtry","Default options":"Výchozí volby","Delete":"Smazat","Delete ...":"Smazat…","Delete backup":"Smazat zálohu","Delete backups that are older than":"Smazat zálohy starší než","Delete local database":"Smazat místní databázi","Delete remote files":"Smazat soubory na protějšku","Delete the local database":"Smazat místní databázi","Delete {{filecount}} files ({{filesize}}) from the remote storage?":"Smazat {{filecount}} souborů ({{filesize}}) ze vzdáleného úložiště?","Deleting remote files ...":"Mazání souborů na protějšku…","Deleting unwanted files ...":"Mazání nepotřebných souborů…","Desktop":"Osobní počítač","Destination":"Cíl","Did we help save your files? If so, please consider supporting Duplicati with a donation. We suggest {{smallamount}} for private use and {{largeamount}} for commercial use.":"Pomohli jsme vám zachránit vaše soubory? Pokud ano, zvažte prosím podpoření Duplicati darem. Doporučujeme {{smallamount}} pro soukromé a {{largeamount}} pro komerční použití.","Direct restore from backup files ...":"Přímé obnovování ze záložních souborů…","Disabled":"Vypnuto","Dismiss":"Odmítnout","Display and color theme":"Motiv vzhledu zobrazení a barev","Do you really want to delete the backup: \"{{name}}\" ?":"Opravdu chcete smazat zálohu: „{{name}}“?","Do you really want to delete the local database for: {{name}}":"Opravdu chcete smazat místní databázi pro: {{name}}","Donate":"Darovat","Donation messages":"Darovací zprávy","Donation messages are hidden, click to show":"Darovací zprávy jsou skryté, kliknutím je zobrazíte","Donation messages are visible, click to hide":"Darovací zprávy jsou zobrazené, kliknutím je skryjete","Done":"Hotovo","Download":"Stáhnout","Downloading ...":"Stahování…","Downloading files ...":"Stahování souborů…","Downloading update...":"Stahování aktualizace…","Duplicate option {{opt}}":"Volba duplikace {{opt}}","Duplicati Website":"Webové stránky projektu Duplicati","Duplicati forum":"Diskuzní fórum o Duplicati","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\n When deleting a backup, you can also delete the local database without affecting the ability to restore the remote files.\n If you are using the local database for backups from the commandline, you should keep the database.":"Ke každé záloze je přiřazena místní databáze, která uchovává informace o vzdálené záloze na místním stroji.\n Při mazání zálohy je také možné smazat lokální databázi aniž by tím byla postižena schopnost obnovovat vzdálené soubory.\n Pokud používáte místní databáze pro zálohy z příkazového řádku, měli byste databázi ponechat.","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\\nThis makes it faster to perform many operations, and reduces the amount of data that needs to be downloaded for each operation.":"Ke každé záloze je přiřazena místní databáze, která uchovává informace o vzdálené záloze na místním stroji.\\nTo zrychluje provádění mnoha operací a snižuje množství dat které je při každé operaci třeba stahovat.","Edit ...":"Upravit…","Edit as list":"Upravit jako seznam","Edit as text":"Upravit jako text","Encrypt file":"Zašifrovat soubor","Encryption":"Šifrování","Encryption changed":"Šifrování změněno","Encryption modules:":"Šifrovací moduly:","Enter URL":"Zadejte URL adresu","Enter a retention strategy manually. Placeholders are D/W/Y for days/weeks/years. The syntax is: 7D:1D,4W:1W,36M:1M. This example keeps one backup for each of the next 7 days, one for each of the next 4 weeks, and one for each of the next 36 months. This can also be written as 1W:1D,1M:1W,3Y:1M.":"Zadejte strategii uchovávání záloh ručně. Výplň je D/W/Y pro dny/týdny/roky. Forma zápisu je: 7D:1D,4W:1W,36M:1M. V tomto příkladu je ponechána jedna záloha z každého dne po dobu příštích 7 dnů, jedna z každého týdne po dobu příštích 4 týdnů a jedna z každého měsíce po dobu příštích 36 měsíců. Je možné zapsat také jako 1W:1D,1M:1W,3Y:1M.","Enter access key":"Zadejte přístupový klíč","Enter account name":"Zadejte název účtu","Enter backup passphrase, if any":"Zadejte záložní heslovou frázi, pokud existuje","Enter configuration details":"Zadejte podrobnosti nastavení","Enter container name":"Zadejte název kontejneru","Enter encryption passphrase":"Zadejte šifrovací heslovou frázi","Enter expression here":"Sem zadejte výraz","Enter folder path name":"Zadejte popis umístění složky","Enter one option per line in command-line format, eg. {0}":"Každou z voleb zadejte zvlášť na samostatný řádek, např. {0}","Enter the destination path":"Zadejte popis cílového umístění ","Error":"Chyba","Error!":"Chyba!","Errors and crashes":"Chyby a pády","Exclude":"Vynechat","Exclude directories whose names contain":"Vynechat složky jejichž názvy obsahují","Exclude expression":"Výraz pro vynechané","Exclude file":"Vynechat soubor","Exclude file extension":"Vynechat soubory s příponami","Exclude files whose names contain":"Vynechat soubory jejichž názvy obsahují","Exclude folder":"Vynechat složku","Exclude regular expression":"Regulární výraz pro vynechávané","Existing file found":"Nalezen existující soubor","Experimental":"Experimentální","Export":"Exportovat","Export ...":"Exportovat…","Export backup configuration":"Exportovat zálohu nastavení","Export configuration":"Exportovat nastavení","Exporting ...":"Exportování…","External link":"Vnější odkaz","FTP (Alternative)":"FTP (alternativní)","Failed to build temporary database: {{message}}":"Nepodařilo se vytvořit dočasnou databázi: {{message}}","Failed to connect:":"Nepodařilo se připojit:","Failed to connect: {{message}}":"Nepodařilo se připojit: {{message}}","Failed to delete:":"Nepodařilo se smazat:","Failed to fetch path information: {{message}}":"Nepodařilo se stáhnout informaci o popisu umístění: {{message}}","Failed to import:":"Nepodařilo se importovat:","Failed to read backup defaults:":"Nepodařilo se načíst výchozí parametry zálohy:","Failed to restore files: {{message}}":"Nepodařilo se obnovit soubory: {{message}}","Failed to save:":"Nepodařilo se uložit:","Fetching path information ...":"Získávání informací o popisu umístění…","File":"Soubor","Files larger than:":"Soubory větší než:","Filters":"Filtry","Finished!":"Dokončeno!","First run setup":"Úvodní nastavení při prvním spuštění","Folder":"Složka","Folder path":"Popis umístění složky","Fri":"Pá","GByte":"GB","GByte/s":"GB/s","GCS Project ID":"GCS identifikátor projektu","General":"Obecné","General backup settings":"Obecná nastavení zálohy","General options":"Obecné volby","Generate":"Vytvořit","Generate IAM access policy":"Vytvořit IAM zásady přístupu","Getting file versions ...":"Získávání verzí souboru…","Hidden files":"Skryté soubory","Hide":"Skrýt","Hide hidden folders":"Skrýt skryté složky","Home":"Domovská složka","Hours":"Hodin","How do you want to handle existing files?":"Jak chcete zacházet s existujícími soubory?","Hyper-V Machine":"Hyper-V stroj","Hyper-V Machine:":"Hyper-V stroj:","Hyper-V Machines":"Hyper-V stroje","ID:":"Identifikátor:","If a date was missed, the job will run as soon as possible.":"Pokud chybělo datum, úloha bude spuštěna co možná nejdříve.","If at least one newer backup is found, all backups older than this date are deleted.":"Pokud je nalezena alespoň jedna novější záloha, všechny zálohy starší než tento datum budou smazány.","If the backup and the remote storage is out of sync, Duplicati will require that you perform a repair operation to synchronize the database.\\nIf the repair is unsuccesful, you can delete the local database and re-generate.":"Pokud záloha a vzdálené úložiště ztratí synchronizaci, Duplicati bude potřebovat abyste provedli operaci opravy a databáze se synchronizovala.\\nPokud oprava nebude úspěšná, je možné smazat místní databázi a nechat ji znovu vytvořit.","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"Pokud soubor se zálohou nebyl stažen automaticky, klikněte pravým tlačítkem a zvolte „Uložit jako…“;","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"Pokud soubor se zálohou nebyl stažen automaticky, klikněte pravým tlačítkem a zvolte „Uložit jako…“;","If you do not enter a path, all files will be stored in the login folder.\nAre you sure this is what you want?":"Pokud nezadáte popis umístění, všechny soubory budou uloženy v přihlašovací složce.\nJe to to, co chcete?","If you do not enter an API Key, the tenant name is required":"Pokud nezadáte klíč k API, je vyžadováno jméno nájemníka (tenant)","If you want to use the backup later, you can export the configuration before deleting it":"Pokud zálohu chcete použít později, můžete exportovat nastavení než jí smažete","If your machine is in a multi-user environment (i.e. the machine has more than one account), you need to set a password to prevent other users from accessing data on your account.\nDo you want to set a password now?":"Pokud je stroj používán vícero uživateli (tj. je na něm více než jeden uživatelský účet), je třeba nastavit heslo, které ostatním uživatelům brání v přístupu k datům ve vašem účtu.\nNastavit heslo nyní?","Import":"Import","Import Destination URL":"Importovat URL adresu cíle","Import backup configuration":"Importovat nastavení zálohy","Import completed, but no certificates were found after the import":"Import dokončen, ale nebyly po něm nalezeny žádné certifikáty","Import failed":"Import se nezdařil","Import from a file":"Importovat ze souboru","Import metadata":"Importovat metadata","Importing ...":"Importování…","Include a file?":"Zahrnout soubor?","Include expression":"Výraz pro zahrnutí","Include regular expression":"Regulární výraz pro zahrnutí","Incorrect answer, try again":"Nesprávná odpověď, zkuste to znovu","Individual builds for developers only.":"Jednotlivá sestavení pouze pro vývojáře.","Information":"Informace","Install":"Nainstalovat","Install failed:":"Instalace se nezdařila:","Invalid characters in path":"Neplatné znaky v popisu umístění","Invalid retention time":"Neplatná doba ponechání","It is possible to connect to some FTP without a password.\nAre you sure your FTP server supports password-less logins?":"K některým FTP serverům je možné se připojit i bez hesla.\nOpravdu to tento FTP server umožňuje?","KByte":"KB","KByte/s":"KB/s","Keep a specific number of backups":"Ponechat konkrétní počet záloh","Keep all backups":"Ponechat všechny zálohy","Language in user interface":"Jazyk textů v uživatelském rozhraní","Last month":"Minulý měsíc","Last successful run:":"Poslední úspěšný běh:","Latest":"Poslední","Libraries":"Knihovny","Linux":"GNU/Linux","Listing backup dates ...":"Vypisování datumů záloh…","Listing remote files ...":"Vypisování vzdálených souborů…","Live":"Aktuální","Load a configuration from an exported job or a storage provider":"Načíst nastavení z exportované úlohy nebo z poskytovatele úložiště","Load destination from an exported job or a storage provider":"Načíst cíl z exportované úlohy nebo poskytovatele úložiště","Load older data":"Načíst starší data","Loading ...":"Načítání…","Loading remote storage usage ...":"Načítání údajů o využití vzdáleného úložiště…","Local Repository":"Místní repozitář","Local database for":"Místní databáze pro","Local database path:":"Popis umístění místní databáze:","Local repository":"Místní repozitář","Local storage":"Místní úložiště","Location":"Umístění","Location where buckets are created":"Umístění ve kterém jsou „nádoby“ (bucket) vytvářeny","Log data for {{Backup.Backup.Name}}":"Zaznamenávat (log) údaje pro {{Backup.Backup.Name}}","Log data from the server":"Zaznamenávat data ze serveru","Log out":"Odhlásit se","MByte":"MB","MByte/s":"MB/s","Maintenance":"Údržba","Manually type path":"Zadejte popis umístění ručně","Max download speed":"Nejvyšší rychlost stahování","Max upload speed":"Nejvyšší rychlost odesílání","Menu":"Nabídka","Microsoft SQL Database:":"Databáze Microsoft SQL:","Microsoft SQL Databases":"Databáze Microsoft SQL","Minimum redundancy":"Minimální redundance","Minimum redundancy is 1.0":"Minimální redundance je 1.0","Minutes":"Minut","Missing name":"Chybějící název","Missing passphrase":"Chybějící heslová fráze","Missing sources":"Chybějící zdroje","Mon":"Po","Months":"Měsíců","Move existing database":"Přesunout existující databázi","Move failed:":"Přesun se nezdařil:","My Documents":"Moje dokumenty","My Music":"Hudba","My Photos":"Fotografie","My Pictures":"Obrázky","Name":"Název","Never":"Nikdy","New update found: {{message}}":"Nalezena nová aktualizace: {{message}}","New user name is {{user}}.\nUpdated credentials to use the new limited user":"Nové uživatelské jméno je {{user}}.\nAktualizované přihlašovací údaje které použít pro uživatele s omezenými přístupovými právy","Next":"Další","Next scheduled run:":"Příští naplánované spuštění:","Next scheduled task:":"Příští naplánovaná úloha:","Next task:":"Příští úloha:","Next time":"Příště","No":"Ne","No certificate was specified previously, please verify with the server administrator that the key is correct: {{key}} \n\nDo you want to approve the reported host key?":"Předtím nebyl určen žádný certifikát, ověřte se správcem serveru že klíč je správný: {{key}}\n\nSchvalujete tento klíč stroje?","No editor found for the "{{backend}}" storage type":"Nebyl nalezen žádný editor pro typ úložiště „{{backend}}“","No encryption":"Nešifrovat","No items selected":"Nejsou vybrané žádné položky","No items to restore, please select one or more items":"Žádné položky pro obnovení – vyberte alespoň jednu","No passphrase entered":"Není zadaná žádná heslová fráze","No scheduled tasks":"Žádné naplánované úlohy","No, my machine has only a single account":"Ne, na mém stroji je pouze jediný uživatelský účet","Non-matching passphrase":"Zadání heslové fráze se neshodují","None / disabled":"Žádné / vypnuté","Nothing will be deleted. The backup size will grow with each change.":"Nic nebude smazáno. Velikost zálohy naroste při každé změně.","OK":"OK","OSX":"Apple macOS","Once there are more backups than the specified number, the oldest backups are deleted.":"Jakmile je zde více záloh než zadané číslo, nejstarší zálohy budou smazané.","OpenStack AuthURI":"AuthURI pro OpenStack","OpenStack Object Storage / Swift":"Objektové úložiště OpenStack (Swift)","Operation failed:":"Operace se nezdařila:","Operations:":"Operace:","Optional authentication password":"Volitelné ověřovací heslo","Optional authentication username":"Volitelné uživatelské jméno pro ověření","Options":"Předvolby","Options added here are applied to all backups, but can be overridden in each individual backup":"Zde přidané volby jsou použity na všechny zálohy, ale je možné je přepsat v nastavení jednotlivých záloh","Original location":"Původní umístění","Others":"Ostatní","Over time backups will be deleted automatically. There will remain one backup for each of the last 7 days, each of the last 4 weeks, each of the last 12 months. There will always be at least one remaining backup.":"Po čase jsou zálohy automaticky odmazávány. Bude udržována jedna záloha z každého dne za minulých 7 dnů, jedna z každého týdne za minulé 4 týdny a jedna z každého měsíce za minulých 12 měsíců. A vždy zde bude přinejmenším jedna ponechaná záloha.","Overwrite":"Přepsat","Passphrase":"Heslová fráze","Passphrase (if encrypted)":"Heslová fráze (v případě, že je použito šifrování)","Passphrase changed":"Heslová fráze změněna","Passphrases are not matching":"Zadání heslové fráze se neshodují","Password":"Heslo","Passwords do not match":"Zadání hesla se neshodují","Patching files with local blocks ...":"Opravování souborů pomocí místních bloků…","Path not found":"Umístění nenalezeno","Path on server":"Popis umístění na serveru","Path or subfolder in the bucket":"Umístění nebo podsložka v „nádobě“ (bucket)","Pause":"Pozastavit","Pause after startup or hibernation":"Pozastavit po spuštění nebo hibernaci","Pause options":"Předvolby pozastavení","Permissions":"Přístupová práva","Pick location":"Vyberte umístění","Point to your backup files and restore from there":"Nasměrujte na soubory se zálohou a obnovte odsud","Port":"Port","Previous":"Předchozí","ProjectID is optional if the bucket exist":"Pokud „nádoba“ (bucket) existuje, je identifikátor projektu (ProjectID) nepovinný","Proprietary":"Proprietární","Purging files ...":"Trvalé vymazávání souborů…","Rebuilding local database ...":"Znovuvytváření místní databáze…","Recreate (delete and repair)":"Vytvořit znovu (smazat a opravit)","Recreating database ...":"Znovuvytváření databáze…","Registering temporary backup ...":"Registrace dočasné zálohy…","Relative paths not allowed":"Vztažené (relativní) popisy umístění není možné použít","Reload":"Načíst znovu","Remote":"Vzdálené","Remote Path":"Vzdálené umístění","Remote Repository":"Vzdálený repozitář","Remote path":"Vzdálené umístění","Remote repository":"Vzdálený repozitář","Remove":"Odebrat","Remove option":"Odebrat volbu","Repair":"Opravit","Reparing ...":"Opravování…","Repeat Passphrase":"Zopakování heslové fráze","Reporting:":"Hlášení:","Reset":"Resetovat","Restore":"Obnovit","Restore files":"Obnovit soubory","Restore files ...":"Obnovit soubory…","Restore files from {{backupname}}":"Obnovit soubory z {{backupname}}","Restore from":"Obnovit z","Restore from backup configuration":"Obnovit nastavení ze zálohy","Restore from configuration ...":"Obnovit z nastavení…","Restore options":"Volby obnovení","Restore read/write permissions":"Obnovit práva pro čtení/zápis","Restoring files ...":"Obnovování souborů…","Resume":"Pokračovat","Run again every":"Spustit znovu každou","Run now":"Spustit nyní","Running ...":"Spuštěné…","Running ....":"Spuštěné…","Running commandline entry":"Spuštěná položka příkazového řádku","Running task:":"Spuštěná úloha:","S3 Compatible":"Kompatibilní s S3","Same as the base install version: {{channelname}}":"Stejné jako základní nainstalovaná verze: {{channelname}}","Sat":"So","Save":"Uložit","Save and repair":"Uložit a opravit","Save different versions with timestamp in file name":"Uložit různé verze odlišené časovou značkou v názvu souboru","Save immediately":"Okamžitě uložit","Scanning existing files ...":"Skenování existujících souborů…","Scanning for local blocks ...":"Skenování místních bloků…","Schedule":"Plán","Search":"Hledat","Search for files":"Hledat soubory","Seconds":"Sekund","Select a log level and see messages as they happen:":"Vyberte úroveň podrobnosti zaznamenávaných událostí a sledujte zprávy:","Select files":"Vybrat soubory","Server":"Server","Server and port":"Server a port","Server hostname or IP":"Název nebo IP adresa serveru","Server is currently paused,":"Server je nyní pozastavený,","Server is currently paused, do you want to resume now?":"Server je nyní pozastavený, chcete ho nyní znovu spustit?","Server password":"Heslo serveru","Server paused":"Server pozastaven","Server state properties":"Vlastnosti stavu serveru","Settings":"Nastavení","Show":"Zobrazit","Show advanced editor":"Zobrazit pokročilý editor","Show hidden folders":"Zobrazit skryté složky","Show log":"Zobrazit záznam událostí (log)","Show log ...":"Zobrazit záznam událostí (log)…","Show treeview":"Zobrazit stromový pohled","Sia server password":"Heslo Sia serveru","Smart backup retention":"Chytrá doba uchovávání záloh","Some OpenStack providers allow an API key instead of a password and tenant name":"Někteří poskytovatelé OpenStack umožňují použití klíče k API namísto hesla a jména nájemníka (tenant)","Source Data":"Zdrojová data","Source data":"Zdrojová data","Source folders":"Zdrojové složky","Source:":"Zdroj:","Specific builds for developers only.":"Konkrétní sestavení pouze pro vývojáře.","Standard protocols":"Standardní protokoly","Starting ...":"Spouštění…","Starting the restore process ...":"Spouštění procesu obnovení…","Stop after the current file":"Zastavit po stávajícím souboru","Stop after upload":"Zastavit po nahrání","Stop now":"Zastavit nyní","Stop running backup":"Zastavit probíhající zálohu","Stop running task":"Zastavit probíhající úlohu","Stopping after upload:":"Zastavování po nahrávání:","Stopping task:":"Zastavování úlohy:","Storage Type":"Typ úložiště","Storage class":"Třída úložiště","Storage class for creating a bucket":"Třída úložiště pro vytváření „nádoby“ (bucket)","Stored":"Uloženo","Strong":"Silné","Success":"Úspěch","Sun":"Ne","Symbolic link":"Symbolický odkaz","System default ({{levelname}})":"Systémové výchozí ({{levelname}})","System files":"Systémové soubory","System info":"Informace o systému","System properties":"Vlastnosti systému","TByte":"TB","TByte/s":"TB/s","Target path, ie /backup":"Popis umístění cíle, tj. /zaloha","Task is running":"Úloha je spuštěná","Temporary files":"Dočasné soubory","Tenant Name":"Jméno nájemníka (tenant)","Test connection":"Vyzkoušet spojení","Testing ...":"Testování…","Testing connection ...":"Zkouška spojení…","Testing permissions ...":"Zkouška přístupových práv…","Testing permissions...":"Zkouška přístupových práv…","The bucket name should be all lower-case, convert automatically?":"Název nádoby by měl být malými písmeny, převést automaticky?","The bucket name should start with your username, prepend automatically?":"Název „nádoby“ (bucket) by měl začínat vaším uživatelským jménem – předřadit automaticky?","The connection to the server is lost, attempting again in {{time}} ...":"Spojení se serverem ztraceno, opětovný pokus za {{time}}…","The dark theme (by Michal)":"Tmavé téma vzhledu (od Michala)","The default blue on white theme (by Alex)":"Výchozí téma vzhledu modrá na bílé (od Alexe)","The folder {{folder}} does not exist.\nCreate it now?":"Složka {{folder}} neesxistuje.\nVytvořit nyní?","The host key has changed, please check with the server administrator if this is correct, otherwise you could be the victim of a MAN-IN-THE-MIDDLE attack.\n\nDo you want to REPLACE your CURRENT host key \"{{prev}}\" with the REPORTED host key: {{key}}?":"Klíč stroje se změnil, zkontrolujte se správcem serveru zda je správný, protože byste mohli být obětí útoku typu člověk uprostřed (man-in-the-midle).\n\nChcete NAHRADIT STÁVAJÍCÍ klíč stroje \"{{prev}}\" NAHLÁŠENÝM klíčem stroje: {{key}}?","The path does not appear to exist, do you want to add it anyway?":"Popisované umístění zdá se neexistuje, přejete si ho přidat i tak?","The path does not end with a '{{dirsep}}' character, which means that you include a file, not a folder.\n\nDo you want to include the specified file?":"Dané umístění nekončí na znak „{{dirsep}}“, což znamená, že jste zahrnuli soubor, ne složku.\n\nChcete zahrnout daný soubor?","The path must be an absolute path, i.e. it must start with a forward slash '/'":"Je třeba, aby se jednalo o úplný popis umístění, tj. aby začínal dopředným lomítkem „/“","The path should start with \"{{prefix1}}\" or \"{{prefix2}}\", otherwise you will not be able to see the files in the HubiC web interface.\n\nDo you want to add the prefix to the path automatically?":"Popis umístění by měl začínat na „{{prefix1}}“ nebo „{{prefix2}}“, jinak soubory neuvidíte ve webovém rozhraní HubiC.\n\nChcete přidat předponu k popisu umístění automaticky?","The region parameter is only applied when creating a new bucket":"Parametr region je použit pouze při vytváření nové „nádoby“ (bucket)","The region parameter is only used when creating a bucket":"Parametr region je použit pouze při vytváření „nádoby“ (bucket)","The server certificate could not be validated.\nDo you want to approve the SSL certificate with the hash: {{hash}}?":"Certifikát serveru se nepodařilo ověřit.\nChcete schválit SSL certifikát s otiskem: {{hash}}?","The storage class affects the availability and price for a stored file":"Třída úložiště ovlivňuje dostupnost a cenu za uložení souboru","The target folder contains encrypted files, please supply the passphrase":"Cílová složka obsahuje zašifrované soubory, zadejte heslovou frázi","The user has too many permissions. Do you want to create a new limited user, with only permissions to the selected path?":"Uživatel má příliš vysoká přístupová práva. Chcete vytvořit nového uživatele s právy omezenými pouze na vybraný popis umístění?","This backup was created on another operating system. Restoring files without specifying a destination folder can cause files to be restored in unexpected places. Are you sure you want to continue without choosing a destination folder?":"Tato záloha byla vytvořena na jiném operačním systému. Obnovení souborů bez zadání cílové složky může způsobit, že soubory budou obnoveny do neočekávaných míst. Opravdu chcete pokračovat bez zvolení cílové složky?","This month":"Tento měsíc","This week":"Tento týden","Throttle settings":"Nastavení přiškrcování","Thu":"Čt","To File":"Do soubour","To confirm you want to delete all remote files for \"{{name}}\", please enter the word you see below":"Svůj úmysl smazat všechny vzdálené soubory pro „{{name}}“ potvrďte opsáním níže uvedeného slova ","To export without a passphrase, uncheck the \"Encrypt file\" box":"Pro exportování bez heslové fráze odškrtněte „Šifrovat soubor“","Today":"Út","Trust host certificate?":"Důvěřovat certifikátu stroje?","Trust server certificate?":"Důvěřovat certifikátu serveru?","Try out the new features we are working on. Don't use with important data.":"Vyzkoušejte nové funkce na kterých pracujeme. Nepoužívejte pro důležitá data.","Tue":"Út","Type to highlight files":"Soubory zvýrazňujte psaním","Unknown backup size and versions":"Neznámá velikost a verze databáze","Until resumed":"Dokud není pokračováno","Update channel":"Aktualizační kanál","Update failed:":"Aktualizace se nezdařila:","Updating with existing database":"Aktualizace se stávající databází","Upload volume size":"Velikost nahrávaného svazku","Uploading verification file ...":"Nahrávání ověřovacího souboru…","Usage reports help us improve the user experience and evaluate impact of new features. We use them to generate public usage statistics":"Hlášení o využití pomáhá vývojářům zlepšovat dojem z používání a vyhodnocovat dopad nových funkcí. Slouží k vytváření anonymizovaných veřejných statistik využívání","Usage statistics":"Statistiky využití","Usage statistics, warnings, errors, and crashes":"Statistiky využití, varování, chyby a pády","Use SSL":"Použít SSL","Use existing database?":"Použít existující databázi?","Use weak passphrase":"Použít slabou heslovou frázi","Useless":"Nepoužitelné","User data":"Uživatelská data","User has too many permissions":"Uživatel má příliš mnoho oprávnění","User interface settings":"Nastavení uživatelského rozhraní","Username":"Uživatelské jméno","Validating ...":"Ověřování…","Verify files":"Ověřit soubory","Verifying ...":"Ověřování…","Verifying answer":"Ověřování odpovědi","Verifying backend data ...":"Ověřování dat podpůrné vrstvy (backend)…","Verifying remote data ...":"Ověřování vzdálených dat…","Verifying restored files ...":"Ověřování obnovených souborů…","Very strong":"Velmi silné","Very weak":"Velmi slabé","Visit us on":"Navštivte nás na","WARNING: The remote database is found to be in use by the commandline library":"VAROVÁNÍ: bylo zjištěno, že vzdálená databáze je používána knihovnou pro příkazový řádek","WARNING: This will prevent you from restoring the data in the future.":"VAROVÁNÍ: toto zabrání v budoucnu obnovovat data!","Waiting for task to begin":"Čekání na zahájení úlohy","Waiting for task to start ....":"Čekání na zahájení úlohy…","Waiting for upload ...":"Čekání na nahrání…","Warnings, errors and crashes":"Varování, chyby a pády","We accept donations via different services, such as OpenCollective, PayPal, BountySource and various crypto currencies.":"Přijímáme dary prostřednictvím různých služeb, jako například OpenCollective, PayPal, BountySource a různé kryptoměny.","We recommend that you encrypt all backups stored outside your system":"Doporučujeme šifrovat všechny zálohy, které jsou ukládány mimo váš stroj","Weak":"Slabé","Weak passphrase":"Slabá heslová fráze","Wed":"St","Weeks":"Týdny","Where do you want to restore from?":"Odkud chcete obnovit?","Where do you want to restore the files to?":"Kam chcete soubory obnovit?","Windows":"MS Windows","Years":"Let","Yes":"Ano","Yes, I have stored the passphrase safely":"Ano, heslovou frázi mám bezpečně uloženou","Yes, I'm brave!":"Ano, mám odvahu!","Yes, please break my backup!":"Ano, chci rozbít své zálohy!","Yesterday":"Včera","You appear to be running Mono with no SSL certificates loaded.\nDo you want to import the list of trusted certificates from Mozilla?":"Zdá se, že provozujete Mono bez načtených SSL certifikátů.\nChcete importovat seznam důvěryhodných certifikátů z Mozilla?","You are changing the database path away from an existing database.\nAre you sure this is what you want?":"Měníte umístění databáze pryč z existující databáze.\nOpravdu je to to, co chcete?","You are currently running {{appname}} {{version}}":"Nyní provozujete {{appname}} {{version}}","You can stop the backup immediately, or stop after the current file has been uploaded.":"Zálohu můžete zastavit buď teď hned, nebo po dokončení probíhajícího nahrávání souboru.","You can stop the task immediately, or allow the process to continue its current file and the stop.":"Úlohu můžete ukončit buď teď hned, nebo procesu umožnit zpracovat stávající soubor a pak zastavit.","You have changed the encryption mode. This may break stuff. You are encouraged to create a new backup instead":"Změnili jste režim šifrování. To může něco rozbít. Doporučujeme namísto toho vytvořit novou zálohu","You have changed the passphrase, which is not supported. You are encouraged to create a new backup instead.":"Změnili jste heslovou frázi, což není podporováno. Doporučujeme namísto toho vytvořit novou zálohu.","You have chosen not to encrypt the backup. Encryption is recommended for all data stored on a remote server.":"Zvolili jste že záloha nebude šifrována. Šifrování je doporučeno pro veškerá data ukládaná na vzdálený server.","You have chosen to restore to a new location, but not entered one":"Zvolili jste obnovu do nového umístění, ale nezadali jste ho","You have generated a strong passphrase. Make sure you have made a safe copy of the passphrase, as the data cannot be recovered if you lose the passphrase.":"Vytvořili jste odolnou heslovou frázi. Tu si dobře uschovejte, protože v případě její ztráty data nebude možné obnovit.","You must choose at least one source folder":"Je třeba zvolit alespoň jednu zdrojovou složku","You must enter a name for the backup":"Je třeba zadat název zálohy","You must enter a passphrase or disable encryption":"Buď je třeba zadat heslovou frázi nebo šifrování vypnout","You must enter a positive number of backups to keep":"Je třeba zadat kladný počet záloh které uchovávat","You must enter a tenant name if you do not provide an API Key":"Pokud nezadáte klíč k API, je třeba zadat jméno nájemníka (tenant)","You must enter a valid duration for the time to keep backups":"Je třeba zadat platnou dobu po kterou ponechávat zálohy","You must enter a valid rentention policy string":"Je třeba zadat platný řetězec zásady doby uchovávání záloh","You must enter either a password or an API Key":"Je třeba zadat buď klíč k API nebo heslo","You must enter either a password or an API Key, not both":"Je třeba zadat buď heslo, nebo klíč k API – ne obojí naráz","You must fill in the password":"Je třeba vyplnit heslo","You must fill in the server name or address":"Je třeba vyplnit název nebo adresu serveru","You must fill in the username":"Je třeba vyplnit uživatelské jméno","You must fill in {{field}}":"Je třeba vyplnit kolonku {{field}}","You must select or fill in the AuthURI":"Je třeba vybrat nebo vyplnit AuthURI","You must select or fill in the server":"Je třeba vybrat nebo vyplnit server","You must specify a path":"Je třeba zadat popis umístění","Your files and folders have been restored successfully.":"Soubory a složky byly úspěšně obnoveny.","Your passphrase is easy to guess. Consider changing passphrase.":"Vaše heslová fráze je snadno uhodnutelná. Zvažte volbu jiné.","bucket/folder/subfolder":"nadoba/slozka/podslozka","byte":"B","byte/s":"B/s","custom":"vlastní","resume now":"pokračovat nyní","{{appname}} was primarily developed by {{dev1}} and {{dev2}}. {{appname}} can be downloaded from {{websitename}}. {{appname}} is licensed under the {{licensename}}.":"{{appname}} bylo vyvynuto hlavně {{dev1}} a {{dev2}}. {{appname}} je možné si stáhnout z {{websitename}}. {{appname}} je šířeno pod licencí {{licensename}}.","{{files}} files ({{size}}) to go {{speed_txt}}":"{{files}} souborů ({{size}}) zbývá {{speed_txt}}","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Version":["{{item.Backup.Metadata.TargetSizeString}} / {{$count}} verze","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} verze","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} verzí"],"{{number}} Hour":"{{number}} hodin","{{number}} Minutes":"{{number}} minut","{{time}} (took {{duration}})":"{{time}} (trvalo {{duration}})"}); + gettextCatalog.setStrings('da', {"- pick an option -":"- vælg indstilling -","...loading...":"...indlæser...","API Key":"API Key","AWS Access ID":"AWS Access ID","AWS Access Key":"AWS Access Key","AWS IAM Policy":"AWS IAM Policy","About":"Om","About {{appname}}":"Om {{appname}}","Access Key":"Access Key","Access denied":"Adgang nægtet","Access to user interface":"Adgang til brugerinterface","Account name":"Konto navn","Activate":"Aktiver","Activate failed:":"Aktivering fejlede:","Add a new backup":"Tilføj en ny backup","Add a path directly":"Tilføj en sti","Add advanced option":"Tilføj en avanceret indstilling","Add backup":"Tilføj backup","Add filter":"Tilføj filter","Add path":"Tilføj sti","Adjust bucket name?":"Tilpas bucket navnet?","Adjust path name?":"Juster stien?","Advanced Options":"Avancerede indstillinger","Advanced options":"Avancerede indstillinger","Advanced:":"Avanceret:","All":"Alle","All Hyper-V Machines":"Alle Hyper-V maskiner","All Microsoft SQL Databases":"Alle Microsoft SQL databaser","All usage reports are sent anonymously and do not contain any personal information. They contain information about hardware and operating system, the type of backend, backup duration, overall size of source data and similar data. They do not contain paths, filenames, usernames, passwords or similar sensitive information.":"Alle brugs rapporter bliver sendt anonymt og indeholder ikke personlige oplysninger. De indeholder oplysninger om hardware, operativsystem, destinationstype, backup varighed, backup størrelse og lignende information. De indeholder ikke stier, filnavne, brugernavne, kodeord eller lignende følsom information.","Allow remote access (requires restart)":"Tillad fjernadgang (kræver genstart)","Allowed days":"Tilladte dage","An existing file was found at the new location":"En eksisterende fil blev fundet på den nye placering","An existing file was found at the new location\nAre you sure you want the database to point to an existing file?":"En eksisterende fil blev funder på den nye placering.\nEr du sikker på at du vil have databasen til at pege på en eksisterende fil?","An existing local database for the storage has been found.\nRe-using the database will allow the command-line and server instances to work on the same remote storage.\n\n Do you wish to use the existing database?":"En eksisterende lokal database for destinationen er fundet.\nHvis du genbruger databasen, kan du bruge både kommandolinie og serveren til at arbejde på samme destination.\n\nVil du bruge den eksisterende database?","Anonymous usage reports":"Anonyme brugsstatistiker","As Command-line":"Som kommandolinie","AuthID":"AuthID","Authentication password":"Kodeord til godkendelse","Authentication username":"Brugernavn til godkendelse","Autogenerated passphrase":"Autogenereret kodeord","Automatically run backups.":"Kør backups automatisk","B2 Account ID":"B2 Account ID","B2 Application Key":"B2 Application Key","B2 Cloud Storage Account ID":"B2 Cloud Storage Account ID","B2 Cloud Storage Application Key":"B2 Cloud Storage Application Key","Back":"Tilbage","Backend modules:":"Backend moduler:","Backup destination":"Backup destination","Backup location":"Backup placering","Backup:":"Backup:","Beta":"Beta","Broken access":"Adgang defekt","Browse":"Gennemse","Browser default":"Browser standard","Bucket Name":"Bucket navn","Bucket create location":"Bucket placering ved oprettelse","Bucket create region":"Bucket region ved oprettelse","Bucket name":"Bucket navn","Bucket storage class":"Bucket storage class","Building list of files to restore ...":"Bygger liste af filer til gendannelse ...","Building partial temporary database ...":"Bygger en midlertidig database ...","Busy ...":"Optaget ...","Canary":"Canary","Cancel":"Annuller","Cannot move to existing file":"Kan ikke flytte til eksisterende fil","Changelog":"Ændringslog","Changelog for {{appname}} {{version}}":"Ændringslog for {{appname}} {{version}}","Check failed:":"Kontrol fejlede:","Check for updates now":"Tjek for opdateringer nu","Checking ...":"Kontrollerer ...","Checking for updates ...":"Leder efter opdateringer...","Chose a storage type to get started":"Valgte en destinationstype at komme i gang","Click the AuthID link to create an AuthID":"Click på AuthID linket for at oprettet et AuthID","Click to set throttle options":"Klik for at sætte hastigheds begrænsning","Commandline ...":"Kommandolinie ...","Compact now":"Komprimer nu","Compacting remote data ...":"Komprimerer data på destinationen ...","Completing backup ...":"Fuldfører backup ...","Completing previous backup ...":"Fuldfører forrige backup ...","Compression modules:":"Kompressions moduler:","Computer":"Computer","Configuration file:":"Konfigurationsfil:","Configuration:":"Konfiguration:","Configure a new backup":"Indstil en ny backup","Confirm delete":"Bekræft sletning","Confirmation required":"Bekræftelse kræves","Connect":"Forbind","Connect now":"Forbind nu","Connecting to server ...":"Forbinder til server ...","Connecting to task ....":"Forbinder til opgave ...","Connecting...":"Forbinder ...","Connection lost":"Forbindelse mistet","Connection worked!":"Forbindelsen virkede!","Container name":"Container navn","Container region":"Container region","Continue":"Fortsæt","Continue without encryption":"Fortsæt uden kryptering","Copied!":"Kopieret!","Copy":"Kopier","Copy Destination URL to Clipboard":"Kopier URL-destinationsadressen til udklipsholder","Copy failed. Please manually copy the URL":"Kopiering mislykkedes. Kopier venligst URL-adressen manuelt","Core options":"Grund indstillinger","Counting ({{files}} files found, {{size}})":"Tæller ({{files}} filer fundet, {{size}})","Crashes only":"Kun nedbrud","Create bug report ...":"Opret fejlrapport ...","Create folder?":"Opret mappe?","Created new limited user":"Opret en ny begrænset bruger","Creating bug report ...":"Opretter fejlrapport ...","Creating new user with limited access ...":"Opretter en ny bruger med begrænset adgang ...","Creating target folders ...":"Opretter destinations mapper ...","Creating temporary backup ...":"Opretter en midlertidig backup ...","Creating user...":"Opretter bruger ...","Current version is {{versionname}} ({{versionnumber}})":"Nuværende version er {{versionname}} ({{versionnumber}})","Custom S3 endpoint":"Brugerdefineret S3 endpoint","Custom authentication url":"Brugerdefineret godkendelses url","Custom location ({{server}})":"Brugerdefineret placering ({{server}})","Custom region for creating buckets":"Brugerdefineret region for at oprette buckets","Custom region value ({{region}})":"Brugerdefineret regions værdi ({{region}})","Custom server url ({{server}})":"Brugerdefineret server url ({{server}})","Custom storage class ({{class}})":"Brugerdefineret storage class ({{klasse}})","Database ...":"Database ...","Days":"Dage","Default":"Standard","Default ({{channelname}})":"Standard ({{channelname}})","Default Filters":"Standard filtre","Default options":"Standardindstillinger","Delete":"Slet","Delete ...":"Slet ...","Delete backup":"Slet backup","Delete backups that are older than":"Slet sikkerhedskopier, der er ældre end","Delete local database":"Slet lokal database","Delete remote files":"Slette filer fra destinationen","Delete the local database":"Slet den lokale database","Delete {{filecount}} files ({{filesize}}) from the remote storage?":"Slet {{filecount}} filer ({{filesize}}) fra destinationen?","Deleting remote files ...":"Sletter filer fra destinationen ...","Deleting unwanted files ...":"Sletter uønskede filer ...","Desktop":"Skrivebord","Destination":"Destination","Did we help save your files? If so, please consider supporting Duplicati with a donation. We suggest {{smallamount}} for private use and {{largeamount}} for commercial use.":"Hjalp vi med at redde dine filer? Du kan overveje at støtte Duplicati med en donation. Vi foreslår {{smallamount}} ved privat brug og {{largeamount}} ved kommerciel brug.","Direct restore from backup files ...":"Direkte gendannelse fra backup filer ...","Disabled":"Deaktiveret","Dismiss":"Afvis","Display and color theme":"Visning og farvevalg","Do you really want to delete the backup: \"{{name}}\" ?":"Vil du virkelig slette backupen: \"{{name}}\"?","Do you really want to delete the local database for: {{name}}":"Vil du virkelig slette den lokale database for: {{navn}}","Donate":"Donér","Donation messages":"Donations beskeder","Donation messages are hidden, click to show":"Donations beskeder er skjult, klik for at vise","Donation messages are visible, click to hide":"Donation beskeder er synlige, klik for at skjule","Done":"Færdig","Download":"Download","Downloading ...":"Downloader ...","Downloading files ...":"Downloader filer ...","Downloading update...":"Downloader opdatering ...","Duplicate option {{opt}}":"Dublet af indstilling {{opt}}","Duplicati Website":"Duplicati hjemmeside","Duplicati forum":"Duplicati forum","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\n When deleting a backup, you can also delete the local database without affecting the ability to restore the remote files.\n If you are using the local database for backups from the commandline, you should keep the database.":"Hver backup har en lokal database tilknyttet, som gemmer information om data på fjerndestinationen lokalt på maskinen.\nNår du sletter en backup kan du også slette den lokale database uden at dette påvirker muligheden for at gendanne filer.\nHvis du bruger den lokale database til at køre backup via kommandolinien skal du beholde databasen.","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\\nThis makes it faster to perform many operations, and reduces the amount of data that needs to be downloaded for each operation.":"Hver backup har en lokal database forbundet, som gemmer oplysninger om destinationens filer på den lokale maskine. \\nDette gør det hurtigere at udføre mange operationer, og reducerer mængden af data, der skal hentes for hver operation.","Edit ...":"Rediger ...","Edit as list":"Rediger som liste","Edit as text":"Rediger som tekst","Encrypt file":"Krypter fil","Encryption":"Kryptering","Encryption changed":"Kryptering ændret","Encryption modules:":"Krypterings moduler:","Enter URL":"Indtast URL","Enter access key":"Indtast adgangsnøgle","Enter account name":"Indtast kontonavn","Enter backup passphrase, if any":"Indtast krypteringssætning, hvis krævet","Enter configuration details":"Indtast konfigurationsdetaljer","Enter container name":"Indtast container navn","Enter encryption passphrase":"Indtast krypteringssætning","Enter expression here":"Indtast udtryk her","Enter folder path name":"indtast mappe navn","Enter one option per line in command-line format, eg. {0}":"Indtast én indstilling per linie i kommandolinieformat, f.eks. {0}","Enter the destination path":"Indtast destinations stien","Error":"Fejl","Error!":"Fejl!","Errors and crashes":"Fejl og nedbrud","Exclude":"Eksludér","Exclude directories whose names contain":"Ekskluder mapper hvor navnet indeholder","Exclude expression":"Excluder udtryk","Exclude file":"Excluder fil","Exclude file extension":"Ekskluder filendelse","Exclude files whose names contain":"Ekskluder filer hvor navnet indeholder","Exclude folder":"Ekskluder mappe","Exclude regular expression":"Ekskluder regulært udtryk","Existing file found":"Eksisterende fil fundet","Experimental":"Eksperimental","Export":"Eksporter","Export ...":"Eksporter ...","Export backup configuration":"Eksporter backup konfiguration","Export configuration":"Eksporter konfiguration","Exporting ...":"Eksporterer ...","External link":"Eksternt link","FTP (Alternative)":"FTP (alternativ)","Failed to build temporary database: {{message}}":"Kunne ikke bygge midlertidig database: {{message}}","Failed to connect:":"Kunne ikke forbinde:","Failed to connect: {{message}}":"Kunne ikke forbinde: {{message}}","Failed to delete:":"Kunne ikke slette:","Failed to fetch path information: {{message}}":"Kunne ikke hente sti-information: {{message}}","Failed to import:":"Kunne ikke importere:","Failed to read backup defaults:":"Kunne ikke læse backup standardværdier:","Failed to restore files: {{message}}":"Kunne ikke gendanne filer: {{message}}","Failed to save:":"Kunne ikke gemme:","Fetching path information ...":"Henter information om stier ...","File":"Fil","Files larger than:":"Filer større end:","Filters":"Filtre","Finished!":"Færdig!","First run setup":"Førstegangsopsætning","Folder":"Mappe","Folder path":"Mappe sti","Fri":"Fre","GByte":"GByte","GByte/s":"GByte/s","GCS Project ID":"GCS Projekt ID","General":"Generelt","General backup settings":"Generelle backup indstillinger","General options":"Generelle indstillinger","Generate":"Generér","Generate IAM access policy":"Generér IAM access policy","Getting file versions ...":"Henter fil versioner ...","Hidden files":"Skjulte filer","Hide":"Skjul","Hide hidden folders":"Skjul skjulte filer","Home":"Hjem","Hours":"Timer","How do you want to handle existing files?":"Hvordan vil du håndtere eksisterende filer?","Hyper-V Machine":"Hyper-V maskine","Hyper-V Machine:":"Hyper-V maskine:","Hyper-V Machines":"Hyper-V maskiner","ID:":"ID:","If a date was missed, the job will run as soon as possible.":"Hvis der ikke blev kørt på det angivne tidspunkt, vil jobbet køre så hurtigt som muligt.","If at least one newer backup is found, all backups older than this date are deleted.":"Hvis der findes mindst en nyere sikkerhedskopi, slettes alle backups, der er ældre end denne dato.","If the backup and the remote storage is out of sync, Duplicati will require that you perform a repair operation to synchronize the database.\\nIf the repair is unsuccesful, you can delete the local database and re-generate.":"Hvis backup og data på destinationen ikke er synkroniseret, vil Duplicati kræve at du kører en reparation for at synkronisere databasen.\\nHvis reparationen ikke lykkes kan du slette den lokale database og gendanne den.","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"Hvis backup filen ikke blev downloaded automatisk, så højreklik og vælg "Gem som... "","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"Hvis backup filen ikke blev downloaded automatisk, så højreklik og vælg "Gem som... "","If you do not enter a path, all files will be stored in the login folder.\nAre you sure this is what you want?":"Hvis du ikke indtaster en sti, vil alle filer blive gemt i login mappen.\nEr du sikke på at det er det du vil gøre?","If you do not enter an API Key, the tenant name is required":"Hvis du ikke indtaster en API key, skal du angive tenant navnet","If you want to use the backup later, you can export the configuration before deleting it":"Hvis du vil bruge din backup senere, kan du eksportere konfigurationen før du sletter den","If your machine is in a multi-user environment (i.e. the machine has more than one account), you need to set a password to prevent other users from accessing data on your account.\nDo you want to set a password now?":"Hvis flere personer bruger denne computer (med forskellig brugerkonti) bør du indstille et kodeord for at forhindre andre i at tilgå din data.\nVil du indstille et kodeord nu?","Import":"Importér","Import Destination URL":"Importer destinations URL","Import backup configuration":"Importer backup konfiguration","Import completed, but no certificates were found after the import":"Importen blev færdig, men der blev ikke funder certifikater efter importen","Import failed":"Importen fejlede","Import from a file":"Importer fra en fil","Import metadata":"Importer metadata","Importing ...":"Importerer ...","Include a file?":"Inkluder en fil?","Include expression":"Inkluder udtryk","Include regular expression":"Inkluder regulært udtryk","Incorrect answer, try again":"Forkert svar, prøv igen","Individual builds for developers only.":"Individuelle versioner for udviklere","Information":"Information","Install":"Installer","Install failed:":"Installationen fejlede:","Invalid characters in path":"Ugyldige tegn i stien","Invalid retention time":"Ugyldig bevaringstid","It is possible to connect to some FTP without a password.\nAre you sure your FTP server supports password-less logins?":"Det er muligt at oprette forbindelse til nogle FTP servere uden en adgangskode.\nEr du sikker på din FTP-server understøtter password-fri login?","KByte":"KByte","KByte/s":"KByte/s","Keep a specific number of backups":"Gem et bestemt antal backups","Keep all backups":"Gem alle backups","Language in user interface":"Sprog i brugergrænsefladen","Last month":"Sidste måned","Last successful run:":"Sidste succesfulde kørsel:","Latest":"Nyeste","Libraries":"Biblioteker","Linux":"Linux","Listing backup dates ...":"Henter backup datoer...","Listing remote files ...":"Henter filer fra destinationen ...","Live":"Live","Load a configuration from an exported job or a storage provider":"Indlæs konfiguration fra en eksporteret fil eller en pladsudbyder","Load destination from an exported job or a storage provider":"Indlæs destination fra en eksporteret fil eller en pladsudbyder","Load older data":"Indlæs ældre data","Loading ...":"Indlæser ...","Loading remote storage usage ...":"Indlæser forbrug fra fjerndestinationen ...","Local database for":"Lokal database for","Local database path:":"Lokal database sti:","Local storage":"Local opbevaring","Location":"Placering","Location where buckets are created":"Placering hvor buckets bliver oprettet","Log data for {{Backup.Backup.Name}}":"Logdata for {{Backup.Backup.Name}}","Log data from the server":"Logdata fra serveren","Log out":"Log ud","MByte":"MByte","MByte/s":"MByte/s","Maintenance":"Vedligehold","Manually type path":"Indtast en sti manuelt","Max download speed":"Max downloadhastighed","Max upload speed":"Maks uploadhastighed","Menu":"Menu","Microsoft SQL Database:":"Microsoft SQL Database:","Microsoft SQL Databases":"Microsoft SQL Databaser","Minimum redundancy":"Mindste tilladte redundans","Minimum redundancy is 1.0":"Mindste redundans er 1.0","Minutes":"Minutter","Missing name":"Navn mangler","Missing passphrase":"Kodesætning mangler","Missing sources":"Kilder mangler","Mon":"Man","Months":"Måneder","Move existing database":"Flyt eksisterende database","Move failed:":"Flytning fejlede:","My Documents":"Mine dokumenter","My Music":"Min musik","My Photos":"Mine foto","My Pictures":"Mine billeder","Name":"Navn","Never":"Aldrig","New update found: {{message}}":"Ny opdatering fundet: {{message}}","New user name is {{user}}.\nUpdated credentials to use the new limited user":"Nyt bruger navn er {{user}}.\nLoginoplysninger er opdateret til den nye begrænsede bruger","Next":"Næste","Next scheduled run:":"Næste planlagte kørsel:","Next scheduled task:":"Næste planlagte opgave:","Next task:":"Næste opgave:","Next time":"Næste tidspunkt","No":"Nej","No certificate was specified previously, please verify with the server administrator that the key is correct: {{key}} \n\nDo you want to approve the reported host key?":"Intet certifikat har været anvendt før, kontroller venligst at nøglen er korrekt hos serveradministratoren: {{key}} \n\nVil du godkende den angivne nøgle?","No editor found for the "{{backend}}" storage type":"Ingen editor blev fundet for "{{backend}}" destinationen","No encryption":"Ingen kryptering","No items selected":"Ingen emner valgt","No items to restore, please select one or more items":"Ingen emner er valgt til gendannelse, vælg venligst en eller flere emner","No passphrase entered":"Ingen adgangssætning angivet","No scheduled tasks":"Ingen planlagte opgaver","No, my machine has only a single account":"Nej, min computer har kun en brugerkonto","Non-matching passphrase":"Uoverenstemmelse mellem kodesætninger","None / disabled":"Ingen / deaktiveret","Nothing will be deleted. The backup size will grow with each change.":"Intet vil blive slettet. Backup størrelsen vokser med hver ændring.","OK":"OK","OSX":"OSX","Once there are more backups than the specified number, the oldest backups are deleted.":"Når der er flere backups end det angivne antal, slettes de ældste sikkerhedskopier.","OpenStack AuthURI":"OpenStack AuthURI","OpenStack Object Storage / Swift":"OpenStack Object Storage / Swift","Operation failed:":"Operation fejlede:","Operations:":"Operationer:","Optional authentication password":"Valgfrit kodeord til godkendelse","Optional authentication username":"Valgfrit brugernavn til godkendelse","Options":"Indstillinger","Options added here are applied to all backups, but can be overridden in each individual backup":"Indstilliger tilføjet here bliver anvendt på alle backups, men kan blive overskrevet individuelt på hver backup","Original location":"Oprindelig placering","Others":"Andre","Over time backups will be deleted automatically. There will remain one backup for each of the last 7 days, each of the last 4 weeks, each of the last 12 months. There will always be at least one remaining backup.":"Over tid vil backups blive slettet automatisk. Der vil forblive en backup for hver af de sidste 7 dage, hver af de sidste 4 uger, hver af de sidste 12 måneder. Der vil altid være mindst en tilbageværende backup.","Overwrite":"Overskriv","Passphrase":"Kodesætning","Passphrase (if encrypted)":"Kodesætning (hvis krypteret)","Passphrase changed":"Kodesætning ændret","Passphrases are not matching":"Kodesætninger er ikke ens","Password":"Kodeord","Passwords do not match":"Kodeord er ikke ens","Patching files with local blocks ...":"Opdaterer filer med lokale blokke ...","Path not found":"Stien blev ikke fundet","Path on server":"Sti på server","Path or subfolder in the bucket":"Sti eller undermappe i bucket","Pause":"Pause","Pause after startup or hibernation":"Pause efter start eller dvale","Pause options":"Pause indstillinger","Permissions":"Tilladelser","Pick location":"Vælg placering","Point to your backup files and restore from there":"Udpeg dine backup-filer og gendan fra dem","Port":"Port","Previous":"Forrige","ProjectID is optional if the bucket exist":"ProjectID er valgfrit hvis bucket eksisterer","Proprietary":"Proprietære","Purging files ...":"Fjerner filer ...","Rebuilding local database ...":"Genopbygger lokal database ...","Recreate (delete and repair)":"Gendan (slet og reparer)","Recreating database ...":"Gendanner database ...","Registering temporary backup ...":"Registrerer midlertidig backup ...","Relative paths not allowed":"Relative stier er ikke tilladt","Reload":"Genindlæs","Remote":"Destination","Remove":"Fjern","Remove option":"Fjern indstilling","Repair":"Reparer","Reparing ...":"Reparerer ...","Repeat Passphrase":"Gentag kodesætning","Reporting:":"Rapporterer:","Reset":"Nulstil","Restore":"Gendan","Restore files":"Gendan filer","Restore files ...":"Gendan filer ...","Restore files from {{backupname}}":"Gendan filer fra {{backupname}}","Restore from":"Gendan fra","Restore from backup configuration":"Gendan fra konfiguration i backup","Restore from configuration ...":"Gendan fra konfiguration ...","Restore options":"Indstillinger til gendannelse","Restore read/write permissions":"Gendan læse/skrive tilladelser","Restoring files ...":"Gendanner filer ...","Resume":"Genoptag","Run again every":"Kør igen hver","Run now":"Kør nu","Running ...":"Kører ...","Running ....":"Kører ...","Running commandline entry":"Kører kommandolinie opgave","Running task:":"Kørende opgave:","S3 Compatible":"S3 kompatibel","Same as the base install version: {{channelname}}":"Samme som grundinstallationsversionen: {{channelname}}","Sat":"Lør","Save":"Gem","Save and repair":"Gem og reparer","Save different versions with timestamp in file name":"Gem forskellige versioner med tidstempel i filnavnet","Save immediately":"Gem med det samme","Scanning existing files ...":"Skanner eksisterende filer ...","Scanning for local blocks ...":"Scanner for lokale blokke ...","Schedule":"Planlagt","Search":"Søg","Search for files":"Søg efter filer","Seconds":"Sekunder","Select a log level and see messages as they happen:":"Vælg et log niveau og se beskeder som de kommer:","Select files":"Vælg filer","Server":"Server","Server and port":"Server og port","Server hostname or IP":"Server navn eller IP","Server is currently paused,":"Serveren er sat på pause.","Server is currently paused, do you want to resume now?":"Serveren er sat på pause, vil du genoptage med det samme?","Server password":"Server kodeord","Server paused":"Server på pause","Server state properties":"Egenskaber for serveren","Settings":"Indstillinger","Show":"Vis","Show advanced editor":"Vis avanceret redigering","Show hidden folders":"Vis skjulte mapper","Show log":"Vis log","Show log ...":"Vis log ...","Show treeview":"Vis træstruktur","Sia server password":"Sia server kodeord","Some OpenStack providers allow an API key instead of a password and tenant name":"Nogle OpenStack udbydere tillader en API nøgle istedet for et kodeord og et tenant navn","Source Data":"Kilde data","Source data":"Kilde data","Source folders":"Kilde mapper","Source:":"Kilde:","Specific builds for developers only.":"Specielle versioner til udviklere.","Standard protocols":"Standard protokoller","Starting ...":"Starter ...","Starting the restore process ...":"Starter gendannelses processen ...","Stop after the current file":"Stop efter den nuværende fil","Stop after upload":"Stop efter upload","Stop now":"Stop nu","Stop running backup":"Stop den kørende backup","Stop running task":"Stop den kørende opgave","Stopping after upload:":"Stopper efter upload:","Stopping task:":"Stopper opgave:","Storage Type":"Opbevaringstype","Storage class":"Opbevaringsklasse","Storage class for creating a bucket":"Opbevaringsklasse når der oprettes en bucket","Stored":"Gemt","Strong":"Stærk","Success":"Succes","Sun":"Søn","Symbolic link":"Symbolsk kæde","System default ({{levelname}})":"System standard ({{levelname}})","System files":"System filer","System info":"System info","System properties":"System egenskaber","TByte":"TByte","TByte/s":"TByte/s","Target path, ie /backup":"Destinationsstien, f.eks. /backup","Task is running":"Opgave kører","Temporary files":"Midlertidige filer","Tenant Name":"Tenant navn","Test connection":"Test forbindelse","Testing ...":"Tester ...","Testing connection ...":"Tester forbindelse ...","Testing permissions ...":"Tester tilladelser ...","Testing permissions...":"Tester tilladelser...","The bucket name should be all lower-case, convert automatically?":"Bucket navnet bør være med små bogstaver, konverter automatisk?","The bucket name should start with your username, prepend automatically?":"Bucket navnet bør starte med dit brugernavn, vil du sætte det foran automatisk?","The connection to the server is lost, attempting again in {{time}} ...":"Forbindelsen til serveren er mistet, forsøger igen om {{time}} ...","The dark theme (by Michal)":"Mørke farver (af Michal)","The default blue on white theme (by Alex)":"Standard blå på hvid (af Alex)","The folder {{folder}} does not exist.\nCreate it now?":"Mappen {{folder}} eksisterer ikke.\nOpret den nu?","The host key has changed, please check with the server administrator if this is correct, otherwise you could be the victim of a MAN-IN-THE-MIDDLE attack.\n\nDo you want to REPLACE your CURRENT host key \"{{prev}}\" with the REPORTED host key: {{key}}?":"Nøglen fra værten er ændret, kontroller venligst med server administratoren om dette er korrekt, ellers kan du være offer for et MAN-IN-THE-MIDDLE angreb.\n\nVil du ERSTATTE din NUVÆRENDE værtsnøgle \"{{prev}}\" med den RAPPORTEREDE værtsnøgle: {{key}}?","The path does not appear to exist, do you want to add it anyway?":"Stien ser ikke ud til at findes, vil du tilføje den alligevel?","The path does not end with a '{{dirsep}}' character, which means that you include a file, not a folder.\n\nDo you want to include the specified file?":"Stien slutter ikke med '{{dirsep}}' tegnet, hvilket betyder at du inkluderer en file og ikke en mappe.\n\nVil du inkludere den valgte fil?","The path must be an absolute path, i.e. it must start with a forward slash '/'":"Stien skal være en absolut sti, altså skal den starte med '/'","The path should start with \"{{prefix1}}\" or \"{{prefix2}}\", otherwise you will not be able to see the files in the HubiC web interface.\n\nDo you want to add the prefix to the path automatically?":"Stien bør starte med \"{{præfiks1}}\" eller \"{{præfiks2}}\", ellers vil du ikke kunne se andre filer i HubiC web konsollen\n\nVil du tilføje præfikset til stien automatisk?","The region parameter is only applied when creating a new bucket":"Regionsparameteren anvendes kun når der oprettes en ny bucket","The region parameter is only used when creating a bucket":"Regionsparameteren bruges kun når der oprettes en ny bucket","The server certificate could not be validated.\nDo you want to approve the SSL certificate with the hash: {{hash}}?":"Server certifikatet kunne ikke valideres.\nVil du godkende SSL certifikatet med dette hash: {{hash}}?","The storage class affects the availability and price for a stored file":"Opbevaringsklasen påvirker tilgængeligheden og prisen for en opbevaret fil","The target folder contains encrypted files, please supply the passphrase":"Destinationsmappen indeholder krypterede filer, angiv venligst kodesætningen","The user has too many permissions. Do you want to create a new limited user, with only permissions to the selected path?":"Brugeren har for mange tilladelser. Vil du oprette en ny begrænset bruger der kun har adgang til den valgte sti?","This backup was created on another operating system. Restoring files without specifying a destination folder can cause files to be restored in unexpected places. Are you sure you want to continue without choosing a destination folder?":"Denne backup blev oprettet på et andet operativsystem. Når der gendannes filer uden at angive en destination, kan disse blive oprettet på uventede placeringer. Er du sikker på at du vil fortsætte uden at vælge en destinationsmappe?","This month":"Denne måned","This week":"Denne uge","Throttle settings":"Indstillinger for hastighedsbegrænsning","Thu":"Tor","To File":"Til fil","To confirm you want to delete all remote files for \"{{name}}\", please enter the word you see below":"For at bekræfte at du vil slette all fjernfiler til \"{{name}}\", indtast venligst det ord ud ser herunder","To export without a passphrase, uncheck the \"Encrypt file\" box":"For at eksportere uden en adgangsætning, fjern mærket ud for \"Krypter filen\"","Today":"I dag","Trust host certificate?":"Stol på værtscertifikatet?","Trust server certificate?":"Stol på server certifikatet?","Try out the new features we are working on. Don't use with important data.":"Prøv de nye ting vi arbejder på. Undlad at bruge denne med vigtige data.","Tue":"Tir","Type to highlight files":"Skriv for at markere filer","Unknown backup size and versions":"Ukendt backup størrelse og versionsantal","Until resumed":"Indtil genoptaget","Update channel":"Opdateringskanal","Update failed:":"Opdatering fejlede:","Updating with existing database":"Opdaterer med eksisterende database","Upload volume size":"Filstørrelse til upload","Uploading verification file ...":"Uploader verifikationsfil ...","Usage statistics":"Brugsstatistik","Usage statistics, warnings, errors, and crashes":"Brugsstatistik, advarsler, fejl og nedbrud","Use SSL":"Brug SSL","Use existing database?":"Brug eksisterende database?","Use weak passphrase":"Brug svag kodesætning","Useless":"Ubrugelig","User data":"Brugerdata","User has too many permissions":"Brugeren har for mange tilladelser","User interface settings":"Indstillinger til brugergrænseflade","Username":"Brugernavn","Validating ...":"Validerer ...","Verify files":"Verificer filer","Verifying ...":"Verificerer ...","Verifying answer":"Verificerer svar","Verifying backend data ...":"Verificerer destinationsdata ...","Verifying remote data ...":"Verificerer fjerndata ...","Verifying restored files ...":"Verificerer gendannede filer ...","Very strong":"Meget stærk","Very weak":"Meget svag","Visit us on":"Besøg os på","WARNING: The remote database is found to be in use by the commandline library":"ADVARSEL: Databasen benyttes af kommandolinie programmet","WARNING: This will prevent you from restoring the data in the future.":"ADVARSEL: Dette vil forhindre dig i at gendanne data i fremtiden.","Waiting for task to begin":"Venter på at opgaven starter","Waiting for task to start ....":"Venter på at opgaven starter ...","Waiting for upload ...":"Venter på upload ...","Warnings, errors and crashes":"Advarsler, fejl og nedbrud","We accept donations via different services, such as OpenCollective, PayPal, BountySource and various crypto currencies.":"Vi accepterer donationer via forskellige tjenester, såsom OpenCollective, PayPal, BountySource og forskellige krypto-valutaer.","We recommend that you encrypt all backups stored outside your system":"Vi anbefaler at du krypterer alle backups der er gemt uden for dit system","Weak":"Svag","Weak passphrase":"Svag kodesætning","Wed":"Ons","Weeks":"Uger","Where do you want to restore from?":"Hvor vil du gerne gendanne fra?","Where do you want to restore the files to?":"Hvor vil du gendanne filerne til?","Windows":"Windows","Years":"År","Yes":"Ja","Yes, I have stored the passphrase safely":"Ja, jeg har opbevaret kodesætningen sikkert","Yes, I'm brave!":"Ja, jeg er modig!","Yes, please break my backup!":"Ja, ødelæg venligst min backup!","Yesterday":"I går","You appear to be running Mono with no SSL certificates loaded.\nDo you want to import the list of trusted certificates from Mozilla?":"Det ser ud til at du kører Mono uden nogen SSL certifikater.\nVil du importere listen af certifikater som Mozilla bruger?","You are changing the database path away from an existing database.\nAre you sure this is what you want?":"Du er ved at ændre database stien væk fra en eksisterende database.\nEr du sikker på at det er det du vil?","You are currently running {{appname}} {{version}}":"Du kører med {{appname}} {{version}}","You can stop the backup immediately, or stop after the current file has been uploaded.":"Du kan stoppe backup'en med det samme, eller stoppe efter den nuværende fil er uploaded.","You can stop the task immediately, or allow the process to continue its current file and the stop.":"Du kan stoppe opgaven med det samme, eller lade den afslutte den nuværende fil og så stoppe.","You have changed the encryption mode. This may break stuff. You are encouraged to create a new backup instead":"Du har skiftet krypteringsmetode. Dette kan ødelægge ting. Du opfordres til at oprette en ny backup i stedet.","You have changed the passphrase, which is not supported. You are encouraged to create a new backup instead.":"Du har skiftet kodesætningen, hvilket ikke understøttes. Du opfordres til at oprette en ny backup i stedet.","You have chosen not to encrypt the backup. Encryption is recommended for all data stored on a remote server.":"Du har valgt at undlade at kryptere din backup. Kryptering anbefales for alt data der gemmes på en fjerndestination.","You have chosen to restore to a new location, but not entered one":"Du har valgt at gendanne til en ny placering, men ikke angivet en","You have generated a strong passphrase. Make sure you have made a safe copy of the passphrase, as the data cannot be recovered if you lose the passphrase.":"Du har genereret en stærk adgangskode. Sørg for, at du har en sikker kopi af adgangskoden, da data ikke kan gendannes, hvis du mister adgangskoden.","You must choose at least one source folder":"Du skal vælge mindst en kilde mappe","You must enter a name for the backup":"Du skal angive et navn for denne backup","You must enter a passphrase or disable encryption":"Du skal indtaste en kodesætning eller fravælge kryptering","You must enter a positive number of backups to keep":"Du skal indtaste et positivt antal backups der skal bevares","You must enter a tenant name if you do not provide an API Key":"Du skal angive et tenant navn hvis du ikke angiver en API nøgle","You must enter a valid duration for the time to keep backups":"Du skal angive en gyldig periode som backups gemmes i","You must enter either a password or an API Key":"Du skal angive enten et kodeord eller en API nøgle","You must enter either a password or an API Key, not both":"Du skal angive enten et kodeord eller en API nøgle, men ikke begge","You must fill in the password":"Du skal angive et kodeord","You must fill in the server name or address":"Du skal angive server navnet eller adressen","You must fill in the username":"Du skal angive et brugernavn","You must fill in {{field}}":"Du skal udfylde {{field}}","You must select or fill in the AuthURI":"Du skal vælge eller udfylde AuthURI","You must select or fill in the server":"Du skal vælge eller indtaste server navnet","You must specify a path":"Du skal angive en sti","Your files and folders have been restored successfully.":"Dine filer og mapper blev gendannet korrekt.","Your passphrase is easy to guess. Consider changing passphrase.":"Din kodesætning er let at gætte. Overvej at skifte den.","bucket/folder/subfolder":"buvket/mappe/undermappe","byte":"byte","byte/s":"byte/s","custom":"tilpasset","resume now":"genoptag nu","{{appname}} was primarily developed by {{dev1}} and {{dev2}}. {{appname}} can be downloaded from {{websitename}}. {{appname}} is licensed under the {{licensename}}.":"{{appname}} er primært udviklet af {{dev1}} og {{dev2}}. {{appname}} kan downloades fra {{websitename}}. {{appname}} er licenseret med {{licensename}}.","{{files}} files ({{size}}) to go {{speed_txt}}":"{{files}} filer ({{size}}) tilbage {{speed_txt}}","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Version":["{{item.Backup.Metadata.TargetSizeString}} / {{$count}} version","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} versioner"],"{{number}} Hour":"{{number}} Timer","{{number}} Minutes":"{{number}} Minutter","{{time}} (took {{duration}})":"{{time}} (varighed: {{duration}})"}); gettextCatalog.setStrings('de', {"- pick an option -":"- Option auswählen -","...loading...":"...laden...","API Key":"API-Schlüssel","AWS Access ID":"AWS Access ID","AWS Access Key":"AWS Access Key","AWS IAM Policy":"AWS IAM Policy","About":"Über","About {{appname}}":"Über {{appname}}","Access Key":"Zugriffsschlüssel","Access denied":"Zugriff verweigert","Access to user interface":"Zugriff auf die Benutzeroberfläche","Account name":"Kontoname","Activate":"Aktivieren","Activate failed:":"Aktivierung fehlgeschlagen:","Add a new backup":"Neues Backup hinzufügen","Add a path directly":"Pfad direkt eingeben","Add advanced option":"Option für Profis hinzufügen","Add backup":"Sicherung hinzufügen","Add filter":"Filter hinzufügen","Add path":"Pfad hinzufügen","Adjust bucket name?":"Bucket-Name anpassen?","Adjust path name?":"Pfad anpassen?","Advanced Options":"Optionen für Profis","Advanced options":"Optionen für Profis","Advanced:":"Für Profis:","All":"Alle","All Hyper-V Machines":"Alle Hyper-V Maschinen","All Microsoft SQL Databases":"Alle Microsoft SQL-Datenbanken","All usage reports are sent anonymously and do not contain any personal information. They contain information about hardware and operating system, the type of backend, backup duration, overall size of source data and similar data. They do not contain paths, filenames, usernames, passwords or similar sensitive information.":"Alle Nutzungsberichte werden anonym verschickt und enthalten keine personenbezogenen oder personenbeziehbare Daten. Sie enthalten Daten über Hardware, Betriebssystem, das verwendete Backend, die Sicherungsdauer, die Gesamtgröße der Sicherungen und ähnliche Daten. Sie enthalten NICHT Pfade, Dateinamen, Benutzernamen, Passwörter oder andere sensible Informationen.","Allow remote access (requires restart)":"Fernzugriff erlauben (Neustart notwendig)","Allowed days":"Erlaubte Tage","An existing file was found at the new location":"An dem angegebenen Ort wurde eine bereits vorhandene Datenbank gefunden.","An existing file was found at the new location\nAre you sure you want the database to point to an existing file?":"Eine vorhandene Datenbank wurde gefunden.\nSoll diese Datenbank von nun an verwendet werden?","An existing local database for the storage has been found.\nRe-using the database will allow the command-line and server instances to work on the same remote storage.\n\n Do you wish to use the existing database?":"Eine lokale Datenbank für den Onlinespeicher wurde gefunden.\nMit dieser Datenbank können GUI und Kommandozeile auf dem gleichen Onlinespeicher arbeiten.\n\nSoll die lokale Datenbank genutzt werden?","Anonymous usage reports":"Anonyme Nutzungsberichte","As Command-line":"als Befehl für Kommandozeile","AuthID":"AuthID","Authentication password":"Passwort für Anmeldung","Authentication username":"Benutzername für Anmeldung","Autogenerated passphrase":"Automatisch generierte Passphrase","Automatically run backups.":"Sicherungen automatisch ausführen.","B2 Account ID":"B2 Account ID","B2 Application Key":"B2 Application Key","B2 Cloud Storage Account ID":"B2 Cloud Storage Account ID","B2 Cloud Storage Application Key":"B2 Cloud Storage Application Key","Back":"Zurück","Backend modules:":"Backend-Module:","Backup destination":"Sicherungsziel","Backup location":"Sicherungsort","Backup:":"Sicherung:","Beta":"Beta","Broken access":"Defekter Zugriff","Browse":"Anzeigen","Browser default":"Standard Browser","Bucket Name":"Bucket-Name","Bucket create location":"Bucket-Speicherort","Bucket create region":"Bucket Bereich erstellen","Bucket name":"Bucket-Name","Bucket storage class":"Bucket Speicherklasse","Building list of files to restore ...":"Dateiliste erstellen...","Building partial temporary database ...":"Temporäre Datenbank wird erstellt...","Busy ...":"Beschäftigt...","Canary":"Canary","Cancel":"Abbrechen","Cannot move to existing file":"Verschieben auf bereits existierende Datei nicht möglich","Changelog":"Änderungsprotokoll","Changelog for {{appname}} {{version}}":"Änderungsprotokoll für {{appname}} {{version}}","Check failed:":"Prüfung fehlgeschlagen:","Check for updates now":"Aktualisierung suchen","Checking ...":"Überprüfen...","Checking for updates ...":"Suche Aktualisierung...","Chose a storage type to get started":"Wähle einen Speichertypen zum Starten","Click the AuthID link to create an AuthID":"Auf AuthID klicken um eine AuthID zu erstellen","Click to set throttle options":"Klicken, um die Drosseloptionen einzustellen","Commandline ...":"Kommandozeile","Compact now":"Sicherung komprimieren","Compacting remote data ...":"Remotedaten verkleinern...","Completing backup ...":"Sicherung fertigstellen...","Completing previous backup ...":"Vorherige Sicherung fertigstellen...","Compression modules:":"Kompression:","Computer":"Computer","Configuration file:":"Konfigurationsdatei:","Configuration:":"Konfiguration:","Configure a new backup":"Neues Backup konfigurieren","Confirm delete":"Löschen bestätigen","Confirmation required":"Bestätigung erfolderlich","Connect":"Verbinden","Connect now":"Jetzt verbinden","Connecting to server ...":"Verbindung zum Server herstellen ...","Connecting to task ....":"Verbinde mit Aufgabe...","Connecting...":"Verbinden...","Connection lost":"Verbindung verloren","Connection worked!":"Verbindung erfolgreich!","Container name":"Container-Name","Container region":"Container-Region","Continue":"Fortfahren","Continue without encryption":"Ohne Verschlüsselung fortfahren","Copied!":"Kopiert!","Copy Destination URL to Clipboard":"Kopiere Ziel-URL in Zwischenablage","Copy failed. Please manually copy the URL":"Kopie fehlgeschlagen. Bitte kopiere die URL manuell","Core options":"Allgemeine Optionen","Counting ({{files}} files found, {{size}})":"Dateien ermitteln ({{files}} files found, {{size}})","Crashes only":"Nur Abstürze","Create bug report ...":"Fehlerbericht erstellen...","Create folder?":"Ordner erstellen?","Created new limited user":"Nutzer mit eingeschränkten Rechten anlegen","Creating bug report ...":"Fehlerbericht wird erstellt...","Creating new user with limited access ...":"Nutzer mit eingeschränkten Rechten wird erstellt...","Creating target folders ...":"Zielverzeichnisse erstellen...","Creating temporary backup ...":"Temporäre Sicherung erstellen...","Creating user...":"Nutzer anlegen...","Current version is {{versionname}} ({{versionnumber}})":"Aktuelle Version: {{versionname}} ({{versionnumber}})","Custom S3 endpoint":"Benutzerdefinierter S3 endpoint","Custom authentication url":"Benutzerdefinierte URL für Authentifizierung","Custom location ({{server}})":"Benutzerdefinierter Standort ({{server}})","Custom region for creating buckets":"Benutzerdefinierte Region, um Buckets zu erstellen","Custom region value ({{region}})":"Benutzerdefinierter Wert für Region ({{region}})","Custom server url ({{server}})":"Benutzerdefinierte Server-URL ({{server}})","Custom storage class ({{class}})":"Benutzerdefinierte Speicher-Klasse ({{class}})","Database ...":"Datenbank ...","Days":"Tage","Default":"Standard","Default ({{channelname}})":"Standard ({{channelname}})","Default Filters":"Standard Filter","Default options":"Standard-Optionen","Delete":"Löschen","Delete ...":"Löschen...","Delete backup":"Sicherung löschen","Delete local database":"Lokale Datenbank löschen","Delete remote files":"Remote-Dateien löschen","Delete the local database":"Die lokale Datenbank löschen","Delete {{filecount}} files ({{filesize}}) from the remote storage?":"{{filecount}} Dateien ({{filesize}}) vom Remote-Speicher löschen?","Deleting remote files ...":"Remote-Dateien löschen...","Deleting unwanted files ...":"Veraltete Daten löschen...","Desktop":"Desktop","Destination":"Ziel","Did we help save your files? If so, please consider supporting Duplicati with a donation. We suggest {{smallamount}} for private use and {{largeamount}} for commercial use.":"Konnten wir Deine Daten retten? Falls ja, würden wir uns über eine angemessene Spende sehr freuen. Wir empfehlen {{smallamount}} bei privater Nutzung und {{largeamount}} bei geschäftlicher Nutzung.","Direct restore from backup files ...":"Direkte Wiederherstellung von Sicherungsdateien","Disabled":"Deaktiviert","Dismiss":"Verwerfen","Display and color theme":"Anzeige und Farbthema","Do you really want to delete the backup: \"{{name}}\" ?":"Möchtest Du die Sicherung wirklich löschen: \"{{name}}\" ?","Do you really want to delete the local database for: {{name}}":"Möchtest du die lokale Datenbank wirklich löschen für: {{name}}","Donate":"Spenden","Donate with PayPal":"Spenden per PayPal","Donate with crypto currency":"Spenden mit Krypto-Währungen","Donation messages":"Spenden-Links","Donation messages are hidden, click to show":"Spenden-Links werden versteckt (jetzt anzeigen)","Donation messages are visible, click to hide":"Spendenlinks werden angezeigt (jetzt ausblenden)","Done":"Fertig","Download":"Herunterladen","Downloading ...":"Herunterladen...","Downloading files ...":"Dateien herunterladen...","Downloading update...":"Update Herunterladen...","Duplicate option {{opt}}":"doppelte Option {{opt}}","Duplicati Website":"Duplicati Website","Duplicati forum":"Duplicati Forum","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\n When deleting a backup, you can also delete the local database without affecting the ability to restore the remote files.\n If you are using the local database for backups from the commandline, you should keep the database.":"Jedes Backup hat eine lokale Datenbank.\nBeim Löschen des Backups kann die lokale Datenbank, ohne die Wiederherstellung der Remote-Dateien zu beeinträchtigen.\nWenn Sie die lokale Datenbank für Backups von der Befehlszeile aus verwenden, sollten Sie die Datenbank behalten.","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\\nThis makes it faster to perform many operations, and reduces the amount of data that needs to be downloaded for each operation.":"Jede Sicherung hat eine lokale Datenbank. Diese Datenbank beschleunigt viele Aktionen und führt dazu, dass weniger Daten heruntergeladen werden müssen.","Edit ...":"Bearbeiten...","Edit as list":"Als Liste bearbeiten","Edit as text":"Als Text bearbeiten","Encrypt file":"Datei verschlüsseln","Encryption":"Verschlüsselung","Encryption changed":"Verschlüsselung geändert","Encryption modules:":"Verschlüsselungen:","Enter URL":"URL eingeben","Enter access key":"Zugriffsschlüssel angeben","Enter account name":"Account-Name angeben","Enter backup passphrase, if any":"Sicherungspassphrase eingeben, wenn nötig","Enter configuration details":"Konfigurationsdetails eingeben","Enter container name":"Container-Name angeben","Enter encryption passphrase":"Verschlüsselungpassphrase eingeben","Enter expression here":"Ausdruck hier eingeben","Enter folder path name":"Ordnerpfad eingeben","Enter one option per line in command-line format, eg. {0}":"Gib eine Option pro Zeile an im Kommandozeilen-Format, z.B. {0}","Enter the destination path":"Ziel-Pfad angeben","Error":"Fehler","Error!":"Fehler!","Errors and crashes":"Fehler und Abstürze","Exclude":"Ausschließen","Exclude directories whose names contain":"Ordner ausschließen dessen Namen beinhaltet","Exclude expression":"Filter (ausschließen)","Exclude file":"Datei ausschließen","Exclude file extension":"Dateiendung ausschließen","Exclude files whose names contain":"Dateien ausschließen dessen Namen beinhaltet","Exclude folder":"Ordner ausschließen","Exclude regular expression":"Regulären Ausdruck (ausschließen)","Existing file found":"Vorhandene Datenbank gefunden","Experimental":"Experimental","Export":"Exportieren","Export ...":"Exportieren...","Export backup configuration":"Sicherungskonfiguration exportieren","Export configuration":"Konfiguration exportieren","Exporting ...":"Exportieren...","FTP (Alternative)":"FTP (Alternativ)","Failed to build temporary database: {{message}}":"Erstellen der temporären Datenbank fehlgeschlagen: {{message}}","Failed to connect:":"Verbindung fehlgeschlagen:","Failed to connect: {{message}}":"Verbindung fehlgeschlagen: {{message}}","Failed to delete:":"Löschen fehlgeschlagen:","Failed to fetch path information: {{message}}":"Konnte Pfadangaben nicht abrufen: {{message}}","Failed to import:":"Import fehlgeschlagen:","Failed to read backup defaults:":"Konnte Sicherungsstandardeinstellungen nicht lesen:","Failed to restore files: {{message}}":"Wiederherstellung der Dateien fehlgeschlagen: {{message}}","Failed to save:":"Fehler beim Speichern:","Fetching path information ...":"Pfad-Infos werden ermittelt...","File":"Datei","Files larger than:":"Dateien größer als:","Filters":"Filter","Finished!":"Fertiggestellt!","First run setup":"Zuerst Setup starten","Folder":"Ordner","Folder path":"Ordnerpfad","Fri":"Fr","GByte":"GByte","GByte/s":"GByte/s","GCS Project ID":"GCS Project ID","General":"Allgemein","General backup settings":"Allgemeine Sicherungseinstellungen","General options":"Allgemeine Einstellungen","Generate":"Erzeugen","Generate IAM access policy":"Generieren IAM Zugriffsrichtlinie","Getting file versions ...":"Erhalte Dateiversionen ...","Hidden files":"Versteckte Dateien","Hide":"Ausblenden","Hide hidden folders":"versteckte Ordner ausblenden","Home":"Home","Hours":"Stunden","How do you want to handle existing files?":"Wie sollen bestehende Dateien behandelt werden?","Hyper-V Machine":"Hyper-V-Maschine","Hyper-V Machine:":"Hyper-V-Maschine:","Hyper-V Machines":"Hyper-V-Maschinen","ID:":"ID:","If a date was missed, the job will run as soon as possible.":"Wurde ein Zeitpunkt verpasst, startet die Sicherung so bald wie möglich.","If the backup and the remote storage is out of sync, Duplicati will require that you perform a repair operation to synchronize the database.\\nIf the repair is unsuccesful, you can delete the local database and re-generate.":"Wenn lokale Daten und die Sicherung nicht mehr synchron sind, muss die lokale Datenbank repariert werden.\\nSollte die Reparatur nicht erfolgreich sein, so kann die lokale Datenbank gelöscht und neu erstellt werden.","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"Wenn die Sicherungsdatei nicht automatisch heruntergeladen wurde, klickst Du mit der rechten Maustaste und wählst \"Speichern unter...\" aus","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"Wenn die Sicherungsdatei nicht automatisch heruntergeladen wurde, klickst De mit der rechten Maustaste und wählst \"Speichern unter...\" aus","If you do not enter a path, all files will be stored in the login folder.\nAre you sure this is what you want?":"Ohne Pfad werden alle Dateien im Anmelde-Verzeichnis gespeichert.\nMöchtest du das?","If you do not enter an API Key, the tenant name is required":"Wenn kein API Schlüssel angegeben wurde, ist der Tenant-Name erforderlich.","If you want to use the backup later, you can export the configuration before deleting it":"Wenn Du die Sicherung später verwenden möchtest, kann die Konfiguration vor dem Löschen exportiert werden","If your machine is in a multi-user environment (i.e. the machine has more than one account), you need to set a password to prevent other users from accessing data on your account.\nDo you want to set a password now?":"Wenn sich Ihr Gerät in einer Mehrbenutzerumgebung befindet (d. h. die Maschine hat mehr als ein Benutzerkonto), müssen Sie ein Kennwort festlegen, um zu verhindern, dass andere Benutzer auf Daten Ihres Kontos zugreifen.\nMöchten Sie jetzt ein Passwort setzen?","Import":"Importieren","Import Destination URL":"Ziel-URL importieren","Import backup configuration":"Sicherungskonfiguration importieren","Import completed, but no certificates were found after the import":"Import abgeschlossen, aber es wurde kein Zertifikat nach dem Import gefunden","Import failed":"Import fehlgeschlagen","Import from a file":"Von einer Datei importieren","Importing ...":"Importieren...","Include a file?":"Datei einfügen?","Include expression":"Filter (einschließen)","Include regular expression":"Regulären Ausdruck (einschließen)","Incorrect answer, try again":"Fehlerhafte Antwort, versuche es erneut","Individual builds for developers only.":"Individuelle Versionen für Entwickler.","Information":"Information","Install":"Installieren","Install failed:":"Installation fehlgeschlagen:","Invalid characters in path":"Unzulässige Zeichen im Pfad","Invalid retention time":"Ungültige Aufbewahrungszeit","It is possible to connect to some FTP without a password.\nAre you sure your FTP server supports password-less logins?":"Manche FTP-Server erlauben ein Verbinden ohne Passwort.\nBist Du sicher, dass Dein FTP-Server dazu gehört?","KByte":"KByte","KByte/s":"KByte/s","Keep this number of backups":"Behalte diese Anzahl von Backups","Language in user interface":"Sprache der Benutzeroberfläche","Last month":"Letzter Monat","Last successful run:":"Letzte erfolgreiche Sicherung:","Latest":"Neuste","Libraries":"Bibliotheken","Linux":"Linux","Listing backup dates ...":"Sicherungsdaten werden aufgelistet...","Listing remote files ...":"Auflisten von Remote-Dateien...","Live":"Live","Load a configuration from an exported job or a storage provider":"Konfiguration aus einem exportierten Job oder Speicheranbieter laden","Load destination from an exported job or a storage provider":"Ziel aus einem exportierten Job oder Speicheranbieter laden","Load older data":"ältere Einträge laden","Loading ...":"Laden...","Loading remote storage usage ...":"Remote-Speicherplatznutzung abfragen...","Local database for":"Lokale Datenbank für","Local database path:":"Lokale Datenbank:","Local storage":"Lokaler Speicher","Location":"Ort","Location where buckets are created":"Speicherort, wo die Buckets erstellt werden","Log data for {{Backup.Backup.Name}}":"Protokolldaten für {{Backup.Backup.Name}}","Log data from the server":"Protokolldaten vom Server","Log out":"Abmelden","MByte":"MByte","MByte/s":"MByte/s","Maintenance":"Wartung","Manually type path":"Pfad eingeben","Max download speed":"Max. Downloadgeschwindigkeit","Max upload speed":"Max. Upload-Geschwindigkeit","Menu":"Menü","Microsoft SQL Database:":"Microsoft SQL Datenbank:","Microsoft SQL Databases":"Microsoft SQL Datenbanken","Minimum redundancy":"Minimale Redundanz","Minimum redundancy is 1.0":"Die minimale Redundanz ist 1,0","Minutes":"Minuten","Missing name":"Name fehlt","Missing passphrase":"Passphrase fehlt","Missing sources":"Quelle fehlt","Mon":"Mo","Months":"Monate","Move existing database":"Datenbank verschieben","Move failed:":"Verschieben fehlgeschlagen:","My Documents":"Dokumente","My Music":"Musik","My Photos":"Meine Fotos","My Pictures":"Bilder","Name":"Name","Never":"Nie","New update found: {{message}}":"Neues Update verfügbar: {{message}}","New user name is {{user}}.\nUpdated credentials to use the new limited user":"Neuer Benutzername ist {{user}}.\nZugangsdaten für eingeschränken Benutzer verwendet","Next":"Weiter","Next scheduled run:":"Nächste geplante Ausführung:","Next scheduled task:":"Nächste geplante Aufgabe:","Next task:":"Nächste Aufgabe:","Next time":"Nächstes Mal","No":"Nein","No certificate was specified previously, please verify with the server administrator that the key is correct: {{key}} \n\nDo you want to approve the reported host key?":"Es wurde kein Zertifikat angegeben, mit dem der Serveradministrator prüft, ob der Schlüssel korrekt ist: {{key}}\n\nMöchtest Du den gemeldeten Host-Schlüssel freigeben?","No editor found for the "{{backend}}" storage type":"Kein Editor für den "{{backend}}" Speichertyp gefunden","No encryption":"Keine Verschlüsselung","No items selected":"Nichts ausgewählt","No items to restore, please select one or more items":"Es wurden keine Daten für die Wiederherstellung ausgewählt. Wähle eine Datei oder einen Ordner aus.","No passphrase entered":"Keine Passphrase eingegeben","No scheduled tasks":"Keine geplanten Aufgaben","No, my machine has only a single account":"Nein, meine Maschine hat nur ein einziges Konto","Non-matching passphrase":"Nicht übereinstimmende Passphrase","None / disabled":"Keine / deaktiviert","OK":"OK","OSX":"OSX","OpenStack AuthURI":"OpenStack AuthURI","OpenStack Object Storage / Swift":"OpenStack Object Storage / Swift","Operation failed:":"Operation fehlgeschlagen:","Operations:":"Operationen:","Optional authentication password":"Passwort für Anmeldung (optional)","Optional authentication username":"Benutzername für Anmeldung (optional)","Options":"Optionen","Options added here are applied to all backups, but can be overridden in each individual backup":"Optionen, die hier gesetzt werden, werden auf alle Backups angewandt, können aber in jedem einzelnen Backup überschrieben werden","Original location":"Ursprünglicher Speicherort","Others":"Weitere","Overwrite":"Überschreiben","Passphrase":"Passphrase","Passphrase (if encrypted)":"Passphrase (falls verschlüsselt)","Passphrase changed":"Passphrase gändert","Passphrases are not matching":"Passphrasen stimmen nicht überein","Password":"Passwort","Passwords do not match":"Die Passwörter stimmen nicht überein","Patching files with local blocks ...":"Dateien mit vorhandenen Daten aufbauen...","Path not found":"Pfad nicht gefunden","Path on server":"Pfad auf Server","Path or subfolder in the bucket":"Pfad oder Unterverzeichnis im Bucket","Pause":"Pause","Pause after startup or hibernation":"Pause nach dem Start oder Aufwachen","Pause options":"Anhalten Optionen","Permissions":"Berechtigungen","Pick location":"Speicherort auswählen","Point to your backup files and restore from there":"Sicherungsdateien auswählen und wiederherstellen","Port":"Port","Previous":"Zurück","ProjectID is optional if the bucket exist":"Die Projekt-ID ist optional, wenn der Bucket existiert","Proprietary":"Proprietär","Purging files ...":"Lösche Dateien ...","Rebuilding local database ...":"Lokale Datenbank wieder aufbauen...","Recreate (delete and repair)":"Wiederherstellen (löschen und reparieren)","Recreating database ...":"Datenbank wird neu erstellt...","Registering temporary backup ...":"Temporäre Sicherung registrieren...","Relative paths not allowed":"Relative Pfade sind nicht möglich","Reload":"Neu laden","Remote":"Remote","Remove":"Entfernen","Remove option":"Option entfernen","Repair":"Reparieren","Reparing ...":"Reparieren...","Repeat Passphrase":"Passphrase wiederholen","Reporting:":"Bericht:","Reset":"Zurücksetzen","Restore":"Wiederherstellen","Restore files":"Dateien wiederherstellen","Restore files ...":"Dateien wiederherstellen...","Restore files from {{backupname}}":"Stelle Dateien von {{backupname}} wieder her","Restore from":"Wiederherstellen von","Restore from backup configuration":"Aus Sicherungskonfiguration wiederherstellen","Restore from configuration ...":"Aus Konfiguration wiederherstellen...","Restore options":"Wiederherstellungsoptionen","Restore read/write permissions":"Schreib- und Leserechte wiederherstellen","Restoring files ...":"Dateien werden wiederhergestellt...","Resume":"Fortsetzen","Run again every":"Wiederholen alle","Run now":"Jetzt sichern","Running ...":"Läuft...","Running ....":"Läuft ....","Running commandline entry":"Führe Kommandozeilenbefehl aus","Running task:":"Laufende Aufgabe:","S3 Compatible":"S3 Kompatibel","Same as the base install version: {{channelname}}":"Wie die zuerst installierte Version: {{channelname}}","Sat":"Sa","Save":"Speichern","Save and repair":"Speichern und reparieren","Save different versions with timestamp in file name":"Mehrere Versionen mit Zeitstempel im Dateinamen speichern","Save immediately":"Sofort speichern","Scanning existing files ...":"Vorhandene Dateien scannen...","Scanning for local blocks ...":"Vorhandene Daten scannen...","Schedule":"Zeitplan","Search":"Suche","Search for files":"Dateien suchen","Seconds":"Sekunden","Select a log level and see messages as they happen:":"Wählen Sie eine Protokollierungsstufe aus und sehen Sie sich die Meldungen an:","Select files":"Wähle Dateien","Server":"Server","Server and port":"Server und Port","Server hostname or IP":"Server-Hostname oder IP","Server is currently paused,":"Server ist pausiert,","Server is currently paused, do you want to resume now?":"Server ist zurzeit pausiert, Server starten?","Server password":"Server-Paßwort","Server paused":"Server pausiert","Server state properties":"Server Zustandseigenschaften","Settings":"Einstellungen","Show":"Zeigen","Show advanced editor":"Profi-Modus anzeigen","Show hidden folders":"Zeige versteckte Ordner","Show log":"Protokolldatei anzeigen","Show log ...":"Protokolldatei anzeigen...","Show treeview":"Zeige Baumansicht","Sia server password":"Sia Server-Paßwort","Some OpenStack providers allow an API key instead of a password and tenant name":"Einige OpenStack Anbieter erlauben einen API Schlüssel anstelle eines Passwortes und Tenant Namen","Source Data":"Quell-Daten","Source data":"Quell-Daten","Source folders":"Quell-Verzeichnisse","Source:":"Quelle:","Specific builds for developers only.":"Spezielle Versionen für Entwickler.","Standard protocols":"Standardprotokolle","Starting ...":"Los geht's...","Starting the restore process ...":"Wiederherstellung wird gestartet...","Stop after the current file":"Beende nach aktueller Datei","Stop after upload":"Beende nach Hochladen","Stop now":"Beenden","Stop running backup":"Beende laufende Sicherung","Stop running task":"Beende laufenden Vorgang","Stopping after upload:":"Beende nach Hochladen","Stopping task:":"Beende Vorgang","Storage Type":"Speichertyp","Storage class":"Speicherklasse","Storage class for creating a bucket":"Speicherklasse zum Erstellen eines Bucket","Stored":"Gespeichert","Strong":"Stark","Success":"Erfolgreich","Sun":"So","Symbolic link":"Symbolischer Link","System default ({{levelname}})":"System-Standard ({{levelname}})","System files":"Systemdateien","System info":"System-Informationen","System properties":"System-Eigenschaften","TByte":"TByte","TByte/s":"TByte/s","Target path, ie /backup":"Zielpfad, z. B. /backup","Task is running":"Aufgabe wird ausgeführt","Temporary files":"Temporäre Dateien","Tenant Name":"Tenant-Name","Test connection":"Verbindung prüfen","Testing ...":"Testen...","Testing connection ...":"Teste Verbindung...","Testing permissions ...":"Rechte werden geprüft...","Testing permissions...":"Rechte werden geprüft...","The bucket name should be all lower-case, convert automatically?":"Der Bucket sollte klein geschrieben sein. Jetzt klein schreiben?","The bucket name should start with your username, prepend automatically?":"Der Bucket-Name sollte mit Deinem Benutzernamen beginnen. Benutzername hinzufügen?","The connection to the server is lost, attempting again in {{time}} ...":"Die Verbindung zum Server wurde verloren. Versuch erneut in {{time}}...","The dark theme (by Michal)":"Dunkles Thema (von Michal)","The default blue on white theme (by Alex)":"Blau-auf-Weiß Thema (von Alex)","The folder {{folder}} does not exist.\nCreate it now?":"Der Ordner {{folder}} existiert nicht.\nOrdner erstellen?","The host key has changed, please check with the server administrator if this is correct, otherwise you could be the victim of a MAN-IN-THE-MIDDLE attack.\n\nDo you want to REPLACE your CURRENT host key \"{{prev}}\" with the REPORTED host key: {{key}}?":"Der Host-Schlüssel wurde geändert, bitte prüfe mit dem Server Administrator ob dieser korrekt ist, ansonsten könntest Du ein Opfer eines MAN-IN-THE-MIDDLE-Angriffs sein.\n\nMöchtest du den AKTUELLEN Host-Schüssel \"{{prev}}\" mit dem GEMELDETEN Host-Schüssel {{key}} ERSETZEN?","The path does not appear to exist, do you want to add it anyway?":"Der Pfad scheint nicht zu existieren. Möchtest Du ihn trotzdem hinzufügen?","The path does not end with a '{{dirsep}}' character, which means that you include a file, not a folder.\n\nDo you want to include the specified file?":"Ohne das abschließende '{{dirsep}}' fügst du eine Datei hinzu und kein Verzeichnis.\n\nMöchtest du diese Datei hinzufügen?","The path must be an absolute path, i.e. it must start with a forward slash '/'":"Der Pfad muss ein absoluter Pfad sein. Das heißt, er muss mit '/' beginnen","The path should start with \"{{prefix1}}\" or \"{{prefix2}}\", otherwise you will not be able to see the files in the HubiC web interface.\n\nDo you want to add the prefix to the path automatically?":"Der Pfad sollte mit \"{{prefix1}}\" oder \"{{prefix2}}\" beginnen. Ansonsten wirst du die Dateien nicht auf der HubiC-Webseite sehen können.\n\nSoll das Präfix automatisch hinzugefügt werden?","The region parameter is only applied when creating a new bucket":"Der Bereich Parameter wird nur angewendet, wenn ein neuer Bucket erzeugt wird","The region parameter is only used when creating a bucket":"Der Bereich Parameter wird nur angewendet, wenn ein Bucket erzeugt wird","The server certificate could not be validated.\nDo you want to approve the SSL certificate with the hash: {{hash}}?":"Das Server Zertifikat könnte nicht validiert werden.\nMöchtest du das SSL-Zertifikat mit dem folgenden Hash freigeben: {{hash}}?","The storage class affects the availability and price for a stored file":"Die Speicherklasse wirkt sich auf die Verfügbarkeit und den Preis einer gespeicherten Datei aus","The target folder contains encrypted files, please supply the passphrase":"Das Ziel enthält verschlüsselte Dateien. Wir benötigen ein Passwort!","The user has too many permissions. Do you want to create a new limited user, with only permissions to the selected path?":"Der Nutzer hat zu viele Rechte. Möchtest Du einen Nutzer mit eingeschränkten Berechtigungen für den gewählten Pfad erstellen?","This backup was created on another operating system. Restoring files without specifying a destination folder can cause files to be restored in unexpected places. Are you sure you want to continue without choosing a destination folder?":"Dieses Backup wurde mit einem anderen Betriebssystem erstellt. Die Wiederherstellung von Dateien ohne Angabe eines Zielverzeichnisses, kann dazu führen das diese an ungewünschten Stellen wiederhergestellt werden. Bist du dir sicher fortzufahren ohne ein Zielverzeichnis zu wählen?","This month":"Dieser Monat","This week":"Diese Woche","Throttle settings":"Drosseleinstellungen","Thu":"Do","To File":"als Datei","To confirm you want to delete all remote files for \"{{name}}\", please enter the word you see below":"Zum Bestätigen für das Löschen der Remote-Dateien für \"{{name}}\", bitte das unten angegebene Wort eingeben","To export without a passphrase, uncheck the \"Encrypt file\" box":"Entferne den Haken für die Verschlüsselung, um ohne Passwort zu exportieren","Today":"Heute","Trust host certificate?":"Host Zertifikat vertrauen?","Trust server certificate?":"Server Zertifikat vertrauen?","Try out the new features we are working on. Don't use with important data.":"Neue Funktionen ausprobieren. Nutze diese Versionen nicht mit wichtigen Daten!","Tue":"Di","Type to highlight files":"Tippen, um Dateien zu markieren","Unknown backup size and versions":"Unbekannte Backupgröße und -versionen","Until resumed":"Bis zur Wiederaufnahme","Update channel":"Update-Kanal","Update failed:":"Update fehlgeschlagen:","Updating with existing database":"Datenbank wird aktualisiert","Upload volume size":"Dateigröße beim Upload","Uploading verification file ...":"Prüfdatei hochladen...","Usage reports help us improve the user experience and evaluate impact of new features. We use them to generate public usage statistics":"Nutzungsberichte helfen uns bei der Weiterentwicklung. Wir generieren daraus öffentliche Nutzungsstatistiken","Usage statistics":"Nutzungsstatistiken","Usage statistics, warnings, errors, and crashes":"Nutzungsberichte, Warnungen, Fehler und Abstürze","Use SSL":"SSL benutzen","Use existing database?":"Bestehende Datenbank nutzen?","Use weak passphrase":"Schwache Passphrase verwenden","Useless":"Nutzlos","User data":"Benutzer Daten","User has too many permissions":"Nutzer hat zu viele Rechte","User interface settings":"Einstellungen der Benutzeroberfläche","Username":"Benutzername","Validating ...":"Validieren...","Verify files":"Dateien prüfen","Verifying ...":"Prüfen...","Verifying answer":"Antwort verifizieren","Verifying backend data ...":"Verifiziere Backend-Daten...","Verifying remote data ...":"Remotedaten prüfen ...","Verifying restored files ...":"Wiederhergestellte Dateien prüfen...","Very strong":"Sehr stark","Very weak":"Sehr schwach","Visit us on":"Besuche uns auf","WARNING: The remote database is found to be in use by the commandline library":"WARNUNG: Die Remote-Datenbank wird bereits von der Kommandozeilen Bibliothek verwendet","WARNING: This will prevent you from restoring the data in the future.":"WARNUNG: Dadurch kannst Du die Daten in Zukunft nicht wiederherstellen.","Waiting for task to begin":"Warte darauf, loslegen zu können","Waiting for task to start ....":"Warte auf Aufgabenstart","Waiting for upload ...":"Auf den Upload warten...","Warnings, errors and crashes":"Warnungen, Fehler und Abstürze","We accept donations via different services, such as OpenCollective, PayPal, BountySource and various crypto currencies.":"Wir nehmen Spenden über OpenCollective, PayPal, BountySource und verschiedene Krypto-Währungen.","We recommend that you encrypt all backups stored outside your system":"Wir empfehlen, alle Sicherungen außerhalb Deines Systems zu verschlüsseln","Weak":"Schwach","Weak passphrase":"Schwache Passphrase","Wed":"Mi","Weeks":"Wochen","Where do you want to restore from?":"Von wo wollen Sie wiederherstellen?","Where do you want to restore the files to?":"Wohin sollen die Dateien wiederhergestellt werden?","Windows":"Windows","Years":"Jahre","Yes":"Ja","Yes, I have stored the passphrase safely":"Ja, ich habe die Passphrase sicher gespeichert","Yes, I'm brave!":"Ja, ich bin mutig!","Yes, please break my backup!":"Ja, mach meine Sicherung kaputt!","Yesterday":"Gestern","You appear to be running Mono with no SSL certificates loaded.\nDo you want to import the list of trusted certificates from Mozilla?":"Mono scheint ohne geladenen SSL-Zertifikate zu laufen.\nMöchtest du die Liste von vertrauenswürdigen Zertifikate von Mozilla importieren?","You are changing the database path away from an existing database.\nAre you sure this is what you want?":"Du änderst gerade den Pfad zur lokalen Datenbank.\nWeißt Du, was Du da tust?","You are currently running {{appname}} {{version}}":"Aktuell wird {{appname}} {{version}} verwendet","You can stop the backup immediately, or stop after the current file has been uploaded.":"Das Backup kann sofort angehalten werden, oder nachdem die aktuelle Datei hochgeladen wurde.","You can stop the task immediately, or allow the process to continue its current file and the stop.":"Die Aufgabe kann sofort angehalten werden, oder nachdem der Prozess die aktuelle Datei abgeschlossen hat.","You have changed the encryption mode. This may break stuff. You are encouraged to create a new backup instead":"Du hast die Verschlüsselung geändert. Dadurch kann die bestehende Sicherung unbenutzbar sein. Erstelle lieber eine neue Sicherung.","You have changed the passphrase, which is not supported. You are encouraged to create a new backup instead.":"Du hast die Passphrase geändert. Dadurch kann die bestehende Sicherung unbenutzbar sein. Erstelle lieber eine neue Sicherung.","You have chosen not to encrypt the backup. Encryption is recommended for all data stored on a remote server.":"Du hast gewählt, die Sicherung nicht zu verschlüsseln. Die Verschlüsselung wird für alle auf einem Remoteserver gespeicherten Daten empfohlen.","You have chosen to restore to a new location, but not entered one":"Wiederherstellen an einen neuen Ort wurde gewählt, aber kein Ort angegeben","You have generated a strong passphrase. Make sure you have made a safe copy of the passphrase, as the data cannot be recovered if you lose the passphrase.":"Du hast ein starkes Passwort erstellt. Stelle sicher, dass du eine Sicherheitskopie des Passwortes hast, da die Daten nicht wiederhergestellt werden können, falls du es vergisst.","You must choose at least one source folder":"Du musst schon ein Quellverzeichnis wählen","You must enter a name for the backup":"Du musst einen Namen für die Sicherung eingeben","You must enter a passphrase or disable encryption":"Du musst eine Passphrase eingeben oder die Verschlüsselung deaktivieren","You must enter a positive number of backups to keep":"Du musst eine positive Nummer der zu behaltenden Sicherungen eingeben","You must enter a tenant name if you do not provide an API Key":"Gib einen Kundennamen an, wenn Du keinen API-Key hast.","You must enter a valid duration for the time to keep backups":"Du musst einen gültigen Zeitraum der zu behaltenden Sicherungen eingeben","You must enter either a password or an API Key":"Gib einen API-Key oder ein Passwort ein.","You must enter either a password or an API Key, not both":"Gib einen API-Key oder ein Passwort an. Aber nicht beides!","You must fill in the password":"Du musst ein Passwort eintragen!","You must fill in the server name or address":"Du musst einen Servernamen oder eine Adresse eintragen!","You must fill in the username":"Du musst einen Benutzernamen eintragen!","You must fill in {{field}}":"{{field}} muss ausgefüllt sein","You must select or fill in the AuthURI":"Du musst die AuthURI auswählen oder eintragen","You must select or fill in the server":"Du musst den Server auswählen oder eintragen","You must specify a path":"Du musst einen Pfad angeben","Your files and folders have been restored successfully.":"Dateien und Ordner erfolgreich wiederhergestellt.","Your passphrase is easy to guess. Consider changing passphrase.":"Deine Passphrase ist leicht zu erraten. Nimm lieber etwas Komplizierteres.","a specific number":"eine Anzahl","bucket/folder/subfolder":"Bucket/Ordner/Unterordner","byte":"Byte","byte/s":"Byte/s","custom":"benutzerdefiniert","resume now":"Jetzt starten","unlimited":"unbegrenzt","until they are older than":"Bis sie älter sind als","{{appname}} was primarily developed by {{dev1}} and {{dev2}}. {{appname}} can be downloaded from {{websitename}}. {{appname}} is licensed under the {{licensename}}.":"{{appname}} wurde hauptsächlich von {{dev1}} und {{dev2}} entwickelt. {{appname}} kann unter folgender Adresse heruntergeladen werden: {{websitename}}. {{appname}} ist unter {{licensename}} lizenziert.","{{files}} files ({{size}}) to go {{speed_txt}}":"{{files}} Dateien ({{size}}) zu erledigen {{speed_txt}}","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Version":["{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Version","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Versionen"],"{{number}} Hour":"{{number}} Stunde","{{number}} Minutes":"{{number}} Minuten","{{time}} (took {{duration}})":"{{time}} (dauerte {{duration}})"}); gettextCatalog.setStrings('es', {"- pick an option -":"- escoja una opción -","...loading...":"...cargando...","API Key":"Clave API","AWS Access ID":"AWS Acceso ID","AWS Access Key":"AWS Clave de aceso","AWS IAM Policy":"AWS IAM Política","About":"Acerca de","About {{appname}}":"Acerca de {{appname}}","Access Key":"Clave de acceso","Access denied":"Acceso denegado","Access to user interface":"Acceso a la interfaz de usuario","Account name":"Nombre de la cuenta","Activate":"Activar","Activate failed:":"Activar fallido:","Add a new backup":"Añadir nueva copia de seguridad","Add advanced option":"Añadir opción avanzada","Add backup":"Añadir copia de seguridad","Add filter":"Añadir filtro","Add path":"Añadir ruta","Adjust bucket name?":"¿Ajustar el nombre del deposito?","Adjust path name?":"¿Ajustar el nombre de la ruta?","Advanced Options":"Opciones Avanzadas","Advanced options":"Opciones avanzadas","Advanced:":"Avanzado:","All Hyper-V Machines":"Todas las máquinas de Hyper-V","All Microsoft SQL Databases":"Las bases de datos de Microsoft SQL","All usage reports are sent anonymously and do not contain any personal information. They contain information about hardware and operating system, the type of backend, backup duration, overall size of source data and similar data. They do not contain paths, filenames, usernames, passwords or similar sensitive information.":"Todos los informes de uso son enviados anónimamente y no contienen ninguna información personal. Contiene información sobre hardware y sistema operativo, el tipo de respaldo, duración de copia de seguridad, tamaño de fuente de datos y similares. No contiene rutas, nombres de archivos, nombres de usuarios, contraseñas o información sensible similar.","Allow remote access (requires restart)":"Permitir el acceso remoto (requiere reiniciar)","Allowed days":"Días permitidos","An existing file was found at the new location":"Se encontró un archivo existente en la nueva ubicación","An existing file was found at the new location\nAre you sure you want the database to point to an existing file?":"Se encontró un archivo existente en la nueva ubicación\n¿Está seguro que desea que la base de datos apunte a un archivo existente?","An existing local database for the storage has been found.\nRe-using the database will allow the command-line and server instances to work on the same remote storage.\n\n Do you wish to use the existing database?":"Se ha encontrado una base de datos local existente para el almacenamiento.\nVolver a utilizar la base de datos permitirá a las instancias de línea de comandos y al servidor trabajar con el mismo almacenamiento remoto.\n\n¿Desea utilizar la base de datos existente?","Anonymous usage reports":"Informes de uso anónimos","As Command-line":"Como Línea de comandos","AuthID":"AuthID","Authentication password":"Contraseña de autenticación","Authentication username":"Nombre de usuario de autenticación","Autogenerated passphrase":"Autogenerar frase de seguridad","Automatically run backups.":"Ejecutar automáticamente las copias de seguridad.","B2 Account ID":"B2 Cuenta ID","B2 Application Key":"B2 clave de aplicación","B2 Cloud Storage Account ID":"B2 Cuenta Cloud Storage ID","B2 Cloud Storage Application Key":"B2 Clave de aplicación de Cloud Storage","Back":"Volver","Backend modules:":"Módulos de respaldo:","Backup destination":"Destino de la copia de seguridad","Backup location":"Ubicación de la copia de seguridad","Backup:":"Copia de seguridad:","Beta":"Beta","Broken access":"Acceso roto","Browse":"Navega","Browser default":"Navegador por defecto","Bucket Name":"Nombre del depósito","Bucket create location":"Crear la ubicación del depósito","Bucket create region":"Crear región en depósito","Bucket name":"Nombre del depósito","Bucket storage class":"Categoría de almacenamiento del depósito","Building list of files to restore ...":"Construir lista de archivos a restaurar ...","Building partial temporary database ...":"Construcción parcial de la base de datos temporal ...","Busy ...":"Ocupado ...","Canary":"Experimental e inestable (Canary)","Cancel":"Cancelar","Cannot move to existing file":"No se puede mover al archivo existente","Changelog":"Registro de cambios","Changelog for {{appname}} {{version}}":"Registro de cambios para {{appname}} {{version}}","Check failed:":"Error en chequeo:","Check for updates now":"Comprobar actualizaciones ahora","Checking ...":"Comprobando ...","Checking for updates ...":"Comprobando actualizaciones ...","Chose a storage type to get started":"Elija un tipo de almacenamiento para empezar","Click the AuthID link to create an AuthID":"Haga clic en el enlace de AuthID para crear una AuthID","Commandline ...":"Línea de comandos ...","Compact now":"Compactar ahora","Compacting remote data ...":"Compactando datos remotos ...","Completing backup ...":"Completando copia de seguridad ...","Completing previous backup ...":"Completando copia de seguridad anterior ...","Compression modules:":"Módulos de compresión:","Computer":"Ordenador","Configuration file:":"Archivo de configuración:","Configuration:":"Configuración:","Configure a new backup":"Configurar nueva copia de seguridad","Confirm delete":"Confirmar borrado","Confirmation required":"Confirmación necesaria","Connect":"Conectar","Connect now":"Conectar ahora","Connecting to server ...":"Conectando al servidor ...","Connecting...":"Conectando...","Connection lost":"Conexión perdida","Connection worked!":"¡La conexión funcionó!","Container name":"Nombre del contenedor","Container region":"Contenedor de región","Continue":"Continuar","Continue without encryption":"Continuar sin cifrado","Copied!":"¡Copiado!","Copy Destination URL to Clipboard":"Copiar la URL de destino al portapapeles","Copy failed. Please manually copy the URL":"Copía fallida. Por favor, copia manualmente la dirección URL","Core options":"Opciones de base","Counting ({{files}} files found, {{size}})":"Contando ({{files}} archivos encontrados, {{size}})","Crashes only":"Sólo bloqueos","Create bug report ...":"Crear informe de error ...","Create folder?":"¿Crear carpeta?","Created new limited user":"Creó un nuevo usuario limitado","Creating bug report ...":"Creando un informe de error ...","Creating new user with limited access ...":"Crear nuevo usuario con acceso limitado ...","Creating target folders ...":"Creando las carpetas de destino ...","Creating temporary backup ...":"Creando una copia de seguridad temporal ...","Creating user...":"Creando usuario...","Current version is {{versionname}} ({{versionnumber}})":"La versión actual es {{versionname}} ({{versionnumber}})","Custom S3 endpoint":"Personalizada S3 endpoint","Custom authentication url":"Url de autenticación personalizada","Custom location ({{server}})":"Ubicación personalizada ({{server}})","Custom region for creating buckets":"Región personalizada para la creación de depósitos","Custom region value ({{region}})":"Personalizar el valor de la región ({{region}})","Custom server url ({{server}})":"Url del servidor personalizada ({{server}})","Custom storage class ({{class}})":"Categoría de almacenamiento personalizado ({{class}})","Days":"Días","Default":"Por defecto","Default ({{channelname}})":"({{channelname}}) por defecto","Default options":"Opciones por defecto","Delete":"Eliminar","Delete ...":"Eliminar ...","Delete backup":"Eliminar copia de seguridad","Delete local database":"Eliminar base de datos local","Delete remote files":"Eliminar archivos remotos","Delete the local database":"Eliminar la base de datos local","Delete {{filecount}} files ({{filesize}}) from the remote storage?":"¿Eliminar {{filecount}} archivos con ({{filesize}}) del almacenamiento remoto?","Deleting remote files ...":"Eliminando archivos remotos ...","Deleting unwanted files ...":"Eliminando archivos no deseados ...","Desktop":"Escritorio","Destination":"Destino","Did we help save your files? If so, please consider supporting Duplicati with a donation. We suggest {{smallamount}} for private use and {{largeamount}} for commercial use.":"¿Le hemos ayudado a guardar sus archivos? Si es así, por favor considere apoyar a Duplicati con una donación. Le sugerimos {{smallamount}} para uso privado y {{largeamount}} para uso comercial.","Direct restore from backup files ...":"Restaurar directamente desde ficheros de copia de seguridad...","Disabled":"Desactivar","Dismiss":"Descartar","Do you really want to delete the backup: \"{{name}}\" ?":"¿Realmente desea eliminar la copia de seguridad: \"{{name}}\"?","Do you really want to delete the local database for: {{name}}":"Realmente desea eliminar la base de datos local: {{name}}","Donate":"Donar","Donation messages":"Mensajes de donación","Donation messages are hidden, click to show":"El mensaje de donación está oculto, haga clic para mostrar","Donation messages are visible, click to hide":"El mensaje de donación está visible, haga clic para ocultar","Done":"Hecho","Download":"Descargar","Downloading ...":"Descargando ...","Downloading files ...":"Descargando archivos ...","Downloading update...":"Descargando actualizaciones...","Duplicate option {{opt}}":"Opciones de duplicado {{opt}}","Duplicati Website":"Sitio Web Duplicati","Duplicati forum":"Foro de Duplicati","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\n When deleting a backup, you can also delete the local database without affecting the ability to restore the remote files.\n If you are using the local database for backups from the commandline, you should keep the database.":"Cada copia tiene una base de datos local asociada que almacena información sobre la copia de seguridad remota en la máquina local.\nAl eliminar una copia de seguridad, también puede borrar la base de datos local sin afectar a la habilidad de restaurar los archivos remotos.\nSi está utilizando la base de datos local para copias de seguridad desde la línea de comandos, debe mantener la base de datos.","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\\nThis makes it faster to perform many operations, and reduces the amount of data that needs to be downloaded for each operation.":"Cada copia de seguridad tiene una base de datos local asociado a él, esta almacena información acerca de la copia de seguridad remota en el equipo local.\\nEsto hace más rápido realizar muchas operaciones y reduce la cantidad de datos que necesita descargarse para cada operación.","Edit ...":"Editar ...","Edit as list":"Editar lista","Edit as text":"Editar como texto","Encrypt file":"Cifrar archivo","Encryption":"Cifrado","Encryption changed":"Cambios de cifrado","Encryption modules:":"Módulos de cifrado:","Enter URL":"Introduzca URL","Enter access key":"Introduzca la clave de acceso","Enter account name":"Introduce el nombre de la cuenta","Enter backup passphrase, if any":"Introduzca la frase de seguridad, si la hay","Enter configuration details":"Introduzca los detalles de configuración","Enter container name":"Introduce el nombre de contenedor","Enter encryption passphrase":"Introduzca la frase de seguridad","Enter expression here":"Introduzca aquí la expresión","Enter folder path name":"Introduzca nombre de ruta de la carpeta","Enter one option per line in command-line format, eg. {0}":"Introduzca una opción por línea, en formato de línea de comandos, por ejemplo: {0}","Enter the destination path":"Introduzca la ruta de destino","Error":"Error","Error!":"¡Error!","Errors and crashes":"Errores y bloqueos","Exclude":"Excluir","Exclude directories whose names contain":"Excluir directorios cuyos nombres contienen","Exclude expression":"Excluir expresión","Exclude file":"Excluir archivos","Exclude file extension":"Excluir extensión de archivo","Exclude files whose names contain":"Excluir archivos cuyos nombres contengan","Exclude folder":"Excluir la carpeta","Exclude regular expression":"Excluir la expresión regular","Existing file found":"Archivo existente encontrado","Experimental":"Experimental","Export":"Exportar","Export ...":"Exportar ...","Export backup configuration":"Exportar configuración de copia de seguridad","Export configuration":"Exportar configuración","Exporting ...":"Exportando ...","FTP (Alternative)":"FTP (Alternativa)","Failed to build temporary database: {{message}}":"Error al crear base de datos temporal: {{message}}","Failed to connect:":"Fallo al conectar:","Failed to connect: {{message}}":"No se pudo conectar: {{message}}","Failed to delete:":"Error al eliminar:","Failed to fetch path information: {{message}}":"Error al recuperar información de la ruta: {{message}}","Failed to import:":"Fallo al importar:","Failed to read backup defaults:":"Error al leer los valores predeterminados de copia de seguridad:","Failed to restore files: {{message}}":"Fallo al restaurar archivos: {{message}}","Failed to save:":"Error al guardar:","Fetching path information ...":"Obteniendo información de ruta ...","File":"Archivo","Files larger than:":"Archivos que superen:","Filters":"Filtros","Finished!":"¡Terminado!","First run setup":"Configuración de primera ejecución","Folder":"Carpeta","Folder path":"Ruta de la carpeta","Fri":"Vie","GByte":"GByte","GByte/s":"GByte/s","GCS Project ID":"GCS Proyecto ID","General":"General","General backup settings":"Configuración general de la copia de seguridad","General options":"Opciones generales","Generate":"Generar","Generate IAM access policy":"Generar política de acceso IAM","Getting file versions ...":"Recuperando versiones de ficheros...","Hidden files":"Archivos ocultos","Hide":"Ocultar","Hide hidden folders":"Ocultar carpetas ocultas","Home":"Inicio","Hours":"Horas","How do you want to handle existing files?":"¿Cómo desea manejar los archivos existentes?","Hyper-V Machine":"Máquina Hyper-V","Hyper-V Machine:":"Máquina Hyper-V:","Hyper-V Machines":"Máquinas Hyper-V","ID:":"ID:","If a date was missed, the job will run as soon as possible.":"Si la fecha se paso, se ejecutará el trabajo tan pronto como sea posible.","If the backup and the remote storage is out of sync, Duplicati will require that you perform a repair operation to synchronize the database.\\nIf the repair is unsuccesful, you can delete the local database and re-generate.":"Si la copia de seguridad y el almacenamiento remoto están fuera de sincronización, Duplicati requerirá que realice una operación de reparación para sincronizar la base de datos. \\nSi la reparación fracasa, puede eliminar la base de datos local y volver a generarla.","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"Si el archivo de copia de seguridad no se descarga automáticamente, haga click derecho y elija "Guardar como ..."","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"Si el archivo de copia de seguridad no se descarga automáticamente, haga click derecho y elija "Guardar como ..."","If you do not enter a path, all files will be stored in the login folder.\nAre you sure this is what you want?":"Si no introduce una ruta, todos los archivos se almacenarán en la carpeta de inicio de sesión.\n¿Está seguro que es lo que quiere?","If you do not enter an API Key, the tenant name is required":"Si no introduce una clave API, requerirá el nombre de cliente","If you want to use the backup later, you can export the configuration before deleting it":"Si desea utilizar la copia de seguridad más adelante, puede exportar la configuración antes de eliminarla","Import":"Importar","Import Destination URL":"Importar Destino URL","Import backup configuration":"Importar configuración de copias de seguridad","Import completed, but no certificates were found after the import":"Importación completada, pero no se han encontrado certificados despues de la importación","Import failed":"Importación fallida","Import from a file":"Importar desde un archivo","Importing ...":"Importando ...","Include a file?":"¿Incluir un archivo?","Include expression":"Incluir una expresión","Include regular expression":"Incluir una expresión regular","Incorrect answer, try again":"Respuesta incorrecta, intente de nuevo","Individual builds for developers only.":"Compilación individual sólo para desarrolladores.","Information":"Información","Install":"Instalar","Install failed:":"Error de instalación:","Invalid retention time":"Tiempo de retención no válido","It is possible to connect to some FTP without a password.\nAre you sure your FTP server supports password-less logins?":"Es posible conectar a un FTP sin contraseña.\n¿Está seguro que su servidor FTP admite los inicios de sesión sin contraseña?","KByte":"KByte","KByte/s":"KByte/s","Language in user interface":"Idioma de interfaz de usuario","Last month":"Mes pasado","Last successful run:":"Última ejecución exitosa:","Latest":"Más reciente","Libraries":"Librerías","Listing backup dates ...":"Listado de fechas de copia de seguridad ...","Listing remote files ...":"Listado de archivos remotos ...","Live":"En vivo","Load a configuration from an exported job or a storage provider":"Cargar una configuración desde un trabajo exportado o un proveedor de almacenamiento","Load destination from an exported job or a storage provider":"Cargar un destino desde un trabajo exportado o un proveedor de almacenamiento","Load older data":"Cargar datos anteriores","Loading ...":"Cargando ...","Loading remote storage usage ...":"Cargando el uso del almacenamiento remoto ...","Local database for":"Base de datos local para","Local database path:":"Ruta de la base de datos local:","Local storage":"Almacenamiento local","Location":"Localización","Location where buckets are created":"La ubicación donde se crean los depósitos","Log data for {{Backup.Backup.Name}}":"Registrar datos para {{Backup.Backup.Name}}","Log data from the server":"Registrar datos desde el servidor","Log out":"Desconectar","MByte":"MByte","MByte/s":"MByte/s","Maintenance":"Mantenimiento","Manually type path":"Escribir manualmente la ruta","Max download speed":"Velocidad máxima de descarga","Max upload speed":"Velocidad máxima de carga","Menu":"Menú","Microsoft SQL Database:":"Base de datos Microsoft SQL:","Microsoft SQL Databases":"Bases de datos Microsoft SQL:","Minimum redundancy":"Redundancia mínima","Minimum redundancy is 1.0":"Redundancia mínima es 1.0","Minutes":"Minutos","Missing name":"Falta el nombre","Missing passphrase":"Falta la frase de seguridad","Missing sources":"Faltan las fuentes","Mon":"Lun","Months":"Meses","Move existing database":"Mover base de datos existente","Move failed:":"Fallos al mover:","My Documents":"Mis Documentos","My Music":"Mi Música","My Photos":"Mis Fotos","My Pictures":"Mis Imágenes","Name":"Nombre","Never":"Nunca","New update found: {{message}}":"Nueva actualización encontrada: {{message}}","New user name is {{user}}.\nUpdated credentials to use the new limited user":"El nuevo nombre de usuario es {{user}}.\nCredenciales actualizadas para el nuevo usuario restringido","Next":"Siguiente","Next scheduled run:":"Siguiente ejecución programada:","Next scheduled task:":"Siguiente tarea programada:","Next task:":"Siguiente tarea:","Next time":"La próxima vez","No":"No","No certificate was specified previously, please verify with the server administrator that the key is correct: {{key}} \n\nDo you want to approve the reported host key?":"No se especificó previamente un certificado, por favor verifica con el administrador del servidor que la llave es correcta: {{key}}\n\n¿Desea aprobar la llave del host reportada?","No editor found for the "{{backend}}" storage type":"Ningún editor para el "{{backend}}" tipo de almacenamiento","No encryption":"Sin cifrado","No items selected":"No hay artículos seleccionados","No items to restore, please select one or more items":"No hay artículos para restaurar, seleccione uno o más elementos","No passphrase entered":"No se introdujo clave de seguridad","No scheduled tasks":"No hay tareas programadas","No, my machine has only a single account":"No, mi equipo tiene sólo una cuenta","Non-matching passphrase":"No coincide la frase de seguridad","None / disabled":"Ninguno / desactivado","OK":"OK","OpenStack AuthURI":"OpenStack AuthURI","OpenStack Object Storage / Swift":"OpenStack Object Storage / Swift","Operation failed:":"Operación fallida:","Operations:":"Operaciones:","Optional authentication password":"Contraseña de autentificación opcional","Optional authentication username":"Nombre de usuario para autentificación opcional","Options":"Opciones","Options added here are applied to all backups, but can be overridden in each individual backup":"Las opciones agregadas aquí aplican a todos los respaldos, pero pueden ser modificadas individualmente en ellos","Original location":"Localización original","Others":"Otros","Overwrite":"Sobrescribir","Passphrase":"Frase de seguridad","Passphrase (if encrypted)":"Frase de seguridad (con cifrado)","Passphrase changed":"Frase de seguridad cambiada","Passphrases are not matching":"Las frases de seguridad no coinciden","Password":"Contraseña","Passwords do not match":"La contraseña no coincide","Patching files with local blocks ...":"Arreglar los archivos con bloques locales ...","Path not found":"Ruta no encontrada","Path on server":"Ruta del servidor","Path or subfolder in the bucket":"Ruta o subcarpeta en el depósito","Pause":"Pausa","Pause after startup or hibernation":"Pausar después del arranque o de hibernación","Pause options":"Opciones de pausa","Permissions":"Permisos","Pick location":"Elegir ubicación","Point to your backup files and restore from there":"Indique sus ficheros de copia de seguridad y restáurelos desde allí","Port":"Puerto","Previous":"Anterior","ProjectID is optional if the bucket exist":"ProjectID es opcional si el depósito existe","Proprietary":"Propietario","Purging files ...":"Purgando ficheros...","Rebuilding local database ...":"Reconstruyendo la base de datos local ...","Recreate (delete and repair)":"Recrear (borrar y reparar)","Recreating database ...":"Recreando base de datos ...","Registering temporary backup ...":"Registrando copia de seguridad temporal …","Relative paths not allowed":"No se permiten rutas relativas","Reload":"Recargar","Remote":"Remoto","Remove":"Quitar","Remove option":"Quitar opción","Repair":"Reparar","Reparing ...":"Reparando ...","Repeat Passphrase":"Repita la frase de seguridad","Reporting:":"Reportando:","Reset":"Resetear","Restore":"Restaurar","Restore files":"Restaurar archivos","Restore files ...":"Restaurar archivos ...","Restore files from {{backupname}}":"Restaurar ficheros desde {{backupname}}","Restore from":"Restaurar desde","Restore from backup configuration":"Restaurar desde una configuración de copia de seguridad","Restore from configuration ...":"Restaurar desde una configuración...","Restore options":"Opciones de restauración","Restore read/write permissions":"Restaurar permisos de lectura/escritura","Restoring files ...":"Restaurando archivos ...","Resume":"Resumir","Run again every":"Volver a ejecutar cada","Run now":"Ejecutar ahora","Running ...":"Ejecutando ...","Running ....":"Ejecutando ...","Running task:":"Ejecutando tarea:","S3 Compatible":"S3 Compatible","Same as the base install version: {{channelname}}":"Igual que la versión base instalada: {{channelname}}","Sat":"Sab","Save":"Guardar","Save and repair":"Guardar y reparar","Save different versions with timestamp in file name":"Guardar diferentes versiones con fecha y hora en el nombre de archivo","Save immediately":"Guardar inmediatamente","Scanning existing files ...":"Analizando los archivos existentes ...","Scanning for local blocks ...":"Analizando bloques locales ...","Schedule":"Horario","Search":"Buscar","Search for files":"Buscar archivos","Seconds":"Segundos","Select a log level and see messages as they happen:":"Seleccione un nivel de registro y vea los mensajes a medida que ocurren:","Select files":"Seleccionar ficheros","Server":"Servidor","Server and port":"Servidor y puerto","Server hostname or IP":"Nombre del servidor o IP","Server is currently paused,":"El servidor se encuentra en pausa,","Server is currently paused, do you want to resume now?":"El servidor se encuentra en pausa, ¿quiere reanudar ahora?","Server paused":"Servidor pausado","Server state properties":"Propiedades del estado del servidor","Settings":"Configuraciones","Show":"Mostrar","Show advanced editor":"Mostrar el editor avanzado","Show hidden folders":"Mostrar carpetas ocultas","Show log":"Mostrar registro","Show log ...":"Mostrar registro ...","Show treeview":"Mostrar vista de árbol","Some OpenStack providers allow an API key instead of a password and tenant name":"Algunos proveedores de OpenStack permiten una clave API en lugar de un nombre del cliente y contraseña","Source Data":"Datos de Origen","Source data":"Datos de origen","Source folders":"Carpetas de origen","Source:":"Origen:","Specific builds for developers only.":"Compilación específica solo para desarrolladores.","Standard protocols":"Protocolos estándar","Starting ...":"Iniciando ...","Starting the restore process ...":"Iniciando el proceso de restauración ...","Stop after the current file":"Detener después del archivo actual","Stop after upload":"Detener después de cargar","Stop now":"Detener ahora","Stop running backup":"Detener respaldo en curso","Stop running task":"Detener tarea en ejecución","Stopping after upload:":"Deteniendo después de cargar:","Stopping task:":"Deteniendo tarea:","Storage Type":"Tipo de Almacenamiento","Storage class":"Categoría de almacenamiento","Storage class for creating a bucket":"Categoría de almacenamiento para la creación de un depósito","Stored":"Almacenados","Strong":"Fuerte","Success":"Éxito","Sun":"Dom","Symbolic link":"Enlace simbólico","System default ({{levelname}})":"Sistema por defecto ({{levelname}})","System files":"Archivos de sistema","System info":"Información del sistema","System properties":"Propiedades del sistema","TByte":"TByte","TByte/s":"TByte/s","Task is running":"La tarea está ejecutandose","Temporary files":"Archivos temporales","Tenant Name":"Nombre del Cliente","Test connection":"Conexión de prueba","Testing ...":"Probando …","Testing connection ...":"Probando la conexión ...","Testing permissions ...":"Probando permisos …","Testing permissions...":"Probando permisos…","The bucket name should be all lower-case, convert automatically?":"El nombre del depósito debe ser todo en minúsculas, ¿convertir automáticamente?","The bucket name should start with your username, prepend automatically?":"El nombre del depósito debe empezar con su nombre de usuario, ¿anteponer automáticamente?","The connection to the server is lost, attempting again in {{time}} ...":"La conexión al servidor se perdió, intentar otra vez en {{time}} ...","The dark theme (by Michal)":"Tema oscuro (por Michal)","The default blue on white theme (by Alex)":"Tema por defecto azul sobre blanco (por Alex)","The host key has changed, please check with the server administrator if this is correct, otherwise you could be the victim of a MAN-IN-THE-MIDDLE attack.\n\nDo you want to REPLACE your CURRENT host key \"{{prev}}\" with the REPORTED host key: {{key}}?":"La clave de host fue cambiada, compruebe con el administrador del servidor si esto es correcto, de lo contrario usted podría ser víctima de un ataque MAN-IN-THE-MIDDLE.\n\n¿Desea REMPALAZAR su ACTUAL clave de host \"{{prev}}\" con la clave del host REGISTRADA: {{key}}?","The path does not appear to exist, do you want to add it anyway?":"La ruta parece que no existe, ¿desea agregar de todos modos?","The path does not end with a '{{dirsep}}' character, which means that you include a file, not a folder.\n\nDo you want to include the specified file?":"La ruta no termina con un carácter '{{dirsep}}', que significa que incluye un archivo, no una carpeta.\n\n¿Desea incluir el archivo especificado?","The path must be an absolute path, i.e. it must start with a forward slash '/'":"La ruta debe ser una ruta absoluta, es decir, debe comenzar con una barra '/'","The region parameter is only applied when creating a new bucket":"El parámetro de la región sólo se aplica al crear un nuevo depósito","The region parameter is only used when creating a bucket":"El parámetro de la región sólo se utiliza al crear un depósito","The server certificate could not be validated.\nDo you want to approve the SSL certificate with the hash: {{hash}}?":"El certificado del servidor no puede ser validado.\n¿Quieres aprobar el certificado SSL con el hash: {{hash}}?","The storage class affects the availability and price for a stored file":"La categoría de almacenamiento afecta la disponibilidad y precio de un archivo almacenado","The target folder contains encrypted files, please supply the passphrase":"La carpeta de destino contiene archivos encriptados, por favor suministra la frase de seguridad","The user has too many permissions. Do you want to create a new limited user, with only permissions to the selected path?":"El usuario tiene demasiados permisos. ¿Quieres crear un usuario nuevo, con sólo permisos para la ruta seleccionada?","This backup was created on another operating system. Restoring files without specifying a destination folder can cause files to be restored in unexpected places. Are you sure you want to continue without choosing a destination folder?":"Esta copia de seguridad fue creada en otro sistema operativo. Restaurar estos ficheros sin indicar una carpeta de destino puede provocar que sean restaurados en ubicaciones imprevistas ¿Está seguro de que quiere continuar sin elegir una carpeta de destino?","This month":"Este mes","This week":"Esta semana","Thu":"Jue","To File":"A archivo","To confirm you want to delete all remote files for \"{{name}}\", please enter the word you see below":"Para confirmar que desea eliminar todos los archivos remotos \"{{name}}\", por favor ingrese la palabra que ves abajo","To export without a passphrase, uncheck the \"Encrypt file\" box":"Para exportar sin una frase de seguridad, desactive la casilla \"Cifrar el archivo\"","Today":"Hoy","Trust host certificate?":"¿Confiar en el certificado del host?","Trust server certificate?":"¿Confiar en el certificado del servidor?","Try out the new features we are working on. Don't use with important data.":"Pruebe las nuevas funciones en las que estamos trabajando. No utilizar con datos importantes.","Tue":"Mar","Type to highlight files":"Tipo para seleccionar archivos","Unknown backup size and versions":"Tamaño y versiones de la copia de seguridad desconocidas","Until resumed":"Hasta reanudar","Update channel":"Canal de actualización","Update failed:":"Error de actualización:","Updating with existing database":"Actualizando la base de datos existente","Upload volume size":"Tamaño del volumen de subida","Uploading verification file ...":"Cargar archivo de verificación ...","Usage statistics":"Estadísticas de uso","Usage statistics, warnings, errors, and crashes":"Estadísticas de uso, advertencias, errores y bloqueos","Use SSL":"Usar SSL","Use existing database?":"¿Usar base de datos existente?","Use weak passphrase":"Uso de frase de seguridad débil","Useless":"Inútil","User data":"Datos de usuario","User has too many permissions":"El usuario tiene demasiados permisos","User interface settings":"Preferencias de la interfaz de usuario","Username":"Nombre de usuario","Validating ...":"Validando …","Verify files":"Verificar archivos","Verifying ...":"Verificando ...","Verifying answer":"Verificando respuesta","Verifying backend data ...":"Verificando datos de respaldo ...","Verifying remote data ...":"Verificando datos remotos ...","Verifying restored files ...":"Verificando archivos restaurados ...","Very strong":"Muy fuerte","Very weak":"Muy débil","Visit us on":"Visítenos en","WARNING: The remote database is found to be in use by the commandline library":"ADVERTENCIA: La base de datos remota se encuentre en uso por la biblioteca de la línea de comandos","WARNING: This will prevent you from restoring the data in the future.":"ADVERTENCIA: Esto le impedirá restaurar los datos en el futuro.","Waiting for task to begin":"Esperando que se inicie la tarea","Waiting for task to start ....":"Esperando que comience la tarea ....","Waiting for upload ...":"Esperando la subida ...","Warnings, errors and crashes":"Advertencias, errores y bloqueos","We recommend that you encrypt all backups stored outside your system":"Recomendamos cifrar todas las copias de seguridad almacenadas fuera de su sistema","Weak":"Débil","Weak passphrase":"Frase de seguridad débil","Wed":"Mié","Weeks":"Semanas","Where do you want to restore from?":"¿Desde dónde quiere restaurar?","Where do you want to restore the files to?":"¿Dónde desea restaurar los archivos?","Years":"Años","Yes":"Sí","Yes, I have stored the passphrase safely":"Sí, he guardado la frase de seguridad de forma segura","Yes, I'm brave!":"Sí, ¡soy valiente!","Yes, please break my backup!":"Sí, por favor, ¡rompe mi copia de seguridad!","Yesterday":"Ayer","You appear to be running Mono with no SSL certificates loaded.\nDo you want to import the list of trusted certificates from Mozilla?":"Parece estar ejecutando Mono sin certificados SSL cargados.\n¿Desea importar la lista de certificados de confianza de Mozilla?","You are changing the database path away from an existing database.\nAre you sure this is what you want?":"Está cambiando la ruta de la base de datos de una base de datos existente.\n¿Realmente es lo que quieres?","You are currently running {{appname}} {{version}}":"Actualmente está ejecutando {{appname}} {{version}}","You have changed the encryption mode. This may break stuff. You are encouraged to create a new backup instead":"Ha cambiado el modo de encriptación. Esto puede quebrar cosas. Le animamos a crear una nueva copia de seguridad en su lugar","You have changed the passphrase, which is not supported. You are encouraged to create a new backup instead.":"Ha cambiado la frase de seguridad, la cual no es compatible. Le animamos a crear una nueva copia de seguridad en su lugar.","You have chosen not to encrypt the backup. Encryption is recommended for all data stored on a remote server.":"Ha optado por no cifrar la copia de seguridad. El cifrado se recomienda para todos los datos almacenados en un servidor remoto.","You have chosen to restore to a new location, but not entered one":"Ha elegido restaurar a una nueva ubicación, pero no la ha indicado","You must choose at least one source folder":"Debe seleccionar al menos una carpeta de origen","You must enter a name for the backup":"Debe introducir un nombre para la copia de seguridad","You must enter a passphrase or disable encryption":"Debe ingresar una frase de seguridad o deshabilitar el cifrado","You must enter a positive number of backups to keep":"Debe especificar un número positivo de copias de seguridad a guardar","You must enter a tenant name if you do not provide an API Key":"Debe introducir un nombre de cliente si no proporciona una clave API","You must enter a valid duration for the time to keep backups":"Debe introducir una duración válida para el tiempo de retención de las copias de seguridad","You must enter either a password or an API Key":"Debe introducir una contraseña o una clave API","You must enter either a password or an API Key, not both":"Debe introducir una contraseña o una clave API, no ambos","You must fill in the password":"Debe rellenar la contraseña","You must fill in the server name or address":"Debe introducir el nombre del servidor o la dirección","You must fill in the username":"Debe rellenar el nombre de usuario","You must fill in {{field}}":"Debe rellenar el {{field}}","You must select or fill in the AuthURI":"Debe seleccionar o rellenar la AuthURI","You must select or fill in the server":"Debe seleccionar o rellenar en el servidor","You must specify a path":"Debe especificar una ruta de acceso","Your files and folders have been restored successfully.":"Los archivos y carpetas han sido restaurados con éxito.","Your passphrase is easy to guess. Consider changing passphrase.":"Tu frase de seguridad es fácil de adivinar. Considere cambiarla.","bucket/folder/subfolder":"depósito/carpeta/subcarpeta","byte":"byte","byte/s":"byte/s","custom":"Personalizar","resume now":"reanudar ahora","{{appname}} was primarily developed by {{dev1}} and {{dev2}}. {{appname}} can be downloaded from {{websitename}}. {{appname}} is licensed under the {{licensename}}.":"{{appname}} fue desarrollado principalmente por {{dev1}} y {{dev2}}. Puede descargarse {{appname}} desde {{websitename}}. {{appname}} está licenciado bajo {{licensename}}.","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Version":["{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Versión","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Versiones"],"{{number}} Hour":"{{number}} Hora","{{number}} Minutes":"{{number}} Minutos","{{time}} (took {{duration}})":"{{time}} (llevó {{duration}})"}); gettextCatalog.setStrings('fi', {"- pick an option -":"- Valitse jokin vaihtoehto -","...loading...":"...ladataan...","API Key":"API-avain","AWS Access ID":"Tunniste \"Access Key ID\" palveluun AWS","AWS Access Key":"Tunniste \"Access Key ID\" palveluun AWS","AWS IAM Policy":"Palvelun AWS IAM-asetukset","About":"Tietoja","About {{appname}}":"Tietoja sovelluksesta {{appname}}","Access Key":"Pääsyavain","Access denied":"Pääsy evätty","Access to user interface":"Käyttöoikeus käyttöliittymään","Account name":"Käyttäjätunnus","Activate":"Aktivoi","Activate failed:":"Aktivointi epäonnistui","Add a new backup":"Lisää uusi varmuuskopio","Add advanced option":"Anna harvoin tarvittava valitsin","Add backup":"Lisää varmuuskopio","Add filter":"Lisää suodatin","Add path":"Lisää polku","Adjust bucket name?":"Muuta ämpärin nimeä?","Adjust path name?":"Muuta polkua?","Advanced Options":"Harvoin tarvittavat valitsimet","Advanced options":"Harvoin tarvittavat valitsimet","Advanced:":"Harvoin tarvittavat asetukset","All Hyper-V Machines":"Kaikki Hyper-V-virtuaalikoneet","All Microsoft SQL Databases":"Kaikki Microsoft SQL -tietokannat","All usage reports are sent anonymously and do not contain any personal information. They contain information about hardware and operating system, the type of backend, backup duration, overall size of source data and similar data. They do not contain paths, filenames, usernames, passwords or similar sensitive information.":"Kaikki käyttöraportit lähetetään anonyymisti. Ne eivät sisällä mitään henkilökohtaisia tietoja. Raportit sisältävät tietoja laitteistosta ja käyttöjärjestelmästä, käytetystä etäpalvelusta, varmuuskopion kestosta, varmuuskopioitavan datan määrästä yms.Raportit eivät sisällä polkuja, tiedostonimiä, käyttäjätunnuksia, salasanoja tai vastaavia tietoja.","Allow remote access (requires restart)":"Salli etäyhteydet (Vaatii Duplicatin uudeleenkäynnistämisen)","Allowed days":"Sallitut päivät","An existing file was found at the new location":"Olemassaoleva tiedosto löydettiin uudesta paikasta","An existing file was found at the new location\nAre you sure you want the database to point to an existing file?":"Annettu tietokanta on jo olemassa.\nOletko varma, että haluat käyttää olemassaolevaa tietokantaa?","An existing local database for the storage has been found.\nRe-using the database will allow the command-line and server instances to work on the same remote storage.\n\n Do you wish to use the existing database?":"Löydettiin olemassaoleva paikallinen tietokanta tälle varmuuskopiolle.\nSaman tietokannan käyttäminen mahdollistaa kometorivi-ohjelman ja palvelimen käyttämisen saman varmuuskopion kanssa.\n\nHaluatko käyttää samaa tietokantaa?","Anonymous usage reports":"Anonyymit käyttöraportit","As Command-line":"Komentona","AuthID":"AuthID","Authentication password":"Kirjautumissalasana","Authentication username":"Käyttäjätunnus","Autogenerated passphrase":"Automaattisesti luoto salauslause","Automatically run backups.":"Tee varmuuskopiot automaattisesti","B2 Account ID":"B2-tilin ID","B2 Application Key":"B2 Application Key","B2 Cloud Storage Account ID":"Tunnus B2 Cloud Storage Account ID","B2 Cloud Storage Application Key":"B2 Cloud Storage Application Key","Back":"Palaa","Backend modules:":"Etäpalvelinmoduulit:","Backup destination":"Sijainti, johon varmuuskopio tehdään","Backup location":"Varmuuskopion sijainti","Backup:":"Varmuuskopio:","Beta":"Beta","Broken access":"Pääsy epäonnistui","Browse":"Selaa","Browser default":"Selaimen oletusasetus","Bucket Name":"Ämpärin nimi","Bucket create location":"Luo ämpäri sijaintiin","Bucket create region":"Luo ämpäri alueelle","Bucket name":"Ämpärin nimi","Bucket storage class":"Ämpärin tallennusluokka","Building list of files to restore ...":"Kootaan listaa palautettavista tiedostoista ...","Building partial temporary database ...":"Koostan osittaista tilapäistä tietokantaa ...","Busy ...":"Työskentelen ...","Canary":"Canary","Cancel":"Peruuta","Cannot move to existing file":"Ei voida korvata olemassaolevaa tiedostoa","Changelog":"Muutokset","Changelog for {{appname}} {{version}}":"Muutokset versiossa {{appname}} {{version}}","Check failed:":"Päivitysten haku epäonnistui:","Check for updates now":"Hae päivityksiä nyt","Checking ...":"Haetaan ...","Checking for updates ...":"Haetaan päivityksiä ...","Chose a storage type to get started":"Valitseensin tallennustyyppi","Click the AuthID link to create an AuthID":"Klikkaa AuthID-linkkiä luodaksesi AuthID-tunnisteen","Compact now":"Tiivistä nyt","Compacting remote data ...":"Tiivistän varmuuskopiota etäpalvelimella ...","Completing backup ...":"Viimeistelen varmuuskopiota ...","Completing previous backup ...":"Viimeistelen edellistä varmuuskopiota ...","Compression modules:":"Pakkausmoduulit","Computer":"Tietokone","Configuration file:":"Asetustiedosto","Configuration:":"Asetukset:","Configure a new backup":"Määrittele uusi varmuuskopio","Confirm delete":"Vahvista poistaminen","Confirmation required":"Tarvitsen vahvistuksen","Connect":"Yhdistä","Connect now":"Yhdistä nyt","Connecting...":"Yhdistän ...","Connection lost":"Yhteys katkesi","Connection worked!":"Yhteys toimi!","Container name":"Kontin nimi","Container region":"Kontin alue","Continue":"Jatka","Continue without encryption":"Jatka salaamatta","Copied!":"Kopioitu!","Copy Destination URL to Clipboard":"Kopio etäpalvelimen osoite leikepöydälle","Copy failed. Please manually copy the URL":"Kopionti epäonnistui. Kopio osoite käsin","Core options":"Ydinasetukset","Counting ({{files}} files found, {{size}})":"Lasketaan tiedostoja. (Löydetty {{files}} tiedostoa, {{size}})","Crashes only":"Vain kaatumiset","Create bug report ...":"Luo ilmoitus ohjelmistovirheestä ...","Create folder?":"Luo kansio?","Created new limited user":"Luotiin uusi rajoitettu käyttäjä","Creating bug report ...":"Luodaan ilmoitusta ohjelmistovirheestä ...","Creating new user with limited access ...":"Luon uutta rajoitettua käyttäjää ...","Creating target folders ...":"Luon kohdekansioita","Creating temporary backup ...":"Luon tilapäistä varmuuskopiota ...","Creating user...":"Luon käyttäjää ...","Current version is {{versionname}} ({{versionnumber}})":"Nykyinen versio on {{versionname}} ({{versionnumber}})","Custom S3 endpoint":"Vaihtoehtoinen S3 päätepiste","Custom authentication url":"Vaihtoehtoinen autentikointiosoite","Custom location ({{server}})":"Vaihtoehtoinen sijainti ({{server}})","Custom region for creating buckets":"Vaihtoehtoinen alue ämpärin luomista varten","Custom region value ({{region}})":"Vaihtoehtoinen alue ({{region}})","Custom server url ({{server}})":"Vaihtoehtoisen palvelimen osoite ({{server}})","Custom storage class ({{class}})":"Vaihtoehtoinen tallennusluokka ({{class}})","Days":"Päivää","Default":"Oletus","Default ({{channelname}})":"Oletus ({{channelname}})","Default options":"Oletusasetukset","Delete":"Poista","Delete ...":"Poistan ...","Delete backup":"Poista varmuuskopio","Delete local database":"Poista paikallinen tietokanta","Delete remote files":"Poista tiedostot etäpalvelimelta","Delete the local database":"Poista paikallinen tietokanta","Delete {{filecount}} files ({{filesize}}) from the remote storage?":"Poistetaanko {{filecount}} tiedostoa ({{filesize}}) etäpalvelimelta","Deleting remote files ...":"Poistan tiedostoja etäpalvelimelta ...","Deleting unwanted files ...":"Poistan tiedotoja ...","Desktop":"Työpöytä","Destination":"Kohde","Did we help save your files? If so, please consider supporting Duplicati with a donation. We suggest {{smallamount}} for private use and {{largeamount}} for commercial use.":"Autoimmeko me pelastamaan tiedostosi? Jos autoimme, harkitse Duplicatin tukemista pienellä lahjoituksella. Suossitamme {{smallamount}} kotikäytössä ja {{largeamount}} yrityskäytössä.","Disabled":"Positetteu käytöstä","Dismiss":"Ohita","Do you really want to delete the backup: \"{{name}}\" ?":"Haluatko varmasti poistaa varmuuskopion \"{{name}}\"?","Do you really want to delete the local database for: {{name}}":"Haluatko varmasti poistaa varmuuskopion {{name}} paikallisen tietokannan?","Donate":"Lahjoita","Donation messages":"Lahjoituskehoitukset","Donation messages are hidden, click to show":"Lahjoituskehoitukset on poistettu käytöstä. Klikkaa ottaaksesi ne käyttöön.","Donation messages are visible, click to hide":"Lahjoituskehoitukset ovat käytössä. Klikkaa poistaaksesi ne käytöstä.","Done":"Valmis","Download":"Lataa","Downloading ...":"Lataan ...","Downloading files ...":"Lataan tiedostoja ...","Downloading update...":"Lataan päivitystä ...","Duplicate option {{opt}}":"Sama valitsin {{opt}} annettiin kahdesti","Duplicati Website":"Duplicatin verkkosivu","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\\nThis makes it faster to perform many operations, and reduces the amount of data that needs to be downloaded for each operation.":"Jokaisella varmuuskopiolla on oma paikallinen tietokanta, joka sisältää tiedot etäpalvelimella olevista varmuuskopioista.\\nTämä nopeuttaa monia toimenpiteitä ja vähentää etäpalvelimelta ladattavan datan määrää.","Edit ...":"Muokkaa ...","Edit as list":"Muokkaa listana","Edit as text":"Muokkaa tekstinä","Encrypt file":"Salaa tiedosto","Encryption":"Salaus","Encryption changed":"Salausasetukset ovat muuttuneet","Encryption modules:":"Saluasmoduulit:","Enter URL":"Anna URL","Enter access key":"Anna pääsyavain","Enter account name":"Anna käyttäjätunnus","Enter backup passphrase, if any":"Anna varmuuskopion salauslause, jos käytät salausta.","Enter container name":"Anna kontin nimi","Enter encryption passphrase":"Anna salauslause","Enter expression here":"Anna ilmaisu","Enter folder path name":"Anna kansion polku","Enter one option per line in command-line format, eg. {0}":"Syötä valitsimet yksi kullekin riville. Esim: {0}","Enter the destination path":"Anna kohdekansion polku","Error":"Virhe","Error!":"Virhe!","Errors and crashes":"Virheet ja kaatumiset","Exclude":"Ohita","Exclude directories whose names contain":"Ohita kansiot, joiden nimessä on","Exclude expression":"Ohita ilmaisu","Exclude file":"Ohita tiedosto","Exclude file extension":"Ohita tämän tyyppiset tiedostot","Exclude files whose names contain":"Ohita tiedostot, joiden nimessä on","Exclude folder":"Ohita kansio","Exclude regular expression":"Ohita säännöllistä ilmaisua vastaavat kohteet","Existing file found":"Löydettiin olemassaoleva tiedosto","Experimental":"Experimental","Export":"Vie","Export ...":" Vien ...","Export backup configuration":"Vie varmuuskopion asetukset","Export configuration":"Vie asetukset","Exporting ...":"Vien ...","FTP (Alternative)":"FTP (vaihtoehtoinen)","Failed to build temporary database: {{message}}":"Tilapäisen tietokannan luominen epäonnistui. Virhe: {{message}}","Failed to connect:":"Yhteyden muodostaminen epäonnistui:","Failed to connect: {{message}}":"Yhteyden muodostaminen epäonnistui: {{message}}","Failed to delete:":"Poistaminen epäonnistui:","Failed to fetch path information: {{message}}":"Polkutietojen noutaminen epäonnistui: {{message}}","Failed to import:":"Tuominen epäonnistui:","Failed to read backup defaults:":"Varmuuskopion oletusasetusten lukeminen epäonnistui:","Failed to restore files: {{message}}":"Tiedostojen palauttaminen epäonnistui: {{message}}","Failed to save:":"Tallennus epäonnistui:","Fetching path information ...":"Haen tietoja poluista ...","File":"Tiedosto","Files larger than:":"Tiedostot, joiden koko on suurempi kuin:","Filters":"Suodattimet","Finished!":"Valmis!","Folder":"Kansio","Folder path":"Kansion polku","Fri":"Pe","GByte":"GT","GByte/s":"GT/s","GCS Project ID":"GCS Projektin ID","General":"Yleinen","General backup settings":"Yleiset varmuuskopioasetukset","General options":"Yleiset asetukset","Generate":"Luo","Generate IAM access policy":"Luo Amazon IAM access policy","Getting file versions ...":"Haetaan tiedostojen versioita ...","Hidden files":"Piilotetut tiedostot","Hide":"Piilota","Hide hidden folders":"Älä näytä piilotettuja kansioita","Home":"Etusivu","Hours":"tuntia","How do you want to handle existing files?":"Mitä tehdään olemassa oleville tiedostoille?","Hyper-V Machine":"Hyper-V-virtuaalikone","Hyper-V Machine:":"Hyper-V-virtuaalikone:","Hyper-V Machines":"Hyper-V-virtuaalikoneet","ID:":"ID:","If a date was missed, the job will run as soon as possible.":"Jos ajastettu varmuuskopio jää tekemättä, se tehdään niin pian kuin mahdollista.","If the backup and the remote storage is out of sync, Duplicati will require that you perform a repair operation to synchronize the database.\\nIf the repair is unsuccesful, you can delete the local database and re-generate.":"Jos etäpalvelimella oleva varmuuskopio ja paikallinen tietokanta eivät ole synkronoituja, Duplicati vaatii tietokannan korjauksen.\\nJos korjaus ei onnistu voit poistaa luoda uudelleen paikallisen tietokannan.","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"Jos varmuuskopiotiedosto ei latautunut automaattisesti, klikkaa oikealla näppäimellä ja valitse "Tallenna nimellä ..."","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"Jos varmuuskopiotiedosto ei latautunut automaattisesti, klikkaa oikealla näppäimellä ja valitse "Tallenna nimellä ..."","If you do not enter a path, all files will be stored in the login folder.\nAre you sure this is what you want?":"Jos et anna polkua, kaikki tiedostot tallennetaan kirjautumiskansioon.\nOletko varma, että haluat tätä?","If you do not enter an API Key, the tenant name is required":"Jos et anna tunnistetta API key, on tunniste \"tenant name\" pakollinen","If you want to use the backup later, you can export the configuration before deleting it":"Jos haluat luoda varmuuskopion myöhemmin uudelleen, voit viedä tiedostoon ennen poistamista.","Import":"Tuo","Import Destination URL":"Tuo etäpalvelimen osoite","Import backup configuration":"Tuo varmuuskopion asetukset","Import completed, but no certificates were found after the import":"Tuominen valmistui, mutta yhtään sertifikaattia ei löytynyt sen jälkeen","Import failed":"Tuominen epäonnistui","Importing ...":"Tuon ...","Include a file?":"Sisällytä tiedosto?","Include expression":"Sisällytä ilmaisua vastaavat kohteet","Include regular expression":"Sisällytä säännöllistä ilmaisua vastaavat kohteet","Incorrect answer, try again":"Virheellinen vastaus. Yritä uudelleen.","Individual builds for developers only.":"Kehittäjille tarkoitetut testiversiot","Information":"Informaatio","Install":"Asenna","Install failed:":"Asennus epäonnistui:","Invalid retention time":"Epäkelpo säilytysaika","It is possible to connect to some FTP without a password.\nAre you sure your FTP server supports password-less logins?":"JOtkut FTP-palvelimet sallivat yhteyden muodostamisen ilman salasanaa.\nOleko varma, että käyttämäsi FTP-palvelin sallii anonyymit kirjautumiset?","KByte":"KB","KByte/s":"KB/s","Language in user interface":"Käytettävä kieli","Last month":"Viime kuussa","Last successful run:":"Edellinen onnistunut varmuuskopio:","Latest":"Viimesin","Libraries":"Kirjastot","Listing backup dates ...":"Listaan varmuuskopioiden ajankohtia ...","Listing remote files ...":"Listaan etäpalvelimen tiedostoja ...","Live":"Live","Load older data":"Lataa vanhoja tietoja","Loading ...":"Lataan ...","Loading remote storage usage ...":"Haetaan tietoja etäpalvelimen tilankäytöstä ...","Local database for":"Paikallinen tietoknata varmuuskopiolle","Local database path:":"Paikallisen tietokannan sijainti:","Local storage":"Paikallinen tilankäyttö","Location":"Sijainti","Location where buckets are created":"Alue, jolle ämpärit luodaan","Log data for {{Backup.Backup.Name}}":"Varmuuskopion {{Backup.Backup.Name}} lokitiedot","Log data from the server":"Palvelimen lokitiedot","Log out":"Kirjaudu ulos","MByte":"MB","MByte/s":"MB/s","Maintenance":"Ylläpito","Manually type path":"Anna polku","Menu":"Valikko","Microsoft SQL Database:":"Microsoft SQL-tietokanta:","Microsoft SQL Databases":"Microsoft SQL -tietokannat","Minutes":"Minuuttia","Missing name":"Et antanut nimeä","Missing passphrase":"Salasana puuttuuEt antanut salasanaa","Missing sources":"Et valinnut varmuuskopioitavia tietostoja","Mon":"ma","Months":"Kuukautta","Move existing database":"Siirrä olemassa oleva tietokanta","Move failed:":"Siirto epäonnistui:","My Documents":"Tiedostot","My Music":"Musiikki","My Photos":"Kuvat","My Pictures":"Kuvat","Name":"Nimi","Never":"Ei koskaan","New update found: {{message}}":"Uusi päivitys on ladattavissa: {{message}}","New user name is {{user}}.\nUpdated credentials to use the new limited user":"Uusi käyttäjätunnus on {{user}}.\nPäivitä tunnukset käyttääksesi uutta rajoitettua käyttäjää.","Next":"Seuraava","Next scheduled run:":"Seuraava varmuuskopio tehdään:","Next scheduled task:":"Seuraava ajoitettu tehtävä:","Next task:":"Seuraava tehtävä:","Next time":"Seuraavalla kerralla","No":"Ei","No certificate was specified previously, please verify with the server administrator that the key is correct: {{key}} \n\nDo you want to approve the reported host key?":"Sertifikaattia ei ole määritelty aikaisemmin. Varmista palvelimen ylläpitäjältä, että avain onn oikea: {{key}}\n\nHaluatko hyväksyä tämän avaimen?","No editor found for the "{{backend}}" storage type":"Etäpalvelimelle "{{backend}}" ei löytynyt editoria.","No encryption":"Ei salausta","No items selected":"Et valinnut yhtään kohdetta","No items to restore, please select one or more items":"Et valinnut yhtään tiedostoa palautettavaksi. Valitse yksi tai useampi tiedosto.","No passphrase entered":"Et antanut salasanaa","No scheduled tasks":"Ei ajastettuja tehtäviä","Non-matching passphrase":"Salasanat eivät ole samat","None / disabled":"Ei mitään/poistettu käytöstä","OK":"OK","OpenStack AuthURI":"Openstack autentikointiosoite","OpenStack Object Storage / Swift":"OpenStack Object Storage / Swift","Operation failed:":"Toimenpide epäonnistui","Operations:":"Toimenpiteet:","Optional authentication password":"Salasana (ei välttämätön)","Optional authentication username":"Käyttäjätunnus (ei välttämätön)","Options":"Valitsimet","Original location":"Alkuperäinen sijainti","Others":"Muut","Overwrite":"Korvaa","Passphrase":"Salauslause","Passphrase (if encrypted)":"Salauslause (jos varmuuskopio on salattu)","Passphrase changed":"Salauslause vaihdettiin","Passphrases are not matching":"Salauslauseet eivät täsmää","Password":"Salasana","Passwords do not match":"Salasanat eivät täsmää","Patching files with local blocks ...":"Käytän paikallisia tiedostoja apuna ...","Path not found":"Polkua ei löydy","Path on server":"Polku etäpalvelimella","Path or subfolder in the bucket":"Ämpärin polku tai alikansio","Pause":"Tauko","Pause after startup or hibernation":"Tauko käynnistyksen tai lepotilasta heräämisen jälkeen","Permissions":"Oikeudet","Pick location":"Valitse sijainti","Port":"Portti","Previous":"Edellinen","ProjectID is optional if the bucket exist":"Tunniste ProjectID on valinnainen, jos ämpäri on jo olemassa","Proprietary":"Suljettu","Purging files ...":"Poistetaan tiedostoja ...","Rebuilding local database ...":"Luon paikallista tietokantaa uudelleen ...","Recreate (delete and repair)":"Luo uudelleen (poista ja korjaa)","Recreating database ...":"Luon tietokantaa uudelleen ...","Registering temporary backup ...":"Rekisteroin tilapäisen varmuuskopion ...","Relative paths not allowed":"Suhteelliset polut eivät ole sallittuja","Reload":"Lataa uudelleen","Remote":"Etäpalvelimella","Remove":"Poista","Remove option":"Poisto-asetukset","Repair":"Korjaa","Reparing ...":"Korjaan ...","Repeat Passphrase":"Toista salauslause","Reporting:":"Raportoin:","Reset":"Palauta edelliset asetukset","Restore":"Palauta","Restore files":"Palauta tiedostoja","Restore files ...":"Palautan tiedostoja ...","Restore from":"Palauta etäpalvelimelta","Restore options":"Palautusasetukset","Restore read/write permissions":"Palauta luku- ja kirjoitusoikeudet","Restoring files ...":"Palautan tiedostoja ...","Resume":"Jatka","Run again every":"Suorita uudelleen joka","Run now":"Suorita nyt","Running ...":"Teen varmuuskopiota ...","Running task:":"Suoritettava tehtävä:","S3 Compatible":"S3-yhteensopiva","Same as the base install version: {{channelname}}":"Sama kuin asennettu versio: {{channelname}}","Sat":"La","Save":"Tallenna","Save and repair":"Tallenna ja korjaa","Save different versions with timestamp in file name":"Tallenna eri versiot aikaleima tiedoston nimessä","Save immediately":"Tallenna heti","Scanning existing files ...":"Luen olemassa olevia tiedostoja","Scanning for local blocks ...":"Etsin paikallisia lohkoja ...","Schedule":"Aikataulu","Search":"Etsi","Search for files":"Etsi tiedostoja","Seconds":"Sekuntia","Select a log level and see messages as they happen:":"Valitse lokitiedot ja näe ne heti, kun ne ilmoitetaan lokiin:","Select files":"Valitse tiedostot","Server":"Palvelin","Server and port":"Palvelin ja portti:","Server hostname or IP":"Palvelimen nimi ja IP-osoite","Server is currently paused,":"Palvelin on pysäytetty,","Server is currently paused, do you want to resume now?":"Palvelin on pysäytetty, haluatko aktivoida sen nyt?","Server paused":"Palvelin on pysäytetty","Server state properties":"Palvelimen tila","Settings":"Asetukset","Show":"Näytä","Show advanced editor":"Näytä asetusten muokkain","Show hidden folders":"Näytä piilotetut tiedostot","Show log":"Näytä loki","Show log ...":"Lataan lokitietoja ...","Show treeview":"Näytä puunäkymä","Some OpenStack providers allow an API key instead of a password and tenant name":"Jotkin OpenStack-palveluntarjoajat sallivat API-avaimen käytön salasanan ja käyttäjätunnuksen sijaan","Source Data":"Lähdetiedostot","Source data":"Lähdetiedostot","Source folders":"Lähekansiot","Source:":"Varmuuskopioitavat tiedostot:","Specific builds for developers only.":"Testiversiot kehittäjille.","Standard protocols":"Standardinmukaiset protokollat","Starting ...":"Käynnistän ...","Starting the restore process ...":"Aloitan tiedostojen palauttamisen ...","Storage Type":"Tallennustyyppi","Storage class":"Tallennusluokka","Storage class for creating a bucket":"Tallennusluokka ämpärin luomista varten","Stored":"Tallennettu","Strong":"Vahva","Success":"Onnistui","Sun":"Su","Symbolic link":"Symbolinen linkki","System default ({{levelname}})":"Järjestelmän oletus ({{levelname}})","System files":"Järjestelmätiedostot","System info":"Järjestelmän tiedot","System properties":"Järjestelmän ominaisuudet","TByte":"TB","TByte/s":"TB/s","Task is running":"Tehtävää suoritetaan","Temporary files":"Tilapäistiedostot","Tenant Name":"Vuokralaisen nimi","Test connection":"Kokeile yhteysasetuksia","Testing ...":"Yhdistän ...","Testing connection ...":"Testaan yhteyttä ...","Testing permissions ...":"Testaan oikeuksia ...","Testing permissions...":"Testaan oikeuksia ...","The bucket name should be all lower-case, convert automatically?":"Bucketin nimen pitää olla kirjoitettu pienillä kirjaimilla. Muuta automaattisesti?","The bucket name should start with your username, prepend automatically?":"Bucketin nimen pitäisi alkaa käyttäjätunnuksellasi. Haluatko liittää tunnuksesi nimen alkuun automaattisesti?","The connection to the server is lost, attempting again in {{time}} ...":"Yhteys palvelimeen katkesi, yritetään uudelleen {{time}} kuluttua ...","The path does not appear to exist, do you want to add it anyway?":"Polku ei vaikuta olevan olemassa, haluatko lisätä sen silti?","The path does not end with a '{{dirsep}}' character, which means that you include a file, not a folder.\n\nDo you want to include the specified file?":"Polku ei pääty '{{dirsep}}' -merkkiin, eli olet lisäämässä tiedoston etkä kansiota. Haluatko lisätä määritellyn tiedoston?","The path must be an absolute path, i.e. it must start with a forward slash '/'":"Polun pitää olla absoluuttinen, eli sen tulee alkaa vinoviivalla \"/\"","The region parameter is only applied when creating a new bucket":"Alue -parametria käytetään vain bucketia luodessa.","The region parameter is only used when creating a bucket":"Alue -parametria käytetään vain bucketia luodessa.","The server certificate could not be validated.\nDo you want to approve the SSL certificate with the hash: {{hash}}?":"Palvelimen varmennetta ei pystytty todentamaan. Haluatko hyväksyä SSL-varmenteen, jonka tiiviste on {{hash}}?","The storage class affects the availability and price for a stored file":"Tietovaraston tyyppi vaikuttaa talennetun tiedoston saatavuuteen ja hintaan.","The target folder contains encrypted files, please supply the passphrase":"Kohdekansio sisältää salattuja tiedostoja. Anna salasana","The user has too many permissions. Do you want to create a new limited user, with only permissions to the selected path?":"Käyttäjällä on liikaa oikeuksia. Haluatko luoda uuden rajoitetun käyttäjän, jolla on käyttöoikeus vain valittuun polkuun?","This backup was created on another operating system. Restoring files without specifying a destination folder can cause files to be restored in unexpected places. Are you sure you want to continue without choosing a destination folder?":"Tämä varmuuskopio on luotu toisessa käyttöjärjestelmässä. Tiedostojen palauttaminen ilman kohdekansion määrittelyä voi johtaa tiedostojen palauttamiseen odottamattomiin paikkoihin. Haluatko varmasti jatkaa määrittelemättä kohdekansiota?","This month":"Tässä kuussa","This week":"Tällä viikolla","Thu":"To","To File":"Tiedostoon","To export without a passphrase, uncheck the \"Encrypt file\" box":"Viedäksesi ilmaan salasanaa poista rasti \"Salaa tiedosto\" -valinnasta","Today":"Tänään","Trust host certificate?":"Luota palvelimen varmenteeseen?","Trust server certificate?":"Luota palvelimen varmenteeseen?","Try out the new features we are working on. Don't use with important data.":"Kokeile uusia ominaisuuksia, jotka ovat kehityksessä. Älä käytä tätä tärkeiden tietojen kanssa.","Tue":"ti","Type to highlight files":"Kirjoita korostaaksesi tiedostoja","Until resumed":"Toistaiseksi","Update channel":"Päivityskanava","Update failed:":"Päivitys epäonnistui:","Upload volume size":"Lähetettävän datatiedoston koko","Uploading verification file ...":"Lähetetään varmennustiedostoa ...","Usage statistics":"Käyttötilastot","Usage statistics, warnings, errors, and crashes":"Käyttötilastot, varoitukset, virheet ja kaatumiset","Use SSL":"Käytä SSL:ää","Use existing database?":"Käytä olemassaolevaa tietokantaa?","Use weak passphrase":"Käytä heikkoa salasanaa","Useless":"Hyödytön","User has too many permissions":"Käyttäjällä on liikaa oikeuksia","Username":"Käyttäjätunnus","Validating ...":"tarkistetaan ...","Verify files":"Tarkista tiedostot","Verifying ...":"Tarkistetaan ...","Verifying answer":"Tarkistetaan vastausta","Verifying backend data ...":"Tarkistetaan taustajärjestelmän tietoja ...","Verifying remote data ...":"Vahvistetaan taustajärjestelmän dataa ...","Verifying restored files ...":"Tarkistetaan palautetut tiedostot ...","Very strong":"Hyvin vahva","Very weak":"Hyvin heikko","Visit us on":"Tutustu meihin","WARNING: The remote database is found to be in use by the commandline library":"VAROITUS: etätietokanta on komentorivikirjaston käytössä.","WARNING: This will prevent you from restoring the data in the future.":"VAROITUS: Tämä estää tietojen palauttamisen tulevaisuudessa","Waiting for task to begin":"Odotetaan tehtävän alkamista","Waiting for upload ...":"Odotetaan lähetystä ...","Warnings, errors and crashes":"Varoitukset, virheet ja kaatumiset","We recommend that you encrypt all backups stored outside your system":"Suosittelemme salausta varmuuskopioihin, jotka säilötään oman tietokoneesi ulkopuolelle.","Weak":"Heikko","Weak passphrase":"Heikko salasana","Wed":"ke","Weeks":"Viikkoa","Where do you want to restore from?":"Mistä haluat palauttaa?","Where do you want to restore the files to?":"Mihin tiedostot palautetaan?","Years":"Vuotta","Yes":"Kyllä","Yes, I have stored the passphrase safely":"Kyllä, olen tallentanut salasanan turvallisesti","Yes, I'm brave!":"Kyllä, olen rohkea!","Yes, please break my backup!":"Kyllä, riko varmuuskopioni!","Yesterday":"Eilen","You appear to be running Mono with no SSL certificates loaded.\nDo you want to import the list of trusted certificates from Mozilla?":"Käytät Mono:a ilman SSL-varmenteita. Haluatko tuoda luotetut varmenteet Mozillasta?","You are currently running {{appname}} {{version}}":"Käytössä oleva versio: {{appname}} {{version}}","You have changed the encryption mode. This may break stuff. You are encouraged to create a new backup instead":"Vaihdoit salausmenetelmää, ja se saattaa rikkoa asioita. Harkitse kokonaan uuden varmuuskopion luomista sen sijaan.","You have changed the passphrase, which is not supported. You are encouraged to create a new backup instead.":"Vaihdoit salasanaa, mutta tätä toiminnallisuutta ei tueta. Luo sen sijaan kokonaan uusi varmuuskopio.","You have chosen not to encrypt the backup. Encryption is recommended for all data stored on a remote server.":"Valitsit salaamattoman varmuuskopioinnin. Salaaminen on suositeltua kaikella datalle, joka säilötään etäpalvelimelle.","You have chosen to restore to a new location, but not entered one":"Valitsit palautuksen uuteen sijaintiin, mutta et antanut sijaintia.","You must choose at least one source folder":"Vähintään yksi lähdekansio pitää valita","You must enter a name for the backup":"Varmuuskopiolle pitää antaa nimi","You must enter a passphrase or disable encryption":"Anna salasana tai poista salaus käytöstä","You must enter a positive number of backups to keep":"Syötä säilytettävien varmuuskopioiden määrä (positiivinen kokonaisluku)","You must enter a valid duration for the time to keep backups":"Syötä sallittu varmuuskopioiden säilytysaika","You must enter either a password or an API Key":"Syötä salasana tai API-avain","You must enter either a password or an API Key, not both":"Syötä joko salasana tai API-avain, ei molempia","You must fill in the password":"Täytä salasana","You must fill in the server name or address":"Täytä palvelimen nimi tai osoite","You must fill in the username":"Täytä käyttäjätunnus","You must fill in {{field}}":"Täytä kenttä {{field}}","You must select or fill in the AuthURI":"Valitse tai syötä AuthURI","You must select or fill in the server":"Valitse tai syötä palvelin","You must specify a path":"Määritä polku","Your files and folders have been restored successfully.":"Tiedostot ja kansiot palautettiin onnistuneesti.","Your passphrase is easy to guess. Consider changing passphrase.":"Salasanasi on helppo arvata. Harkitse salasanan vaihtamista.","bucket/folder/subfolder":"bucket/kansio/alikansio","byte":"tavu","byte/s":"tavua/s","custom":"mukautettu","resume now":"jatka nyt","{{appname}} was primarily developed by {{dev1}} and {{dev2}}. {{appname}} can be downloaded from {{websitename}}. {{appname}} is licensed under the {{licensename}}.":"{{appname}}n on pääasiallisesti kehittänyt {{dev1}} and {{dev2}}. {{appname}}n voi ladata osoitteesta {{websitename}}. {{appname}} on lisensoitu {{licensename}} -lisenssillä.","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Version":["{{item.Backup.Metadata.TargetSizeString}} / {{$count}} versio","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} versiota"],"{{number}} Hour":"{{number}} tuntia","{{number}} Minutes":"{{number}} minuuttia","{{time}} (took {{duration}})":"{{time}} (kesto: {{duration}})"}); gettextCatalog.setStrings('fr', {"- pick an option -":"- Choisissez une option -","...loading...":"...chargement...","API Key":"Clé API","AWS Access ID":"AWS Access ID","AWS Access Key":"AWS Access Key","AWS IAM Policy":"AWS IAM Policy","About":"À propos","About {{appname}}":"À propos de {{appname}}","Access Key":"Clé d'accès","Access denied":"Accès refusé","Access to user interface":"Accès à l'interface utilisateur","Account name":"Nom du compte","Activate":"Activer","Activate failed:":"Echec d'activation:","Add a new backup":"Ajouter une nouvelle sauvegarde","Add a path directly":"Ajouter un répertoire directement","Add advanced option":"Ajouter une option avancée","Add backup":"Ajouter sauvegarde","Add filter":"Ajouter un filtre","Add path":"Ajouter un chemin","Adjust bucket name?":"Ajuster le nom du bucket","Adjust path name?":"Adapter le nom du chemin ?","Advanced Options":"Options avancées","Advanced options":"options avancées","Advanced:":"Avancé :","All Hyper-V Machines":"Toutes les machines Hyper-V","All Microsoft SQL Databases":"Toutes les bases de données Microsoft SQL","All usage reports are sent anonymously and do not contain any personal information. They contain information about hardware and operating system, the type of backend, backup duration, overall size of source data and similar data. They do not contain paths, filenames, usernames, passwords or similar sensitive information.":"Tous les rapports d'utilisation sont envoyés de manière anonyme et ne contiennent aucune information personnelle. Ils contiennent des informations sur le matériel et le système d'exploitation, sur le type d'infrastructure, la durée de la sauvegarde, la taille générale des fichiers sources et d'autres données similaires. Ils ne contiennent pas de chemin d'accès, noms de fichiers, noms d'utilisateurs, mots de passe ou des informations sensibles de ce type.","Allow remote access (requires restart)":"Autoriser l'accès à distance (nécessite un redémarrage)","Allowed days":"Jours autorisés","An existing file was found at the new location":"Un fichier existant a été trouvé au nouvel endroit","An existing file was found at the new location\nAre you sure you want the database to point to an existing file?":"Un fichier existant a été trouvé au nouvel endroit.\nÊtes-vous sûr de vouloir faire pointer la base de données vers un fichier existant ?","An existing local database for the storage has been found.\nRe-using the database will allow the command-line and server instances to work on the same remote storage.\n\n Do you wish to use the existing database?":"Une base de données locale pour le stockage a été trouvée.\nRéutiliser la base de données va permettre la ligne de commande et les instances serveur de travailler sur le même stockage à distance.\n\nVoulez-vous utiliser la base de donnée existante ?","Anonymous usage reports":"Rapports d'utilisation anonyme","As Command-line":"Comme ligne de commande","AuthID":"AuthID","Authentication password":"Mot de passe d'identification","Authentication username":"Nom d'utilisateur d'identification","Autogenerated passphrase":"Phrase secrète auto-générée","Automatically run backups.":"Lancer des sauvegardes automatiques.","B2 Account ID":"B2 Account ID","B2 Application Key":"B2 Application Key","B2 Cloud Storage Account ID":"B2 Cloud Storage Account ID","B2 Cloud Storage Application Key":"B2 Cloud Storage Application Key","Back":"Retour","Backend modules:":"Modules back-end :","Backup destination":"Destination de sauvegarde","Backup location":"Emplacement de la sauvegarde","Backup:":"Sauvegarde :","Beta":"Béta","Broken access":"Accès rompu","Browse":"Parcourir","Browser default":"Paramètre par défaut du navigateur","Bucket Name":"Nom du bucket","Bucket create location":"Emplacement de la création du bucket","Bucket create region":"Région de création du bucket","Bucket name":"nom du bucket","Bucket storage class":"Classe de stockage du bucket","Building list of files to restore ...":"Construction d'une liste de fichiers à restaurer","Building partial temporary database ...":"Construction d'une base de données temporaire partielle","Busy ...":"Occupé ...","Canary":"Canary","Cancel":"Annuler","Cannot move to existing file":"Impossible de déplacer vers un fichier existant","Changelog":"Journal des modifications","Changelog for {{appname}} {{version}}":"Journal des modifications pour {{appname}} {{version}}","Check failed:":"Vérification échouée :","Check for updates now":"Vérifier les mise à jour maintenant","Checking ...":"Vérification ...","Checking for updates ...":"Vérification des mises à jour ...","Chose a storage type to get started":"Sélectionnez un type de stockage pour commencer","Click the AuthID link to create an AuthID":"Cliquez sur le lien AuthID pour créer un AuthID","Click to set throttle options":"Cliquez pour définir les options d'accélération","Commandline ...":"Ligne de commande","Compact now":"Compacter maintenant","Compacting remote data ...":"Compactage des données distantes ...","Completing backup ...":"Finalisation de la sauvegarde ...","Completing previous backup ...":"Finalisation de la précédente sauvegarde ...","Compression modules:":"Modules de compression :","Computer":"Ordinateur","Configuration file:":"Fichier de configuration :","Configuration:":"Configuration :","Configure a new backup":"Configurer une nouvelle sauvegarde","Confirm delete":"Confirmer suppression","Confirmation required":"Confirmation nécessaire","Connect":"Connecter","Connect now":"Connecter maintenant","Connecting to server ...":"Connexion au serveur ...","Connecting to task ....":"Connexion à la tâche ...","Connecting...":"Connexion ...","Connection lost":"Connexion perdue","Connection worked!":"Connection fonctionnelle !","Container name":"Nom du conteneur","Container region":"Région du conteneur","Continue":"Continuer","Continue without encryption":"Continuer sans chiffrement","Copied!":"Copié !","Copy Destination URL to Clipboard":"Copier l'URL de destination dans le presse-papier","Copy failed. Please manually copy the URL":"Copie échouée. Veuillez copier manuellement l'URL","Core options":"Options du noyau","Counting ({{files}} files found, {{size}})":"Comptage ({{files}} fichiers trouvés, {{size}})","Crashes only":"Uniquement les accidents","Create bug report ...":"Crée un rapport d'erreur ...","Create folder?":"Créer un dossier ?","Created new limited user":"Nouvel utilisateur limité créé","Creating bug report ...":"Création d'un rapport d'erreur ...","Creating new user with limited access ...":"Création d'un nouvel utilisateur avec un accès limité ...","Creating target folders ...":"Création des répertoires de destination ...","Creating temporary backup ...":"Création d'une sauvegarde temporaire ...","Creating user...":"Création d'un utilisateur ...","Current version is {{versionname}} ({{versionnumber}})":"La version actuelle est {{versionname}} ({{versionnumber}})","Custom S3 endpoint":"S3 endpoint personnalisé","Custom authentication url":"URL d'authentification personnalisée","Custom location ({{server}})":"Emplacement personnalisé ({{server)}}","Custom region for creating buckets":"Région personnalisée pour la créations de buckets","Custom region value ({{region}})":"Valeur personnalisée de région ({{region}})","Custom server url ({{server}})":"URL serveur personnalisée ({{server}})","Custom storage class ({{class}})":"Classe de stockage personnalisée ({{class}})","Database ...":"Base de donnée","Days":"Jours","Default":"Défaut","Default ({{channelname}})":"({{channelname}}) par défaut","Default options":"Options par défaut","Delete":"Supprimer","Delete ...":"Suppression ...","Delete backup":"Supprimer sauvegarde","Delete local database":"Supprimer base de données locale","Delete remote files":"Supprimer les fichiers distants","Delete the local database":"Supprimer la base de données locale","Delete {{filecount}} files ({{filesize}}) from the remote storage?":"Supprimer {{filecount}} fichiers ({{filesize}}) du stockage distant ?","Deleting remote files ...":"Suppression des fichiers distants ...","Deleting unwanted files ...":"Suppression des fichiers non désirés ...","Desktop":"Bureau","Destination":"Destination","Did we help save your files? If so, please consider supporting Duplicati with a donation. We suggest {{smallamount}} for private use and {{largeamount}} for commercial use.":"Nous vous avons aidé à sauvegarder vos fichiers ? Dans ce cas, songez à supporter Duplicati avec une donation. Nous vous suggérons {{smallamount}} pour un usage privé et {{largeamount}} pour un usage commercial.","Direct restore from backup files ...":"Restauration directe depuis les fichiers de sauvegarde","Disabled":"Désactivé","Dismiss":"Rejeter","Display and color theme":"Affichage et couleur","Do you really want to delete the backup: \"{{name}}\" ?":"Voulez-vous vraiment supprimer la sauvegarde : \"{{name}}\" ?","Do you really want to delete the local database for: {{name}}":"Voulez-vous vraiment supprimer la base de données locale pour : {{name}} ?","Donate":"Faire un don","Donation messages":"Messages de donation","Donation messages are hidden, click to show":"Les messages de donation sont cachés, cliquez ici pour les afficher","Donation messages are visible, click to hide":"Les messages de donation sont affichés, cliquez ici pour les cacher","Done":"Fait","Download":"Téléchargement","Downloading ...":"Téléchargement ...","Downloading files ...":"Téléchargement des fichiers ...","Downloading update...":"Téléchargement de mise à jour ...","Duplicate option {{opt}}":"Option de duplication {{opt}}","Duplicati Website":"Site internet de Duplicati","Duplicati forum":"Forum de Duplicati","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\n When deleting a backup, you can also delete the local database without affecting the ability to restore the remote files.\n If you are using the local database for backups from the commandline, you should keep the database.":"Chaque sauvegarde a une base de données locale associée à elle, elle stocke des informations localement à propos de la sauvegarde distante.\nQuand vous supprimez une sauvegarde, vous pouvez aussi supprimer la base de données locale sans affecter votre capacité à restaurer vos fichiers distants.\nSi vous utilisez la base de données locale pour vos sauvegardes à partir de la ligne de commande, vous devez conserver la base de données.","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\\nThis makes it faster to perform many operations, and reduces the amount of data that needs to be downloaded for each operation.":"Chaque sauvegarde a une base de données locale associée à elle, elle enregistre localement les informations à propos de la sauvegarde distante. \\nCela rend la réalisation de beaucoup d'opérations plus rapide et réduit la quantité de données qui doit être téléchargé pour chaque opération.","Edit ...":"Éditer ...","Edit as list":"Éditer en tant que liste","Edit as text":"Éditer en tant que texte","Encrypt file":"Chiffrement de fichier","Encryption":"Chiffrement","Encryption changed":"Chiffrement changé","Encryption modules:":"Modules de Chiffrement :","Enter URL":"Entrer l'URL","Enter access key":"Entrez clé d'accès","Enter account name":"Entrez nom du compte","Enter backup passphrase, if any":"Entrez la phrase secrète de sauvegarde, si présente","Enter configuration details":"Entrer les détails de configuration","Enter container name":"Entrez le nom du conteneur","Enter encryption passphrase":"Entrez la phrase secrète de chiffrement","Enter expression here":"Entrez l'expression ici","Enter folder path name":"Entrez le nom du chemin du répertoire","Enter one option per line in command-line format, eg. {0}":"Entrez une option par ligne dans le format ligne de commande, ex : {0}","Enter the destination path":"Entrez le chemin de destination","Error":"Erreur","Error!":"Erreur !","Errors and crashes":"Erreurs et accidents","Exclude":"Exclure","Exclude directories whose names contain":"Exclure répertoires dont le nom contient","Exclude expression":"Exclure expression","Exclude file":"Exclure fichier","Exclude file extension":"Exclure extension de fichier","Exclude files whose names contain":"Exclure fichiers dont le nom contient","Exclude folder":"Exclure dossier","Exclude regular expression":"Exclure expression régulière","Existing file found":"Fichier existant trouvé","Experimental":"Expérimental","Export":"Exporter","Export ...":"Exportation ...","Export backup configuration":"Exporter la configuration de sauvegarde","Export configuration":"Exporter la configuration","Exporting ...":"Exportation ...","FTP (Alternative)":"FTP (Alternatif)","Failed to build temporary database: {{message}}":"Échec de la construction de la base de données temporaire : {{message}}","Failed to connect:":"Échec de la connexion :","Failed to connect: {{message}}":"Échec de la connexion : {{message}}","Failed to delete:":"Échec de la suppression :","Failed to fetch path information: {{message}}":"Échec de la récupération des information du chemin : {{message}}","Failed to import:":"Échec de l'import :","Failed to read backup defaults:":"Échec de la lecture des paramètres par défaut de la sauvegarde :","Failed to restore files: {{message}}":"Échec de la restauration des fichiers : {{message}}","Failed to save:":"Échec d'enregistrement :","Fetching path information ...":"Récupération des informations du chemin ...","File":"Fichier","Files larger than:":"Fichiers plus gros que :","Filters":"Filtres","Finished!":"Terminé !","First run setup":"Première mise en route","Folder":"Dossier","Folder path":"Chemin du dossier","Fri":"Ven.","GByte":"GByte","GByte/s":"GByte/s","GCS Project ID":"GCS Project ID","General":"Général","General backup settings":"Paramètres généraux de sauvegarde","General options":"Options générales","Generate":"Générer","Generate IAM access policy":"Générer IAM access policy","Getting file versions ...":"Récupération des versions des fichiers…","Hidden files":"Fichiers cachés","Hide":"Cacher","Hide hidden folders":"Masquer les dossiers cachés","Home":"Poste de travail","Hours":"Heures","How do you want to handle existing files?":"Comment voulez-vous traiter les fichiers existants ?","Hyper-V Machine":"Machine Hyper-V","Hyper-V Machine:":"Machine Hyper-V :","Hyper-V Machines":"Machines Hyper-V","ID:":"ID :","If a date was missed, the job will run as soon as possible.":"Si une date a été manquée, le travail démarrera dès que possible.","If the backup and the remote storage is out of sync, Duplicati will require that you perform a repair operation to synchronize the database.\\nIf the repair is unsuccesful, you can delete the local database and re-generate.":"Si la sauvegarde et le stockage distant ne sont plus synchronisés, Duplicati demandera d'effectuer une opération de réparation pour synchroniser la base de données. \\n Si la réparation ne réussit pas, vous pouvez supprimer la base de données locale et la régénérer.","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"Si les fichiers de sauvegarde n'ont pas été téléchargés automatiquement, cliquez bouton-droit et choisissez "Sauvegarder sous ..."","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"Si les fichiers de sauvegarde n'ont pas été téléchargés automatiquement, cliquez bouton-droit et choisissez \"Sauvegarder sous ...\"","If you do not enter a path, all files will be stored in the login folder.\nAre you sure this is what you want?":"Si vous n'entrez pas de chemin, tous les fichiers seront stockés dans le dossier de connexion.\nÊtes-vous sûr que c'est ce que vous voulez ?","If you do not enter an API Key, the tenant name is required":"Si vous n'entrez pas de clé API, le nom de l'entité est requis","If you want to use the backup later, you can export the configuration before deleting it":"Si vous voulez utiliser la sauvegarde plus tard, vous pouvez exporter la configuration avant de la supprimer","If your machine is in a multi-user environment (i.e. the machine has more than one account), you need to set a password to prevent other users from accessing data on your account.\nDo you want to set a password now?":"Si votre machine est dans un environnement multi-utilisateur (votre machine a plus d'un compte), vous avez besoin de définir un mot de passe pour éviter que les autres utilisateurs puissent accéder à vos données sur votre compte.\nVoulez-vous définir un mot de passe maintenant ?","Import":"Importer","Import Destination URL":"Importer l'URL de destination","Import backup configuration":"Importer la configuration de sauvegarde","Import completed, but no certificates were found after the import":"Import terminé, mais aucun certificat n'a été trouvé après l'import","Import failed":"Échec de l'import","Import from a file":"Importer depuis un fichier","Importing ...":"Importation ...","Include a file?":"Inclure un fichier ?","Include expression":"Inclure expression","Include regular expression":"Inclure expression régulière","Incorrect answer, try again":"Réponse incorrecte, essayez encore","Individual builds for developers only.":"Compilations individuelles pour les developpeurs uniquement.","Information":"Information","Install":"Installer","Install failed:":"Échec d'installation :","Invalid characters in path":"Caractères invalides dans le chemin","Invalid retention time":"Temps de rétention invalide","It is possible to connect to some FTP without a password.\nAre you sure your FTP server supports password-less logins?":"Il est possible de se connecter à certains FTP sans mot de passe.\nÊtes-vous sûr que votre serveur FTP prend en charge l'identification sans mot de passe ?","KByte":"KByte","KByte/s":"KByte/s","Language in user interface":"Langue dans l'interface utilisateur","Last month":"Mois dernier","Last successful run:":"Dernière exécution réussie :","Latest":"Dernière","Libraries":"Librairies","Listing backup dates ...":"Listing des dates de sauvegardes ...","Listing remote files ...":"Listing des fichiers distants ...","Live":"Direct","Load a configuration from an exported job or a storage provider":"Charger une configuration depuis un export ou un opérateur de stockage","Load destination from an exported job or a storage provider":"Charger la destination depuis un export ou un opérateur de stockage","Load older data":"Charger des données plus anciennes","Loading ...":"Chargement ...","Loading remote storage usage ...":"Chargement de l'utilisation du stockage distant ...","Local database for":"Base de données locale pour","Local database path:":"Chemin de la base de données locale :","Local storage":"Stockage local","Location":"Emplacement","Location where buckets are created":"Emplacement ou les buckets sont créés","Log data for {{Backup.Backup.Name}}":"Historique pour {{Backup.Backup.Name}}","Log data from the server":"Données d'historique du serveur","Log out":"Déconnexion","MByte":"MByte","MByte/s":"MByte/s","Maintenance":"Maintenance","Manually type path":"Entrée manuelle du chemin","Max download speed":"Vitesse maximum de téléchargement","Max upload speed":"Vitesse maximum de téléversement","Menu":"Menu","Microsoft SQL Database:":"Base de données Microsoft SQL :","Microsoft SQL Databases":"Bases de données Microsoft SQL","Minimum redundancy":"Redondance minimale","Minimum redundancy is 1.0":"La redondance minimale est de 1,0","Minutes":"Minutes","Missing name":"Nom manquant","Missing passphrase":"Phrase secrète manquante","Missing sources":"Sources manquantes","Mon":"Lun.","Months":"Mois","Move existing database":"Déplacer base de données existante","Move failed:":"Échec de déplacement :","My Documents":"Mes documents","My Music":"Ma musique","My Photos":"Mes photos","My Pictures":"Mes photos","Name":"Nom","Never":"Jamais","New update found: {{message}}":"Nouvelle mise à jour trouvée : {{message}}","New user name is {{user}}.\nUpdated credentials to use the new limited user":"Le nouveau nom d'utilisateur est {{user}}.\nMise à jour des accès pour le nouvel utilisateur limité","Next":"Suivant","Next scheduled run:":"Prochaine exécution programmée :","Next scheduled task:":"Prochaine tâche planifiée :","Next task:":"Prochaine tâche :","Next time":"Prochaine fois","No":"Non","No certificate was specified previously, please verify with the server administrator that the key is correct: {{key}} \n\nDo you want to approve the reported host key?":"Aucun certificat n'a été spécifié auparavant, veuillez vérifier que la clé est correcte auprès de votre administrateur système : {{key}}\n\nVoulez-vous approuver la clé de l'hôte mentionné ?","No editor found for the "{{backend}}" storage type":"Aucun éditeur trouvé pour le "{{backend}}" type de stockage","No encryption":"Pas de chiffrement","No items selected":"Aucun élément sélectionné","No items to restore, please select one or more items":"Aucun élément à restaurer, merci de sélectionner un ou plusieurs éléments","No passphrase entered":"Aucune phrase secrète entrée","No scheduled tasks":"Pas de tâche planifié","No, my machine has only a single account":"Non, ma machine n'a qu'un seul compte","Non-matching passphrase":"La phrase secrète ne correspond pas","None / disabled":"Aucun / Désactivé","OK":"Ok","OpenStack AuthURI":"OpenStack AuthURI","OpenStack Object Storage / Swift":"OpenStack Object Storage / Swift","Operation failed:":"Échec de l'opération :","Operations:":"Opérations :","Optional authentication password":"Mot de passe d'identification optionel","Optional authentication username":"Nom d'utilisateur d'identification optionel","Options":"Options","Options added here are applied to all backups, but can be overridden in each individual backup":"Les options ajoutées ici sont appliquées pour toutes les sauvegardes, mais elles peuvent être outrepassées pour chaque sauvegarde","Original location":"Emplacement d'origine","Others":"Autres","Overwrite":"Écraser","Passphrase":"Phrase secrète","Passphrase (if encrypted)":"Phrase secrète (si chiffré)","Passphrase changed":"Phrase secrète changée","Passphrases are not matching":"Les phrases secrètes ne correspondent pas","Password":"Mot de passe","Passwords do not match":"Les mots de passe ne correspondent pas","Patching files with local blocks ...":"Correction des fichiers avec les blocs locaux ...","Path not found":"Chemin non trouvé","Path on server":"Chemin sur le serveur","Path or subfolder in the bucket":"Chemin ou sous-dossier dans le bucket","Pause":"Pause","Pause after startup or hibernation":"Pause après le démarrage ou l'hibernation","Pause options":"Options de pause","Permissions":"Permissions","Pick location":"Choisir emplacement","Point to your backup files and restore from there":"Donner votre fichier de sauvegarde et restaurer depuis celui-ci ","Port":"Port","Previous":"Précédent","ProjectID is optional if the bucket exist":"Le ProjectID est optionel si le bucket existe","Proprietary":"Propriétaire","Purging files ...":"Nettoyage des fichiers…","Rebuilding local database ...":"Reconstruction de la base de données locale","Recreate (delete and repair)":"Récrée (suppression et réparation)","Recreating database ...":"Recréation de la base de données ...","Registering temporary backup ...":"Enregistrement de la sauvegarde temporaire ..","Relative paths not allowed":"Les chemins relatifs ne sont pas autorisés","Reload":"Recharger","Remote":"Distant","Remove":"Retirer","Remove option":"Option de retrait","Repair":"Réparer","Reparing ...":"Réparation ....","Repeat Passphrase":"Répeter la phrase secrète","Reporting:":"Communication de données :","Reset":"Réinitialiser","Restore":"Restaurer","Restore files":"Restaurer fichiers","Restore files ...":"Restaurer fichier ...","Restore files from {{backupname}}":"Restaurer les fichiers depuis {{backupname}}","Restore from":"Restaurer depuis","Restore from backup configuration":"Restaurer depuis une sauvegarde de configuration","Restore from configuration ...":"Restaurer depuis une configuration","Restore options":"Options de restauration","Restore read/write permissions":"Autorisations de lecture/écriture de restauration","Restoring files ...":"Restauration des fichiers ...","Resume":"Reprendre","Run again every":"Relancer tous les","Run now":"Démarrer maintenant","Running ...":"En cours d'exécution ...","Running ....":"En cour ...","Running commandline entry":"Execution d'une ligne de commnde","Running task:":"Tâche en cours :","S3 Compatible":"Compatible S3","Same as the base install version: {{channelname}}":"Identique à la version de base installée : {{channelname}}","Sat":"Sam.","Save":"Enregistrer","Save and repair":"Enregistrer et réparer","Save different versions with timestamp in file name":"Enregistrer des versions différentes avec l'horodatage dans le nom du fichier","Save immediately":"Sauver immédiatement ","Scanning existing files ...":"Scannage des fichiers existants ...","Scanning for local blocks ...":"Scannage de blocs locaux ...","Schedule":"Planifier","Search":"Recherche","Search for files":"Recherche de fichiers","Seconds":"Secondes","Select a log level and see messages as they happen:":"Sélectionner un niveau d'historique et voyez les messages quand ils apparaissent :","Select files":"Sélectionner les fichiers","Server":"Serveur","Server and port":"Serveur et port","Server hostname or IP":"Nom d'hôte du serveur ou IP","Server is currently paused,":"Le serveur est actuellement en pause,","Server is currently paused, do you want to resume now?":"Le serveur est actuellement en pause, voulez-vous reprendre maintenant ?","Server password":"Mot de passe du serveur","Server paused":"Serveur en pause","Server state properties":"Propriétés du statut serveur","Settings":"Paramètres","Show":"Montrer","Show advanced editor":"Montrer l'éditeur avancé","Show hidden folders":"Montrer les dossiers cachés","Show log":"Montrer l'historique","Show log ...":"Montrer l'historique ...","Show treeview":"Afficher l'arborescence","Sia server password":"Mot de passe du serveur Sia","Some OpenStack providers allow an API key instead of a password and tenant name":"Certains fournisseurs OpenStack autorisent une clé API à la place d'un mot de passe et d'un nom d'entité","Source Data":"Données source","Source data":"Données source","Source folders":"Dossiers source","Source:":"Source :","Specific builds for developers only.":"Compilations spécifiques pour développeurs uniquement.","Standard protocols":"Protocoles standards","Starting ...":"Démarrage ...","Starting the restore process ...":"Démarrage du processus de restauration ...","Stop after the current file":"Stopper après le fichier en cour","Stop after upload":"Stopper après le transfert","Stop now":"Stopper maintenant","Stop running backup":"Stopper la sauvegarde en cour","Stop running task":"Stopper la tâche en cour","Stopping after upload:":"Arrêter après transfert","Stopping task:":"Arrêt de la tâche","Storage Type":"Type de stockage","Storage class":"Classe de stockage","Storage class for creating a bucket":"Classe de stockage pour la création d'un bucket","Stored":"Stocké","Strong":"Fort","Success":"Succès","Sun":"Dim.","Symbolic link":"Lien symbolique","System default ({{levelname}})":"Paramètre par défaut du système ({{levelname}})","System files":"Fichiers système","System info":"Info système","System properties":"Propriétés système","TByte":"TByte","TByte/s":"TByte/s","Target path, ie /backup":"Chemin cible, c'est-à-dire /sauvegarde","Task is running":"La tâche est en cours","Temporary files":"Fichiers temporaires","Tenant Name":"Nom d'entité","Test connection":"Tester la connexion","Testing ...":"Test ...","Testing connection ...":"Essai de connexion ...","Testing permissions ...":"Test des permissions ...","Testing permissions...":"Test des permissions ...","The bucket name should be all lower-case, convert automatically?":"Le nom du bucket devrait être entièrement en minuscule, convertir automatiquement ?","The bucket name should start with your username, prepend automatically?":"Le nom du bucket devrait commencer par votre nom d'utilisateur, l'ajouter automatiquement ?","The connection to the server is lost, attempting again in {{time}} ...":"La connexion au serveur a été perdue, nouvelle tentative dans {{time}} ...","The dark theme (by Michal)":"Le thème sombre (de Michal)","The default blue on white theme (by Alex)":"Thème par défaut bleu sur fond blanc (by Alex)","The host key has changed, please check with the server administrator if this is correct, otherwise you could be the victim of a MAN-IN-THE-MIDDLE attack.\n\nDo you want to REPLACE your CURRENT host key \"{{prev}}\" with the REPORTED host key: {{key}}?":"La clé de l'hôte a changé, veuillez vérifier avec l'administrateur du serveur si cela est correcte, car il pourrait s'agir d'une attaque de type \"intermédiaire\".\n\nVoulez-vous REMPLACER votre clé d'hôte COURANTE \"{{prev}}\" par la clé MENTIONNÉE : {{key}} ?","The path does not appear to exist, do you want to add it anyway?":"Le chemin ne semble pas exister, voulez-vous l'ajouter quand même ?","The path does not end with a '{{dirsep}}' character, which means that you include a file, not a folder.\n\nDo you want to include the specified file?":"Le répertoire ne se termine pas par un caractère '{{dirsep}}', ce qui signifie que vous sélectionnez un fichier et non un dossier.\n\nVoulez-vous inclure le fichier spécifié ?","The path must be an absolute path, i.e. it must start with a forward slash '/'":"Le chemin doit être un chemin absolu, c.-à-d. Il doit commencer par un slash avant '/'","The path should start with \"{{prefix1}}\" or \"{{prefix2}}\", otherwise you will not be able to see the files in the HubiC web interface.\n\nDo you want to add the prefix to the path automatically?":"Le chemin d'accès doit commencer par \"{{prefix1}}\" ou \"{{prefix2}}\", sinon vous ne pourrez pas voir les fichiers dans l'interface web d'HubiC.\n\nVoulez-vous automatiquement ajouter le préfixe au chemin ?","The region parameter is only applied when creating a new bucket":"Le paramètre régional n'est appliqué qu'à la création d'un nouveau bucket","The region parameter is only used when creating a bucket":"Le paramètre régional n'est utilisé qu'à la création d'un bucket","The server certificate could not be validated.\nDo you want to approve the SSL certificate with the hash: {{hash}}?":"Le certificat du serveur n'a pas pu être validé.\nVoulez-vous approuver le certificat SSL avec la somme de contrôle : {{hash}} ?","The storage class affects the availability and price for a stored file":"La classe de stockage affecte la disponibilité et le prix d'un fichier stocké","The target folder contains encrypted files, please supply the passphrase":"Le fichier cible contient des fichiers chiffrés, merci de fournir la phrase secrète","The user has too many permissions. Do you want to create a new limited user, with only permissions to the selected path?":"L'utilisateur à trop d'autorisations. Voulez-vous créer un nouvel utilisateur limité avec uniquement les autorisations pour les chemins sélectionnés ?","This backup was created on another operating system. Restoring files without specifying a destination folder can cause files to be restored in unexpected places. Are you sure you want to continue without choosing a destination folder?":"Cette sauvegarde a été créée sur un autre système d’exploitation. Restaurer les fichiers sans préciser un dossier de destination peut créer des fichiers à des endroits inattendus. Êtes-vous surs de vouloir poursuivre sans choisir de dossier de destination ?","This month":"Ce mois","This week":"Cette semaine","Throttle settings":"Options d'accélération","Thu":"Jeu.","To File":"Vers fichier","To confirm you want to delete all remote files for \"{{name}}\", please enter the word you see below":"Pour confirmer que vous souhaitez supprimer tous les fichiers distants pour \"{{name}}\", veuillez entrer le mot situé ci-dessous","To export without a passphrase, uncheck the \"Encrypt file\" box":"Pour exporter sans phrase secrète, décochez la case \"Chiffrer fichier\"","Today":"Aujourd'hui","Trust host certificate?":"Faire confiance au certificat de l'hôte ?","Trust server certificate?":"Faire confiance au certificat du serveur ?","Try out the new features we are working on. Don't use with important data.":"Essayez les nouvelles fonctions sur lesquelles nous travaillons. Ne l'utilisez pas avec des données importantes.","Tue":"Mar.","Type to highlight files":"Tapez pour mettre en surbrillance les fichiers","Unknown backup size and versions":"Taille et version de sauvegarde inconnue","Until resumed":"Jusqu'à la reprise","Update channel":"Canal de mise à jour","Update failed:":"Échec de mise à jour","Updating with existing database":"Mettre à jour avec une base de données existante","Upload volume size":"Taille du volume téléversé","Uploading verification file ...":"Téléversement du fichier de vérification ...","Usage statistics":"Statistiques d'utilisation","Usage statistics, warnings, errors, and crashes":"Statistiques d'utilisation, avertissements, erreurs et accidents","Use SSL":"Utiliser SSL","Use existing database?":"Utiliser une base de données existante ?","Use weak passphrase":"Utiliser une phrase secrète faible","Useless":"Inutile","User data":"Données utilisateur","User has too many permissions":"L'utilisateur à trop d'autorisations","User interface settings":"Réglages interface utilisateur","Username":"Nom d'utilisateur","Validating ...":"Validation ...","Verify files":"Vérifier fichier","Verifying ...":"Vérification ...","Verifying answer":"Vérification de la réponse","Verifying backend data ...":"Vérification des données back-end","Verifying remote data ...":"Vérifications des données distantes","Verifying restored files ...":"Vérification des fichiers restaurés","Very strong":"Très fort","Very weak":"Très faible","Visit us on":"Rendez nous visite sur","WARNING: The remote database is found to be in use by the commandline library":"ATTENTION : La base de données locale est rapportée comme étant utilisée par la librairie de ligne de commande","WARNING: This will prevent you from restoring the data in the future.":"ATTENTION : Cela va vous empêcher de restaurer vos données dans le futur.","Waiting for task to begin":"En attente du début de la tâche","Waiting for task to start ....":"En attente du début de la tâche","Waiting for upload ...":"En attente du téléversement ...","Warnings, errors and crashes":"Avertissements, erreurs et accidents","We recommend that you encrypt all backups stored outside your system":"Nous vous recommandons de chiffrer toutes les sauvegardes stockées en dehors de votre système","Weak":"Faible","Weak passphrase":"Phrase secrète faible","Wed":"Mer.","Weeks":"Semaines","Where do you want to restore from?":"Ou voulez-vous restaurer vos fichiers ?","Where do you want to restore the files to?":"Ou voulez-vous restaurer vos fichiers ?","Years":"Années","Yes":"Oui","Yes, I have stored the passphrase safely":"Oui, j'ai conservé ma phrase secrète en sécurité","Yes, I'm brave!":"Oui, je suis courageux !","Yes, please break my backup!":"Oui, s'il vous plait cassez ma sauvegarde","Yesterday":"Hier","You appear to be running Mono with no SSL certificates loaded.\nDo you want to import the list of trusted certificates from Mozilla?":"Mono semble fonctionner sans certificat SSL chargé.\nVoulez-vous importer la liste de certificats de confiance depuis Mozilla ?","You are changing the database path away from an existing database.\nAre you sure this is what you want?":"Vous êtes en train de changer le chemin de la base de données depuis une base de donnée existante.\nÊtes-vous sûr que c'est ce que vous voulez ?","You are currently running {{appname}} {{version}}":"Vous êtes actuellement en train d'utiliser {{appname}} {{version}}","You can stop the backup immediately, or stop after the current file has been uploaded.":"Vous pouvez arrêter la sauvegarde immédiatement, ou stopper après télé-versement du fichier courant","You can stop the task immediately, or allow the process to continue its current file and the stop.":"Vous pouvez stopper la tâche immédiatement, ou autoriser le processus en cour et stopper ensuite","You have changed the encryption mode. This may break stuff. You are encouraged to create a new backup instead":"Vous avez changé la méthode de chiffrement. Ceci peut endommager certaines choses. Nous vous encourageons à créer une nouvelle sauvegarde à la place.","You have changed the passphrase, which is not supported. You are encouraged to create a new backup instead.":"Vous avez changé la phrase secrète, ce qui n'est pas pris en charge. Nous vous encourageons à créer une nouvelle sauvegarde à la place.","You have chosen not to encrypt the backup. Encryption is recommended for all data stored on a remote server.":"Vous avez choisi de ne pas chiffrer votre sauvegarde. Le chiffrement est recommandé pour toutes les données stockées sur un serveur distant.","You have chosen to restore to a new location, but not entered one":"Vous avez demandé à restaurer vers un nouveau dossier, mais sans indiquer son chemin","You must choose at least one source folder":"Vous devez choisir au moins un dossier source","You must enter a name for the backup":"Vous devez entrer un nom pour votre sauvegarde","You must enter a passphrase or disable encryption":"Vous devez entrer une phrase secrète ou désactiver le chiffrement","You must enter a positive number of backups to keep":"Vous devez entrer un nombre positif de sauvegarde à conserver","You must enter a tenant name if you do not provide an API Key":"Vous devez entrer un nom d'entité si vous ne fournissez pas une clé API","You must enter a valid duration for the time to keep backups":"Vous devez entrer une valeur correcte pour la durée de conservation de vos sauvegardes","You must enter either a password or an API Key":"Vous devez entrer soit un mot de passe, soit une clé API","You must enter either a password or an API Key, not both":"Vous devez entrer soit un mot de passe, soit une clé API, mais pas les deux","You must fill in the password":"Vous devez renseigner le mot de passe","You must fill in the server name or address":"Vous devez renseigner le nom du serveur ou l'adresse","You must fill in the username":"Vous devez renseigner le nom d'utilisateur","You must fill in {{field}}":"Vous devez renseigner le champ : {{field}}","You must select or fill in the AuthURI":"Vous devez sélectionner ou renseigner l'AuthURI","You must select or fill in the server":"Vous devez sélectionner ou renseigner le serveur","You must specify a path":"Vous devez spécifier un chemin.","Your files and folders have been restored successfully.":"Vos fichiers et dossiers ont été restaurés avec succès.","Your passphrase is easy to guess. Consider changing passphrase.":"Votre phrase secrète est facile à deviner. Songez à la changer.","bucket/folder/subfolder":"bucket/dossier/sous-dossier","byte":"byte","byte/s":"byte/s","custom":"personnalisé ","resume now":"reprendre maintenant","{{appname}} was primarily developed by {{dev1}} and {{dev2}}. {{appname}} can be downloaded from {{websitename}}. {{appname}} is licensed under the {{licensename}}.":"{{appname}} a été principalement développée par {{dev1}} et {{dev2}}. {{appname}} peut être téléchargée depuis {{websitename}}. {{appname}} est sous licence {{licensename}}.","{{files}} files ({{size}}) to go {{speed_txt}}":"{{files}} fichiers {{size}}) à afficher {{speed_txt}}","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Version":["{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Version","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Versions"],"{{number}} Hour":"{{number}} Heure","{{number}} Minutes":"{{number}} Minutes","{{time}} (took {{duration}})":"{{time}} (durée {{duration}})"}); - gettextCatalog.setStrings('it', {"- pick an option -":"- seleziona un'opzione -","...loading...":"... caricamento in corso ...","API Key":"Chiave API","AWS Access ID":"ID di accesso AWS","AWS Access Key":"Chiave di accesso AWS","AWS IAM Policy":"Norme AWS IAM","About":"Informazioni","About {{appname}}":"Informazioni {{appname}}","Access Key":"Chiave di accesso","Access denied":"Accesso negato","Access to user interface":"Accesso all'interfaccia utente","Account name":"Nome account","Activate":"Attiva","Activate failed:":"Attivazione fallita:","Add a new backup":"Aggiungi un nuovo backup","Add a path directly":"Aggiungi direttamente un percorso","Add advanced option":"Aggiungi opzione","Add backup":"Aggiungi backup","Add filter":"Aggiungi filtro","Add path":"Aggiungi percorso","Adjust bucket name?":"Sistemare il nome bucket?","Adjust path name?":"Sistemare il nome del percorso?","Advanced Options":"Opzioni Avanzate","Advanced options":"Opzioni avanzate","Advanced:":"Avanzate:","All":"Tutti","All Hyper-V Machines":"Tutte le Macchine Hyper-V","All Microsoft SQL Databases":"Tutti i database Microsoft SQL","All usage reports are sent anonymously and do not contain any personal information. They contain information about hardware and operating system, the type of backend, backup duration, overall size of source data and similar data. They do not contain paths, filenames, usernames, passwords or similar sensitive information.":"Tutti i rapporti sono inviati in modo anonimo e non contengono informazioni personali. Contengono informazioni sull'hardware, sul sistema operativo, il tipo di backend, la durata del backup, la dimensione complessiva dei dati sorgente ed dati simili. Non contengono i percorsi, nomi dei file, nomi utente, password o altre informazioni sensibili.","Allow remote access (requires restart)":"Consenti accesso remoto (richiede il riavvio)","Allowed days":"Giorni consentiti","An existing file was found at the new location":"Un file esistente è stato trovato nella nuova posizione","An existing file was found at the new location\nAre you sure you want the database to point to an existing file?":"Un file esistente è stato trovato nella nuova posizione.\nSei sicuro di volere che il database punti ad un file esistente?","An existing local database for the storage has been found.\nRe-using the database will allow the command-line and server instances to work on the same remote storage.\n\n Do you wish to use the existing database?":"Un database locale esistente per l'archiviazione è stato trovato.\nIl riutilizzo del database consentirà alle istanze da riga di comando e dal server di lavorare sullo stesso archivio remoto.\n\nVuoi usare il database esistente?","Anonymous usage reports":"Rapporti d'uso anonimi","As Command-line":"Come riga di comando","AuthID":"AuthID","Authentication password":"Password di autenticazione","Authentication username":"Nome utente di autenticazione","Autogenerated passphrase":"Genera automaticamente passphrase","Automatically run backups.":"Esegui automaticamente i backup.","B2 Account ID":"ID Account B2","B2 Application Key":"Chiave Applicazione B2","B2 Cloud Storage Account ID":"ID Account Cloud B2 Storage","B2 Cloud Storage Application Key":"Chiave applicazione Archiviazione Cloud B2","Back":"Indietro","Backend modules:":"Moduli backend:","Backup destination":"Destinazione backup","Backup location":"Posizione Backup","Backup:":"Dimensione backup:","Beta":"Beta","Broken access":"Accesso non riuscito","Browse":"Browse","Browser default":"Browser predefinito","Bucket Name":"Nome Bucket","Bucket create location":"Crea posizione bucket","Bucket create region":"Crea area bucket","Bucket name":"Nome bucket","Bucket storage class":"Classe bucket","Building list of files to restore ...":"Creazione della lista dei file da ripristinare...","Building partial temporary database ...":"Creazione di un database parziale temporaneo...","Busy ...":"Occupato...","Canary":"Canary","Cancel":"Annulla","Cannot move to existing file":"Non puoi spostare in un file esistente","Changelog":"Changelog","Changelog for {{appname}} {{version}}":"Changelog di {{appname}} {{version}}","Check failed:":"Controllo fallito:","Check for updates now":"Controlla aggiornamenti ora","Checking ...":"Controllo...","Checking for updates ...":"Controllo aggiornamenti...","Chose a storage type to get started":"Scegliere un tipo di archiviazione per iniziare","Click the AuthID link to create an AuthID":"Clicca sul link AuthID per creare un nuovo AuthID","Click to set throttle options":"Clicca per impostare le opzioni di limitazione","Commandline ...":"Riga di comando...","Compact now":"Comprimi","Compacting remote data ...":"Comprimendo dati remoti...","Completing backup ...":"Completamento backup...","Completing previous backup ...":"Completamento backup precedente...","Compression modules:":"Moduli di compressione:","Computer":"Computer","Configuration file:":"File di configurazione:","Configuration:":"Configurazione: ","Configure a new backup":"Configura un nuovo backup","Confirm delete":"Conferma cancellazione","Confirmation required":"Conferma richiesta","Connect":"Connetti","Connect now":"Connetti ora","Connecting to server ...":"Connessione al server...","Connecting to task ....":"Connessione all'attività...","Connecting...":"Connessione...","Connection lost":"Connessione persa","Connection worked!":"Connessione funzionante!","Container name":"Nome contenitore","Container region":"Area contenitore","Continue":"Continua","Continue without encryption":"Continua senza crittografia","Copied!":"Copiato!","Copy Destination URL to Clipboard":"Copia URL Destinazione negli Appunti","Copy failed. Please manually copy the URL":"Copia non riuscita. Per favore copia manualmente l'URL","Core options":"Opzioni base","Counting ({{files}} files found, {{size}})":"Conteggio ({{files}} file trovati, {{size}})","Crashes only":"Solo arresti anomali","Create bug report ...":"Crea segnalazione bug...","Create folder?":"Creare cartella?","Created new limited user":"Creato nuovo utente limitato","Creating bug report ...":"Creazione segnalazione bug...","Creating new user with limited access ...":"Creazione nuovo utente con accesso limitato...","Creating target folders ...":"Creazione cartelle di destinazione...","Creating temporary backup ...":"Creazione backup temporaneo...","Creating user...":"Creazione utente...","Current version is {{versionname}} ({{versionnumber}})":"La versione attuale è {{versionname}} ({{versionnumber}})","Custom S3 endpoint":"End point S3 personalizzato","Custom authentication url":"URL di autenticazione personalizzato","Custom location ({{server}})":"Posizione personalizzata ({{server}})","Custom region for creating buckets":"Area personalizzata per la creazione bucket","Custom region value ({{region}})":"Valore area personalizzata ({{region}})","Custom server url ({{server}})":"URL del server personalizzato ({{server}})","Custom storage class ({{class}})":"Classe di archiviazione personalizzata ({{class}})","Database ...":"Database...","Days":"Giorni","Default":"Predefinito","Default ({{channelname}})":"Predefinito ({{channelname}})","Default Filters":"Filtri predefiniti","Default options":"Opzioni predefinite","Delete":"Cancella","Delete ...":"Cancella...","Delete backup":"Cancella backup","Delete local database":"Cancella database locale","Delete remote files":"Cancella file remoti","Delete the local database":"Cancella il database locale","Delete {{filecount}} files ({{filesize}}) from the remote storage?":"Cancella {{filecount}} file ({{filesize}}) dall'archivio remoto?","Deleting remote files ...":"Cancellazione file remoti...","Deleting unwanted files ...":"Cancellazione file indesiderati...","Desktop":"Desktop","Destination":"Destinazione","Did we help save your files? If so, please consider supporting Duplicati with a donation. We suggest {{smallamount}} for private use and {{largeamount}} for commercial use.":"Ti abbiamo aiutato a salvare i tuoi file? Se è così, per favore considera di supportare Duplicati con una donazione. Suggeriamo {{smallamount}} per uso privato e {{largeamount}} per uso commerciale.","Direct restore from backup files ...":"Ripristino diretto da file di backup...","Disabled":"Disattivato","Dismiss":"Annulla","Display and color theme":"Tema interfaccia","Do you really want to delete the backup: \"{{name}}\" ?":"Vuoi veramente cancellare il backup: \"{{name}}\" ?","Do you really want to delete the local database for: {{name}}":"Vuoi veramente cancellare il database locale per: {{name}} ?","Donate":"Donazione","Donate with PayPal":"Donazione con PayPal","Donate with crypto currency":"Dona con valuta criptata","Donation messages":"Messaggi donazione","Donation messages are hidden, click to show":"I messaggi di donazione sono nascosti, clicca per mostrarli","Donation messages are visible, click to hide":"I messaggi di donazione sono visibili, clicca per nasconderli","Done":"Fatto","Download":"Scarica","Downloading ...":"Sto scaricando...","Downloading files ...":"Sto scaricando i file...","Downloading update...":"Sto scaricando l'aggiornamento...","Duplicate option {{opt}}":"Opzione duplicata {{opt}}","Duplicati Website":"Sito web di Duplicati","Duplicati forum":"Forum Duplicati","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\n When deleting a backup, you can also delete the local database without affecting the ability to restore the remote files.\n If you are using the local database for backups from the commandline, you should keep the database.":"Ogni backup dispone di un database locale associato, che archivia le informazioni del backup remoto sul computer locale.\nQuando si cancella un backup, è anche possibile cancellare il database locale senza influire sulla possibilità di ripristinare i file remoti.\nSe si utilizza il database locale per i backup dalla riga di comando, è necessario mantenere il database.","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\\nThis makes it faster to perform many operations, and reduces the amount of data that needs to be downloaded for each operation.":"Ogni backup dispone di un database locale associato, che archivia le informazioni del backup remoto sul computer locale.\nIn questo modo è più veloce eseguire molte operazioni e riduce la quantità di dati che devono essere scaricati per ogni operazione.","Edit ...":"Modifica...","Edit as list":"Modifica come elenco","Edit as text":"Modifica come testo","Encrypt file":"Cripta file","Encryption":"Crittografia","Encryption changed":"Crittografia cambiata","Encryption modules:":"Moduli crittografia:","Enter URL":"Inserisci URL","Enter access key":"Inserisci chiave di accesso","Enter account name":"Inserisci nome account","Enter backup passphrase, if any":"Inserisci la passphrase del backup, se presente","Enter configuration details":"Inserisci dettagli configurazione","Enter container name":"Inserire nome contenitore","Enter encryption passphrase":"Inserisci passphrase crittografia","Enter expression here":"Inserisci qui espressione","Enter folder path name":"Inserire il nome del percorso della cartella","Enter one option per line in command-line format, eg. {0}":"Inserire un'opzione per riga in formato riga di comando, ad es. {0}","Enter the destination path":"Inserisci percorso destinazione","Error":"Errore","Error!":"Errore!","Errors and crashes":"Errori e arresti anomali","Exclude":"Escludi","Exclude directories whose names contain":"Escludi cartelle il cui nome contiene","Exclude expression":"Escludi espressione","Exclude file":"Escludi file","Exclude file extension":"Escludi estensione del file","Exclude files whose names contain":"Escludi file il cui nome contiene","Exclude folder":"Escludi cartella","Exclude regular expression":"Escludi espressione regolare","Existing file found":"Trovato file esistente","Experimental":"Sperimentale","Export":"Esporta","Export ...":"Esporta...","Export backup configuration":"Esporta configurazione backup","Export configuration":"Esporta configurazione","Exporting ...":"Esportazione...","FTP (Alternative)":"FTP (Alternativo)","Failed to build temporary database: {{message}}":"Fallita creazione del database temporaneo: {{message}}","Failed to connect:":"Connessione fallita:","Failed to connect: {{message}}":"Connessione fallita: {{message}}","Failed to delete:":"Cancellazione fallita: ","Failed to fetch path information: {{message}}":"Recupero informazioni sul percorso fallito: {{message}}","Failed to import:":"Importazione fallita:","Failed to read backup defaults:":"Lettura impostazioni predefinite backup fallita:","Failed to restore files: {{message}}":"Ripristino dei file fallito: {{message}}","Failed to save:":"Salvataggio fallito:","Fetching path information ...":"Recupero informazioni percorso...","File":"File","Files larger than:":"File più grandi di:","Filters":"Filtri","Finished!":"Finito!","First run setup":"Impostazione prima esecuzione","Folder":"Cartella","Folder path":"Percorso cartella","Fri":"Ven","GByte":"GByte","GByte/s":"GByte/s","GCS Project ID":"ID Progetto GCS","General":"Generale","General backup settings":"Impostazioni generali backup","General options":"Opzioni generali","Generate":"Genera","Generate IAM access policy":"Genera criteri di accesso IAM","Getting file versions ...":"Ottenimento versione file...","Hidden files":"File nascosti","Hide":"Nascondi","Hide hidden folders":"Nascondi cartelle nascoste","Home":"Home","Hours":"Ore","How do you want to handle existing files?":"Come vuoi gestire i file esistenti?","Hyper-V Machine":"Sitema Hyper-V","Hyper-V Machine:":"Sistema Hyper-V:","Hyper-V Machines":"Sistemi Hyper-V","ID:":"ID:","If a date was missed, the job will run as soon as possible.":"Se una pianificazione non è eseguita, il backup sarà effettuato il prima possibile.","If the backup and the remote storage is out of sync, Duplicati will require that you perform a repair operation to synchronize the database.\\nIf the repair is unsuccesful, you can delete the local database and re-generate.":"Se il backup e l'archivio remoto non sono sincronizzati, Duplicati sarà necessario eseguire un'operazione di ripristino per sincronizzare il database.\nSe la riparazione non è riuscita, è possibile cancellare il database locale e rigenerarlo.","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"Se il file di backup non è scaricato automaticamente, fai clic con il tasto desto e seleziona "Salva come..."","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"Se il file di backup non è scaricato automaticamente,fai clic con il tasto desto e seleziona "Salva come..."","If you do not enter a path, all files will be stored in the login folder.\nAre you sure this is what you want?":"Se non inserisci un percorso, tutti i file saranno salvati nella cartella di accesso.\nSei sicuro che questo è quello che vuoi?","If you do not enter an API Key, the tenant name is required":"Se non inserisci una Chiave API, è richiesto il nome dell'inquilino","If you want to use the backup later, you can export the configuration before deleting it":"Se desideri utilizzare il backup in un secondo momento, è possibile esportare la configurazione prima di cancellarla","If your machine is in a multi-user environment (i.e. the machine has more than one account), you need to set a password to prevent other users from accessing data on your account.\nDo you want to set a password now?":"Se la tua macchina è in un ambiente multi-utente (cioè la macchina ha più di un account), è necessario impostare una password per impedire ad altri utenti di accedere ai dati del tuo account. \nVuoi impostare una password ora?","Import":"Importa","Import Destination URL":"Importa URL Destinazione","Import backup configuration":"Importa configurazione backup","Import completed, but no certificates were found after the import":"Importazione completata, ma non sono stati trovati certificati dopo l'importazione","Import failed":"Importazione fallita","Import from a file":"Importa da un file","Importing ...":"Importazione...","Include a file?":"Includi un file?","Include expression":"Includi espressione","Include regular expression":"Includi espressione regolare","Incorrect answer, try again":"Risposta errata, riprova","Individual builds for developers only.":"Build individuali per soli sviluppatori.","Information":"Informazioni","Install":"Installa","Install failed:":"Installazione fallita:","Invalid characters in path":"Caratteri non validi nel percorso","Invalid retention time":"Tempo ritenzione non valido","It is possible to connect to some FTP without a password.\nAre you sure your FTP server supports password-less logins?":"È possibile connettersi ad alcuni FTP senza una password.\nSei sicuro che il tuo server FTP supporta gli accessi senza password?","KByte":"KByte","KByte/s":"KByte/s","Keep this number of backups":"Backup da mantenere","Language in user interface":"Lingua interfaccia utente","Last month":"Lo scorso mese","Last successful run:":"Ultima esecuzione corretta:","Latest":"Più recente","Libraries":"Librerie","Linux":"Linux","Listing backup dates ...":"Creazione elenco date backup...","Listing remote files ...":"Creazione elenco file remoti...","Live":"In tempo reale","Load a configuration from an exported job or a storage provider":"Carica una configurazione da un lavoro esportato o da un provider di archiviazione","Load destination from an exported job or a storage provider":"Carica una destinazione da un lavoro esportato o da un provider di archiviazione","Load older data":"Carica dati precedenti","Loading ...":"Caricamento...","Loading remote storage usage ...":"Caricamento dell'archivio remoto utilizzato ...","Local database for":"Database locale per ","Local database path:":"Percorso database locale:","Local storage":"Archivio locale","Location":"Posizione","Location where buckets are created":"Posizione in cui sono creati i bucket","Log data for {{Backup.Backup.Name}}":"Dati di log per {{Backup.Backup.Name}}","Log data from the server":"Dati di log dal server","Log out":"Log out","MByte":"MByte","MByte/s":"MByte/s","Maintenance":"Manutenzione","Manually type path":"Digita manualmente il percorso","Max download speed":"Velocità massima per scaricare","Max upload speed":"Velocità massima per caricare","Menu":"Menu","Microsoft SQL Database:":"Microsoft SQL Database:","Microsoft SQL Databases":"Microsoft SQL Database","Minimum redundancy":"Ridondanza minima","Minimum redundancy is 1.0":"Ridondanza minima è 1.0","Minutes":"Minuti","Missing name":"Nome mancante","Missing passphrase":"Passphrase mancante","Missing sources":"Sorgente mancante","Mon":"Lun","Months":"Mesi","Move existing database":"Sposta database esistente","Move failed:":"Spostamento fallito:","My Documents":"Documenti","My Music":"Musica","My Photos":"Foto","My Pictures":"Immagini","Name":"Nome","Never":"Mai","New update found: {{message}}":"Nuovo aggiornamento trovato: {{message}}","New user name is {{user}}.\nUpdated credentials to use the new limited user":"Il nuovo nome utente è {{user}}.\nCredenziali aggiornate per utilizzare il nuovo utente limitato","Next":"Avanti","Next scheduled run:":"Prossima esecuzione: ","Next scheduled task:":"Prossima attività pianificata:","Next task:":"Prossima attività:","Next time":"Prossima volta","No":"No","No certificate was specified previously, please verify with the server administrator that the key is correct: {{key}} \n\nDo you want to approve the reported host key?":"Nessun certificato è stato specificato in precedenza, per favore verifica con l'amministratore del server che la chiave è corretta: {{key}}\n\nVuoi approvare la chiave host riportata?","No editor found for the "{{backend}}" storage type":"Nessun editor trovato per il "{{backend}}" tipo archivio","No encryption":"Nessuna crittografia","No items selected":"Nessun elemento selezionato","No items to restore, please select one or more items":"Nessun elemento da ripristinare, seleziona uno o più elementi","No passphrase entered":"Nessuna passphrase inserita","No scheduled tasks":"Nessuna attività pianificata","No, my machine has only a single account":"No, la mia macchina ha solo un singolo account","Non-matching passphrase":"Passphrase non corrispondente","None / disabled":"Nessuno / disattivato","OK":"OK","OSX":"OSX","OpenStack AuthURI":"OpenStack AuthURI","OpenStack Object Storage / Swift":"OpenStack Object Storage / Swift","Operation failed:":"Operazione fallita:","Operations:":"Operazioni:","Optional authentication password":"Password opzionale per l'autenticazione","Optional authentication username":"Nome utente opzionale per l'autenticazione","Options":"Opzioni","Options added here are applied to all backups, but can be overridden in each individual backup":"Le opzioni aggiunte qui sono applicate a tutti i backup, ma possono essere sovrascritte per ogni backup","Original location":"Percorso originale","Others":"Altri","Overwrite":"Sovrascrivi","Passphrase":"Passphrase","Passphrase (if encrypted)":"Passphrase (se criptato)","Passphrase changed":"Passphrase modificata","Passphrases are not matching":"Passphrase non corrispondenti","Password":"Password","Passwords do not match":"Password non corrispondenti","Patching files with local blocks ...":"Sistemazione file con blocchi locali...","Path not found":"Percorso non trovato","Path on server":"Percorso sul server","Path or subfolder in the bucket":"Percorso o sottocartella bucket","Pause":"Pausa","Pause after startup or hibernation":"Pausa dopo avvio o ibernazione","Pause options":"Opzioni pausa","Permissions":"Autorizzazioni","Pick location":"Scegli posizione","Point to your backup files and restore from there":"Puntare ai file di backup e ripristinare da lì","Port":"Porta","Previous":"Precedente","ProjectID is optional if the bucket exist":"ID Progetto è opzionale se esiste un bucket","Proprietary":"Proprietario","Purging files ...":"Cancellazione dei file...","Rebuilding local database ...":"Ricostruzione database locale...","Recreate (delete and repair)":"Ricrea (cancella e ripara)","Recreating database ...":"Ricreazione database...","Registering temporary backup ...":"Registrazione backup temporaneo...","Relative paths not allowed":"Percorsi relativi non consentiti","Reload":"Ricarica","Remote":"Remoto","Remove":"Rimuovi","Remove option":"Rimuovi opzione","Repair":"Ripara","Reparing ...":"Riparazione...","Repeat Passphrase":"Ripeti Passphrase","Reporting:":"Segnalazione:","Reset":"Reset","Restore":"Ripristina","Restore files":"Ripristina file","Restore files ...":"Ripristina file...","Restore files from {{backupname}}":"Ripristina file da {{backupname}}","Restore from":"Ripristina da","Restore from backup configuration":"Ripristino dalla configurazione backup","Restore from configuration ...":"Ripristino da file di configurazione...","Restore options":"Opzioni ripristino","Restore read/write permissions":"Ripristina autorizzazioni lettura/scrittura","Restoring files ...":"Ripristino file...","Resume":"Riprendi","Run again every":"Esegui ogni","Run now":"Esegui ora","Running ...":"Esecuzione...","Running ....":"Esecuzione...","Running commandline entry":"Riga di comando in esecuzione","Running task:":"Attività in esecuzione:","S3 Compatible":"Compatibile S3","Same as the base install version: {{channelname}}":"Come la versione di base installata: {{channelname}}","Sat":"Sab","Save":"Salva","Save and repair":"Salva e ripara","Save different versions with timestamp in file name":"Salva versioni diverse con timestamp nel nome del file","Save immediately":"Salva immediatamente","Scanning existing files ...":"Scansione file esistenti...","Scanning for local blocks ...":"Scansione dei blocchi locali...","Schedule":"Pianificazione","Search":"Cerca","Search for files":"Cerca per file","Seconds":"Secondi","Select a log level and see messages as they happen:":"Selezionare un livello di log e visiona i messaggi che avvengono:","Select files":"Seleziona file","Server":"Server","Server and port":"Server e porta","Server hostname or IP":"Nome host o IP del server","Server is currently paused,":"Server è attualmente in pausa,","Server is currently paused, do you want to resume now?":"Server attualmente in pausa, vuoi riprendere ora?","Server password":"Password del server","Server paused":"Server in pausa","Server state properties":"Proprietà stato del server","Settings":"Impostazioni","Show":"Mostra","Show advanced editor":"Mostra editor avanzato","Show hidden folders":"Mostra cartelle nascoste","Show log":"Mostra log","Show log ...":"Mostra log ...","Show treeview":"Visualizza ad albero","Sia server password":"Password del server Sia","Some OpenStack providers allow an API key instead of a password and tenant name":"Alcuni provider OpenStack consentono una chiave API anziché una password e un nome inquilino","Source Data":"Dati Sorgente","Source data":"Dati sorgente","Source folders":"Cartella sorgente","Source:":"Dimensione sorgente:","Specific builds for developers only.":"Build specifiche per soli sviluppatori.","Standard protocols":"Protocolli standard","Starting ...":"Avvio....","Starting the restore process ...":"Avvio del processo di ripristino...","Stop after the current file":"Ferma dopo il file corrente","Stop after upload":"Ferma dopo caricamento","Stop now":"Ferma adesso","Stop running backup":"Ferma esecuzione backup","Stop running task":"Ferma esecuzione attività","Stopping after upload:":"Ferma dopo caricamento:","Stopping task:":"Ferma attività:","Storage Type":"Tipo archivio","Storage class":"Classe archivio","Storage class for creating a bucket":"Classe di archiviazione per la creazione di un bucket","Stored":"Archiviati","Strong":"Forte","Success":"Successo","Sun":"Dom","Symbolic link":"Link simbolico","System default ({{levelname}})":"Sistema predefinito ({{levelname}})","System files":"File di sistema","System info":"Informazioni di sistema","System properties":"Proprietà di sistema","TByte":"TByte","TByte/s":"TByte/s","Target path, ie /backup":"Percorso di destinazione, cioè /backup","Task is running":"Attività in esecuzione","Temporary files":"File temporanei","Tenant Name":"Nome Inquilino","Test connection":"Prova connessione","Testing ...":"Test in corso...","Testing connection ...":"Prova connessione...","Testing permissions ...":"Prova autorizzazioni...","Testing permissions...":"Prova autorizzazioni...","The bucket name should be all lower-case, convert automatically?":"Il nome del bucket dovrebbe essere tutto minuscolo, convertirlo automaticamente?","The bucket name should start with your username, prepend automatically?":"Il nome del bucket dovrebbe iniziare con il tuo nome utente, anteporlo automaticamente?","The connection to the server is lost, attempting again in {{time}} ...":"Connessione al server persa, nuovo tentativo tra {{time}}...","The dark theme (by Michal)":"Tema scuro (da Michal)","The default blue on white theme (by Alex)":"Predefinito - Tema blu su bianco (da Alex)","The folder {{folder}} does not exist.\nCreate it now?":"La cartella {{folder}} non esiste. \nCreala adesso?","The host key has changed, please check with the server administrator if this is correct, otherwise you could be the victim of a MAN-IN-THE-MIDDLE attack.\n\nDo you want to REPLACE your CURRENT host key \"{{prev}}\" with the REPORTED host key: {{key}}?":"La chiave host è cambiata, per favore consulta l'amministratore del server se questa è corretta, altrimenti potresti essere la vittima di un attacco UOMO-NEL-MEZZO.\n\nVuoi SOSTITUIRE la chiave host CORRENTE \"{{prev}}\" con la chiave host SEGNALATA: {{key}}?","The path does not appear to exist, do you want to add it anyway?":"Il percorso sembra non esistere, vuoi aggiungerlo comunque?","The path does not end with a '{{dirsep}}' character, which means that you include a file, not a folder.\n\nDo you want to include the specified file?":"Il percorso non termina con un carattere '{{dirsep}}', il che significa che si include un file, non una cartella.\n\nVuoi includere il file specificato?","The path must be an absolute path, i.e. it must start with a forward slash '/'":"Il percorso deve essere un percorso assoluto, cioè deve iniziare con una barra '/'","The path should start with \"{{prefix1}}\" or \"{{prefix2}}\", otherwise you will not be able to see the files in the HubiC web interface.\n\nDo you want to add the prefix to the path automatically?":"Il percorso deve iniziare con \"{{prefix1}}\" o \"{{prefix2}}\", altrimenti non sarà possibile visualizzare i file nell'interfaccia Web di HubiC.\n\nVuoi aggiungere automaticamente il prefisso al percorso?","The region parameter is only applied when creating a new bucket":"Il parametro area è applicato solo quando si crea un nuovo bucket","The region parameter is only used when creating a bucket":"Il parametro area è utilizzato solo quando si crea un bucket","The server certificate could not be validated.\nDo you want to approve the SSL certificate with the hash: {{hash}}?":"Il certificato del server non può essere convalidato.\n\nVuoi approvare il certificato SSL con l'hash: {{hash}}?","The storage class affects the availability and price for a stored file":"La classe di archiviazione influisce sulla disponibilità e sul prezzo per un file archiviato","The target folder contains encrypted files, please supply the passphrase":"La cartella di destinazione contiene file criptati, per favore fornisci la passphrase","The user has too many permissions. Do you want to create a new limited user, with only permissions to the selected path?":"L'utente dispone di troppe autorizzazioni. Vuoi creare un nuovo utente limitato, con solo autorizzazioni per il percorso selezionato?","This backup was created on another operating system. Restoring files without specifying a destination folder can cause files to be restored in unexpected places. Are you sure you want to continue without choosing a destination folder?":"Questo backup è stato creato su un altro sistema operativo. Il ripristino dei file senza specificare una cartella di destinazione può causare il ripristino di file in luoghi imprevisti. Sei sicuro di voler continuare senza scegliere una cartella di destinazione?","This month":"Questo mese","This week":"Questa settimana","Throttle settings":"Impostazioni limitazione","Thu":"Mar","To File":"Al File","To confirm you want to delete all remote files for \"{{name}}\", please enter the word you see below":"Per confermare che vuoi cancellare tutti i file remoti che contengono \"{{name}}\", digita la parla che vedi di seguito","To export without a passphrase, uncheck the \"Encrypt file\" box":"Per esportare senza una passphrase, deselezionare la casella \"Cripta file\"","Today":"Oggi","Trust host certificate?":"Certificato host affidabile?","Trust server certificate?":"Certificato server affidabile?","Try out the new features we are working on. Don't use with important data.":"Prova le nuove funzioni su cui stiamo lavorando. Non usarlo in ambienti di produzione.","Tue":"Gio","Type to highlight files":"Digitare per evidenziare i file","Unknown backup size and versions":"Dimensione e versione backup sconosciute","Until resumed":"Finché non riprende","Update channel":"Canale di aggiornamento","Update failed:":"Aggiornamento fallito:","Updating with existing database":"Aggiornamento con database esistente","Upload volume size":"Dimensione file caricati","Uploading verification file ...":"Caricamento file di verifica...","Usage reports help us improve the user experience and evaluate impact of new features. We use them to generate public usage statistics":"I rapporti sull'utilizzo ci aiutano a migliorare l'esperienza dell'utente e a valutare l'impatto delle nuove funzionalità. Li usiamo per generare statistiche di utilizzo pubblico","Usage statistics":"Statistiche di utilizzo","Usage statistics, warnings, errors, and crashes":"Statistiche di utilizzo, avvisi, errori e arresti anomali","Use SSL":"Usa SSL","Use existing database?":"Usare database esistente?","Use weak passphrase":"Usa passphrase debole","Useless":"Inutile","User data":"Dati utente","User has too many permissions":"L'utente ha troppe autorizzazioni","User interface settings":"Impostazioni interfaccia utente","Username":"Nome utente","Validating ...":"Convalida...","Verify files":"Verifica file","Verifying ...":"Verifica...","Verifying answer":"Verifica risposta","Verifying backend data ...":"Verifica dati backend...","Verifying remote data ...":"Verifica dati remoti...","Verifying restored files ...":"Verifica file ripristinati...","Very strong":"Molto forte","Very weak":"Molto debole","Visit us on":"Seguici su","WARNING: The remote database is found to be in use by the commandline library":"ATTENZIONE: Il database remoto si trova in uso dalla libreria riga di comando","WARNING: This will prevent you from restoring the data in the future.":"ATTENZIONE: Questo ti impedirà di ripristinare i dati in futuro.","Waiting for task to begin":"In attesa dell'attività per iniziare","Waiting for task to start ....":"In attesa dell'attività per iniziare...","Waiting for upload ...":"In attesa del caricamento...","Warnings, errors and crashes":"Avvisi, errori e arresti anomali","We accept donations via different services, such as OpenCollective, PayPal, BountySource and various crypto currencies.":"Accettiamo donazioni tramite diversi servizi, come OpenCollective, PayPal, BountySource e varie criptovalute.","We recommend that you encrypt all backups stored outside your system":"Ti consigliamo di criptare tutti i backup archiviati al di fuori del tuo sistema","Weak":"Debole","Weak passphrase":"Passphrase debole","Wed":"Mer","Weeks":"Settimane","Where do you want to restore from?":"Da dove vuoi ripristinare?","Where do you want to restore the files to?":"Dove vuoi ripristinare i files?","Windows":"Windows","Years":"Anni","Yes":"Si","Yes, I have stored the passphrase safely":"Si, ho archiviato la passphrase in modo sicuro","Yes, I'm brave!":"Sì, sono coraggioso!","Yes, please break my backup!":"Sì, per favore rompi il mio backup!","Yesterday":"Ieri","You appear to be running Mono with no SSL certificates loaded.\nDo you want to import the list of trusted certificates from Mozilla?":"Sembra che tu sia in esecuzione Mono senza certificati SSL caricati.\nVuoi importare l'elenco dei certificati attendibili da Mozilla?","You are changing the database path away from an existing database.\nAre you sure this is what you want?":"Stai cambiando il percorso di un database esistente.\nSei sicuro che questo è ciò che vuoi?","You are currently running {{appname}} {{version}}":"Attualmente stai eseguendo {{appname}} {{version}}","You can stop the backup immediately, or stop after the current file has been uploaded.":"È possibile fermare immediatamente il backup o fermarlo dopo che il file corrente è stato caricato.","You can stop the task immediately, or allow the process to continue its current file and the stop.":"Puoi arrestare immediatamente l'attività o consentire al processo di continuare il file in corso e fermarlo.","You have changed the encryption mode. This may break stuff. You are encouraged to create a new backup instead":"Hai modificato l'algoritmo di crittografia. Questa azione potrebbe corrompere i dati. Ti consigliamo di creare un nuovo backup.","You have changed the passphrase, which is not supported. You are encouraged to create a new backup instead.":"Hai modificato la passphrase ma questo non è supportato. Ti consigliamo di creare un nuovo backup.","You have chosen not to encrypt the backup. Encryption is recommended for all data stored on a remote server.":"Hai scelto di non criptare il backup. È consigliabile criptare tutti i dati custoditi su server remoti.","You have chosen to restore to a new location, but not entered one":"Si è scelto di ripristinare in una nuova posizione, ma non ne è stata inserita una","You have generated a strong passphrase. Make sure you have made a safe copy of the passphrase, as the data cannot be recovered if you lose the passphrase.":"Hai generato una passphrase forte. Assicurati di aver fatto una copia sicura della passphrase, poiché i dati non possono essere recuperati se perdi la passphrase.","You must choose at least one source folder":"Devi scegliere almeno una cartella sorgente","You must enter a name for the backup":"Devi inserire un nome un nome per il backup","You must enter a passphrase or disable encryption":"Devi inserire una passphrase o disattivare la crittografia","You must enter a positive number of backups to keep":"Devi inserire un numero positivo di backup da mantenere","You must enter a tenant name if you do not provide an API Key":"Devi inserire il nome di un inquilino se non fornisci una Chiave API","You must enter a valid duration for the time to keep backups":"Devi inserire un periodo di tempo valido in cui mantenere i backup","You must enter either a password or an API Key":"Devi inserire una password o una Chiave API","You must enter either a password or an API Key, not both":"Devi inserire una password o una Chiave API, non entrambe","You must fill in the password":"Devi compilare in password","You must fill in the server name or address":"Devi compilare in nome del server o indirizzo","You must fill in the username":"Devi compilare in nome utente","You must fill in {{field}}":"Devi compilare in {{field}}","You must select or fill in the AuthURI":"Devi selezionare o compilare in AuthURI","You must select or fill in the server":"Devi selezionare o compilare in server","You must specify a path":"Devi specificare un percorso","Your files and folders have been restored successfully.":"I tuoi file e cartelle sono stati ripristinati correttamente.","Your passphrase is easy to guess. Consider changing passphrase.":"La tua passphrase è facile da indovinare. Considera l'idea di cambiarla.","a specific number":"un numero specifico","bucket/folder/subfolder":"bucket/cartella/sottocartella","byte":"byte","byte/s":"byte/s","custom":"Personalizzato","resume now":"riprendi ora","unlimited":"illimitato","until they are older than":"finché non sono più vecchi di","{{appname}} was primarily developed by {{dev1}} and {{dev2}}. {{appname}} can be downloaded from {{websitename}}. {{appname}} is licensed under the {{licensename}}.":"{{appname}} è stato sviluppato principalmente da {{dev1}} e {{dev2}}. {{appname}} può essere scaricato da {{websitename}}. {{appname}} è sotto la licenza {{licensename}}.","{{files}} files ({{size}}) to go {{speed_txt}}":"Caricamento di {{files}} file ({{size}}) {{speed_txt}}","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Version":["{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Versione","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Versioni"],"{{number}} Hour":"{{number}} Ore","{{number}} Minutes":"{{number}} Minuti","{{time}} (took {{duration}})":"{{time}} (durato {{duration}})"}); + gettextCatalog.setStrings('it', {"- pick an option -":"- seleziona un'opzione -","...loading...":"... caricamento in corso ...","API Key":"Chiave API","AWS Access ID":"ID di accesso AWS","AWS Access Key":"Chiave di accesso AWS","AWS IAM Policy":"Norme AWS IAM","About":"Informazioni","About {{appname}}":"Informazioni {{appname}}","Access Key":"Chiave di accesso","Access denied":"Accesso negato","Access to user interface":"Accesso all'interfaccia utente","Account name":"Nome account","Activate":"Attiva","Activate failed:":"Attivazione fallita:","Add a new backup":"Aggiungi un nuovo backup","Add a path directly":"Aggiungi direttamente un percorso","Add advanced option":"Aggiungi opzione","Add backup":"Aggiungi backup","Add filter":"Aggiungi filtro","Add path":"Aggiungi percorso","Adjust bucket name?":"Sistemare il nome bucket?","Adjust path name?":"Sistemare il nome del percorso?","Advanced Options":"Opzioni Avanzate","Advanced options":"Opzioni avanzate","Advanced:":"Avanzate:","All":"Tutti","All Hyper-V Machines":"Tutte le Macchine Hyper-V","All Microsoft SQL Databases":"Tutti i database Microsoft SQL","All usage reports are sent anonymously and do not contain any personal information. They contain information about hardware and operating system, the type of backend, backup duration, overall size of source data and similar data. They do not contain paths, filenames, usernames, passwords or similar sensitive information.":"Tutti i rapporti sono inviati in modo anonimo e non contengono informazioni personali. Contengono informazioni sull'hardware, sul sistema operativo, il tipo di backend, la durata del backup, la dimensione complessiva dei dati sorgente ed dati simili. Non contengono i percorsi, nomi dei file, nomi utente, password o altre informazioni sensibili.","Allow remote access (requires restart)":"Consenti accesso remoto (richiede il riavvio)","Allowed days":"Giorni consentiti","An existing file was found at the new location":"Un file esistente è stato trovato nella nuova posizione","An existing file was found at the new location\nAre you sure you want the database to point to an existing file?":"Un file esistente è stato trovato nella nuova posizione.\nSei sicuro di volere che il database punti ad un file esistente?","An existing local database for the storage has been found.\nRe-using the database will allow the command-line and server instances to work on the same remote storage.\n\n Do you wish to use the existing database?":"Un database locale esistente per l'archiviazione è stato trovato.\nIl riutilizzo del database consentirà alle istanze da riga di comando e dal server di lavorare sullo stesso archivio remoto.\n\nVuoi usare il database esistente?","Anonymous usage reports":"Rapporti d'uso anonimi","As Command-line":"Come riga di comando","AuthID":"AuthID","Authentication password":"Password di autenticazione","Authentication username":"Nome utente di autenticazione","Autogenerated passphrase":"Genera automaticamente passphrase","Automatically run backups.":"Esegui automaticamente i backup.","B2 Account ID":"ID Account B2","B2 Application Key":"Chiave Applicazione B2","B2 Cloud Storage Account ID":"ID Account Cloud B2 Storage","B2 Cloud Storage Application Key":"Chiave applicazione Archiviazione Cloud B2","Back":"Indietro","Backend modules:":"Moduli backend:","Backup destination":"Destinazione backup","Backup location":"Posizione Backup","Backup retention":"Conservazione backup","Backup:":"Dimensione backup:","Beta":"Beta","Broken access":"Accesso non riuscito","Browse":"Browse","Browser default":"Browser predefinito","Bucket Name":"Nome Bucket","Bucket create location":"Crea posizione bucket","Bucket create region":"Crea area bucket","Bucket name":"Nome bucket","Bucket storage class":"Classe bucket","Building list of files to restore ...":"Creazione della lista dei file da ripristinare...","Building partial temporary database ...":"Creazione di un database parziale temporaneo...","Busy ...":"Occupato...","Canary":"Canary","Cancel":"Annulla","Cannot move to existing file":"Non puoi spostare in un file esistente","Changelog":"Changelog","Changelog for {{appname}} {{version}}":"Changelog di {{appname}} {{version}}","Check failed:":"Controllo fallito:","Check for updates now":"Controlla aggiornamenti ora","Checking ...":"Controllo...","Checking for updates ...":"Controllo aggiornamenti...","Chose a storage type to get started":"Scegliere un tipo di archiviazione per iniziare","Click the AuthID link to create an AuthID":"Clicca sul link AuthID per creare un nuovo AuthID","Click to set throttle options":"Clicca per impostare le opzioni di limitazione","Commandline ...":"Riga di comando...","Compact now":"Comprimi","Compacting remote data ...":"Comprimendo dati remoti...","Completing backup ...":"Completamento backup...","Completing previous backup ...":"Completamento backup precedente...","Compression modules:":"Moduli di compressione:","Computer":"Computer","Configuration file:":"File di configurazione:","Configuration:":"Configurazione: ","Configure a new backup":"Configura un nuovo backup","Confirm delete":"Conferma cancellazione","Confirmation required":"Conferma richiesta","Connect":"Connetti","Connect now":"Connetti ora","Connecting to server ...":"Connessione al server...","Connecting to task ....":"Connessione all'attività...","Connecting...":"Connessione...","Connection lost":"Connessione persa","Connection worked!":"Connessione funzionante!","Container name":"Nome contenitore","Container region":"Area contenitore","Continue":"Continua","Continue without encryption":"Continua senza crittografia","Copied!":"Copiato!","Copy":"Copia","Copy Destination URL to Clipboard":"Copia URL Destinazione negli Appunti","Copy failed. Please manually copy the URL":"Copia non riuscita. Per favore copia manualmente l'URL","Core options":"Opzioni base","Counting ({{files}} files found, {{size}})":"Conteggio ({{files}} file trovati, {{size}})","Crashes only":"Solo arresti anomali","Create bug report ...":"Crea segnalazione bug...","Create folder?":"Creare cartella?","Created new limited user":"Creato nuovo utente limitato","Creating bug report ...":"Creazione segnalazione bug...","Creating new user with limited access ...":"Creazione nuovo utente con accesso limitato...","Creating target folders ...":"Creazione cartelle di destinazione...","Creating temporary backup ...":"Creazione backup temporaneo...","Creating user...":"Creazione utente...","Current version is {{versionname}} ({{versionnumber}})":"La versione attuale è {{versionname}} ({{versionnumber}})","Custom S3 endpoint":"End point S3 personalizzato","Custom authentication url":"URL di autenticazione personalizzato","Custom backup retention":"Conservazione backup personalizzato","Custom location ({{server}})":"Posizione personalizzata ({{server}})","Custom region for creating buckets":"Area personalizzata per la creazione bucket","Custom region value ({{region}})":"Valore area personalizzata ({{region}})","Custom server url ({{server}})":"URL del server personalizzato ({{server}})","Custom storage class ({{class}})":"Classe di archiviazione personalizzata ({{class}})","Database ...":"Database...","Days":"Giorni","Default":"Predefinito","Default ({{channelname}})":"Predefinito ({{channelname}})","Default Filters":"Filtri predefiniti","Default options":"Opzioni predefinite","Delete":"Cancella","Delete ...":"Cancella...","Delete backup":"Cancella backup","Delete backups that are older than":"Elimina i backup più vecchi di","Delete local database":"Cancella database locale","Delete remote files":"Cancella file remoti","Delete the local database":"Cancella il database locale","Delete {{filecount}} files ({{filesize}}) from the remote storage?":"Cancella {{filecount}} file ({{filesize}}) dall'archivio remoto?","Deleting remote files ...":"Cancellazione file remoti...","Deleting unwanted files ...":"Cancellazione file indesiderati...","Desktop":"Desktop","Destination":"Destinazione","Did we help save your files? If so, please consider supporting Duplicati with a donation. We suggest {{smallamount}} for private use and {{largeamount}} for commercial use.":"Ti abbiamo aiutato a salvare i tuoi file? Se è così, per favore considera di supportare Duplicati con una donazione. Suggeriamo {{smallamount}} per uso privato e {{largeamount}} per uso commerciale.","Direct restore from backup files ...":"Ripristino diretto da file di backup...","Disabled":"Disattivato","Dismiss":"Annulla","Display and color theme":"Tema interfaccia","Do you really want to delete the backup: \"{{name}}\" ?":"Vuoi veramente cancellare il backup: \"{{name}}\" ?","Do you really want to delete the local database for: {{name}}":"Vuoi veramente cancellare il database locale per: {{name}} ?","Donate":"Donazione","Donation messages":"Messaggi donazione","Donation messages are hidden, click to show":"I messaggi di donazione sono nascosti, clicca per mostrarli","Donation messages are visible, click to hide":"I messaggi di donazione sono visibili, clicca per nasconderli","Done":"Fatto","Download":"Scarica","Downloading ...":"Sto scaricando...","Downloading files ...":"Sto scaricando i file...","Downloading update...":"Sto scaricando l'aggiornamento...","Duplicate option {{opt}}":"Opzione duplicata {{opt}}","Duplicati Website":"Sito web di Duplicati","Duplicati forum":"Forum Duplicati","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\n When deleting a backup, you can also delete the local database without affecting the ability to restore the remote files.\n If you are using the local database for backups from the commandline, you should keep the database.":"Ogni backup dispone di un database locale associato, che archivia le informazioni del backup remoto sul computer locale.\nQuando si cancella un backup, è anche possibile cancellare il database locale senza influire sulla possibilità di ripristinare i file remoti.\nSe si utilizza il database locale per i backup dalla riga di comando, è necessario mantenere il database.","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\\nThis makes it faster to perform many operations, and reduces the amount of data that needs to be downloaded for each operation.":"Ogni backup dispone di un database locale associato, che archivia le informazioni del backup remoto sul computer locale.\nIn questo modo è più veloce eseguire molte operazioni e riduce la quantità di dati che devono essere scaricati per ogni operazione.","Edit ...":"Modifica...","Edit as list":"Modifica come elenco","Edit as text":"Modifica come testo","Encrypt file":"Cripta file","Encryption":"Crittografia","Encryption changed":"Crittografia cambiata","Encryption modules:":"Moduli crittografia:","Enter URL":"Inserisci URL","Enter a retention strategy manually. Placeholders are D/W/Y for days/weeks/years. The syntax is: 7D:1D,4W:1W,36M:1M. This example keeps one backup for each of the next 7 days, one for each of the next 4 weeks, and one for each of the next 36 months. This can also be written as 1W:1D,1M:1W,3Y:1M.":"Immettere manualmente una strategia di conservazione. I segnaposto sono D/W/Y per giorni/settimane/anni. La sintassi è: 7D:1D,4W:1W,36M:1M. Questo esempio mantiene un backup per ciascuno dei prossimi 7 giorni, uno per ciascuno delle prossime 4 settimane e uno per ciascuno dei prossimi 36 mesi. Questo può anche essere scritta come 1W:1D,1M:1W,3Y:1M.","Enter access key":"Inserisci chiave di accesso","Enter account name":"Inserisci nome account","Enter backup passphrase, if any":"Inserisci la passphrase del backup, se presente","Enter configuration details":"Inserisci dettagli configurazione","Enter container name":"Inserire nome contenitore","Enter encryption passphrase":"Inserisci passphrase crittografia","Enter expression here":"Inserisci qui espressione","Enter folder path name":"Inserire il nome del percorso della cartella","Enter one option per line in command-line format, eg. {0}":"Inserire un'opzione per riga in formato riga di comando, ad es. {0}","Enter the destination path":"Inserisci percorso destinazione","Error":"Errore","Error!":"Errore!","Errors and crashes":"Errori e arresti anomali","Exclude":"Escludi","Exclude directories whose names contain":"Escludi cartelle il cui nome contiene","Exclude expression":"Escludi espressione","Exclude file":"Escludi file","Exclude file extension":"Escludi estensione del file","Exclude files whose names contain":"Escludi file il cui nome contiene","Exclude folder":"Escludi cartella","Exclude regular expression":"Escludi espressione regolare","Existing file found":"Trovato file esistente","Experimental":"Sperimentale","Export":"Esporta","Export ...":"Esporta...","Export backup configuration":"Esporta configurazione backup","Export configuration":"Esporta configurazione","Exporting ...":"Esportazione...","External link":"Link esterno","FTP (Alternative)":"FTP (Alternativo)","Failed to build temporary database: {{message}}":"Fallita creazione del database temporaneo: {{message}}","Failed to connect:":"Connessione fallita:","Failed to connect: {{message}}":"Connessione fallita: {{message}}","Failed to delete:":"Cancellazione fallita: ","Failed to fetch path information: {{message}}":"Recupero informazioni sul percorso fallito: {{message}}","Failed to import:":"Importazione fallita:","Failed to read backup defaults:":"Lettura impostazioni predefinite backup fallita:","Failed to restore files: {{message}}":"Ripristino dei file fallito: {{message}}","Failed to save:":"Salvataggio fallito:","Fetching path information ...":"Recupero informazioni percorso...","File":"File","Files larger than:":"File più grandi di:","Filters":"Filtri","Finished!":"Finito!","First run setup":"Impostazione prima esecuzione","Folder":"Cartella","Folder path":"Percorso cartella","Fri":"Ven","GByte":"GByte","GByte/s":"GByte/s","GCS Project ID":"ID Progetto GCS","General":"Generale","General backup settings":"Impostazioni generali backup","General options":"Opzioni generali","Generate":"Genera","Generate IAM access policy":"Genera criteri di accesso IAM","Getting file versions ...":"Ottenimento versione file...","Hidden files":"File nascosti","Hide":"Nascondi","Hide hidden folders":"Nascondi cartelle nascoste","Home":"Home","Hours":"Ore","How do you want to handle existing files?":"Come vuoi gestire i file esistenti?","Hyper-V Machine":"Sitema Hyper-V","Hyper-V Machine:":"Sistema Hyper-V:","Hyper-V Machines":"Sistemi Hyper-V","ID:":"ID:","If a date was missed, the job will run as soon as possible.":"Se una pianificazione non è eseguita, il backup sarà effettuato il prima possibile.","If at least one newer backup is found, all backups older than this date are deleted.":"Se si trova almeno un backup più recente, tutti i backup precedenti a questa data sono eliminati.","If the backup and the remote storage is out of sync, Duplicati will require that you perform a repair operation to synchronize the database.\\nIf the repair is unsuccesful, you can delete the local database and re-generate.":"Se il backup e l'archivio remoto non sono sincronizzati, Duplicati sarà necessario eseguire un'operazione di ripristino per sincronizzare il database.\nSe la riparazione non è riuscita, è possibile cancellare il database locale e rigenerarlo.","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"Se il file di backup non è scaricato automaticamente, fai clic con il tasto desto e seleziona "Salva come..."","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"Se il file di backup non è scaricato automaticamente,fai clic con il tasto desto e seleziona "Salva come..."","If you do not enter a path, all files will be stored in the login folder.\nAre you sure this is what you want?":"Se non inserisci un percorso, tutti i file saranno salvati nella cartella di accesso.\nSei sicuro che questo è quello che vuoi?","If you do not enter an API Key, the tenant name is required":"Se non inserisci una Chiave API, è richiesto il nome dell'inquilino","If you want to use the backup later, you can export the configuration before deleting it":"Se desideri utilizzare il backup in un secondo momento, è possibile esportare la configurazione prima di cancellarla","If your machine is in a multi-user environment (i.e. the machine has more than one account), you need to set a password to prevent other users from accessing data on your account.\nDo you want to set a password now?":"Se la tua macchina è in un ambiente multi-utente (cioè la macchina ha più di un account), è necessario impostare una password per impedire ad altri utenti di accedere ai dati del tuo account. \nVuoi impostare una password ora?","Import":"Importa","Import Destination URL":"Importa URL Destinazione","Import backup configuration":"Importa configurazione backup","Import completed, but no certificates were found after the import":"Importazione completata, ma non sono stati trovati certificati dopo l'importazione","Import failed":"Importazione fallita","Import from a file":"Importa da un file","Import metadata":"Importa metadati","Importing ...":"Importazione...","Include a file?":"Includi un file?","Include expression":"Includi espressione","Include regular expression":"Includi espressione regolare","Incorrect answer, try again":"Risposta errata, riprova","Individual builds for developers only.":"Build individuali per soli sviluppatori.","Information":"Informazioni","Install":"Installa","Install failed:":"Installazione fallita:","Invalid characters in path":"Caratteri non validi nel percorso","Invalid retention time":"Tempo ritenzione non valido","It is possible to connect to some FTP without a password.\nAre you sure your FTP server supports password-less logins?":"È possibile connettersi ad alcuni FTP senza una password.\nSei sicuro che il tuo server FTP supporta gli accessi senza password?","KByte":"KByte","KByte/s":"KByte/s","Keep a specific number of backups":"Mantieni un numero specifico di backup","Keep all backups":"Mantieni tutti i backup","Language in user interface":"Lingua interfaccia utente","Last month":"Lo scorso mese","Last successful run:":"Ultima esecuzione corretta:","Latest":"Più recente","Libraries":"Librerie","Linux":"Linux","Listing backup dates ...":"Creazione elenco date backup...","Listing remote files ...":"Creazione elenco file remoti...","Live":"In tempo reale","Load a configuration from an exported job or a storage provider":"Carica una configurazione da un lavoro esportato o da un provider di archiviazione","Load destination from an exported job or a storage provider":"Carica una destinazione da un lavoro esportato o da un provider di archiviazione","Load older data":"Carica dati precedenti","Loading ...":"Caricamento...","Loading remote storage usage ...":"Caricamento dell'archivio remoto utilizzato ...","Local Repository":"Repository locale","Local database for":"Database locale per ","Local database path:":"Percorso database locale:","Local repository":"Repository locale","Local storage":"Archivio locale","Location":"Posizione","Location where buckets are created":"Posizione in cui sono creati i bucket","Log data for {{Backup.Backup.Name}}":"Dati di log per {{Backup.Backup.Name}}","Log data from the server":"Dati di log dal server","Log out":"Log out","MByte":"MByte","MByte/s":"MByte/s","Maintenance":"Manutenzione","Manually type path":"Digita manualmente il percorso","Max download speed":"Velocità massima per scaricare","Max upload speed":"Velocità massima per caricare","Menu":"Menu","Microsoft SQL Database:":"Microsoft SQL Database:","Microsoft SQL Databases":"Microsoft SQL Database","Minimum redundancy":"Ridondanza minima","Minimum redundancy is 1.0":"Ridondanza minima è 1.0","Minutes":"Minuti","Missing name":"Nome mancante","Missing passphrase":"Passphrase mancante","Missing sources":"Sorgente mancante","Mon":"Lun","Months":"Mesi","Move existing database":"Sposta database esistente","Move failed:":"Spostamento fallito:","My Documents":"Documenti","My Music":"Musica","My Photos":"Foto","My Pictures":"Immagini","Name":"Nome","Never":"Mai","New update found: {{message}}":"Nuovo aggiornamento trovato: {{message}}","New user name is {{user}}.\nUpdated credentials to use the new limited user":"Il nuovo nome utente è {{user}}.\nCredenziali aggiornate per utilizzare il nuovo utente limitato","Next":"Avanti","Next scheduled run:":"Prossima esecuzione: ","Next scheduled task:":"Prossima attività pianificata:","Next task:":"Prossima attività:","Next time":"Prossima volta","No":"No","No certificate was specified previously, please verify with the server administrator that the key is correct: {{key}} \n\nDo you want to approve the reported host key?":"Nessun certificato è stato specificato in precedenza, per favore verifica con l'amministratore del server che la chiave è corretta: {{key}}\n\nVuoi approvare la chiave host riportata?","No editor found for the "{{backend}}" storage type":"Nessun editor trovato per il "{{backend}}" tipo archivio","No encryption":"Nessuna crittografia","No items selected":"Nessun elemento selezionato","No items to restore, please select one or more items":"Nessun elemento da ripristinare, seleziona uno o più elementi","No passphrase entered":"Nessuna passphrase inserita","No scheduled tasks":"Nessuna attività pianificata","No, my machine has only a single account":"No, la mia macchina ha solo un singolo account","Non-matching passphrase":"Passphrase non corrispondente","None / disabled":"Nessuno / disattivato","Nothing will be deleted. The backup size will grow with each change.":"Niente sarà eliminato. La dimensione del backup crescerà con ogni cambiamento.","OK":"OK","OSX":"OSX","Once there are more backups than the specified number, the oldest backups are deleted.":"Una volta che ci sono più backup del numero specificato, i backup più vecchi sono cancellati.","OpenStack AuthURI":"OpenStack AuthURI","OpenStack Object Storage / Swift":"OpenStack Object Storage / Swift","Operation failed:":"Operazione fallita:","Operations:":"Operazioni:","Optional authentication password":"Password opzionale per l'autenticazione","Optional authentication username":"Nome utente opzionale per l'autenticazione","Options":"Opzioni","Options added here are applied to all backups, but can be overridden in each individual backup":"Le opzioni aggiunte qui sono applicate a tutti i backup, ma possono essere sovrascritte per ogni backup","Original location":"Percorso originale","Others":"Altri","Over time backups will be deleted automatically. There will remain one backup for each of the last 7 days, each of the last 4 weeks, each of the last 12 months. There will always be at least one remaining backup.":"Nel corso del tempo i backup saranno eliminati automaticamente. Rimarrà un backup per ciascuno degli ultimi 7 giorni, ognuna delle ultime 4 settimane, ciascuno degli ultimi 12 mesi. Ci sarà sempre almeno un backup rimanente.","Overwrite":"Sovrascrivi","Passphrase":"Passphrase","Passphrase (if encrypted)":"Passphrase (se criptato)","Passphrase changed":"Passphrase modificata","Passphrases are not matching":"Passphrase non corrispondenti","Password":"Password","Passwords do not match":"Password non corrispondenti","Patching files with local blocks ...":"Sistemazione file con blocchi locali...","Path not found":"Percorso non trovato","Path on server":"Percorso sul server","Path or subfolder in the bucket":"Percorso o sottocartella bucket","Pause":"Pausa","Pause after startup or hibernation":"Pausa dopo avvio o ibernazione","Pause options":"Opzioni pausa","Permissions":"Autorizzazioni","Pick location":"Scegli posizione","Point to your backup files and restore from there":"Puntare ai file di backup e ripristinare da lì","Port":"Porta","Previous":"Precedente","ProjectID is optional if the bucket exist":"ID Progetto è opzionale se esiste un bucket","Proprietary":"Proprietario","Purging files ...":"Cancellazione dei file...","Rebuilding local database ...":"Ricostruzione database locale...","Recreate (delete and repair)":"Ricrea (cancella e ripara)","Recreating database ...":"Ricreazione database...","Registering temporary backup ...":"Registrazione backup temporaneo...","Relative paths not allowed":"Percorsi relativi non consentiti","Reload":"Ricarica","Remote":"Remoto","Remote Path":"Percorso remoto","Remote Repository":"Repository remoto","Remote path":"Percorso remoto","Remote repository":"Repository remoto","Remove":"Rimuovi","Remove option":"Rimuovi opzione","Repair":"Ripara","Reparing ...":"Riparazione...","Repeat Passphrase":"Ripeti Passphrase","Reporting:":"Segnalazione:","Reset":"Reset","Restore":"Ripristina","Restore files":"Ripristina file","Restore files ...":"Ripristina file...","Restore files from {{backupname}}":"Ripristina file da {{backupname}}","Restore from":"Ripristina da","Restore from backup configuration":"Ripristino dalla configurazione backup","Restore from configuration ...":"Ripristino da file di configurazione...","Restore options":"Opzioni ripristino","Restore read/write permissions":"Ripristina autorizzazioni lettura/scrittura","Restoring files ...":"Ripristino file...","Resume":"Riprendi","Run again every":"Esegui ogni","Run now":"Esegui ora","Running ...":"Esecuzione...","Running ....":"Esecuzione...","Running commandline entry":"Riga di comando in esecuzione","Running task:":"Attività in esecuzione:","S3 Compatible":"Compatibile S3","Same as the base install version: {{channelname}}":"Come la versione di base installata: {{channelname}}","Sat":"Sab","Save":"Salva","Save and repair":"Salva e ripara","Save different versions with timestamp in file name":"Salva versioni diverse con timestamp nel nome del file","Save immediately":"Salva immediatamente","Scanning existing files ...":"Scansione file esistenti...","Scanning for local blocks ...":"Scansione dei blocchi locali...","Schedule":"Pianificazione","Search":"Cerca","Search for files":"Cerca per file","Seconds":"Secondi","Select a log level and see messages as they happen:":"Selezionare un livello di log e visiona i messaggi che avvengono:","Select files":"Seleziona file","Server":"Server","Server and port":"Server e porta","Server hostname or IP":"Nome host o IP del server","Server is currently paused,":"Server è attualmente in pausa,","Server is currently paused, do you want to resume now?":"Server attualmente in pausa, vuoi riprendere ora?","Server password":"Password del server","Server paused":"Server in pausa","Server state properties":"Proprietà stato del server","Settings":"Impostazioni","Show":"Mostra","Show advanced editor":"Mostra editor avanzato","Show hidden folders":"Mostra cartelle nascoste","Show log":"Mostra log","Show log ...":"Mostra log ...","Show treeview":"Visualizza ad albero","Sia server password":"Password del server Sia","Smart backup retention":"Conservazione intelligente backup","Some OpenStack providers allow an API key instead of a password and tenant name":"Alcuni provider OpenStack consentono una chiave API anziché una password e un nome inquilino","Source Data":"Dati Sorgente","Source data":"Dati sorgente","Source folders":"Cartella sorgente","Source:":"Dimensione sorgente:","Specific builds for developers only.":"Build specifiche per soli sviluppatori.","Standard protocols":"Protocolli standard","Starting ...":"Avvio....","Starting the restore process ...":"Avvio del processo di ripristino...","Stop after the current file":"Ferma dopo il file corrente","Stop after upload":"Ferma dopo caricamento","Stop now":"Ferma adesso","Stop running backup":"Ferma esecuzione backup","Stop running task":"Ferma esecuzione attività","Stopping after upload:":"Ferma dopo caricamento:","Stopping task:":"Ferma attività:","Storage Type":"Tipo archivio","Storage class":"Classe archivio","Storage class for creating a bucket":"Classe di archiviazione per la creazione di un bucket","Stored":"Archiviati","Strong":"Forte","Success":"Successo","Sun":"Dom","Symbolic link":"Link simbolico","System default ({{levelname}})":"Sistema predefinito ({{levelname}})","System files":"File di sistema","System info":"Informazioni di sistema","System properties":"Proprietà di sistema","TByte":"TByte","TByte/s":"TByte/s","Target path, ie /backup":"Percorso di destinazione, cioè /backup","Task is running":"Attività in esecuzione","Temporary files":"File temporanei","Tenant Name":"Nome Inquilino","Test connection":"Prova connessione","Testing ...":"Test in corso...","Testing connection ...":"Prova connessione...","Testing permissions ...":"Prova autorizzazioni...","Testing permissions...":"Prova autorizzazioni...","The bucket name should be all lower-case, convert automatically?":"Il nome del bucket dovrebbe essere tutto minuscolo, convertirlo automaticamente?","The bucket name should start with your username, prepend automatically?":"Il nome del bucket dovrebbe iniziare con il tuo nome utente, anteporlo automaticamente?","The connection to the server is lost, attempting again in {{time}} ...":"Connessione al server persa, nuovo tentativo tra {{time}}...","The dark theme (by Michal)":"Tema scuro (da Michal)","The default blue on white theme (by Alex)":"Predefinito - Tema blu su bianco (da Alex)","The folder {{folder}} does not exist.\nCreate it now?":"La cartella {{folder}} non esiste. \nCreala adesso?","The host key has changed, please check with the server administrator if this is correct, otherwise you could be the victim of a MAN-IN-THE-MIDDLE attack.\n\nDo you want to REPLACE your CURRENT host key \"{{prev}}\" with the REPORTED host key: {{key}}?":"La chiave host è cambiata, per favore consulta l'amministratore del server se questa è corretta, altrimenti potresti essere la vittima di un attacco UOMO-NEL-MEZZO.\n\nVuoi SOSTITUIRE la chiave host CORRENTE \"{{prev}}\" con la chiave host SEGNALATA: {{key}}?","The path does not appear to exist, do you want to add it anyway?":"Il percorso sembra non esistere, vuoi aggiungerlo comunque?","The path does not end with a '{{dirsep}}' character, which means that you include a file, not a folder.\n\nDo you want to include the specified file?":"Il percorso non termina con un carattere '{{dirsep}}', il che significa che si include un file, non una cartella.\n\nVuoi includere il file specificato?","The path must be an absolute path, i.e. it must start with a forward slash '/'":"Il percorso deve essere un percorso assoluto, cioè deve iniziare con una barra '/'","The path should start with \"{{prefix1}}\" or \"{{prefix2}}\", otherwise you will not be able to see the files in the HubiC web interface.\n\nDo you want to add the prefix to the path automatically?":"Il percorso deve iniziare con \"{{prefix1}}\" o \"{{prefix2}}\", altrimenti non sarà possibile visualizzare i file nell'interfaccia Web di HubiC.\n\nVuoi aggiungere automaticamente il prefisso al percorso?","The region parameter is only applied when creating a new bucket":"Il parametro area è applicato solo quando si crea un nuovo bucket","The region parameter is only used when creating a bucket":"Il parametro area è utilizzato solo quando si crea un bucket","The server certificate could not be validated.\nDo you want to approve the SSL certificate with the hash: {{hash}}?":"Il certificato del server non può essere convalidato.\n\nVuoi approvare il certificato SSL con l'hash: {{hash}}?","The storage class affects the availability and price for a stored file":"La classe di archiviazione influisce sulla disponibilità e sul prezzo per un file archiviato","The target folder contains encrypted files, please supply the passphrase":"La cartella di destinazione contiene file criptati, per favore fornisci la passphrase","The user has too many permissions. Do you want to create a new limited user, with only permissions to the selected path?":"L'utente dispone di troppe autorizzazioni. Vuoi creare un nuovo utente limitato, con solo autorizzazioni per il percorso selezionato?","This backup was created on another operating system. Restoring files without specifying a destination folder can cause files to be restored in unexpected places. Are you sure you want to continue without choosing a destination folder?":"Questo backup è stato creato su un altro sistema operativo. Il ripristino dei file senza specificare una cartella di destinazione può causare il ripristino di file in luoghi imprevisti. Sei sicuro di voler continuare senza scegliere una cartella di destinazione?","This month":"Questo mese","This week":"Questa settimana","Throttle settings":"Impostazioni limitazione","Thu":"Mar","To File":"Al File","To confirm you want to delete all remote files for \"{{name}}\", please enter the word you see below":"Per confermare che vuoi cancellare tutti i file remoti che contengono \"{{name}}\", digita la parla che vedi di seguito","To export without a passphrase, uncheck the \"Encrypt file\" box":"Per esportare senza una passphrase, deselezionare la casella \"Cripta file\"","Today":"Oggi","Trust host certificate?":"Certificato host affidabile?","Trust server certificate?":"Certificato server affidabile?","Try out the new features we are working on. Don't use with important data.":"Prova le nuove funzioni su cui stiamo lavorando. Non usarlo in ambienti di produzione.","Tue":"Gio","Type to highlight files":"Digitare per evidenziare i file","Unknown backup size and versions":"Dimensione e versione backup sconosciute","Until resumed":"Finché non riprende","Update channel":"Canale di aggiornamento","Update failed:":"Aggiornamento fallito:","Updating with existing database":"Aggiornamento con database esistente","Upload volume size":"Dimensione file caricati","Uploading verification file ...":"Caricamento file di verifica...","Usage reports help us improve the user experience and evaluate impact of new features. We use them to generate public usage statistics":"I report di utilizzo ci aiutano a migliorare l'esperienza utente e valutare l'impatto di nuove funzionalità. Li usiamo per generare statistiche di utilizzo pubblico","Usage statistics":"Statistiche di utilizzo","Usage statistics, warnings, errors, and crashes":"Statistiche di utilizzo, avvisi, errori e arresti anomali","Use SSL":"Usa SSL","Use existing database?":"Usare database esistente?","Use weak passphrase":"Usa passphrase debole","Useless":"Inutile","User data":"Dati utente","User has too many permissions":"L'utente ha troppe autorizzazioni","User interface settings":"Impostazioni interfaccia utente","Username":"Nome utente","Validating ...":"Convalida...","Verify files":"Verifica file","Verifying ...":"Verifica...","Verifying answer":"Verifica risposta","Verifying backend data ...":"Verifica dati backend...","Verifying remote data ...":"Verifica dati remoti...","Verifying restored files ...":"Verifica file ripristinati...","Very strong":"Molto forte","Very weak":"Molto debole","Visit us on":"Seguici su","WARNING: The remote database is found to be in use by the commandline library":"ATTENZIONE: Il database remoto si trova in uso dalla libreria riga di comando","WARNING: This will prevent you from restoring the data in the future.":"ATTENZIONE: Questo ti impedirà di ripristinare i dati in futuro.","Waiting for task to begin":"In attesa dell'attività per iniziare","Waiting for task to start ....":"In attesa dell'attività per iniziare...","Waiting for upload ...":"In attesa del caricamento...","Warnings, errors and crashes":"Avvisi, errori e arresti anomali","We accept donations via different services, such as OpenCollective, PayPal, BountySource and various crypto currencies.":"Accettiamo donazioni tramite diversi servizi, come OpenCollective, PayPal, BountySource e varie criptovalute.","We recommend that you encrypt all backups stored outside your system":"Ti consigliamo di criptare tutti i backup archiviati al di fuori del tuo sistema","Weak":"Debole","Weak passphrase":"Passphrase debole","Wed":"Mer","Weeks":"Settimane","Where do you want to restore from?":"Da dove vuoi ripristinare?","Where do you want to restore the files to?":"Dove vuoi ripristinare i files?","Windows":"Windows","Years":"Anni","Yes":"Si","Yes, I have stored the passphrase safely":"Si, ho archiviato la passphrase in modo sicuro","Yes, I'm brave!":"Sì, sono coraggioso!","Yes, please break my backup!":"Sì, per favore rompi il mio backup!","Yesterday":"Ieri","You appear to be running Mono with no SSL certificates loaded.\nDo you want to import the list of trusted certificates from Mozilla?":"Sembra che tu sia in esecuzione Mono senza certificati SSL caricati.\nVuoi importare l'elenco dei certificati attendibili da Mozilla?","You are changing the database path away from an existing database.\nAre you sure this is what you want?":"Stai cambiando il percorso di un database esistente.\nSei sicuro che questo è ciò che vuoi?","You are currently running {{appname}} {{version}}":"Attualmente stai eseguendo {{appname}} {{version}}","You can stop the backup immediately, or stop after the current file has been uploaded.":"È possibile fermare immediatamente il backup o fermarlo dopo che il file corrente è stato caricato.","You can stop the task immediately, or allow the process to continue its current file and the stop.":"Puoi arrestare immediatamente l'attività o consentire al processo di continuare il file in corso e fermarlo.","You have changed the encryption mode. This may break stuff. You are encouraged to create a new backup instead":"Hai modificato l'algoritmo di crittografia. Questa azione potrebbe corrompere i dati. Ti consigliamo di creare un nuovo backup.","You have changed the passphrase, which is not supported. You are encouraged to create a new backup instead.":"Hai modificato la passphrase ma questo non è supportato. Ti consigliamo di creare un nuovo backup.","You have chosen not to encrypt the backup. Encryption is recommended for all data stored on a remote server.":"Hai scelto di non criptare il backup. È consigliabile criptare tutti i dati custoditi su server remoti.","You have chosen to restore to a new location, but not entered one":"Si è scelto di ripristinare in una nuova posizione, ma non ne è stata inserita una","You have generated a strong passphrase. Make sure you have made a safe copy of the passphrase, as the data cannot be recovered if you lose the passphrase.":"Hai generato una passphrase forte. Assicurati di aver fatto una copia sicura della passphrase, poiché i dati non possono essere recuperati se perdi la passphrase.","You must choose at least one source folder":"Devi scegliere almeno una cartella sorgente","You must enter a name for the backup":"Devi inserire un nome un nome per il backup","You must enter a passphrase or disable encryption":"Devi inserire una passphrase o disattivare la crittografia","You must enter a positive number of backups to keep":"Devi inserire un numero positivo di backup da mantenere","You must enter a tenant name if you do not provide an API Key":"Devi inserire il nome di un inquilino se non fornisci una Chiave API","You must enter a valid duration for the time to keep backups":"Devi inserire un periodo di tempo valido in cui mantenere i backup","You must enter a valid rentention policy string":"Devi immettere una stringa di criteri di conservazione valida","You must enter either a password or an API Key":"Devi inserire una password o una Chiave API","You must enter either a password or an API Key, not both":"Devi inserire una password o una Chiave API, non entrambe","You must fill in the password":"Devi compilare in password","You must fill in the server name or address":"Devi compilare in nome del server o indirizzo","You must fill in the username":"Devi compilare in nome utente","You must fill in {{field}}":"Devi compilare in {{field}}","You must select or fill in the AuthURI":"Devi selezionare o compilare in AuthURI","You must select or fill in the server":"Devi selezionare o compilare in server","You must specify a path":"Devi specificare un percorso","Your files and folders have been restored successfully.":"I tuoi file e cartelle sono stati ripristinati correttamente.","Your passphrase is easy to guess. Consider changing passphrase.":"La tua passphrase è facile da indovinare. Considera l'idea di cambiarla.","bucket/folder/subfolder":"bucket/cartella/sottocartella","byte":"byte","byte/s":"byte/s","custom":"Personalizzato","resume now":"riprendi ora","{{appname}} was primarily developed by {{dev1}} and {{dev2}}. {{appname}} can be downloaded from {{websitename}}. {{appname}} is licensed under the {{licensename}}.":"{{appname}} è stato sviluppato principalmente da {{dev1}} e {{dev2}}. {{appname}} può essere scaricato da {{websitename}}. {{appname}} è sotto la licenza {{licensename}}.","{{files}} files ({{size}}) to go {{speed_txt}}":"Caricamento di {{files}} file ({{size}}) {{speed_txt}}","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Version":["{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Versione","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Versioni"],"{{number}} Hour":"{{number}} Ore","{{number}} Minutes":"{{number}} Minuti","{{time}} (took {{duration}})":"{{time}} (durato {{duration}})"}); gettextCatalog.setStrings('lt', {"- pick an option -":"- pasirinkite parametrą -","...loading...":"...įkeliama...","API Key":"API raktas","AWS Access ID":"AWS prieigos ID","AWS Access Key":"AWS prieigos raktas","AWS IAM Policy":"AWS IAM politika","About":"Apie","About {{appname}}":"Apie {{appname}}","Access Key":"Prieigos raktas","Access denied":"Prieiga uždrausta","Access to user interface":"Pasiekti vartotojo sąsają","Account name":"Paskyros vardas","Activate":"Aktyvuoti","Activate failed:":"Aktyvavimas nepavyko:","Add a new backup":"Pridėti naują kopiją","Add a path directly":"Pridėti kelią tiesiiogiai","Add advanced option":"Pridėti papildomą parametrą","Add backup":"Pridėti kopiją","Add filter":"Pridėti filtrą","Add path":"Pridėti kelią","Adjust bucket name?":"Keisti saugyklos pavadinimą?","Adjust path name?":"Keisti kelią?","Advanced Options":"Išplėstiniai parametrai","Advanced options":"Išplėstiniai parametrai","Advanced:":"Papildomai:","All":"Visi","All Hyper-V Machines":"Visos Hyper-V mašinos","All Microsoft SQL Databases":"Visos Microsoft SQL duombazės","All usage reports are sent anonymously and do not contain any personal information. They contain information about hardware and operating system, the type of backend, backup duration, overall size of source data and similar data. They do not contain paths, filenames, usernames, passwords or similar sensitive information.":"Visos naudojimo ataskaitos siunčiamos anonimiškai ir jose nėra jokios asmeninės informacijos. Juose pateikiama informacija apie techninę įrangą ir operacinę sistemą, saugyklos tipą, kopijos kūrimo laiką, visų kopijuojamų failų dydį ir pan. Juose nėra kelių, failų pavadinimų, naudotojų, slaptažodžių ir panašios privačios informacijos.","Allow remote access (requires restart)":"Leisti nuotolinę prieigą (reikia paleisti iš naujo)","Allowed days":"Leidžiamos dienos","An existing file was found at the new location":"Naujoje vietoje rasti jau esantys failai","An existing file was found at the new location\nAre you sure you want the database to point to an existing file?":"Naujoje vietoje rasti jau esantys failai.\nAr tikrai norite duomenų bazę rašyti vietoj esamų failų?","An existing local database for the storage has been found.\nRe-using the database will allow the command-line and server instances to work on the same remote storage.\n\n Do you wish to use the existing database?":"Buvo rasta esama vietinė duomenų saugykla.\nNaudojant tą pačią duombazę, komandinės eilutės ir serverio procesai galės veikti toje pačioje nuotolinėje saugykloje.\n\n Ar norite naudoti esamą duomenų bazę?","Anonymous usage reports":"Anoniminės naudojimo ataskaitos","As Command-line":"Kaip komandinę eilutę","AuthID":"AuthID","Authentication password":"Autorizacijos slaptažodis","Authentication username":"Autorizacijos naudotojas","Autogenerated passphrase":"Automatiškai sugeneruota slapta frazė","Automatically run backups.":"Atsargines kopijas kurti automatiškai.","B2 Account ID":"B2 paskyros ID","B2 Application Key":"B2 programos raktas","B2 Cloud Storage Account ID":"B2 debesų saugyklos paskyros ID","B2 Cloud Storage Application Key":"B2 debesų saugyklos programos raktas","Back":"Atgal","Backend modules:":"Kopijų saugyklos moduliai:","Backup destination":"Kopijų paskirties vieta","Backup location":"Kopijų saugojimo vieta","Backup:":"Kopija:","Beta":"Beta","Broken access":"Sugadinta prieiga","Browse":"Naršyti","Browser default":"Naršyklės numatyta reišmė","Bucket Name":"Saugyklos pavadinimas","Bucket create location":"Sukurti saugyklos vietą","Bucket create region":"Sukurti saugyklos regijoną","Bucket name":"Saugyklos pavadinimas","Bucket storage class":"Saugyklos klasė","Building list of files to restore ...":"Generuojamas atkuriamų failų sąrašas... ","Building partial temporary database ...":"Generuojama dalinė laikina duombazė...","Busy ...":"Užimtas...","Canary":"Canary","Cancel":"Atšaukti","Cannot move to existing file":"Negalima perkelti į esamo failo vietą","Changelog":"Pakeitimų žurnalas","Changelog for {{appname}} {{version}}":"Programos {{appname}} {{version}} pakeitimų žurnalas","Check failed:":"Patikrinimas nepavyko:","Check for updates now":"Ieškoti atnaujinimų dabar","Checking ...":"Tikrinama...","Checking for updates ...":"Ieškoma atnaujinimų...","Chose a storage type to get started":"Norėdami pradėti pasirinkite saugyklos tipą","Click the AuthID link to create an AuthID":"Norėdami sukurti AuthID paspauskite AuthID nuorodą","Click to set throttle options":"Spustelėkite, kad nustatyti akceleratoriaus parametrus","Commandline ...":"Komandinė eilutė ...","Compact now":"Suspausti dabar","Compacting remote data ...":"Suspausti nutolusius duomenis...","Completing backup ...":"Kopija užbaigiama...","Completing previous backup ...":"Užbaigiama ankstesnė kopija...","Compression modules:":"Kompresijos moduliai:","Computer":"Kompiteris","Configuration file:":"Konfigūracijos failas:","Configuration:":"Konfigūracija:","Configure a new backup":"Derinti naują kopiją","Confirm delete":"Patvirtinkite tryminą","Confirmation required":"Reikalingas patvirtinimas","Connect":"Prisijungti","Connect now":"Prisijungti dabar","Connecting to server ...":"Jungiamasi prie serverio...","Connecting to task ....":"Jungiamasi prie užduoties...","Connecting...":"Jungiamasi...","Connection lost":"Prisijungimas nutrūko","Connection worked!":"Prisijungti pavyko!","Container name":"Konteinerio pavadinimas","Container region":"Konteinerio regionas","Continue":"Tęsti","Continue without encryption":"Tęsti be šifravimo","Copied!":"Nukopijuota!","Copy Destination URL to Clipboard":"Kopijuoti paskirties URL į iškarpinę","Copy failed. Please manually copy the URL":"Kopijavimas nepavyko. Nukopijuokite URL rankiniu būdu","Core options":"Pagrindiniai parametrai","Counting ({{files}} files found, {{size}})":"Skaičiuojama, rasta failų: ({{files}}, {{size}})","Crashes only":"Tik lūžimai","Create bug report ...":"Kurti klaidos ataskaitą..","Create folder?":"Sukurti aplanką?","Created new limited user":"Sukurtas naujas ribotas vartotojas","Creating bug report ...":"Klaidos ataskaitos kūrimas ...","Creating new user with limited access ...":"Kuriamas naujas vartotojas, su ribota prieiga...","Creating target folders ...":"Kuriami paskirties aplankai...","Creating temporary backup ...":"Kuriama laikina kopija...","Creating user...":"Kuriamas vartotojas","Current version is {{versionname}} ({{versionnumber}})":"Dabartinė versija: {{versionname}} ({{versionnumber}})","Custom S3 endpoint":"Nestandartinė S3 saugykla","Custom authentication url":"Nestandartinis autorizacijos URL","Custom location ({{server}})":"Nestandartinė vieta ({{server}})","Custom region for creating buckets":"Nestandartinis regionas kuriamoms saugykloms","Custom region value ({{region}})":"Nestandartinio regiono reikšmė ({{region}})","Custom server url ({{server}})":"Nestandartinis serverio url ({{server}})","Custom storage class ({{class}})":"Nestandartinė saugyklos klasė ({{class}})","Database ...":"Duombazė...","Days":"Dienos","Default":"Numatyta","Default ({{channelname}})":"Numatytas ({{channelname}})","Default Filters":"Numatytieji filtrai","Default options":"Numatyti parametrai","Delete":"Ištrinti","Delete ...":"Ištrinti...","Delete backup":"Ištrinti kopiją","Delete local database":"Ištrinti lokalią duombazę","Delete remote files":"Ištrinti nutolusius failus","Delete the local database":"Ištrinti lokalią duombazę","Delete {{filecount}} files ({{filesize}}) from the remote storage?":"Trinti failus {{filecount}}, ({{filesize}}) iš nutolusios saugyklos?","Deleting remote files ...":"Trinami nutolę failai...","Deleting unwanted files ...":"Trinami nepageidaujami failai","Desktop":"Darbastalis","Destination":"Paskirtis","Did we help save your files? If so, please consider supporting Duplicati with a donation. We suggest {{smallamount}} for private use and {{largeamount}} for commercial use.":"Ar mes padėjome išgelbėti duomenis? Jei taip paremkite programos kūrimą. Siūloma parama privatiems naudotojams {{smallamount}} ir {{largeamount}} komerciniams naudotojams.","Direct restore from backup files ...":"Atkurti tiesiogiai iš kopijos failų...","Disabled":"Išjungta","Dismiss":"Neberodyti","Display and color theme":"Vaizdo ir spalvų tema","Do you really want to delete the backup: \"{{name}}\" ?":"Ar tikrai norite ištrinti kopiją: \"{{name}}\" ?","Do you really want to delete the local database for: {{name}}":"Ar tikrai norite ištrinti lokalią duomenų bazę: {{name}}","Donate":"Paremti","Donate with PayPal":"Paremti per PayPal","Donate with crypto currency":"Paremti kriptografine valiuta","Donation messages":"Paramos pranešimai","Donation messages are hidden, click to show":"Paramos pranešimai paslėpti: spustelėkite, kad rodyti","Donation messages are visible, click to hide":"Paramos pranešimai matomi: spustelėkite, kad paslėpti","Done":"Baigta","Download":"Atsisiųsti","Downloading ...":"Siunčiama...","Downloading files ...":"Siunčiami failai...","Downloading update...":"Siunčiamas atnaujinimas...","Duplicate option {{opt}}":"Pasikartojantis parametras {{opt}}","Duplicati Website":"Duplicati svetainė","Duplicati forum":"Duplicati forumas","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\n When deleting a backup, you can also delete the local database without affecting the ability to restore the remote files.\n If you are using the local database for backups from the commandline, you should keep the database.":"Kiekviena atsarginė kopija turi su ja susietą duomenų bazę, kurioje saugoma informacija apie nuotolinę saugykla vietiniame kompiuteryje.\nTrindami kopiją galite ištrinti ir lokalią duombazę, atkurti duomenis iš nutolusių failų vis tiek galėsite.\nJei lokalią duombazę naudojate kopijoms per komandinę eilutę, tada duombazę turėtumėt palikti.","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\\nThis makes it faster to perform many operations, and reduces the amount of data that needs to be downloaded for each operation.":"Kiekviena atsarginė kopija turi su ja susietą duomenų bazę, kurioje saugoma informacija apie nutolusią kopiją vietinėje sistemoje.\\nJos dėka visos operacijos atliekamos greičiau ir kiekvienai operacijai sumažinamas atsisiunčiamų duomenų kiekis.","Edit ...":"Taisyti...","Edit as list":"Taisyti kaip sąrašą","Edit as text":"Taisyti kaip tekstą","Encrypt file":"Šifruoti failą","Encryption":"Šifravimas","Encryption changed":"Šifravimas pakeistas","Encryption modules:":"Šifravimo moduliai","Enter URL":"Įveskite URL","Enter access key":"Įveskite prieigos raktą","Enter account name":"Įveskite naudotojo vardą","Enter backup passphrase, if any":"Jei naudojama šifravimo slapta frazė, įveskite ją","Enter configuration details":"Įveskite konfigūracijos detales","Enter container name":"Įveskite saugyklos pavadinimą","Enter encryption passphrase":"Įveskite šifravimo slaptą frazę","Enter expression here":"Įveskite čia išraišką","Enter folder path name":"Įveskite aplanko kelio pavadinimą","Enter one option per line in command-line format, eg. {0}":"Įveskite vieną parametrą eilutėje komandinės eilutės formatu, pvz.: {0}","Enter the destination path":"Įveskite paskirties kelią","Error":"Klaida","Error!":"Klaida!","Errors and crashes":"Klaidos ir lūžimai","Exclude":"Išimtys","Exclude directories whose names contain":"Neįtraukti aplankų, kurių pavadinime yra","Exclude expression":"Neįtraukti išraiškos","Exclude file":"Neįtraukti failo","Exclude file extension":"Neįtraukti failų plėtinio","Exclude files whose names contain":"Neįtraukti failų, kurių pavadinime yra","Exclude folder":"Neįtraukti aplanko","Exclude regular expression":"Neįtraukti standartinės išraiškos","Existing file found":"Rastas esamas failas","Experimental":"Eksperimentinis","Export":"Eksportas","Export ...":"Eksportas...","Export backup configuration":"Eksportuoti atsarginės kopijos konfigūraciją","Export configuration":"Eksportuoti konfigūraciją","Exporting ...":"Eksportuojama...","FTP (Alternative)":"FTP (Alternatyva)","Failed to build temporary database: {{message}}":"Nepavyko sukurti laikinos duomenų bazės: {{message}}","Failed to connect:":"Nepavyko prisijungti:","Failed to connect: {{message}}":"Nepavyko prisijungti: {{message}}","Failed to delete:":"Nepavyko ištrinti:","Failed to fetch path information: {{message}}":"Nepavyko gauti aplanko informacijos: {{message}}","Failed to import:":"Importas nepavyko:","Failed to read backup defaults:":"Nepavyko nuskaityti kopijos numatytus parametrus:","Failed to restore files: {{message}}":"Failų atkūrimas nepavyko: {{message}}","Failed to save:":"Išsaugoti nepavyko:","Fetching path information ...":"Gaunama aplanko informacija...","File":"Failas","Files larger than:":"Failai didesni nei:","Filters":"Filtrai","Finished!":"Baigta!","First run setup":"Pirmojo paleidimo sąranka","Folder":"Aplankas","Folder path":"Aplanko kelias","Fri":"Pn","GByte":"GB","GByte/s":"GB/s","GCS Project ID":"GCS projekto ID","General":"Pagrindiniai","General backup settings":"Pagrindiniai kopijos nustatymai","General options":"Pagrindiniai parametrai","Generate":"Generuoti","Generate IAM access policy":"Generuoti IAM prieigos politiką","Getting file versions ...":"Gaunamos failų versijos...","Hidden files":"Paslėpti failai","Hide":"Paslepti","Hide hidden folders":"Nerodyti paslėptų aplankų","Home":"Pradžia","Hours":"Valandos","How do you want to handle existing files?":"Kaip elgtis su esamais failais?","Hyper-V Machine":"Hyper-V mašina","Hyper-V Machine:":"Hyper-V mašina:","Hyper-V Machines":"Hyper-V mašinos","ID:":"ID:","If a date was missed, the job will run as soon as possible.":"Jai kopijos laikas praleistas, užduotis bus vykdoma pirmai progai pasitaikius.","If the backup and the remote storage is out of sync, Duplicati will require that you perform a repair operation to synchronize the database.\\nIf the repair is unsuccesful, you can delete the local database and re-generate.":"Jei kopija ir nuotolinė saugykla nesusinchronizuota, Duplicati reikalaus, kad būtu įvykdytas taisymas, kad susinchronizuoti duomenų bazę.\\nJei taisymas nepavyks, reikės ištrinti lokalią duombazę ir ją generuoti iš naujo.","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"Jei kopijos failas nebuvo atsiųstas automatiškai, spustelėkite dešiniuoju mygtuku ir pasirinkite "Išsaugoti kaip..."","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"Jei kopijos failas nebuvo atsiųstas automatiškai, spustelėkite dešiniuoju mygtuku ir pasirinkite "Išsaugoti kaip..."","If you do not enter a path, all files will be stored in the login folder.\nAre you sure this is what you want?":"Jei nenurodysite kelio, visi failai bus išsaugoti pagrindiniame aplanke.\nAr tikrai to norite?","If you do not enter an API Key, the tenant name is required":"Jei nurodysite API raktą, būtina nurodyti savininką","If you want to use the backup later, you can export the configuration before deleting it":"Jei norėsite šia kopija pasinaudoti vėliau, prieš trindami galite eksportuoti konfigūraciją","If your machine is in a multi-user environment (i.e. the machine has more than one account), you need to set a password to prevent other users from accessing data on your account.\nDo you want to set a password now?":"Jei jūsų įrenginys yra daugelio naudotojų aplinkoje (t.y. Įrenginyje yra daugiau nei viena paskyra), turite nustatyti slaptažodį, kad kiti naudotojai negalėtų pasiekti jūsų paskyroje esančių duomenų.\nAr norite dabar nustatyti slaptažodį dabar?","Import":"Importas","Import Destination URL":"Importo paskirties URL","Import backup configuration":"Importuoti kopijos konfigūraciją","Import completed, but no certificates were found after the import":"Importas atliktas, bet nebuvo rastas joks sertifikatas","Import failed":"Importas nepavyko","Import from a file":"Importas iš failo","Importing ...":"Importuojama...","Include a file?":"Įtraukti failą?","Include expression":"Įtraukti išraišką","Include regular expression":"Įtraukti standartinę išraišką","Incorrect answer, try again":"Atsakymas neteisingas, bandykite dar kartą","Individual builds for developers only.":"Sukompiliuota individualiai, tik programuotojams.","Information":"Informacija","Install":"Diegti","Install failed:":"Diegimas nepavyko:","Invalid characters in path":"Kelio pavadinime yra netinkamų simbolių","Invalid retention time":"Netinkamas saugojimo laikas","It is possible to connect to some FTP without a password.\nAre you sure your FTP server supports password-less logins?":"Prie kai kurių FTP serverių galima prisijungti be slaptažodžio.\nAr jūs įsitikinę, kad FTP serveris leidžia prisijungimus be slaptažodžio?","KByte":"KB","KByte/s":"KB/s","Keep this number of backups":"Saugoti tokį kopijų skaičių","Language in user interface":"Kalba vartotojo interfeise","Last month":"Praeitas mėnuo","Last successful run:":"Paskutinis sėkmingas:","Latest":"Naujausias","Libraries":"Bibliotekos","Linux":"Linux","Listing backup dates ...":"Gaunamos kopijų datos...","Listing remote files ...":"Gaunami nutolę failai...","Live":"Gyvai","Load a configuration from an exported job or a storage provider":"Įkelti konfigūraciją iš eksportuotos užduoties arba saugojimo paslaugų tiekėjo","Load destination from an exported job or a storage provider":"Įkelti paskirtį iš eksportuotos užduoties arba saugojimo paslaugų tiekėjo","Load older data":"Įkelti senesnius duomenis","Loading ...":"Įkeliama...","Loading remote storage usage ...":"Gaunama nutolusios saugyklos panaudojimo informacija...","Local database for":"Lokali duombazė dėl","Local database path:":"Lokalios duomenų bazės kelias:","Local storage":"Lokali saugykla","Location":"Vieta","Location where buckets are created":"Vieta, kur sukuriamos saugyklos","Log data for {{Backup.Backup.Name}}":"{{Backup.Backup.Name}}žurnalo duomenys","Log data from the server":"Žurnalo duomenys iš serverio","Log out":"Atsijungti","MByte":"MB","MByte/s":"MB/s","Maintenance":"Priežiūra","Manually type path":"Rankiniu būdu įveskite kelią","Max download speed":"Maksimalus atsisiuntimo greitis","Max upload speed":"Maksimalus įkėlimo greitis","Menu":"Meniu","Microsoft SQL Database:":"Microsoft SQL duomenų bazė:","Microsoft SQL Databases":"Microsoft SQL duomenų bazės","Minimum redundancy":"Minimalus perteklinių kopijų kiekis","Minimum redundancy is 1.0":"Minimalus perteklinių kopijų skaičius yra 1.0","Minutes":"Minutės","Missing name":"Trūksta pavadinimo","Missing passphrase":"Trūksta slaptos frazės","Missing sources":"Trūksta šaltinių","Mon":"Pr","Months":"Mėnesiai","Move existing database":"Perkelti esamą duomenų bazę","Move failed:":"Perkelti nepavyko:","My Documents":"Mano dokumentai","My Music":"Mano muzika","My Photos":"Mano nuotraukos","My Pictures":"Mano paveikslėliai","Name":"Vardas","Never":"Niekada","New update found: {{message}}":"Rastas atnaujinimas: {{message}}","New user name is {{user}}.\nUpdated credentials to use the new limited user":"Naujas vartotojo vardas {{user}}.\nNaujo riboto vartotojo prisijungimo duomenys atnaujinti","Next":"Kitas","Next scheduled run:":"Kitas planuojamas paleidimas:","Next scheduled task:":"Kita planuojama užduotis:","Next task:":"Kita užduotis","Next time":"Kitą kartą","No":"Ne","No certificate was specified previously, please verify with the server administrator that the key is correct: {{key}} \n\nDo you want to approve the reported host key?":"Anksčiau nebuvo nurodytas sertifikatas, su serverio administratoriumi patikrinkite kad raktas teisingas: {{key}} \n\nAr patvirtinate pateiktą mazgo raktą?","No editor found for the "{{backend}}" storage type":"Saugyklos tipui "{{backend}}" nerastas redaktorius","No encryption":"Be šifravimo","No items selected":"Nieko nepasirinkta","No items to restore, please select one or more items":"Nėra ko atkurti, pasirinkite vieną ar kelis elementus","No passphrase entered":"Neįvesta slapta frazė","No scheduled tasks":"Nėra planinių užduočių","No, my machine has only a single account":"Ne, mano kompiuteryje yra tik vienas naudotojas","Non-matching passphrase":"Netinkama slapta frazė","None / disabled":"Nieko / išjungta","OK":"OK","OSX":"OSX","OpenStack AuthURI":"OpenStack AuthURI","OpenStack Object Storage / Swift":"OpenStack objekto saugykla / Swift","Operation failed:":"Operacija nepavyko:","Operations:":"Operacijos","Optional authentication password":"Neprivalomas autorizavimo slaptažodis","Optional authentication username":"Neprivalomas autorizavimo vartotojas","Options":"Parametrai","Options added here are applied to all backups, but can be overridden in each individual backup":"Čia nurodyti parametrai taikomi visoms atsarginėms kopijoms, bet gali būti pakeisti kiekvienoje kopijoje individualiai","Original location":"Originali vieta","Others":"Kiti","Overwrite":"Perrašyti","Passphrase":"Slapta frazė","Passphrase (if encrypted)":"Slapta frazė (jei šifruota)","Passphrase changed":"Slapta frazė pakeista","Passphrases are not matching":"Slaptos frazės nesutampa","Password":"Slaptažodis","Passwords do not match":"Slaptažodžiai nesutampa","Patching files with local blocks ...":"Failai naujinami iš lokalių blokų...","Path not found":"Kelias nerastas","Path on server":"Kelias iki serverio","Path or subfolder in the bucket":"Kelias arba pakatalogis saugykloje","Pause":"Pauzė","Pause after startup or hibernation":"Pauzė po paleidimo ar ramybės būsenos","Pause options":"Pauzės parametrai","Permissions":"Leidimai","Pick location":"Pasirinkite vietą","Point to your backup files and restore from there":"Pasirinkite atsarginės kopijos failus ir atkurkite iš jos","Port":"Portas","Previous":"Ankstesnis","ProjectID is optional if the bucket exist":"ProjectID yra neprivalomas, jei egzistuoja saugykla","Proprietary":"Patentuota","Purging files ...":"Naikinami failai ...","Rebuilding local database ...":"Vietinė duomenų bazė kuriama iš naujo ...","Recreate (delete and repair)":"Perkurti (ištrinti ir taisyti)","Recreating database ...":"Perkuriama duomenų bazė ...","Registering temporary backup ...":"Registruojama laikina atsarginė kopija ...","Relative paths not allowed":"Santykiniai keliai neleidžiami","Reload":"Užkrauti iš naujo","Remote":"Nuotolinis","Remove":"Pašalinti","Remove option":"Pašalinti parinktį","Repair":"Remontuoti","Reparing ...":"Remontuojama ...","Repeat Passphrase":"Pakartokite slaptą frazę","Reporting:":"Ataskaitų teikimas:","Reset":"Atstatyti","Restore":"Atkurti","Restore files":"Atkurti failus","Restore files ...":"Atkurti failus ...","Restore files from {{backupname}}":"Atkurti failus iš {{backupname}}","Restore from":"Atkurti iš","Restore from backup configuration":"Atkurti iš atsarginės kopijos konfigūracijos","Restore from configuration ...":"Atkurti iš konfigūracijos ...","Restore options":"Atkurimo parinktis","Restore read/write permissions":"Atkurti skaitymo/rašymo leidimus","Restoring files ...":"Failai atkūriami ...","Resume":"Tęsti","Run again every":"Vykdyti dar kartą kas","Run now":"Vykdyti dabar","Running ...":"Vykdoma ...","Running ....":"Vykdoma ....","Running commandline entry":"Vykdoma komandų eilutės komanda","Running task:":"Vykdoma užduotis:","S3 Compatible":"Suderinamas su S3","Same as the base install version: {{channelname}}":"Ta pati, kaip pagrindinė diegimo versija: {{channelname}}","Sat":"Šešt","Save":"Įrašyti","Save and repair":"Įrašyti ir taisyti","Save different versions with timestamp in file name":"Išsaugokite kitą versiją su laiko žymoma failo pavadinime","Save immediately":"Įrašyti nedelsiant","Scanning existing files ...":"Ieškoma esamų failų ...","Scanning for local blocks ...":"Ieškoma lokalių blokų ...","Schedule":"Tvarkaraštis","Search":"Paieška","Search for files":"Failų paieška","Seconds":"Sekundės","Select a log level and see messages as they happen:":"Pasirinkite žurnalo lygį ir peržiūrėkite pranešimus, kaip jie įvyksta:","Select files":"Pasirinkite failus","Server":"Serveris","Server and port":"Serveris ir portas","Server hostname or IP":"Serverio pavadinimas ir IP","Server is currently paused,":"Serveris šiuo metu pristabdytas","Server is currently paused, do you want to resume now?":"Serveris šiuo metu pristabdytas, ar norite pratęsti jo darbą?","Server password":"Serverio slaptažodis","Server paused":"Serveris pristabdytas","Server state properties":"Serverio būsenos parametrai","Settings":"Nustatymai","Show":"Rodyti","Show advanced editor":"Rodyti patobulintą redaktorių","Show hidden folders":"Rodyti paslėptus aplankus","Show log":"Rodyti žurnalą","Show log ...":"Rodyti žurnalą ...","Show treeview":"Rodyti medžio vaizdą","Sia server password":"Sia serverio slaptažodis","Some OpenStack providers allow an API key instead of a password and tenant name":"Kai kurie OpenStack tiekėjai vietoj slaptažodžio pateikia API raktą ir nuomininko vardą","Source Data":"Šaltinio duomenys","Source data":"Šaltinio duomenys","Source folders":"Šaltinio aplankai","Source:":"Šaltinis:","Specific builds for developers only.":"Specifinės versijos programuotojams.","Standard protocols":"Standartiniai protokolai","Starting ...":"Pradedama ...","Starting the restore process ...":"Atkūrimo proceso pradžia ...","Stop after the current file":"Stabdyti po dabartinio failo","Stop after upload":"Stabdyti po įkėlimo","Stop now":"Stabdyti dabar","Stop running backup":"Stabdyti vykdomą atsarginę kopiją","Stop running task":"Stabdyti vykdomą užduotį","Stopping after upload:":"Stabdoma po įkėlimo:","Stopping task:":"Stabdoma užduotis:","Storage Type":"Saugyklos tipas","Storage class":"Saugyklos klasė","Storage class for creating a bucket":"Saugyklos klasė saugyklos kūrimui","Stored":"Išsaugota","Strong":"Stiprus","Success":"Sėkmė","Sun":"Sekm","Symbolic link":"Simbolinė nuoroda","System default ({{levelname}})":"Sistemos numatytasis ({{levelname}})","System files":"Sisteminiai failai","System info":"Sistemos informacija","System properties":"Sistemos ypatybės","TByte":"TByte","TByte/s":"TByte/sek","Target path, ie /backup":"Kelias iki tikslo, pvz.: /backup","Task is running":"Užduotis vykdoma","Temporary files":"Laikini failai","Tenant Name":"Nuomininko vardas","Test connection":"Patikrinti prisijungimą","Testing ...":"Tikrinama ...","Testing connection ...":"Tikrinamas prisijungimas ...","Testing permissions ...":"Tikrinamos prieigos teisės ...","Testing permissions...":"Tikrinamos prieigos teisės ...","The bucket name should be all lower-case, convert automatically?":"Saugyklos pavadinimas turi būti iš mažųjų raidžių, konvertuoti automatiškai?","The bucket name should start with your username, prepend automatically?":"Saugyklos pavadinimas turi prasidėti naudotojo vardu, pridėti automatiškai?","The connection to the server is lost, attempting again in {{time}} ...":"Dingo ryšys su serveriu, bandysime prisijungti po {{time}} ...","The dark theme (by Michal)":"Tamsi tema (nuo Michal)","The default blue on white theme (by Alex)":"Numatyta mėlyna ant balto tema (nuo Alex)","The folder {{folder}} does not exist.\nCreate it now?":"Aplankas {{folder}} neegzistuoja.\nSukurti jį dabar?","The host key has changed, please check with the server administrator if this is correct, otherwise you could be the victim of a MAN-IN-THE-MIDDLE attack.\n\nDo you want to REPLACE your CURRENT host key \"{{prev}}\" with the REPORTED host key: {{key}}?":"Serverio raktas pasikeitė, su administratoriumi patikrinkite ar jis geras, priešingu atveju jūsų duomenys gali būti perimti.\n\nAr norite PAKEISTI jūsų DABARTINĮ serverio raktą \"{{prev}}\" PATEIKTU serverio raktu: {{key}}?","The path does not appear to exist, do you want to add it anyway?":"Panašu, kad toks kelias neegzistuoja, vis tiek jį pridėti?","The path does not end with a '{{dirsep}}' character, which means that you include a file, not a folder.\n\nDo you want to include the specified file?":"Kelias pasibaigia ne '{{dirsep}}' simboliu, tai reiškia, kad pridėjote failą, ne aplanką.\n\nAr norite pridėti nurodytą failą?","The path must be an absolute path, i.e. it must start with a forward slash '/'":"Kelias turi būti absoliutus, tai yra turi prasidėti simboliu '/'","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Version":["{{Item.Backup.Metadata.TargetSizeString}} / {{$ count}} versija","{{Item.Backup.Metadata.TargetSizeString}} / {{$ count}} versijos","{{Item.Backup.Metadata.TargetSizeString}} / {{$ count}} versijų"]}); gettextCatalog.setStrings('lv', {"- pick an option -":"- izvēlieties iestatījumu -","...loading...":"...notiek ielāde...","API Key":"API atslēga","About":"Par","About {{appname}}":"Par {{appname}}","Access Key":"Piekļuves atslēga","Access denied":"Piekļuve liegta","Access to user interface":"Piekļuve lietotāja saskarnei","Account name":"Konta nosaukums","Activate":"Aktivizēt","Activate failed:":"Aktivizācija neizdevās:","Add a new backup":"Pievienot jaunu dublējumkopiju","Add a path directly":"Pievienot tiešo ceļu","Add advanced option":"Pievienot pielāgotu iestatījumu","Add backup":"Pievienot dublējumkopiju","Add filter":"Pievienot filtru","Add path":"Pievienot ceļu","Adjust bucket name?":"Precizēt spaiņa iestatījumu?","Adjust path name?":"Precizēt ceļa nosaukumu?","Advanced Options":"Pielāgotas Opcijas","Advanced options":"Pielāgotas opcijas","Advanced:":"Pielāgots:","All Hyper-V Machines":"Visas Hyper-V Mašīnas","All Microsoft SQL Databases":"Visas Microsoft SQL Datubāzes","Allow remote access (requires restart)":"Atļaut attālinātu piekļuvi (nepieciešams restartēt programmu)","Allowed days":"Atļautās dienas","An existing file was found at the new location":"Tika atrasts jau esošs fails jaunajā atrašanās vietā","An existing file was found at the new location\nAre you sure you want the database to point to an existing file?":"Tika atrasts jau esošs fails jaunajā atrašanās vietā\nVai esat pārliecināts, ka vēlaties datubāzi novirzīt uz jau esošo failu?","Anonymous usage reports":"Anonīmas lietošanas atskaites","As Command-line":"Kā Komand-rinda","Authentication password":"Autentifikācijas parole","Authentication username":"Autentifikācijas lietotājvārds","Autogenerated passphrase":"Automātiski izveidota piekļuves frāze","Automatically run backups.":"Automātiski palaist dublējumkopijas.","Back":"Atpakaļ","Backend modules:":"Backend moduļi:","Backup destination":"Dublējumkopijas mērķa atrašanās vieta","Backup location":"Dublējumkopijas atrašanās vieta","Backup:":"Dublējumkopija:","Beta":"Beta versija","Browse":"Pārlūkot","Browser default":"Pārlūka noklusējums","Bucket Name":"Spaiņa Nosaukums","Bucket name":"Spaiņa nosaukums","Bucket storage class":"Spaiņa uzglabāšanas klase","Building partial temporary database ...":"Notiek daļēja pagaidu datubāzes izveide...","Busy ...":"Aizņemts ...","Canary":"Canary","Cancel":"Atcelt","Changelog":"Izmaiņu žurnāls","Check failed:":"Pārbaude neizdevās:","Check for updates now":"Pārbaudīt atjauninājumus tagad","Checking ...":"Pārbauda ...","Checking for updates ...":"Pārbaudīt atjauninājumus ...","Click to set throttle options":"Uzklikšķiniet, lai uzstādītu ierobežojumus","Commandline ...":"Komandrinda ...","Compact now":"Saspiest tagad","Compression modules:":"Saspiešanas moduļi:","Computer":"Dators","Configuration file:":"Konfigurācijas fails:","Configuration:":"Konfigurācija:","Configure a new backup":"Konfigurēt jaunu dublējumkopiju","Confirm delete":"Apstiprināt dzēšanu","Confirmation required":"Nepieciešams apstiprinājums","Connect":"Pieslēgties","Connect now":"Pieslēgties tagad","Connecting to server ...":"Pieslēdzas serverim","Connecting to task ....":"Pieslēdzas uzdevumam","Connecting...":"Pieslēdzas ...","Connection lost":"Savienojums ir zudis","Connection worked!":"Savienojums strādā!","Continue":"Turpināt","Continue without encryption":"Turpināt bez šifrēšanas","Copied!":"Nokopēts!","Core options":"Pamata opcijas","Crashes only":"Tikai avārijas","Create bug report ...":"Izveidot kļūdu atskaiti","Create folder?":"Izveidot mapi?","Creating bug report ...":"Tiek izveidota kļūdas atskaite ...","Creating user...":"Izveido lietotāju...","Custom region for creating buckets":"Specifiskais reģions spaiņu izveidei","Database ...":"Datubāze ...","Days":"Dienas","Default":"Noklusējums","Default options":"Noklusējuma iestatījumi","Delete":"Izdzēst","Delete ...":"Izdzēst ...","Delete backup":"Izdzēst dublējumkopiju","Delete local database":"Izdzēst lokālo datubāzi","Delete remote files":"Dzēst attālinātos failus","Delete the local database":"Izdzēst lokālo datubāzi","Deleting remote files ...":"Tiek dzēsti attālinātie faili ...","Deleting unwanted files ...":"Notiek nevēlamu failu dzēšana...","Desktop":"Darbavirsma","Destination":"Mērķis","Disabled":"Atspējots","Dismiss":"Atmest","Display and color theme":"Displeja un krāsu motīvs","Donate":"Ziedot","Donation messages are hidden, click to show":"Ziedojumu ziņas ir slēptas, uzklikšķiniet lai parādītu tās","Donation messages are visible, click to hide":"Ziedojumu ziņas ir redzamas, uzklikšķiniet lai paslēptu tās","Done":"Pabeigts","Download":"Lejupielādēt","Downloading ...":"Lejupielādē ...","Downloading files ...":"Lejupielādē failus...","Downloading update...":"Lejupielādē atjauninājumu...","Duplicati Website":"Duplicati tīmekļa vietne","Duplicati forum":"Duplicati forums","Edit ...":"Rediģēt ...","Edit as list":"Rediģēt kā sarakstu","Edit as text":"Rediģēt kā tekstu","Encrypt file":"Šifrēt failu","Encryption":"Šifrēšana","Encryption changed":"Šifrēšana mainīta","Encryption modules:":"Šīfrēšanas moduļi:","Enter URL":"Ievadiet URL","Enter access key":"Ievadiet piekļuves atslēgu","Enter account name":"Ievadiet konta nosaukumu","Enter backup passphrase, if any":"Ievadiet dublējumkopijas pieejas frāzi, ja tāda eksistē","Enter configuration details":"Ievadiet konfigurācijas detaļas","Enter encryption passphrase":"Ievadiet pieejas frāzi šifrēšanai","Enter the destination path":"Ievadiet mērķa atrašanās vietu","Error":"Kļūda","Error!":"Kļūda!","Errors and crashes":"Kļūdas un avārijas","Experimental":"Eksperimentāls","Export":"Eksportēt","Export ...":"Eksports ...","Export configuration":"Eksportēt konfigurāciju","Exporting ...":"Eksportē ...","FTP (Alternative)":"FTP (Alternatīvs)","Failed to connect:":"Neizdevās izveidot savienojumu:","Failed to import:":"Neizdevās importēt:","File":"Fails","Files larger than:":"Faili lielāki par:","Filters":"Filtrs","Finished!":"Pabeigts!","Folder":"Mape","General":"Vispārīgi","General backup settings":"Vispārīgie dublējumkopiju iestatījumi","General options":"Vispārīgie iestatījumi","Generate":"Izveidot","Getting file versions ...":"Izveido failu versijas","Hidden files":"Paslēptie faili","Hide":"Paslēpt","Hide hidden folders":"Paslēpt paslēptās mapes","Home":"Mājas","Hours":"Stundas","How do you want to handle existing files?":"Kā jūs vēlaties rīkoties ar jau esošajiem failiem?","Hyper-V Machine":"Hyper-V Mašīna","Hyper-V Machine:":"Hyper-V Mašīna:","Hyper-V Machines":"Hyper-V Mašīnas","ID:":"ID:","If a date was missed, the job will run as soon as possible.":"Ja tika nokavēts datums, uzdevums tiks palaists cik ātri vien iespējams.","If your machine is in a multi-user environment (i.e. the machine has more than one account), you need to set a password to prevent other users from accessing data on your account.\nDo you want to set a password now?":"Ja jūsu mašīna ir vairāku lietotāju vidē (piemēram, māšīnai ir vairāk, kā viens konts), jums nepieciešams uzstādīt paroli, lai izslēgtu iespēju citiem lietotājiem piekļūt jūsu kontam.\nVai vēlaties uzstādīt paroli tagad?","Import":"Importēt","Incorrect answer, try again":"Nepareiza atbilde, mēģiniet vēlreiz","Individual builds for developers only.":"Individuāli laidumi, kuri paredzēti tikai izstrādātājiem","Information":"Informācija","Install":"Uzstādīt","Install failed:":"Uzstādīšana neizdevās","It is possible to connect to some FTP without a password.\nAre you sure your FTP server supports password-less logins?":"Ir iespējams pievienoties pie kāda FTP servera bez paroles.\nVai esat pārliecināts, ka jūsu FTP serveris atbalsta bez-paroles pieslēgšanos?","Language in user interface":"Lietotāja saskarnes valoda:","Last month":"Pagājušais mēnesis","Latest":"Pēdējais","Libraries":"Bibliotēkas","Listing remote files ...":"Kārto attālinātos failus","Load older data":"Ielādēt vecākus datus","Loading ...":"Notiek ielāde ...","Local database path:":"Ceļš uz lokālo datubāzi:","Local storage":"Lokālā krātuve","Location":"Atrašanās vieta","Log out":"Izrakstīties","Maintenance":"Apkope","Max download speed":"Maksimālais lejupielādes ātrums","Max upload speed":"Maksimālais augšupielādes ātrums","Menu":"Izvēlne","Minutes":"Minūtes","Missing passphrase":"Trūkst pieejas frāze","Months":"Mēneši","Move existing database":"Pārvietot esošo datubāzi","Move failed:":"Pārvietošana neizdevās:","My Documents":"Mani dokumenti","My Music":"Mana mūzika","My Photos":"Mani fotoattēli","My Pictures":"Mani attēli","Never":"Nekad","Next":"Nākamais","Next scheduled run:":"Nākamā plānotā norise","Next scheduled task:":"Nākamais plānotais uzdevums:","Next task:":"Nākamais uzdevums:","Next time":"Nākamreiz","No":"Nē","No encryption":"Nav šifrešanas","No items selected":"Nav izvēlētu vienību","No items to restore, please select one or more items":"Nav vienību ko atjaunot, lūdzu izvēlieties vienu vai vairākas vienības","No passphrase entered":"Pieejas frāze nav ievadīta","No scheduled tasks":"Nav ieplānotu uzdevumu","No, my machine has only a single account":"Nē, manai ierīcei ir tikai viens konts","Non-matching passphrase":"Nesakrītoša pieejas frāze","None / disabled":"Nav / Atspējots","OK":"Labi","Operations:":"Darbības:","Optional authentication password":"Neobligāta autentifikācijas parole","Options":"Iestatījumi","Options added here are applied to all backups, but can be overridden in each individual backup":"Šeit pievienotās opcijas tiek piemērotas visām dublējumkopijām, taču tās var ignorēt katrā atsevišķā dublējumkopijā","Original location":"Sākotnējā atrašanās vieta","Others":"Citi","Overwrite":"Pārrakstīt","Passphrase":"Pieejas frāze","Passphrase (if encrypted)":"Pieejas frāze (ja šifrēts)","Passphrase changed":"Pieejas frāze nomainīta","Passphrases are not matching":"Pieejas frāzes nesakrīt","Password":"Parole","Passwords do not match":"Paroles nesakrīt","Path not found":"Ceļš nav atrasts","Path on server":"Ceļs uz servera","Pause":"Pauzēt","Pause options":"Pauzēt opcijas","Permissions":"Atļaujas","Port":"Ports","Reload":"Pārlādēt","Remote":"Attālināts","Remove":"Noņemt","Remove option":"Noņemt iestatījumu","Repair":"Salabot","Reparing ...":"Notiek labošana ...","Repeat Passphrase":"Atkārtot pieejas frāzi","Reset":"Attiestatīt","Restore":"Atgūt","Restore files":"Atgūt failus","Restore files ...":"Atgūt failus ...","Restore options":"Atjaunot opcijas","Restore read/write permissions":"Atjaunot lasīšanas/rakstīšanas atļaujas","Restoring files ...":"Atjauno failus ...","Resume":"Turpināt","Run again every":"Palaist atkal katru","Run now":"Palaist tagad","Save":"Saglabāt","Save and repair":"Saglabāt un salabot","Save immediately":"Saglabāt uzreiz","Search":"Meklēt","Search for files":"Meklēt failus","Seconds":"sekundes","Select files":"Izvēlēties failus","Server":"Serveris","Server and port":"Serveris un ports","Server hostname or IP":"Resursdatora nosaukums vai IP adrese","Server password":"Servera parole","Settings":"Iestatījumi","Show":"Parādīt","Show hidden folders":"Parādīt paslēptās mapes","Show log":"Parādīt žurnālu","Show log ...":"Parādīt žurnālu ...","Sia server password":"Sia servera parole","Source Data":"Avota Dati","Source data":"Avota dati","Source folders":"Avota mapes","Source:":"Avots:","Starting ...":"Sākšana ...","Stop after upload":"Pārtraukt pēc augšupielādes","Stop now":"Pātraukt tagad","Stop running task":"Pārtraukt uzdevuma izpildi","Stopping task:":"Aptur uzdevumu:","Storage Type":"Krātuves Tips","Strong":"Spēcīgs","Symbolic link":"Simboliskā saite","System files":"Sistēmas faili","System info":"Sistēmas informācija","System properties":"Sistēmas īpašības","Task is running":"Uzdevums ir palaists","Temporary files":"Pagaidu faili","Test connection":"Pārbaudīt savienojumu","Testing ...":"Notiek pārbaude...","Testing connection ...":"Pārbauda savienojumu...","Testing permissions ...":"Pārbauda atļaujas...","Testing permissions...":"Pārbauda atļaujas...","The dark theme (by Michal)":"Tumšais motīvs (veidoja Michal)","The default blue on white theme (by Alex)":"Noklusējuma zils uz balta motīvs (veidoja Alex)","This month":"Šis mēnesis","This week":"Šī diena","Today":"Šodien","Update channel":"Atjauninājumu kanāls","Update failed:":"Atjaunināšana neizdevās:","Usage statistics":"Izmantošanas statistika","Use SSL":"Izmantot SSL","Use weak passphrase":"Lietot vāju pieejas frāzi","Useless":"Bezjēdzīgs","User data":"Lietotāja dati","User interface settings":"Lietotāja saskarnes iestatījumi","Username":"Lietotājvārds","Verify files":"Pārbaudīt failus","Verifying ...":"Notiek pārbaude ...","Very strong":"Ļoti stiprs","Very weak":"Ļoti vājš","Waiting for upload ...":"Notiek gaidīšana uz augšupielādes procesu","Warnings, errors and crashes":"Brīdinājumi, kļūdas un avārijas","We recommend that you encrypt all backups stored outside your system":"Mēs iesakām jums šifrēt visas dublējumkopijas, kuras tiek uzglabātas ārpus jūsu sistēmas","Weak":"Vājš","Weak passphrase":"Vāja pieejas frāze","Weeks":"Nedēļas","Years":"Gadi","Yes":"Jā","Yes, I have stored the passphrase safely":"Jā, esmu noglabājais pieejas frāzi droši","Yes, I'm brave!":"Jā, esmu drosmīgs!","Yes, please break my backup!":"Jā, lūdzu salauziet manu dublējumkopiju!","Yesterday":"Vakardiena","You must enter a passphrase or disable encryption":"Jums nepieciešams ievadīt pieejas frāzi vai atspējot šifrēšanu","You must specify a path":"Jums jānorāda ceļš","Your passphrase is easy to guess. Consider changing passphrase.":"Jūsu pieejas frāzi ir vienkārsi uzminēt. Apdomājiet pieejas frāzes nomaiņu.","bucket/folder/subfolder":"spainis/mape/apakšmape","byte":"baits","byte/s":"baiti/sekundē","resume now":"turpināt tagad","{{number}} Hour":"{{number}} Stunda","{{number}} Minutes":"{{number}} Minūtes"}); - gettextCatalog.setStrings('nl_NL', {"- pick an option -":" - kies een optie -","...loading...":"...laden...","API Key":"API sleutel","AWS Access ID":"AWS Toegangs ID","AWS Access Key":"AWS Toegangssleutel","AWS IAM Policy":"AWS IAM Beleid","About":"Over","About {{appname}}":"Over {{appname}}","Access Key":"Toegangssleutel","Access denied":"Toegang geweigerd","Access to user interface":"Toegang tot gebruikersinterface","Account name":"Accountnaam","Activate":"Activeren","Activate failed:":"Activeren mislukt","Add a new backup":"Nieuwe back-up toevoegen","Add a path directly":"Voeg een pad rechtstreeks toe","Add advanced option":"Voeg geavanceerde optie toe","Add backup":"Back-up toevoegen","Add filter":"Voeg filter toe","Add path":"Voeg pad toe","Adjust bucket name?":"Bucket naam aanpassen?","Adjust path name?":"Padnaam aanpassen?","Advanced Options":"Geavanceerde Opties","Advanced options":"Geavanceerde opties","Advanced:":"Geavanceerd:","All":"Alle","All Hyper-V Machines":"Alle Hyper-V Machines","All Microsoft SQL Databases":"Alle Microsoft SQL Databases","All usage reports are sent anonymously and do not contain any personal information. They contain information about hardware and operating system, the type of backend, backup duration, overall size of source data and similar data. They do not contain paths, filenames, usernames, passwords or similar sensitive information.":"Alle gebruiksrapporten worden anoniem verstuurd en bevatten geen enkele persoonlijke informatie. Ze bevatten informatie over hardware en besturingssysteem, het type backend, back-up tijdsduur, totale grootte van brongegevens en soortgelijke gegevens. Ze bevatten geen paden, bestandsnamen, gebruikersnamen, wachtwoorden of soortgelijke gevoelige informatie.","Allow remote access (requires restart)":"Remote toegang toestaan (herstart vereist)","Allowed days":"Alleen op deze dagen","An existing file was found at the new location":"Een bestaand bestand was gevonden op de nieuwe locatie","An existing file was found at the new location\nAre you sure you want the database to point to an existing file?":"Een bestaand bestand was gevonden op de nieuwe locatie. Weet u zeker dat de database moet verwijzen naar een bestaand bestand?","An existing local database for the storage has been found.\nRe-using the database will allow the command-line and server instances to work on the same remote storage.\n\n Do you wish to use the existing database?":"Een bestaande lokale database voor de opslag is gevonden.\nHergebruik van de database zal toestaan dat de opdrachtregel- en server instances werken op dezelfde remote opslag.\n\nWilt u de bestaande database gebruiken?","Anonymous usage reports":"Anonieme gebruiksrapporten","As Command-line":"Als Opdrachtregel","AuthID":"AuthID","Authentication password":"Authenticatie wachtwoord","Authentication username":"Authenticatie gebruikersnaam","Autogenerated passphrase":"Automatisch gegenereerde wachtwoordzin","Automatically run backups.":"Automatisch back-ups uitvoeren","B2 Account ID":"B2 Account ID","B2 Application Key":"B2 Applicatiesleutel","B2 Cloud Storage Account ID":"B2 Cloud Storage Account ID","B2 Cloud Storage Application Key":"B2 Cloud Storage Applicatiesleutel","Back":"Vorige","Backend modules:":"Backend modules:","Backup destination":"Back-updoel","Backup location":"Back-up locatie","Backup:":"Back-up:","Beta":"Beta","Broken access":"Verbroken toegang","Browse":"Bladeren","Browser default":"Browser standaard","Bucket Name":"Bucket Naam","Bucket create location":"Bucket aanmaaklocatie","Bucket create region":"Bucket aanmaakregio","Bucket name":"Bucketnaam","Bucket storage class":"Bucket opslagklasse","Building list of files to restore ...":"Lijst samenstellen met te herstellen bestanden ...","Building partial temporary database ...":"Gedeeltelijke tijdelijke database samenstellen ...","Busy ...":"Bezig ...","Canary":"Canary","Cancel":"Annuleren","Cannot move to existing file":"Kan niet verplaatsen naar bestaand bestand","Changelog":"Aanpassingen-log","Changelog for {{appname}} {{version}}":"Aanpassingen-log voor {{appname}} {{version}}","Check failed:":"Controle mislukt:","Check for updates now":"Controleer nu op updates","Checking ...":"Controleren ...","Checking for updates ...":"Controleren op updates ...","Chose a storage type to get started":"Kies een opslagtype om aan de slag te gaan","Click the AuthID link to create an AuthID":"Klik op de AuthID link om een AuthID aan te maken","Click to set throttle options":"Klik om bandbreedte-opties in te stellen","Commandline ...":"Opdrachtregel ...","Compact now":"Nu opruimen","Compacting remote data ...":"Opruimen van remote gegevens ...","Completing backup ...":"Back-up wordt voltooid ...","Completing previous backup ...":"Vorige back-up wordt voltooid ...","Compression modules:":"Compressiemodules:","Computer":"Computer","Configuration file:":"Configuratiebestand","Configuration:":"Configuratie:","Configure a new backup":"Een nieuwe back-up instellen","Confirm delete":"Bevestig verwijderen","Confirmation required":"Bevestiging vereist","Connect":"Verbind","Connect now":"Verbind nu","Connecting to server ...":"Verbinden met server ...","Connecting to task ....":"Verbinding maken met taak ...","Connecting...":"Verbinden...","Connection lost":"Verbinding verbroken","Connection worked!":"Verbinding werkt!","Container name":"Containernaam","Container region":"Container-regio","Continue":"Volgende","Continue without encryption":"Ga verder zonder versleuteling","Copied!":"Gekopieerd!","Copy Destination URL to Clipboard":"Kopieer doel URL naar Klembord","Copy failed. Please manually copy the URL":"Kopiëren mislukt. Kopieer de URL handmatig","Core options":"Kern-opties","Counting ({{files}} files found, {{size}})":"Tellen ({{files}} bestanden gevonden, {{size}})","Crashes only":"Alleen crashes","Create bug report ...":"Bug rapport maken ...","Create folder?":"Map aanmaken?","Created new limited user":"Nieuwe beperkte gebruiker aangemaakt","Creating bug report ...":"Bug rapport aanmaken ...","Creating new user with limited access ...":"Nieuwe gebruiker met beperkte toegang aanmaken ...","Creating target folders ...":"Doelmappen aanmaken ...","Creating temporary backup ...":"Tijdelijke back-up aanmaken ...","Creating user...":"Gebruiker aanmaken ...","Current version is {{versionname}} ({{versionnumber}})":"Huidige versie is {{versionname}} ({{versionnumber}})","Custom S3 endpoint":"Aangepaste S3 endpoint","Custom authentication url":"Aangepaste authenticatie url","Custom location ({{server}})":"Aangepaste locatie ({{server}})","Custom region for creating buckets":"Aangepaste regio voor het aanmaken van buckets","Custom region value ({{region}})":"Aangepaste regio waarde ({{region}})","Custom server url ({{server}})":"Aangepaste server url ({{server}})","Custom storage class ({{class}})":"Aangepaste opslagklasse ({{class}})","Database ...":"Database ...","Days":"Dagen","Default":"Standaard","Default ({{channelname}})":"Standaard ({{channelname}})","Default Filters":"Standaard Filters","Default options":"Standaard opties","Delete":"Verwijderen","Delete ...":"Verwijderen ...","Delete backup":"Verwijder back-up","Delete local database":"Verwijder lokale database","Delete remote files":"Verwijder remote bestanden","Delete the local database":"Verwijder de lokale database","Delete {{filecount}} files ({{filesize}}) from the remote storage?":"{{filecount}} bestanden ({{filesize}}) van de remote opslag verwijderen?","Deleting remote files ...":"Remote bestanden verwijderen ...","Deleting unwanted files ...":"Onnodige bestanden verwijderen ...","Desktop":"Desktop","Destination":"Doel","Did we help save your files? If so, please consider supporting Duplicati with a donation. We suggest {{smallamount}} for private use and {{largeamount}} for commercial use.":"Hebben we geholpen uw bestanden veilig te stellen? Overweeg in dat geval Duplicati te ondersteunen met een donatie. We raden {{smallamount}} aan voor persoonlijk gebruik en {{largeamount}} voor bedrijfsmatig gebruik.","Direct restore from backup files ...":"Rechtstreeks herstellen vanuit back-up bestanden ...","Disabled":"Uitgeschakeld","Dismiss":"Afwijzen","Display and color theme":"Weergave en kleurenschema","Do you really want to delete the backup: \"{{name}}\" ?":"Wilt u de back-up \"{{name}}\" echt verwijderen?","Do you really want to delete the local database for: {{name}}":"Wilt u de lokale database voor: {{name}} echt verwijderen?","Donate":"Doneren","Donate with PayPal":"Doneer met PayPal","Donate with crypto currency":"Doneer met crypto-valuta","Donation messages":"Doneer-berichten","Donation messages are hidden, click to show":"Doneer-berichten zijn verborgen, klik om ze weer te geven","Donation messages are visible, click to hide":"Doneer-berichten zijn zichtbaar, klik om ze te verbergen","Done":"Klaar","Download":"Download","Downloading ...":"Downloaden ...","Downloading files ...":"Bestanden downloaden ...","Downloading update...":"Update downloaden ...","Duplicate option {{opt}}":"Dupliceer optie {{opt}}","Duplicati Website":"Duplicati Website","Duplicati forum":"Duplicati forum","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\n When deleting a backup, you can also delete the local database without affecting the ability to restore the remote files.\n If you are using the local database for backups from the commandline, you should keep the database.":"Iedere back-up heeft een lokale database waarmee het geassocieerd is, die informatie opslaat over de remote back-up op de lokale machine.\nBij het verwijderen van een back-up kan eveneens de lokale database verwijderd worden, zonder dat dit invloed heeft op de mogelijkheid van het terugzetten van de remote bestanden.\nAls de lokale database gebruikt wordt voor back-ups vanaf de opdrachtregel, moet de database behouden blijven.","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\\nThis makes it faster to perform many operations, and reduces the amount of data that needs to be downloaded for each operation.":"Iedere back-up heeft een lokale database waarmee het geassocieerd is, die informatie opslaat over de remote back-up op de lokale machine.\nDit maakt het sneller bij het uitvoeren van veel bewerkingen, en reduceert de hoeveelheid gegevens die gedownload moeten worden voor iedere bewerking.","Edit ...":"Bewerken ...","Edit as list":"Bewerk als lijst","Edit as text":"Bewerk als tekst","Encrypt file":"Versleutel bestand","Encryption":"Versleuteling","Encryption changed":"Versleuteling aangepast","Encryption modules:":"Versleutelingsmodules:","Enter URL":"Geef URL in","Enter access key":"Geef toegangscode in","Enter account name":"Geef accountnaam in","Enter backup passphrase, if any":"Geef eventueel back-up wachtwoordzin in","Enter configuration details":"Voer configuratie-details in","Enter container name":"Geef containernaam in","Enter encryption passphrase":"Geef een wachtwoordzin in voor versleuteling","Enter expression here":"Geef uitdrukking hier in","Enter folder path name":"Geef padnaam van de map in","Enter one option per line in command-line format, eg. {0}":"Geef één optie per regel in opdracht-prompt indeling, bijvoorbeeld {0}","Enter the destination path":"Geef het doelpad in","Error":"Fout","Error!":"Fout!","Errors and crashes":"Fouten en crashes","Exclude":"Uitsluiten","Exclude directories whose names contain":"Sluit mappen uit waarvan de naam bevat:","Exclude expression":"Sluit uitdrukking uit","Exclude file":"Sluit bestand uit","Exclude file extension":"Sluit bestandsextensie uit","Exclude files whose names contain":"Sluit bestanden uit waarvan de naam bevat:","Exclude folder":"Sluit map uit","Exclude regular expression":"Sluit reguliere expressie uit","Existing file found":"Bestaand bestand gevonden","Experimental":"Experimenteel","Export":"Exporteer","Export ...":"Exporteren ...","Export backup configuration":"Exporteer back-upconfiguratie","Export configuration":"Exporteer configuratie","Exporting ...":"Exporteren ...","FTP (Alternative)":"FTP (Alternatief)","Failed to build temporary database: {{message}}":"Opbouwen tijdelijke database mislukt: {{message}}","Failed to connect:":"Verbinden mislukt:","Failed to connect: {{message}}":"Verbinden mislukt: {{message}}","Failed to delete:":"Verwijderen mislukt:","Failed to fetch path information: {{message}}":"Ophalen pad-informatie mislukt: {{message}}","Failed to import:":"Importeren mislukt:","Failed to read backup defaults:":"Standaard instellingen voor back-up inlezen mislukt:","Failed to restore files: {{message}}":"Herstellen bestanden mislukt: {{message}}","Failed to save:":"Opslaan mislukt:","Fetching path information ...":"Ophalen pad-informatie ...","File":"Bestand","Files larger than:":"Bestanden groter dan:","Filters":"Filters","Finished!":"Klaar!","First run setup":"Instellen voor eerste gebruik","Folder":"Map","Folder path":"Map-pad","Fri":"Vrijdag","GByte":"GByte","GByte/s":"GByte/s","GCS Project ID":"GCS Project ID","General":"Algemeen","General backup settings":"Algemene back-upinstellingen","General options":"Algemene opties","Generate":"Genereer","Generate IAM access policy":"Genereer IAM toegangsbeleid","Getting file versions ...":"Bestandsversies ophalen ...","Hidden files":"Verborgen bestanden","Hide":"Verberg","Hide hidden folders":"Verberg verborgen bestanden","Home":"Start","Hours":"Uur","How do you want to handle existing files?":"Hoe wilt u omgaan met bestaande bestanden?","Hyper-V Machine":"Hyper-V Machine","Hyper-V Machine:":"Hyper-V Machine:","Hyper-V Machines":"Hyper-V Machines","ID:":"ID:","If a date was missed, the job will run as soon as possible.":"Als een geplande taak werd overgeslagen, zal de taak zo snel mogelijk na het geplande tijdstip starten.","If the backup and the remote storage is out of sync, Duplicati will require that you perform a repair operation to synchronize the database.\\nIf the repair is unsuccesful, you can delete the local database and re-generate.":"Als de back-up en de remote opslag niet gesynchroniseerd zijn, zal Duplicati vereisen dat u een repareer-bewerking uitvoert om de database te synchroniseren.\nAls het repareren niet succesvol was, kunt u de lokale database verwijderen en opnieuw samenstellen.","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"Als het back-upbestand niet automatisch is gedownload, klik met rechts en kies "Opslaan als ..."","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"Als het back-upbestand niet automatisch is gedownload, klik met rechts en kies "Opslaan als ..."","If you do not enter a path, all files will be stored in the login folder.\nAre you sure this is what you want?":"Als u geen pad ingeeft, zullen alle bestanden opgeslagen worden in de login map.\nWeet u zeker dat dit is wat u wilt?","If you do not enter an API Key, the tenant name is required":"Als u geen API sleutel ingeeft, is een tenant naam vereist","If you want to use the backup later, you can export the configuration before deleting it":"Als u de back-up later wilt gebruiken, kunt u de configuratie exporteren alvorens hem te verwijderen","If your machine is in a multi-user environment (i.e. the machine has more than one account), you need to set a password to prevent other users from accessing data on your account.\nDo you want to set a password now?":"Als uw machine zich in een multi-user omgeving bevindt (bijvoorbeeld als op de machine met meer dan één account kan worden aangemeld), moet een wachtwoord worden ingesteld om te voorkomen dat andere gebruikers togang kunnen krijgen tot gegevens behorend bij uw account.\nWilt u nu een wachtwoord instellen?","Import":"Importeer","Import Destination URL":"Importeer Doel URL","Import backup configuration":"Importeer back-upconfiguratie","Import completed, but no certificates were found after the import":"Importeren voltooid, maar na het importeren zijn geen certificaten gevonden","Import failed":"Importeren mislukt","Import from a file":"Importeer vanuit een bestand","Importing ...":"Importeren ...","Include a file?":"Een bestand opnemen?","Include expression":"Uitdrukking opnemen","Include regular expression":"Reguliere expressie opnemen","Incorrect answer, try again":"Incorrect antwoord, probeer opnieuw","Individual builds for developers only.":"Individuele builds alleen voor ontwikkelaars.","Information":"Informatie","Install":"Installeren","Install failed:":"Installeren mislukt","Invalid characters in path":"Ongeldige tekens in pad","Invalid retention time":"Ongeldige retentietijd","It is possible to connect to some FTP without a password.\nAre you sure your FTP server supports password-less logins?":"Het is mogelijk te verbinden met sommige FTP servers zonder een wachtwoord.\nWeet u zeker dat uw FTP server aanmelden zonder wachtwoord ondersteunt?","KByte":"KByte","KByte/s":"KByte/s","Keep this number of backups":"Bewaar dit aantal back-ups","Language in user interface":"Taal in gebruikersinterface","Last month":"Vorige maand","Last successful run:":"Laatste succesvolle uitvoering:","Latest":"Laatste","Libraries":"Bibliotheken","Linux":"Linux","Listing backup dates ...":"Back-updata weergeven ...","Listing remote files ...":"Remote bestanden weergeven ...","Live":"Live","Load a configuration from an exported job or a storage provider":"Laad een configuratie vanuit een geëxporteerde taak of een opslagprovider","Load destination from an exported job or a storage provider":"Laad doel vanuit een geëxporteerde taak of een opslagprovider","Load older data":"Laad oudere gegevens","Loading ...":"Laden ...","Loading remote storage usage ...":"Laden van remote opslaggebruik ...","Local database for":"Lokale database voor","Local database path:":"Lokaal database-pad:","Local storage":"Lokale opslag","Location":"Locatie","Location where buckets are created":"Locatie waar buckets gemaakt worden","Log data for {{Backup.Backup.Name}}":"Log gegevens voor {{Backup.Backup.Name}}","Log data from the server":"Log gegevens van de server","Log out":"Uitloggen","MByte":"MByte","MByte/s":"MByte/s","Maintenance":"Onderhoud","Manually type path":"Voer pad handmatig in","Max download speed":"Max downloadsnelheid","Max upload speed":"Max Uploadsnelheid","Menu":"Menu","Microsoft SQL Database:":"Microsoft SQL Database","Microsoft SQL Databases":"Microsoft SQL Databases","Minimum redundancy":"Minimale redundantie","Minimum redundancy is 1.0":"Minimale redundantie is 1.0","Minutes":"Minuten","Missing name":"Ontbrekende naam","Missing passphrase":"Ontbrekende wachtwoordzin","Missing sources":"Ontbrekende bronnen","Mon":"Maandag","Months":"Maanden","Move existing database":"Verplaats bestaande database","Move failed:":"Verplaatsen mislukt:","My Documents":"Mijn Documenten","My Music":"Mijn Muziek","My Photos":"Mijn Foto's","My Pictures":"Mijn Afbeeldingen","Name":"Naam","Never":"Nooit","New update found: {{message}}":"Nieuwe update gevonden: {{message}}","New user name is {{user}}.\nUpdated credentials to use the new limited user":"Nieuwe gebruikersnaam is {{user}}.\nGebruikersreferenties bijgewerkt om de nieuwe beperkte gebruiker te gebruiken","Next":"Volgende","Next scheduled run:":"Volgende geplande uitvoering:","Next scheduled task:":"Volgende geplande taak:","Next task:":"Volgende taak:","Next time":"Volgende keer","No":"Nee","No certificate was specified previously, please verify with the server administrator that the key is correct: {{key}} \n\nDo you want to approve the reported host key?":"Er is eerder geen certificaat opgegeven, controleer svp met de serverbeheerder of de sleutel correct is: {{key}}\n\nWilt u de gerapporteerde host-sleutel goedkeuren?","No editor found for the "{{backend}}" storage type":"Geen bewerkingsprogramma gevonden voor het "{{backend}}" opslagtype","No encryption":"Geen versleuteling","No items selected":"Geen items geselecteerd","No items to restore, please select one or more items":"Geen items om te herstellen, selecteer één of meer items","No passphrase entered":"Geen wachtwoordzin ingegeven","No scheduled tasks":"Geen geplande taken","No, my machine has only a single account":"Nee, mijn machine heeft slechts een enkele account","Non-matching passphrase":"Niet-bijbehorende wachtwoordzin","None / disabled":"Geen / uitgeschakeld","OK":"OK","OSX":"OSX","OpenStack AuthURI":"OpenStack AuthURI","OpenStack Object Storage / Swift":"OpenStack Object Storage / Swift","Operation failed:":"Bewerking mislukt:","Operations:":"Bewerkingen:","Optional authentication password":"Optioneel authenticatie wachtwoord","Optional authentication username":"Optionele authenticatie gebruikersnaam","Options":"Opties","Options added here are applied to all backups, but can be overridden in each individual backup":"Opties die hier worden toegevoegd, worden toegepast op alle back-ups, maar kunnen worden overschreven in iedere afzonderlijke back-up","Original location":"Originele locatie","Others":"Anderen","Overwrite":"Overschrijven","Passphrase":"Wachtwoordzin","Passphrase (if encrypted)":"Wachtwoordzin (indien versleuteld)","Passphrase changed":"Wachtwoordzin veranderd","Passphrases are not matching":"Wachtwoordzinnen komen niet overeen","Password":"Wachtwoord","Passwords do not match":"Wachtwoorden komen niet overeen","Patching files with local blocks ...":"Bestanden bijwerken met lokale blokken ...","Path not found":"Pad niet gevonden","Path on server":"Pad op server","Path or subfolder in the bucket":"Pad of submap in de bucket","Pause":"Pauze","Pause after startup or hibernation":"Pauzeer na opstarten of slaapmodus","Pause options":"Pauzeer-opties","Permissions":"Permissies","Pick location":"Kies locatie","Point to your backup files and restore from there":"Verwijs naar de back-up bestanden en herstel daar vandaan","Port":"Poort","Previous":"Vorige","ProjectID is optional if the bucket exist":"ProjectID is optioneel als de bucket bestaat","Proprietary":"Fabrikantgebonden","Purging files ...":"Bestanden wissen ...","Rebuilding local database ...":"Opnieuw opbouwen van lokale database ...","Recreate (delete and repair)":"Opnieuw aanmaken (verwijderen en repareren)","Recreating database ...":"Opnieuw opbouwen van de database ...","Registering temporary backup ...":"Registreren tijdelijke back-up ...","Relative paths not allowed":"Relatieve paden zijn niet toegestaan","Reload":"Andere code","Remote":"Remote","Remove":"Verwijderen","Remove option":"Verwijder optie","Repair":"Repareer","Reparing ...":"Repareren ...","Repeat Passphrase":"Herhaal wachtwoordzin","Reporting:":"Rapportage:","Reset":"Reset","Restore":"Herstellen","Restore files":"Herstel bestanden","Restore files ...":"Bestanden herstellen ...","Restore files from {{backupname}}":"Herstel bestanden vanuit {{backupname}}","Restore from":"Herstellen vanaf","Restore from backup configuration":"Herstel vanuit back-up configuratie","Restore from configuration ...":"Herstel vanuit configuratie...","Restore options":"Herstelopties","Restore read/write permissions":"Herstel lees/schrijfpermissies","Restoring files ...":"Bestanden worden hersteld ...","Resume":"Hervat","Run again every":"Voer opnieuw uit iedere","Run now":"Nu uitvoeren","Running ...":"In uitvoering ...","Running ....":"Uitvoeren ...","Running commandline entry":"Opdrachtregelinvoer in uitvoering","Running task:":"Taak in uitvoering:","S3 Compatible":"S3 Compatible","Same as the base install version: {{channelname}}":"Zelfde als de basis installatie versie: {{channelname}}","Sat":"Zaterdag","Save":"Opslaan","Save and repair":"Opslaan en repareren","Save different versions with timestamp in file name":"Sla verschillende versies op met tijdstempel in de bestandsnaam","Save immediately":"Onmiddellijk opslaan","Scanning existing files ...":"Scannen bestaande bestanden ...","Scanning for local blocks ...":"Scannen op lokale blokken ...","Schedule":"Planning","Search":"Zoek","Search for files":"Zoek bestanden","Seconds":"Seconden","Select a log level and see messages as they happen:":"Selecteer een logniveau en bekijk meldingen zodra ze zich voordoen:","Select files":"Selecteer bestanden","Server":"Server","Server and port":"Server en poort","Server hostname or IP":"Server hostnaam of IP","Server is currently paused,":"Server is momenteel gepauzeerd,","Server is currently paused, do you want to resume now?":"Server is momenteel gepauzeerd, wilt u nu hervatten?","Server password":"Server wachtwoord","Server paused":"Server gepauzeerd","Server state properties":"Server status eigenschappen","Settings":"Instellingen","Show":"Tonen","Show advanced editor":"Toon geavanceerde editor","Show hidden folders":"Toon verborgen mappen","Show log":"Log weergeven","Show log ...":"Log weergeven ...","Show treeview":"Toon boomstructuur","Sia server password":"Sia server wachtwoord","Some OpenStack providers allow an API key instead of a password and tenant name":"Sommige OpenStack providers staan een API key toe in plaats van een wachtwoord en tenant naam","Source Data":"Bron","Source data":"Brongegevens","Source folders":"Bronmappen","Source:":"Bron:","Specific builds for developers only.":"Specifieke builds alleen voor ontwikkelaars.","Standard protocols":"Standaard protocollen","Starting ...":"Starten ...","Starting the restore process ...":"Starten van het herstelproces ...","Stop after the current file":"Stop na het huidige bestand","Stop after upload":"Stop na de upload","Stop now":"Nu stoppen","Stop running backup":"Stop de back-up in uitvoering","Stop running task":"Stop de taak in uitvoering","Stopping after upload:":"Stop na de upload:","Stopping task:":"Taak wordt gestopt:","Storage Type":"Opslagtype","Storage class":"Opslagklasse","Storage class for creating a bucket":"Opslagklasse voor het aanmaken van een bucket","Stored":"Opgeslagen","Strong":"Sterk","Success":"Succes","Sun":"Zondag","Symbolic link":"Symbolische link","System default ({{levelname}})":"Systeem standaard ({{levelname}})","System files":"Systeembestanden","System info":"Systeeminformatie","System properties":"Systeemeigenschappen","TByte":"TByte","TByte/s":"TByte/s","Target path, ie /backup":"Doelpad, bijvoorbeeld /backup","Task is running":"Taak is in uitvoering","Temporary files":"Tijdelijke bestanden","Tenant Name":"Tenant naam","Test connection":"Test verbinding","Testing ...":"Testen ...","Testing connection ...":"Testen van de verbinding ...","Testing permissions ...":"Testen van de permissies ...","Testing permissions...":"Testen van de permissies ...","The bucket name should be all lower-case, convert automatically?":"De bucket-naam hoort in kleine letters te zijn, automatisch converteren?","The bucket name should start with your username, prepend automatically?":"De bucket naam hoort te beginnen met uw gebruikersnaam, automatisch voorvoegen?","The connection to the server is lost, attempting again in {{time}} ...":"De verbinding met de server is verbroken, opnieuw proberen over {{time}} ...","The dark theme (by Michal)":"Het donkere thema (door Michal)","The default blue on white theme (by Alex)":"Het standaard blauw op wit thema (door Alex)","The folder {{folder}} does not exist.\nCreate it now?":"De map {{folder}} bestaat niet.\nNu aanmaken?","The host key has changed, please check with the server administrator if this is correct, otherwise you could be the victim of a MAN-IN-THE-MIDDLE attack.\n\nDo you want to REPLACE your CURRENT host key \"{{prev}}\" with the REPORTED host key: {{key}}?":"De host sleutel is veranderd, controleer met uw server beheerder of dit correct is, in het andere geval zou u het slachtoffer kunnen zijn van een MAN-IN-THE-MIDDLE aanval.\n\nWilt u de HUIDIGE host sleutel \"{prev}\" VERVANGEN door de GERAPPORTEERDE host sleutel: {{key}}?","The path does not appear to exist, do you want to add it anyway?":"Het pad lijkt niet te bestaan, wilt u het desondanks toevoegen?","The path does not end with a '{{dirsep}}' character, which means that you include a file, not a folder.\n\nDo you want to include the specified file?":"Het pad eindigt niet met een '{{dirsep}}' teken, wat betekent dat u een bestand opneemt, niet een map.\n\nWilt u het aangegeven bestand opnemen?","The path must be an absolute path, i.e. it must start with a forward slash '/'":"Het pad moet een absoluut pad zijn, bijvoorbeeld het moet beginnen met een forward slash '/'","The path should start with \"{{prefix1}}\" or \"{{prefix2}}\", otherwise you will not be able to see the files in the HubiC web interface.\n\nDo you want to add the prefix to the path automatically?":"Het pad moet beginnen met \"{{prefix1}}\" of \"{{prefix2}}\", anders zullen bestanden in de HubiC web interface niet zichtbaar zijn.","The region parameter is only applied when creating a new bucket":"De regio parameter wordt alleen toegepast bij het aanmaken van een bucket","The region parameter is only used when creating a bucket":"De regio parameter wordt alleen gebruikt bij het aanmaken van een bucket","The server certificate could not be validated.\nDo you want to approve the SSL certificate with the hash: {{hash}}?":"Het servercertificaat kon niet gevalideerd worden.\nWilt u het certificaat goedkeuren met deze hash: {{hash}}?","The storage class affects the availability and price for a stored file":"De opslagklasse beïnvloedt de beschikbaarheid en prijs van een opgeslagen bestand","The target folder contains encrypted files, please supply the passphrase":"De doelmap bevat versleutelde bestanden, geef alstublieft de wachtwoordzin","The user has too many permissions. Do you want to create a new limited user, with only permissions to the selected path?":"De gebruiker heeft teveel permmissies. Wilt u een nieuwe beperkte gebruiker aanmaken, met enkel permissies tot het aangegeven pad?","This backup was created on another operating system. Restoring files without specifying a destination folder can cause files to be restored in unexpected places. Are you sure you want to continue without choosing a destination folder?":"De back-up werd aangemaakt op een ander besturingssysteem. Bestanden terugzetten zonder een doelmap op te geven kan tot gevolg hebben dat bestanden worden teruggezet naar onverwachte plaatsen. Bent u er zeker van dat u wilt doorgaan zonder een doelmap te kiezen?","This month":"Afgelopen maand","This week":"Afgelopen week","Throttle settings":"Bandbreedte-instellingen","Thu":"Donderdag","To File":"Naar Bestand","To confirm you want to delete all remote files for \"{{name}}\", please enter the word you see below":"Om te bevestigen dat u alle remote bestanden wilt verwijderen voor \"{{name}}\", geef svp het woord in dat u hieronder ziet","To export without a passphrase, uncheck the \"Encrypt file\" box":"Om te exporteren zonder een wachtwoordzin, deselecteer het \"Versleutel bestand\" vakje","Today":"Vandaag","Trust host certificate?":"Vertrouw host certificaat?","Trust server certificate?":"Vertrouw server certificaat?","Try out the new features we are working on. Don't use with important data.":"Probeer nieuwe mogelijkheden uit waar we aan werken. Niet gebruiken met belangrijke gegevens.","Tue":"Dinsdag","Type to highlight files":"Typ om bestanden uit te lichten","Unknown backup size and versions":"Onbekende back-up grootte en versies","Until resumed":"Tot hervatting","Update channel":"Updatekanaal","Update failed:":"Update mislukt:","Updating with existing database":"Updaten met bestaande database","Upload volume size":"Upload volumegrootte","Uploading verification file ...":"Uploaden controlebestand ...","Usage reports help us improve the user experience and evaluate impact of new features. We use them to generate public usage statistics":"Gebruiksrapporten helpen ons de gebruikerservaring te verbeteren en de impact van nieuwe mogelijkheden te evalueren. We gebruiken ze om openbare gebruikstatistieken te genereren.","Usage statistics":"Gebruikstatistieken","Usage statistics, warnings, errors, and crashes":"Gebruikstatistieken, waarschuwingen, fouten en crashes","Use SSL":"Gebruik SSL","Use existing database?":"Gebruik bestaande database?","Use weak passphrase":"Gebruik zwakke wachtwoordzin","Useless":"Waardeloos","User data":"Gebruikersgegevens","User has too many permissions":"Gebruiker heeft teveel permissies","User interface settings":"Gebruikersinterface instellingen","Username":"Gebruikersnaam","Validating ...":"Valideren ...","Verify files":"Bestanden controleren","Verifying ...":"Controleren ...","Verifying answer":"Antwoord controleren","Verifying backend data ...":"Controleren van backend gegevens ...","Verifying remote data ...":"Controleren van remote gegevens ...","Verifying restored files ...":"Controleren van herstelde bestanden ...","Very strong":"Erg sterk","Very weak":"Erg zwak","Visit us on":"Bezoek ons op","WARNING: The remote database is found to be in use by the commandline library":"WAARSCHUWING: De remote database blijkt in gebruik te zijn door de opdrachtregel bibliotheek","WARNING: This will prevent you from restoring the data in the future.":"WAARSCHUWING: Dit zal het onmogelijk maken om in de toekomst bestanden te herstellen.","Waiting for task to begin":"Wachten op het starten van de taak","Waiting for task to start ....":"Wachten op het starten van de taak ...","Waiting for upload ...":"Wachten op upload ...","Warnings, errors and crashes":"Waarschuwingen, fouten en crashes","We accept donations via different services, such as OpenCollective, PayPal, BountySource and various crypto currencies.":"We accepteren donaties via verschillende services, zoals OpenCollective, PayPal, BountySource en diverse crypto-valuta.","We recommend that you encrypt all backups stored outside your system":"We raden aan dat u alle back-ups die buiten uw systeem worden opgeslagen versleutelt","Weak":"Zwak","Weak passphrase":"Zwakke wachtwoordzin","Wed":"Woensdag","Weeks":"Weken","Where do you want to restore from?":"Waar vandaan wilt u herstellen?","Where do you want to restore the files to?":"Waarheen wilt u de bestanden herstellen?","Windows":"Windows","Years":"Jaren","Yes":"Ja","Yes, I have stored the passphrase safely":"Ja, ik heb de wachtwoordzin op een veilige plaats opgeborgen","Yes, I'm brave!":"Ja, ik ben dapper!","Yes, please break my backup!":"Ja, help mijn back-up om zeep!","Yesterday":"Gisteren","You appear to be running Mono with no SSL certificates loaded.\nDo you want to import the list of trusted certificates from Mozilla?":"Het lijkt er op dat u Mono gebruikt zonder dat SSL certificaten geladen zijn.\nWilt u de lijst met vertrouwde certificaten importeren van Mozilla?","You are changing the database path away from an existing database.\nAre you sure this is what you want?":"U verandert het database pad weg van een bestaande database.\nWeet u zeker dat dit is wat u wilt?","You are currently running {{appname}} {{version}}":"U werkt momenteel met {{appname}} {{version}}","You can stop the backup immediately, or stop after the current file has been uploaded.":"De back-up kan onmiddellijk worden gestopt, of stoppen nadat het huidige bestand is geüpload.","You can stop the task immediately, or allow the process to continue its current file and the stop.":"De taak kan onmiddellijk worden gestopt, of het proces toestaan om door te gaan met het huidige bestand en dan stoppen.","You have changed the encryption mode. This may break stuff. You are encouraged to create a new backup instead":"U hebt de versleutelingsmodus veranderd. Dit kan dingen kapotmaken. U wordt daarom aangemoedigd een nieuwe back-up aan te maken","You have changed the passphrase, which is not supported. You are encouraged to create a new backup instead.":"U hebt de wachtwoordzin aangepast, wat niet wordt ondersteund. U wordt daarom aangemoedigd een nieuwe back-up aan te maken.","You have chosen not to encrypt the backup. Encryption is recommended for all data stored on a remote server.":"U hebt ervoor gekozen de back-up niet te versleutelen. Encryptie is aanbevolen voor alle gegevens die worden opgeslagen op een remote server.","You have chosen to restore to a new location, but not entered one":"U koos voor terugzetten naar een nieuwe locatie, maar hebt geen locatie opgegeven","You have generated a strong passphrase. Make sure you have made a safe copy of the passphrase, as the data cannot be recovered if you lose the passphrase.":"U hebt een sterke wachtwoordzin gegenereerd. Verzeker u ervan dat u een veilige kopie heeft van de wachtwoordzin, omdat de gegevens niet hersteld kunnen worden als u de wachtwoordzin verliest.","You must choose at least one source folder":"U moet tenminste één bronmap kiezen","You must enter a name for the backup":"U moet een naam ingeven voor de back-up","You must enter a passphrase or disable encryption":"U moet een wachtwoordzin ingeven of versleuteling uitschakelen","You must enter a positive number of backups to keep":"U moet een positief getal opgeven voor de hoeveelheid te bewaren back-ups","You must enter a tenant name if you do not provide an API Key":"U moet een tenant naam ingeven als u de API sleutel niet verstrekt","You must enter a valid duration for the time to keep backups":"U moet een geldige tijdsduur ingeven voor de tijd dat back-ups bewaard moeten worden","You must enter either a password or an API Key":"U moet òf een wachtwoord, òf een API sleutel ingeven","You must enter either a password or an API Key, not both":"U moet òf een wachtwoord, òf een API sleutel ingeven, niet beide","You must fill in the password":"U moet het wachtwoord invullen","You must fill in the server name or address":"U moet de servernaam of -adres invullen","You must fill in the username":"U moet de gebruikersnaam invullen","You must fill in {{field}}":"U moet {{field}} invullen","You must select or fill in the AuthURI":"U moet de AuthURI selecteren of invullen","You must select or fill in the server":"U moet de server selecteren of invullen","You must specify a path":"U moet een pad opgeven","Your files and folders have been restored successfully.":"Uw bestanden en mappen zijn succesvol hersteld","Your passphrase is easy to guess. Consider changing passphrase.":"Uw wachtwoordzin is eenvoudig te raden. Overweeg de wachtwoordzin te veranderen.","a specific number":"een bepaald aantal","bucket/folder/subfolder":"bucket/map/submap","byte":"byte","byte/s":"byte/s","custom":"aangepast","resume now":"nu hervatten","unlimited":"onbeperkt","until they are older than":"totdat ze ouder zijn dan","{{appname}} was primarily developed by {{dev1}} and {{dev2}}. {{appname}} can be downloaded from {{websitename}}. {{appname}} is licensed under the {{licensename}}.":"{{appname}} werd in eerste instantie ontwikkeld door {{dev1}} en {{dev2}}. {{appname}} kan gedownload worden van {{websitename}}. {{appname}} is gelicenseerd onder de {{licensename}}.","{{files}} files ({{size}}) to go {{speed_txt}}":"{{files}} bestanden ({{size}}) te gaan {{speed_txt}}","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Version":["{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Versie","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Versies"],"{{number}} Hour":"{{number}} Uur","{{number}} Minutes":"{{number}} Minuten","{{time}} (took {{duration}})":"{{time}} (duurde {{duration}})"}); + gettextCatalog.setStrings('nl_NL', {"- pick an option -":" - kies een optie -","...loading...":"...laden...","API Key":"API sleutel","AWS Access ID":"AWS Toegangs ID","AWS Access Key":"AWS Toegangssleutel","AWS IAM Policy":"AWS IAM Beleid","About":"Over","About {{appname}}":"Over {{appname}}","Access Key":"Toegangssleutel","Access denied":"Toegang geweigerd","Access to user interface":"Toegang tot gebruikersinterface","Account name":"Accountnaam","Activate":"Activeren","Activate failed:":"Activeren mislukt","Add a new backup":"Nieuwe back-up toevoegen","Add a path directly":"Voeg een pad rechtstreeks toe","Add advanced option":"Voeg geavanceerde optie toe","Add backup":"Back-up toevoegen","Add filter":"Voeg filter toe","Add path":"Voeg pad toe","Adjust bucket name?":"Bucket naam aanpassen?","Adjust path name?":"Padnaam aanpassen?","Advanced Options":"Geavanceerde Opties","Advanced options":"Geavanceerde opties","Advanced:":"Geavanceerd:","All":"Alle","All Hyper-V Machines":"Alle Hyper-V Machines","All Microsoft SQL Databases":"Alle Microsoft SQL Databases","All usage reports are sent anonymously and do not contain any personal information. They contain information about hardware and operating system, the type of backend, backup duration, overall size of source data and similar data. They do not contain paths, filenames, usernames, passwords or similar sensitive information.":"Alle gebruiksrapporten worden anoniem verstuurd en bevatten geen enkele persoonlijke informatie. Ze bevatten informatie over hardware en besturingssysteem, het type backend, back-up tijdsduur, totale grootte van brongegevens en soortgelijke gegevens. Ze bevatten geen paden, bestandsnamen, gebruikersnamen, wachtwoorden of soortgelijke gevoelige informatie.","Allow remote access (requires restart)":"Remote toegang toestaan (herstart vereist)","Allowed days":"Alleen op deze dagen","An existing file was found at the new location":"Een bestaand bestand was gevonden op de nieuwe locatie","An existing file was found at the new location\nAre you sure you want the database to point to an existing file?":"Een bestaand bestand was gevonden op de nieuwe locatie. Weet u zeker dat de database moet verwijzen naar een bestaand bestand?","An existing local database for the storage has been found.\nRe-using the database will allow the command-line and server instances to work on the same remote storage.\n\n Do you wish to use the existing database?":"Een bestaande lokale database voor de opslag is gevonden.\nHergebruik van de database zal toestaan dat de opdrachtregel- en server instances werken op dezelfde remote opslag.\n\nWilt u de bestaande database gebruiken?","Anonymous usage reports":"Anonieme gebruiksrapporten","As Command-line":"Als Opdrachtregel","AuthID":"AuthID","Authentication password":"Authenticatie wachtwoord","Authentication username":"Authenticatie gebruikersnaam","Autogenerated passphrase":"Automatisch gegenereerde wachtwoordzin","Automatically run backups.":"Automatisch back-ups uitvoeren","B2 Account ID":"B2 Account ID","B2 Application Key":"B2 Applicatiesleutel","B2 Cloud Storage Account ID":"B2 Cloud Storage Account ID","B2 Cloud Storage Application Key":"B2 Cloud Storage Applicatiesleutel","Back":"Vorige","Backend modules:":"Backend modules:","Backup destination":"Back-updoel","Backup location":"Back-up locatie","Backup retention":"Back-up retentie","Backup:":"Back-up:","Beta":"Beta","Broken access":"Verbroken toegang","Browse":"Bladeren","Browser default":"Browser standaard","Bucket Name":"Bucket Naam","Bucket create location":"Bucket aanmaaklocatie","Bucket create region":"Bucket aanmaakregio","Bucket name":"Bucketnaam","Bucket storage class":"Bucket opslagklasse","Building list of files to restore ...":"Lijst samenstellen met te herstellen bestanden ...","Building partial temporary database ...":"Gedeeltelijke tijdelijke database samenstellen ...","Busy ...":"Bezig ...","Canary":"Canary","Cancel":"Annuleren","Cannot move to existing file":"Kan niet verplaatsen naar bestaand bestand","Changelog":"Aanpassingen-log","Changelog for {{appname}} {{version}}":"Aanpassingen-log voor {{appname}} {{version}}","Check failed:":"Controle mislukt:","Check for updates now":"Controleer nu op updates","Checking ...":"Controleren ...","Checking for updates ...":"Controleren op updates ...","Chose a storage type to get started":"Kies een opslagtype om aan de slag te gaan","Click the AuthID link to create an AuthID":"Klik op de AuthID link om een AuthID aan te maken","Click to set throttle options":"Klik om bandbreedte-opties in te stellen","Commandline ...":"Opdrachtregel ...","Compact now":"Nu opruimen","Compacting remote data ...":"Opruimen van remote gegevens ...","Completing backup ...":"Back-up wordt voltooid ...","Completing previous backup ...":"Vorige back-up wordt voltooid ...","Compression modules:":"Compressiemodules:","Computer":"Computer","Configuration file:":"Configuratiebestand","Configuration:":"Configuratie:","Configure a new backup":"Een nieuwe back-up instellen","Confirm delete":"Bevestig verwijderen","Confirmation required":"Bevestiging vereist","Connect":"Verbind","Connect now":"Verbind nu","Connecting to server ...":"Verbinden met server ...","Connecting to task ....":"Verbinding maken met taak ...","Connecting...":"Verbinden...","Connection lost":"Verbinding verbroken","Connection worked!":"Verbinding werkt!","Container name":"Containernaam","Container region":"Container-regio","Continue":"Volgende","Continue without encryption":"Ga verder zonder versleuteling","Copied!":"Gekopieerd!","Copy":"Kopie","Copy Destination URL to Clipboard":"Kopieer doel URL naar Klembord","Copy failed. Please manually copy the URL":"Kopiëren mislukt. Kopieer de URL handmatig","Core options":"Kern-opties","Counting ({{files}} files found, {{size}})":"Tellen ({{files}} bestanden gevonden, {{size}})","Crashes only":"Alleen crashes","Create bug report ...":"Bug rapport maken ...","Create folder?":"Map aanmaken?","Created new limited user":"Nieuwe beperkte gebruiker aangemaakt","Creating bug report ...":"Bug rapport aanmaken ...","Creating new user with limited access ...":"Nieuwe gebruiker met beperkte toegang aanmaken ...","Creating target folders ...":"Doelmappen aanmaken ...","Creating temporary backup ...":"Tijdelijke back-up aanmaken ...","Creating user...":"Gebruiker aanmaken ...","Current version is {{versionname}} ({{versionnumber}})":"Huidige versie is {{versionname}} ({{versionnumber}})","Custom S3 endpoint":"Aangepaste S3 endpoint","Custom authentication url":"Aangepaste authenticatie url","Custom backup retention":"Aangepaste back-up retentie","Custom location ({{server}})":"Aangepaste locatie ({{server}})","Custom region for creating buckets":"Aangepaste regio voor het aanmaken van buckets","Custom region value ({{region}})":"Aangepaste regio waarde ({{region}})","Custom server url ({{server}})":"Aangepaste server url ({{server}})","Custom storage class ({{class}})":"Aangepaste opslagklasse ({{class}})","Database ...":"Database ...","Days":"Dagen","Default":"Standaard","Default ({{channelname}})":"Standaard ({{channelname}})","Default Filters":"Standaard Filters","Default options":"Standaard opties","Delete":"Verwijderen","Delete ...":"Verwijderen ...","Delete backup":"Verwijder back-up","Delete backups that are older than":"Verwijder back-ups die ouder zijn dan","Delete local database":"Verwijder lokale database","Delete remote files":"Verwijder remote bestanden","Delete the local database":"Verwijder de lokale database","Delete {{filecount}} files ({{filesize}}) from the remote storage?":"{{filecount}} bestanden ({{filesize}}) van de remote opslag verwijderen?","Deleting remote files ...":"Remote bestanden verwijderen ...","Deleting unwanted files ...":"Onnodige bestanden verwijderen ...","Desktop":"Desktop","Destination":"Doel","Did we help save your files? If so, please consider supporting Duplicati with a donation. We suggest {{smallamount}} for private use and {{largeamount}} for commercial use.":"Hebben we geholpen uw bestanden veilig te stellen? Overweeg in dat geval Duplicati te ondersteunen met een donatie. We raden {{smallamount}} aan voor persoonlijk gebruik en {{largeamount}} voor bedrijfsmatig gebruik.","Direct restore from backup files ...":"Rechtstreeks herstellen vanuit back-up bestanden ...","Disabled":"Uitgeschakeld","Dismiss":"Afwijzen","Display and color theme":"Weergave en kleurenschema","Do you really want to delete the backup: \"{{name}}\" ?":"Wilt u de back-up \"{{name}}\" echt verwijderen?","Do you really want to delete the local database for: {{name}}":"Wilt u de lokale database voor: {{name}} echt verwijderen?","Donate":"Doneren","Donation messages":"Doneer-berichten","Donation messages are hidden, click to show":"Doneer-berichten zijn verborgen, klik om ze weer te geven","Donation messages are visible, click to hide":"Doneer-berichten zijn zichtbaar, klik om ze te verbergen","Done":"Klaar","Download":"Download","Downloading ...":"Downloaden ...","Downloading files ...":"Bestanden downloaden ...","Downloading update...":"Update downloaden ...","Duplicate option {{opt}}":"Dupliceer optie {{opt}}","Duplicati Website":"Duplicati Website","Duplicati forum":"Duplicati forum","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\n When deleting a backup, you can also delete the local database without affecting the ability to restore the remote files.\n If you are using the local database for backups from the commandline, you should keep the database.":"Iedere back-up heeft een lokale database waarmee het geassocieerd is, die informatie opslaat over de remote back-up op de lokale machine.\nBij het verwijderen van een back-up kan eveneens de lokale database verwijderd worden, zonder dat dit invloed heeft op de mogelijkheid van het terugzetten van de remote bestanden.\nAls de lokale database gebruikt wordt voor back-ups vanaf de opdrachtregel, moet de database behouden blijven.","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\\nThis makes it faster to perform many operations, and reduces the amount of data that needs to be downloaded for each operation.":"Iedere back-up heeft een lokale database waarmee het geassocieerd is, die informatie opslaat over de remote back-up op de lokale machine.\nDit maakt het sneller bij het uitvoeren van veel bewerkingen, en reduceert de hoeveelheid gegevens die gedownload moeten worden voor iedere bewerking.","Edit ...":"Bewerken ...","Edit as list":"Bewerk als lijst","Edit as text":"Bewerk als tekst","Encrypt file":"Versleutel bestand","Encryption":"Versleuteling","Encryption changed":"Versleuteling aangepast","Encryption modules:":"Versleutelingsmodules:","Enter URL":"Geef URL in","Enter a retention strategy manually. Placeholders are D/W/Y for days/weeks/years. The syntax is: 7D:1D,4W:1W,36M:1M. This example keeps one backup for each of the next 7 days, one for each of the next 4 weeks, and one for each of the next 36 months. This can also be written as 1W:1D,1M:1W,3Y:1M.":"Geef handmatig een retentie-strategie op. Aanduidingen zijn D/W/Y voor dagen/weken/jaren. De syntaxis is: 7D:1D,4W:1W,36M:1M. Dit voorbeeld behoudt één back-up voor elk van de volgende 7 dagen, één voor elk van de volgende 4 weken, en één voor elk van de volgende 36 maanden. Dit kan ook geschreven worden als 1W:1D,1M:1W,3Y:1M.","Enter access key":"Geef toegangscode in","Enter account name":"Geef accountnaam in","Enter backup passphrase, if any":"Geef eventueel back-up wachtwoordzin in","Enter configuration details":"Voer configuratie-details in","Enter container name":"Geef containernaam in","Enter encryption passphrase":"Geef een wachtwoordzin in voor versleuteling","Enter expression here":"Geef uitdrukking hier in","Enter folder path name":"Geef padnaam van de map in","Enter one option per line in command-line format, eg. {0}":"Geef één optie per regel in opdracht-prompt indeling, bijvoorbeeld {0}","Enter the destination path":"Geef het doelpad in","Error":"Fout","Error!":"Fout!","Errors and crashes":"Fouten en crashes","Exclude":"Uitsluiten","Exclude directories whose names contain":"Sluit mappen uit waarvan de naam bevat:","Exclude expression":"Sluit uitdrukking uit","Exclude file":"Sluit bestand uit","Exclude file extension":"Sluit bestandsextensie uit","Exclude files whose names contain":"Sluit bestanden uit waarvan de naam bevat:","Exclude folder":"Sluit map uit","Exclude regular expression":"Sluit reguliere expressie uit","Existing file found":"Bestaand bestand gevonden","Experimental":"Experimenteel","Export":"Exporteer","Export ...":"Exporteren ...","Export backup configuration":"Exporteer back-upconfiguratie","Export configuration":"Exporteer configuratie","Exporting ...":"Exporteren ...","External link":"Externe link","FTP (Alternative)":"FTP (Alternatief)","Failed to build temporary database: {{message}}":"Opbouwen tijdelijke database mislukt: {{message}}","Failed to connect:":"Verbinden mislukt:","Failed to connect: {{message}}":"Verbinden mislukt: {{message}}","Failed to delete:":"Verwijderen mislukt:","Failed to fetch path information: {{message}}":"Ophalen pad-informatie mislukt: {{message}}","Failed to import:":"Importeren mislukt:","Failed to read backup defaults:":"Standaard instellingen voor back-up inlezen mislukt:","Failed to restore files: {{message}}":"Herstellen bestanden mislukt: {{message}}","Failed to save:":"Opslaan mislukt:","Fetching path information ...":"Ophalen pad-informatie ...","File":"Bestand","Files larger than:":"Bestanden groter dan:","Filters":"Filters","Finished!":"Klaar!","First run setup":"Instellen voor eerste gebruik","Folder":"Map","Folder path":"Map-pad","Fri":"Vrijdag","GByte":"GByte","GByte/s":"GByte/s","GCS Project ID":"GCS Project ID","General":"Algemeen","General backup settings":"Algemene back-upinstellingen","General options":"Algemene opties","Generate":"Genereer","Generate IAM access policy":"Genereer IAM toegangsbeleid","Getting file versions ...":"Bestandsversies ophalen ...","Hidden files":"Verborgen bestanden","Hide":"Verberg","Hide hidden folders":"Verberg verborgen bestanden","Home":"Start","Hours":"Uur","How do you want to handle existing files?":"Hoe wilt u omgaan met bestaande bestanden?","Hyper-V Machine":"Hyper-V Machine","Hyper-V Machine:":"Hyper-V Machine:","Hyper-V Machines":"Hyper-V Machines","ID:":"ID:","If a date was missed, the job will run as soon as possible.":"Als een geplande taak werd overgeslagen, zal de taak zo snel mogelijk na het geplande tijdstip starten.","If at least one newer backup is found, all backups older than this date are deleted.":"Als tenminste één nieuwere back-up is gevonden, zullen alle back-ups die ouder zijn dan deze datum worden verwijderd.","If the backup and the remote storage is out of sync, Duplicati will require that you perform a repair operation to synchronize the database.\\nIf the repair is unsuccesful, you can delete the local database and re-generate.":"Als de back-up en de remote opslag niet gesynchroniseerd zijn, zal Duplicati vereisen dat u een repareer-bewerking uitvoert om de database te synchroniseren.\nAls het repareren niet succesvol was, kunt u de lokale database verwijderen en opnieuw samenstellen.","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"Als het back-upbestand niet automatisch is gedownload, klik met rechts en kies "Opslaan als ..."","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"Als het back-upbestand niet automatisch is gedownload, klik met rechts en kies "Opslaan als ..."","If you do not enter a path, all files will be stored in the login folder.\nAre you sure this is what you want?":"Als u geen pad ingeeft, zullen alle bestanden opgeslagen worden in de login map.\nWeet u zeker dat dit is wat u wilt?","If you do not enter an API Key, the tenant name is required":"Als u geen API sleutel ingeeft, is een tenant naam vereist","If you want to use the backup later, you can export the configuration before deleting it":"Als u de back-up later wilt gebruiken, kunt u de configuratie exporteren alvorens hem te verwijderen","If your machine is in a multi-user environment (i.e. the machine has more than one account), you need to set a password to prevent other users from accessing data on your account.\nDo you want to set a password now?":"Als uw machine zich in een multi-user omgeving bevindt (bijvoorbeeld als op de machine met meer dan één account kan worden aangemeld), moet een wachtwoord worden ingesteld om te voorkomen dat andere gebruikers togang kunnen krijgen tot gegevens behorend bij uw account.\nWilt u nu een wachtwoord instellen?","Import":"Importeer","Import Destination URL":"Importeer Doel URL","Import backup configuration":"Importeer back-upconfiguratie","Import completed, but no certificates were found after the import":"Importeren voltooid, maar na het importeren zijn geen certificaten gevonden","Import failed":"Importeren mislukt","Import from a file":"Importeer vanuit een bestand","Import metadata":"Importeer metadata","Importing ...":"Importeren ...","Include a file?":"Een bestand opnemen?","Include expression":"Uitdrukking opnemen","Include regular expression":"Reguliere expressie opnemen","Incorrect answer, try again":"Incorrect antwoord, probeer opnieuw","Individual builds for developers only.":"Individuele builds alleen voor ontwikkelaars.","Information":"Informatie","Install":"Installeren","Install failed:":"Installeren mislukt","Invalid characters in path":"Ongeldige tekens in pad","Invalid retention time":"Ongeldige retentietijd","It is possible to connect to some FTP without a password.\nAre you sure your FTP server supports password-less logins?":"Het is mogelijk te verbinden met sommige FTP servers zonder een wachtwoord.\nWeet u zeker dat uw FTP server aanmelden zonder wachtwoord ondersteunt?","KByte":"KByte","KByte/s":"KByte/s","Keep a specific number of backups":"Behoud een specifiek aantal back-ups","Keep all backups":"Behoud alle back-ups","Language in user interface":"Taal in gebruikersinterface","Last month":"Vorige maand","Last successful run:":"Laatste succesvolle uitvoering:","Latest":"Laatste","Libraries":"Bibliotheken","Linux":"Linux","Listing backup dates ...":"Back-updata weergeven ...","Listing remote files ...":"Remote bestanden weergeven ...","Live":"Live","Load a configuration from an exported job or a storage provider":"Laad een configuratie vanuit een geëxporteerde taak of een opslagprovider","Load destination from an exported job or a storage provider":"Laad doel vanuit een geëxporteerde taak of een opslagprovider","Load older data":"Laad oudere gegevens","Loading ...":"Laden ...","Loading remote storage usage ...":"Laden van remote opslaggebruik ...","Local Repository":"Lokale Opslagplaats","Local database for":"Lokale database voor","Local database path:":"Lokaal database-pad:","Local repository":"Lokale opslagplaats","Local storage":"Lokale opslag","Location":"Locatie","Location where buckets are created":"Locatie waar buckets gemaakt worden","Log data for {{Backup.Backup.Name}}":"Log gegevens voor {{Backup.Backup.Name}}","Log data from the server":"Log gegevens van de server","Log out":"Uitloggen","MByte":"MByte","MByte/s":"MByte/s","Maintenance":"Onderhoud","Manually type path":"Voer pad handmatig in","Max download speed":"Max downloadsnelheid","Max upload speed":"Max Uploadsnelheid","Menu":"Menu","Microsoft SQL Database:":"Microsoft SQL Database","Microsoft SQL Databases":"Microsoft SQL Databases","Minimum redundancy":"Minimale redundantie","Minimum redundancy is 1.0":"Minimale redundantie is 1.0","Minutes":"Minuten","Missing name":"Ontbrekende naam","Missing passphrase":"Ontbrekende wachtwoordzin","Missing sources":"Ontbrekende bronnen","Mon":"Maandag","Months":"Maanden","Move existing database":"Verplaats bestaande database","Move failed:":"Verplaatsen mislukt:","My Documents":"Mijn Documenten","My Music":"Mijn Muziek","My Photos":"Mijn Foto's","My Pictures":"Mijn Afbeeldingen","Name":"Naam","Never":"Nooit","New update found: {{message}}":"Nieuwe update gevonden: {{message}}","New user name is {{user}}.\nUpdated credentials to use the new limited user":"Nieuwe gebruikersnaam is {{user}}.\nGebruikersreferenties bijgewerkt om de nieuwe beperkte gebruiker te gebruiken","Next":"Volgende","Next scheduled run:":"Volgende geplande uitvoering:","Next scheduled task:":"Volgende geplande taak:","Next task:":"Volgende taak:","Next time":"Volgende keer","No":"Nee","No certificate was specified previously, please verify with the server administrator that the key is correct: {{key}} \n\nDo you want to approve the reported host key?":"Er is eerder geen certificaat opgegeven, controleer svp met de serverbeheerder of de sleutel correct is: {{key}}\n\nWilt u de gerapporteerde host-sleutel goedkeuren?","No editor found for the "{{backend}}" storage type":"Geen bewerkingsprogramma gevonden voor het "{{backend}}" opslagtype","No encryption":"Geen versleuteling","No items selected":"Geen items geselecteerd","No items to restore, please select one or more items":"Geen items om te herstellen, selecteer één of meer items","No passphrase entered":"Geen wachtwoordzin ingegeven","No scheduled tasks":"Geen geplande taken","No, my machine has only a single account":"Nee, mijn machine heeft slechts een enkele account","Non-matching passphrase":"Niet-bijbehorende wachtwoordzin","None / disabled":"Geen / uitgeschakeld","Nothing will be deleted. The backup size will grow with each change.":"Er zal niets verwijderd worden. De back-upgrootte zal toenemen met iedere verandering.","OK":"OK","OSX":"OSX","Once there are more backups than the specified number, the oldest backups are deleted.":"Zodra er meer back-ups zijn dan het opgegeven aantal, zullen de oudste back-ups worden verwijderd.","OpenStack AuthURI":"OpenStack AuthURI","OpenStack Object Storage / Swift":"OpenStack Object Storage / Swift","Operation failed:":"Bewerking mislukt:","Operations:":"Bewerkingen:","Optional authentication password":"Optioneel authenticatie wachtwoord","Optional authentication username":"Optionele authenticatie gebruikersnaam","Options":"Opties","Options added here are applied to all backups, but can be overridden in each individual backup":"Opties die hier worden toegevoegd, worden toegepast op alle back-ups, maar kunnen worden overschreven in iedere afzonderlijke back-up","Original location":"Originele locatie","Others":"Anderen","Over time backups will be deleted automatically. There will remain one backup for each of the last 7 days, each of the last 4 weeks, each of the last 12 months. There will always be at least one remaining backup.":"Na verloop van tijd zullen back-ups automatisch verwijderd worden. Er zal één back-up overblijven voor elk van de laatste 7 dagen, voor elk van de laatste 4 weken, en voor elk van de laatste 12 maanden. Er zal altijd tenminste één back-up overblijven.","Overwrite":"Overschrijven","Passphrase":"Wachtwoordzin","Passphrase (if encrypted)":"Wachtwoordzin (indien versleuteld)","Passphrase changed":"Wachtwoordzin veranderd","Passphrases are not matching":"Wachtwoordzinnen komen niet overeen","Password":"Wachtwoord","Passwords do not match":"Wachtwoorden komen niet overeen","Patching files with local blocks ...":"Bestanden bijwerken met lokale blokken ...","Path not found":"Pad niet gevonden","Path on server":"Pad op server","Path or subfolder in the bucket":"Pad of submap in de bucket","Pause":"Pauze","Pause after startup or hibernation":"Pauzeer na opstarten of slaapmodus","Pause options":"Pauzeer-opties","Permissions":"Permissies","Pick location":"Kies locatie","Point to your backup files and restore from there":"Verwijs naar de back-up bestanden en herstel daar vandaan","Port":"Poort","Previous":"Vorige","ProjectID is optional if the bucket exist":"ProjectID is optioneel als de bucket bestaat","Proprietary":"Fabrikantgebonden","Purging files ...":"Bestanden wissen ...","Rebuilding local database ...":"Opnieuw opbouwen van lokale database ...","Recreate (delete and repair)":"Opnieuw aanmaken (verwijderen en repareren)","Recreating database ...":"Opnieuw opbouwen van de database ...","Registering temporary backup ...":"Registreren tijdelijke back-up ...","Relative paths not allowed":"Relatieve paden zijn niet toegestaan","Reload":"Andere code","Remote":"Remote","Remote Path":"Remote Pad","Remote Repository":"Remote Opslagplaats","Remote path":"Remote pad","Remote repository":"Remote opslagplaats","Remove":"Verwijderen","Remove option":"Verwijder optie","Repair":"Repareer","Reparing ...":"Repareren ...","Repeat Passphrase":"Herhaal wachtwoordzin","Reporting:":"Rapportage:","Reset":"Reset","Restore":"Herstellen","Restore files":"Herstel bestanden","Restore files ...":"Bestanden herstellen ...","Restore files from {{backupname}}":"Herstel bestanden vanuit {{backupname}}","Restore from":"Herstellen vanaf","Restore from backup configuration":"Herstel vanuit back-up configuratie","Restore from configuration ...":"Herstel vanuit configuratie...","Restore options":"Herstelopties","Restore read/write permissions":"Herstel lees/schrijfpermissies","Restoring files ...":"Bestanden worden hersteld ...","Resume":"Hervat","Run again every":"Voer opnieuw uit iedere","Run now":"Nu uitvoeren","Running ...":"In uitvoering ...","Running ....":"Uitvoeren ...","Running commandline entry":"Opdrachtregelinvoer in uitvoering","Running task:":"Taak in uitvoering:","S3 Compatible":"S3 Compatible","Same as the base install version: {{channelname}}":"Zelfde als de basis installatie versie: {{channelname}}","Sat":"Zaterdag","Save":"Opslaan","Save and repair":"Opslaan en repareren","Save different versions with timestamp in file name":"Sla verschillende versies op met tijdstempel in de bestandsnaam","Save immediately":"Onmiddellijk opslaan","Scanning existing files ...":"Scannen bestaande bestanden ...","Scanning for local blocks ...":"Scannen op lokale blokken ...","Schedule":"Planning","Search":"Zoek","Search for files":"Zoek bestanden","Seconds":"Seconden","Select a log level and see messages as they happen:":"Selecteer een logniveau en bekijk meldingen zodra ze zich voordoen:","Select files":"Selecteer bestanden","Server":"Server","Server and port":"Server en poort","Server hostname or IP":"Server hostnaam of IP","Server is currently paused,":"Server is momenteel gepauzeerd,","Server is currently paused, do you want to resume now?":"Server is momenteel gepauzeerd, wilt u nu hervatten?","Server password":"Server wachtwoord","Server paused":"Server gepauzeerd","Server state properties":"Server status eigenschappen","Settings":"Instellingen","Show":"Tonen","Show advanced editor":"Toon geavanceerde editor","Show hidden folders":"Toon verborgen mappen","Show log":"Log weergeven","Show log ...":"Log weergeven ...","Show treeview":"Toon boomstructuur","Sia server password":"Sia server wachtwoord","Smart backup retention":"Slimme back-up retentie","Some OpenStack providers allow an API key instead of a password and tenant name":"Sommige OpenStack providers staan een API key toe in plaats van een wachtwoord en tenant naam","Source Data":"Bron","Source data":"Brongegevens","Source folders":"Bronmappen","Source:":"Bron:","Specific builds for developers only.":"Specifieke builds alleen voor ontwikkelaars.","Standard protocols":"Standaard protocollen","Starting ...":"Starten ...","Starting the restore process ...":"Starten van het herstelproces ...","Stop after the current file":"Stop na het huidige bestand","Stop after upload":"Stop na de upload","Stop now":"Nu stoppen","Stop running backup":"Stop de back-up in uitvoering","Stop running task":"Stop de taak in uitvoering","Stopping after upload:":"Stop na de upload:","Stopping task:":"Taak wordt gestopt:","Storage Type":"Opslagtype","Storage class":"Opslagklasse","Storage class for creating a bucket":"Opslagklasse voor het aanmaken van een bucket","Stored":"Opgeslagen","Strong":"Sterk","Success":"Succes","Sun":"Zondag","Symbolic link":"Symbolische link","System default ({{levelname}})":"Systeem standaard ({{levelname}})","System files":"Systeembestanden","System info":"Systeeminformatie","System properties":"Systeemeigenschappen","TByte":"TByte","TByte/s":"TByte/s","Target path, ie /backup":"Doelpad, bijvoorbeeld /backup","Task is running":"Taak is in uitvoering","Temporary files":"Tijdelijke bestanden","Tenant Name":"Tenant naam","Test connection":"Test verbinding","Testing ...":"Testen ...","Testing connection ...":"Testen van de verbinding ...","Testing permissions ...":"Testen van de permissies ...","Testing permissions...":"Testen van de permissies ...","The bucket name should be all lower-case, convert automatically?":"De bucket-naam hoort in kleine letters te zijn, automatisch converteren?","The bucket name should start with your username, prepend automatically?":"De bucket naam hoort te beginnen met uw gebruikersnaam, automatisch voorvoegen?","The connection to the server is lost, attempting again in {{time}} ...":"De verbinding met de server is verbroken, opnieuw proberen over {{time}} ...","The dark theme (by Michal)":"Het donkere thema (door Michal)","The default blue on white theme (by Alex)":"Het standaard blauw op wit thema (door Alex)","The folder {{folder}} does not exist.\nCreate it now?":"De map {{folder}} bestaat niet.\nNu aanmaken?","The host key has changed, please check with the server administrator if this is correct, otherwise you could be the victim of a MAN-IN-THE-MIDDLE attack.\n\nDo you want to REPLACE your CURRENT host key \"{{prev}}\" with the REPORTED host key: {{key}}?":"De host sleutel is veranderd, controleer met uw server beheerder of dit correct is, in het andere geval zou u het slachtoffer kunnen zijn van een MAN-IN-THE-MIDDLE aanval.\n\nWilt u de HUIDIGE host sleutel \"{prev}\" VERVANGEN door de GERAPPORTEERDE host sleutel: {{key}}?","The path does not appear to exist, do you want to add it anyway?":"Het pad lijkt niet te bestaan, wilt u het desondanks toevoegen?","The path does not end with a '{{dirsep}}' character, which means that you include a file, not a folder.\n\nDo you want to include the specified file?":"Het pad eindigt niet met een '{{dirsep}}' teken, wat betekent dat u een bestand opneemt, niet een map.\n\nWilt u het aangegeven bestand opnemen?","The path must be an absolute path, i.e. it must start with a forward slash '/'":"Het pad moet een absoluut pad zijn, bijvoorbeeld het moet beginnen met een forward slash '/'","The path should start with \"{{prefix1}}\" or \"{{prefix2}}\", otherwise you will not be able to see the files in the HubiC web interface.\n\nDo you want to add the prefix to the path automatically?":"Het pad moet beginnen met \"{{prefix1}}\" of \"{{prefix2}}\", anders zullen bestanden in de HubiC web interface niet zichtbaar zijn.","The region parameter is only applied when creating a new bucket":"De regio parameter wordt alleen toegepast bij het aanmaken van een bucket","The region parameter is only used when creating a bucket":"De regio parameter wordt alleen gebruikt bij het aanmaken van een bucket","The server certificate could not be validated.\nDo you want to approve the SSL certificate with the hash: {{hash}}?":"Het servercertificaat kon niet gevalideerd worden.\nWilt u het certificaat goedkeuren met deze hash: {{hash}}?","The storage class affects the availability and price for a stored file":"De opslagklasse beïnvloedt de beschikbaarheid en prijs van een opgeslagen bestand","The target folder contains encrypted files, please supply the passphrase":"De doelmap bevat versleutelde bestanden, geef alstublieft de wachtwoordzin","The user has too many permissions. Do you want to create a new limited user, with only permissions to the selected path?":"De gebruiker heeft teveel permmissies. Wilt u een nieuwe beperkte gebruiker aanmaken, met enkel permissies tot het aangegeven pad?","This backup was created on another operating system. Restoring files without specifying a destination folder can cause files to be restored in unexpected places. Are you sure you want to continue without choosing a destination folder?":"De back-up werd aangemaakt op een ander besturingssysteem. Bestanden terugzetten zonder een doelmap op te geven kan tot gevolg hebben dat bestanden worden teruggezet naar onverwachte plaatsen. Bent u er zeker van dat u wilt doorgaan zonder een doelmap te kiezen?","This month":"Afgelopen maand","This week":"Afgelopen week","Throttle settings":"Bandbreedte-instellingen","Thu":"Donderdag","To File":"Naar Bestand","To confirm you want to delete all remote files for \"{{name}}\", please enter the word you see below":"Om te bevestigen dat u alle remote bestanden wilt verwijderen voor \"{{name}}\", geef svp het woord in dat u hieronder ziet","To export without a passphrase, uncheck the \"Encrypt file\" box":"Om te exporteren zonder een wachtwoordzin, deselecteer het \"Versleutel bestand\" vakje","Today":"Vandaag","Trust host certificate?":"Vertrouw host certificaat?","Trust server certificate?":"Vertrouw server certificaat?","Try out the new features we are working on. Don't use with important data.":"Probeer nieuwe mogelijkheden uit waar we aan werken. Niet gebruiken met belangrijke gegevens.","Tue":"Dinsdag","Type to highlight files":"Typ om bestanden uit te lichten","Unknown backup size and versions":"Onbekende back-up grootte en versies","Until resumed":"Tot hervatting","Update channel":"Updatekanaal","Update failed:":"Update mislukt:","Updating with existing database":"Updaten met bestaande database","Upload volume size":"Upload volumegrootte","Uploading verification file ...":"Uploaden controlebestand ...","Usage reports help us improve the user experience and evaluate impact of new features. We use them to generate public usage statistics":"Gebruiksrapporten helpen ons de gebruikerservaring te verbeteren en de impact van nieuwe mogelijkheden te evalueren. We gebruiken ze omopenbare gebruikstatistieken te genereren. ","Usage statistics":"Gebruikstatistieken","Usage statistics, warnings, errors, and crashes":"Gebruikstatistieken, waarschuwingen, fouten en crashes","Use SSL":"Gebruik SSL","Use existing database?":"Gebruik bestaande database?","Use weak passphrase":"Gebruik zwakke wachtwoordzin","Useless":"Waardeloos","User data":"Gebruikersgegevens","User has too many permissions":"Gebruiker heeft teveel permissies","User interface settings":"Gebruikersinterface instellingen","Username":"Gebruikersnaam","Validating ...":"Valideren ...","Verify files":"Bestanden controleren","Verifying ...":"Controleren ...","Verifying answer":"Antwoord controleren","Verifying backend data ...":"Controleren van backend gegevens ...","Verifying remote data ...":"Controleren van remote gegevens ...","Verifying restored files ...":"Controleren van herstelde bestanden ...","Very strong":"Erg sterk","Very weak":"Erg zwak","Visit us on":"Bezoek ons op","WARNING: The remote database is found to be in use by the commandline library":"WAARSCHUWING: De remote database blijkt in gebruik te zijn door de opdrachtregel bibliotheek","WARNING: This will prevent you from restoring the data in the future.":"WAARSCHUWING: Dit zal het onmogelijk maken om in de toekomst bestanden te herstellen.","Waiting for task to begin":"Wachten op het starten van de taak","Waiting for task to start ....":"Wachten op het starten van de taak ...","Waiting for upload ...":"Wachten op upload ...","Warnings, errors and crashes":"Waarschuwingen, fouten en crashes","We accept donations via different services, such as OpenCollective, PayPal, BountySource and various crypto currencies.":"We accepteren donaties via verschillende services, zoals OpenCollective, PayPal, BountySource en diverse crypto-valuta.","We recommend that you encrypt all backups stored outside your system":"We raden aan dat u alle back-ups die buiten uw systeem worden opgeslagen versleutelt","Weak":"Zwak","Weak passphrase":"Zwakke wachtwoordzin","Wed":"Woensdag","Weeks":"Weken","Where do you want to restore from?":"Waar vandaan wilt u herstellen?","Where do you want to restore the files to?":"Waarheen wilt u de bestanden herstellen?","Windows":"Windows","Years":"Jaren","Yes":"Ja","Yes, I have stored the passphrase safely":"Ja, ik heb de wachtwoordzin op een veilige plaats opgeborgen","Yes, I'm brave!":"Ja, ik ben dapper!","Yes, please break my backup!":"Ja, help mijn back-up om zeep!","Yesterday":"Gisteren","You appear to be running Mono with no SSL certificates loaded.\nDo you want to import the list of trusted certificates from Mozilla?":"Het lijkt er op dat u Mono gebruikt zonder dat SSL certificaten geladen zijn.\nWilt u de lijst met vertrouwde certificaten importeren van Mozilla?","You are changing the database path away from an existing database.\nAre you sure this is what you want?":"U verandert het database pad weg van een bestaande database.\nWeet u zeker dat dit is wat u wilt?","You are currently running {{appname}} {{version}}":"U werkt momenteel met {{appname}} {{version}}","You can stop the backup immediately, or stop after the current file has been uploaded.":"De back-up kan onmiddellijk worden gestopt, of stoppen nadat het huidige bestand is geüpload.","You can stop the task immediately, or allow the process to continue its current file and the stop.":"De taak kan onmiddellijk worden gestopt, of het proces toestaan om door te gaan met het huidige bestand en dan stoppen.","You have changed the encryption mode. This may break stuff. You are encouraged to create a new backup instead":"U hebt de versleutelingsmodus veranderd. Dit kan dingen kapotmaken. U wordt daarom aangemoedigd een nieuwe back-up aan te maken","You have changed the passphrase, which is not supported. You are encouraged to create a new backup instead.":"U hebt de wachtwoordzin aangepast, wat niet wordt ondersteund. U wordt daarom aangemoedigd een nieuwe back-up aan te maken.","You have chosen not to encrypt the backup. Encryption is recommended for all data stored on a remote server.":"U hebt ervoor gekozen de back-up niet te versleutelen. Encryptie is aanbevolen voor alle gegevens die worden opgeslagen op een remote server.","You have chosen to restore to a new location, but not entered one":"U koos voor terugzetten naar een nieuwe locatie, maar hebt geen locatie opgegeven","You have generated a strong passphrase. Make sure you have made a safe copy of the passphrase, as the data cannot be recovered if you lose the passphrase.":"U hebt een sterke wachtwoordzin gegenereerd. Verzeker u ervan dat u een veilige kopie heeft van de wachtwoordzin, omdat de gegevens niet hersteld kunnen worden als u de wachtwoordzin verliest.","You must choose at least one source folder":"U moet tenminste één bronmap kiezen","You must enter a name for the backup":"U moet een naam ingeven voor de back-up","You must enter a passphrase or disable encryption":"U moet een wachtwoordzin ingeven of versleuteling uitschakelen","You must enter a positive number of backups to keep":"U moet een positief getal opgeven voor de hoeveelheid te bewaren back-ups","You must enter a tenant name if you do not provide an API Key":"U moet een tenant naam ingeven als u de API sleutel niet verstrekt","You must enter a valid duration for the time to keep backups":"U moet een geldige tijdsduur ingeven voor de tijd dat back-ups bewaard moeten worden","You must enter a valid rentention policy string":"Er moet een geldige tekenreeks voor retentiebeleid worden opgegeven","You must enter either a password or an API Key":"U moet òf een wachtwoord, òf een API sleutel ingeven","You must enter either a password or an API Key, not both":"U moet òf een wachtwoord, òf een API sleutel ingeven, niet beide","You must fill in the password":"U moet het wachtwoord invullen","You must fill in the server name or address":"U moet de servernaam of -adres invullen","You must fill in the username":"U moet de gebruikersnaam invullen","You must fill in {{field}}":"U moet {{field}} invullen","You must select or fill in the AuthURI":"U moet de AuthURI selecteren of invullen","You must select or fill in the server":"U moet de server selecteren of invullen","You must specify a path":"U moet een pad opgeven","Your files and folders have been restored successfully.":"Uw bestanden en mappen zijn succesvol hersteld","Your passphrase is easy to guess. Consider changing passphrase.":"Uw wachtwoordzin is eenvoudig te raden. Overweeg de wachtwoordzin te veranderen.","bucket/folder/subfolder":"bucket/map/submap","byte":"byte","byte/s":"byte/s","custom":"aangepast","resume now":"nu hervatten","{{appname}} was primarily developed by {{dev1}} and {{dev2}}. {{appname}} can be downloaded from {{websitename}}. {{appname}} is licensed under the {{licensename}}.":"{{appname}} werd in eerste instantie ontwikkeld door {{dev1}} en {{dev2}}. {{appname}} kan gedownload worden van {{websitename}}. {{appname}} is gelicenseerd onder de {{licensename}}.","{{files}} files ({{size}}) to go {{speed_txt}}":"{{files}} bestanden ({{size}}) te gaan {{speed_txt}}","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Version":["{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Versie","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Versies"],"{{number}} Hour":"{{number}} Uur","{{number}} Minutes":"{{number}} Minuten","{{time}} (took {{duration}})":"{{time}} (duurde {{duration}})"}); gettextCatalog.setStrings('pl', {"- pick an option -":"- wybierz opcję -","...loading...":"...ładowanie...","API Key":"Klucz API","AWS Access ID":"Identyfikator dostępu AWS","AWS Access Key":"Klucz dostepu AWS","AWS IAM Policy":"Polisa AWS IAM","About":"O programie","About {{appname}}":"O programie {{appname}}","Access Key":"Klucz dostępu","Access denied":"Dostęp zabroniony","Access to user interface":"Dostęp do interface użytkownika","Account name":"Nazwa konta","Activate":"Aktywuj","Activate failed:":"Niepowodzenie aktywacji:","Add a new backup":"Dodaj nową kopię","Add a path directly":"Dodaj ścieżkę bezpośrednio","Add advanced option":"Dodaj opcję zaawansowaną","Add backup":"Dodaj kopię","Add filter":"Dodaj filtr","Add path":"Dodaj ścieżkę","Adjust bucket name?":"Poprawić nazwę zasobnika?","Adjust path name?":"Poprawić nazwę ścieżki?","Advanced Options":"Opcje Zaawansowane","Advanced options":"Opcje zaawansowane","Advanced:":"Zaawansowane:","All":"Wszystko","All Hyper-V Machines":"Wszystkie Maszyny Hyper-V","All Microsoft SQL Databases":"Wszystkie Bazy Danych Microsoft SQL","All usage reports are sent anonymously and do not contain any personal information. They contain information about hardware and operating system, the type of backend, backup duration, overall size of source data and similar data. They do not contain paths, filenames, usernames, passwords or similar sensitive information.":"Wszystkie raporty użycia są wysyłane anonimowo i nie zawierają żadnych danych osobistych. Raporty zawierają informacje o sprzęcie i systemie operacyjnym, rodzaju kopii zapasowej, czasie trwania, ogólnej ilości danych źródłowych i tym podobne. Raporty nie zawierają ścieżek, nazw plików, nazw użytkowników, haseł i tym podobnych danych wrażliwych.","Allow remote access (requires restart)":"Zezwalaj na dostęp zdalny (wymaga restartu)","Allowed days":"Dozwolone dni","An existing file was found at the new location":"Znaleziono istniejący plik w nowym położeniu","An existing file was found at the new location\nAre you sure you want the database to point to an existing file?":"Istniejący plik został znaleziony w nowej lokalizacji\nCzy na pewno chcesz skierować bazę danych do istniejącego pliku?","An existing local database for the storage has been found.\nRe-using the database will allow the command-line and server instances to work on the same remote storage.\n\n Do you wish to use the existing database?":"Znaleziono istniejącą, lokalną bazę danych dla magazynu.\nPonowne użycie tej bazy pozwoli pracować instancji wiersza poleceń oraz serwerowej z tym samym zdalnym magazynem.\n\nCzy chcesz użyć istniejącej bazy danych?","Anonymous usage reports":"Anonimowy raport użycia","As Command-line":"Jako Linia poleceń","AuthID":"AuthID","Authentication password":"Hasło uwierzytenienia","Authentication username":"Nazwa uwierzytelnienia","Autogenerated passphrase":"Automatycznie wygenerowane długie hasło","Automatically run backups.":"Automatycznie uruchamiaj kopie.","B2 Account ID":"ID Konta B2","B2 Application Key":"Klucz Aplikacji B2","B2 Cloud Storage Account ID":"B2 Cloud Storage Account ID","B2 Cloud Storage Application Key":"B2 Cloud Storage Application Key","Back":"Wstecz","Backend modules:":"Moduły zaplecza:","Backup destination":"Miejsce docelowe kopii","Backup location":"Lokalizacja kopii","Backup:":"Kopia:","Beta":"Beta","Broken access":"Przerwany dostęp","Browse":"Przeglądaj","Browser default":"Domyślna przeglądarka","Bucket Name":"Nazwa Zasobnika","Bucket create location":"Miejsce tworzenia zasobnika","Bucket create region":"Region tworzenia zasobnika","Bucket name":"Nazwa zasobnika","Bucket storage class":"Klasa przechowywania zasobnika","Building list of files to restore ...":"Tworzenie listy plików do odzyskania ...","Building partial temporary database ...":"Tworzenie tymczasowej częściowej bazy danych ...","Busy ...":"Zajęty ...","Canary":"Robocze","Cancel":"Anuluj","Cannot move to existing file":"Nie można przenieść do istniejącego plku","Changelog":"Lista zmian","Changelog for {{appname}} {{version}}":"Lista zmian dla {{appname}} {{version}}","Check failed:":"Sprawdzenie nieudane:","Check for updates now":"Sprawdź uaktualnienia ","Checking ...":"Sprawdzanie...","Checking for updates ...":"Sprawdzanie uaktualnień ...","Chose a storage type to get started":"Wybierz typ magazynu by rozpocząć","Click the AuthID link to create an AuthID":"Kliknij link AuthID by utworzyć AuthID","Click to set throttle options":"Kliknij, aby ustawić limity prędkości","Commandline ...":"Linia poleceń ...","Compact now":"Kompaktuj teraz","Compacting remote data ...":"Kompaktowanie zdalnych danych","Completing backup ...":"Kończenie kopii...","Completing previous backup ...":"Kończenie poprzedniej kopii...","Compression modules:":"Moduły kompresji:","Computer":"Komputer","Configuration file:":"Plik konfiguracyjny:","Configuration:":"Konfiguracja:","Configure a new backup":"Skonfiguruj nową kopię","Confirm delete":"Potwierdź usunięcie","Confirmation required":"Potwierdzenie wymagane","Connect":"Połącz","Connect now":"Połącz teraz","Connecting to server ...":"Łączenie z serwerem ...","Connecting to task ....":"Łączenie z zadaniem ...","Connecting...":"Łączenie ...","Connection lost":"Utracono połączenie","Connection worked!":"Połączenie działa!","Container name":"Nazwa zasobnika","Container region":"Region zasobnika","Continue":"Kontynuuj","Continue without encryption":"Kontynuuj bez szyfrowania","Copied!":"Skopiowane!","Copy Destination URL to Clipboard":"Kopiuj Docelowy URL do Schowka","Copy failed. Please manually copy the URL":"Niepowodzenie kopiowania. Proszę skopiować URL ręcznie","Core options":"Opcje podstawowe","Counting ({{files}} files found, {{size}})":"Liczenie ({{files}} znaleziono plików, {{size}})","Crashes only":"Tylko awarie","Create bug report ...":"Tworzenie raportu błędów ...","Create folder?":"Utworzyć folder","Created new limited user":"Utwórz nowego użytkownika z ograniczeniami","Creating bug report ...":"Tworzenie raportu błędów ...","Creating new user with limited access ...":"Tworzenie nowego użytkownika z ograniczeniami ...","Creating target folders ...":"Tworzenie folderów docelowych ...","Creating temporary backup ...":"Tworzenie kopii tymczasowej ...","Creating user...":"Tworzenie użytkownika ...","Current version is {{versionname}} ({{versionnumber}})":"Bieżąca wersja to {{versionname}} ({{versionnumber}})","Custom S3 endpoint":"Niestandardowy węzeł końcowy S3","Custom authentication url":"Niestandardowy URL uwierzytelniania","Custom location ({{server}})":"Niestandardowa lokalizacja ({{serwer}})","Custom region for creating buckets":"Niestandardowy region do tworzenia zasobników","Custom region value ({{region}})":"Niestandardowa wartość regionu ({{region}})","Custom server url ({{server}})":"Niestandardowy adres url serwera ({{serwer}})","Custom storage class ({{class}})":"Niestandardowa klasa magazynu ({{Klasa}})","Database ...":"Baza danych ...","Days":"Dni","Default":"Domyślny","Default ({{channelname}})":"Domyślny ({{channelname}})","Default Filters":"Filtry domyślne","Default options":"Opcje domyślne","Delete":"Usuń","Delete ...":"Usuń ...","Delete backup":"Usuń kopię","Delete local database":"Usuń lokalną bazę danych","Delete remote files":"Usuń zdalne pliki","Delete the local database":"Usuń lokalną bazę danych","Delete {{filecount}} files ({{filesize}}) from the remote storage?":"Usunąć {{filecount}} plików ({{filesize}}) ze zdalnego magazynu?","Deleting remote files ...":"Usuwanie zdalnych plików ...","Deleting unwanted files ...":"Usuwanie niepotrzebnych plików","Desktop":"Pulpit","Destination":"Lokalizacja docelowa","Did we help save your files? If so, please consider supporting Duplicati with a donation. We suggest {{smallamount}} for private use and {{largeamount}} for commercial use.":"Czy pomogliśmy zabezpieczyć Twoje pliki? Jeśli tal, to rozważ proszę wsparcie programu Duplicati dotacją w wysokości {{smallamount}} dla użytku prywatnego i {{largeamount}} - dla użytku firmowego.","Direct restore from backup files ...":"Odtwórz bezpośrednio z plików kopii ...","Disabled":"Wyłączone","Dismiss":"Ukryj","Display and color theme":"Schemat ekranu i kolorystyki","Do you really want to delete the backup: \"{{name}}\" ?":"Naprawdę chcesz usunąć kopię: \"{{name}}\" ?","Do you really want to delete the local database for: {{name}}":"Czy naprawdę chcesz usunąć lokalna bazę danych: {{name}}","Donate":"Wesprzyj","Donation messages":"Komunikaty o wsparcie","Donation messages are hidden, click to show":"Komunikaty o wsparcie są ukryte, kliknij by przywrócić","Donation messages are visible, click to hide":"Komunikaty o wsparcie są widoczne kliknij by ukryć","Done":"Wykonane","Download":"Pobranie","Downloading ...":"Pobieranie ...","Downloading files ...":"Pobieranie plików ...","Downloading update...":"Pobieranie uaktualnienia ...","Duplicate option {{opt}}":"Powielenie opcji {{opt}}","Duplicati Website":"Strona Duplicati","Duplicati forum":"Forum Duplicati","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\n When deleting a backup, you can also delete the local database without affecting the ability to restore the remote files.\n If you are using the local database for backups from the commandline, you should keep the database.":"Każdy skonfigurowany backup posiada powiązaną z nim lokalną bazę danych, w której przechowuje na komputerze lokalnym informacje o zdalnej kopii zapasowej.\rKiedy konfiguracja backup'u jest usuwana, można również usunąć lokalną bazę danych bez wpływu na możliwość odtworzenia plików zdalnych.\rJeśli używasz lokalnej bazy danych do kopii zapasowych z wiersza poleceń, należy zachować bazę danych.","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\\nThis makes it faster to perform many operations, and reduces the amount of data that needs to be downloaded for each operation.":"Każda kopia zapasowa ma powiązaną z nią lokalną bazę danych, w której na lokalnym komputerze przechowywane są informacje o zdalnej kopii zapasowej. \\nTo sprawia, że można szybciej wykonywać wiele operacji i zmniejsza ilość danych, które muszą być pobrane dla każdej operacji.","Edit ...":"Edycja ...","Edit as list":"Edytuj jako listę","Edit as text":"Edytuj jako tekst","Encrypt file":"Zaszyfruj plik","Encryption":"Szyfrowanie","Encryption changed":"Szyfrowanie zmienione","Encryption modules:":"Moduły szyfrujące:","Enter URL":"Podaj URL","Enter access key":"Podaj klucz dostępu","Enter account name":"Podaj nazwę konta","Enter backup passphrase, if any":"Podaj długie hasło, jeśli jest","Enter configuration details":"Wprowadź szczegóły konfiguracji","Enter container name":"Podaj nazwę zasobnika","Enter encryption passphrase":"Podaj długie hasło szyfrowania","Enter expression here":"Tutaj wprowadź wyrażenie","Enter folder path name":"Wprowadź nazwę ścieżki dostępu","Enter one option per line in command-line format, eg. {0}":"Wprowadź po jednej opcji w wierszu w formacie wiersza poleceń, np. \n{0}","Enter the destination path":"Wprowadź ścieżkę docelową","Error":"Błąd","Error!":"Błąd!","Errors and crashes":"Błędy i awarie","Exclude":"Wyłącz","Exclude directories whose names contain":"Wyłącz katalogi z nazwą zawierającą","Exclude expression":"Wyłącz wyrażenie","Exclude file":"Wyłącz plik","Exclude file extension":"Wyłącz rozszerzenie pliku","Exclude files whose names contain":"Wyłącz pliki z nazwą zawierającą","Exclude folder":"Wyłącz folder","Exclude regular expression":"Wyłącz wyrażenie regularne","Existing file found":"Znaleziono istniejący plik","Experimental":"Eksperymentalne","Export":"Eksport","Export ...":"Eksportowanie ...","Export backup configuration":"Eksportuj konfigurację kopii","Export configuration":"Eksportuj konfigurację","Exporting ...":"Eksportowanie ...","FTP (Alternative)":"FTP (Alternatywny)","Failed to build temporary database: {{message}}":"Nie udało się utworzyć tymczasowej bazy danych: {{message}}","Failed to connect:":"Nie udało się połączyć:","Failed to connect: {{message}}":"Nie udało się połączyć: {{message}}","Failed to delete:":"Nie udało się usunąć:","Failed to fetch path information: {{message}}":"Nie udało się pobrać informacji o ścieżce: {{message}}","Failed to import:":"Nie udało się zaimportować:","Failed to read backup defaults:":"Nie udało się odczytać domyślnych danych kopii:","Failed to restore files: {{message}}":"Nie udało się odtworzyć plików: {{message}}","Failed to save:":"Nie udało się zapisać:","Fetching path information ...":"Pobieranie informacji o ścieżce ...","File":"Plik","Files larger than:":"Pliki większe niż:","Filters":"Filtry","Finished!":"Zakończono!","First run setup":"Konfiguracja początkowa","Folder":"Katalog","Folder path":"Ścieżka katalogu","Fri":"Pt","GByte":"GBajt","GByte/s":"GBajt/s","GCS Project ID":"GCS Project ID","General":"Ogólne","General backup settings":"Ogólne ustawienia kopii","General options":"Opcje ogólne","Generate":"Generuj","Generate IAM access policy":"Wygeneruj politykę dostępu IAM","Getting file versions ...":"Pobieranie wersji plików ...","Hidden files":"Ukryte pliki","Hide":"Ukryj","Hide hidden folders":"Ukryj ukryte foldery","Home":"Domowa","Hours":"Godziny","How do you want to handle existing files?":"Jak chcesz potraktować istniejące pliki?","Hyper-V Machine":"Maszyna Hyper-V","Hyper-V Machine:":"Maszyna Hyper-V:","Hyper-V Machines":"Maszyny Hyper-V","ID:":"ID:","If a date was missed, the job will run as soon as possible.":"Jeśli brak daty, zadanie zostanie uruchomione najwcześniej gdy to możliwe.","If the backup and the remote storage is out of sync, Duplicati will require that you perform a repair operation to synchronize the database.\\nIf the repair is unsuccesful, you can delete the local database and re-generate.":"Jeśli kopia zapasowa i zdalny magazyn nie są zsynchronizowane, Duplicati będzie wymagać wykonania operacji naprawy aby zsynchronizować bazy danych. \\nJeśli naprawa się nie powiedzie, można usunąć lokalną bazę danych i ją ponownie wygenerować.","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"Jeśli plik kopia zapasowa nie została pobrana automatycznie, kliknij prawym przyciskiem myszy i wybierz "Zapisz jako ..."","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"Jeśli plik kopia zapasowa nie została pobrana automatycznie, kliknij prawym przyciskiem myszy i wybierz "Zapisz jako ..."","If you do not enter a path, all files will be stored in the login folder.\nAre you sure this is what you want?":"Jeśli ścieżka nie zostanie wprowadzona, to wszystkie pliki będą przechowywane w katalogu logowania. Czy na pewno tak właśnie ma być?","If you do not enter an API Key, the tenant name is required":"Jeśli nie podasz Klucza API, nawa dzierżawcy jest wymagana","If you want to use the backup later, you can export the configuration before deleting it":"Jeśli chcesz użyć kopii później, możesz wyeksportować konfigurację przed jej usunięciem","If your machine is in a multi-user environment (i.e. the machine has more than one account), you need to set a password to prevent other users from accessing data on your account.\nDo you want to set a password now?":"Jeśli twoje urządzenie działa w środowisku wielodostępowym (np. w komputerze jest więcej niż jedno konto), musisz ustawić hasło, aby uniemożliwić innym użytkownikom dostęp do danych na swoim koncie.\nCzy chcesz teraz ustawić hasło?","Import":"Import","Import Destination URL":"Import Docelowego URL","Import backup configuration":"Importuj konfigurację kopii","Import completed, but no certificates were found after the import":"Import zakończony, ale nie znaleziono certyfikatów po imporcie","Import failed":"Nie udało się zaimportować","Import from a file":"Zaimportuj z pliku","Importing ...":"Importowanie ...","Include a file?":"Dołaczyć plik?","Include expression":"Dołącz wyrażenie","Include regular expression":"Dołącz wyrażenie regularne","Incorrect answer, try again":"Nieprawidłowa odpowiedź, spróbuj ponownie","Individual builds for developers only.":"Indywidualne kompilacje tylko dla developerów","Information":"Informacja","Install":"Instalacja","Install failed:":"Nie udało się zainstalować:","Invalid characters in path":"Nieprawidłowe znaki w ścieżce","Invalid retention time":"Nieprawidłowy czas przechowywania","It is possible to connect to some FTP without a password.\nAre you sure your FTP server supports password-less logins?":"Do niektórych serwerów FTP można łączyć się bez hasła.\nCzy na pewno Twój serwer FTP obsługuje logowanie bez hasła?","KByte":"KBajty","KByte/s":"KBajty/s","Language in user interface":"Język w interfejsie użytkownika","Last month":"Ostatni miesiąc","Last successful run:":"Ostatnie prawidłowe wykonanie:","Latest":"Ostatni","Libraries":"Biblioteki","Linux":"Linux","Listing backup dates ...":"Szukanie dat kopii ...","Listing remote files ...":"Szukanie plików zdalnych","Live":"Aktywne","Load a configuration from an exported job or a storage provider":"Wczytaj konfigurację z wyeksportowanego zadania lub magazynu","Load destination from an exported job or a storage provider":"Wczytaj miejsce docelowe z wyeksportowanego zadania lub magazynu","Load older data":"Załaduj starsze dane","Loading ...":"Ładowanie ...","Loading remote storage usage ...":"Ładowanie użycia magazynu zdalnego ...","Local database for":"Lokalna baza danych dla","Local database path:":"Ścieżka lokalnej bazy danych:","Local storage":"Magazyn lokalny","Location":"Położenie","Location where buckets are created":"Położenie, gdzie będą utworzone zasobniki","Log data for {{Backup.Backup.Name}}":"Loguj dane dla {{Backup.Backup.Name}}","Log data from the server":"Loguj dane z serwera","Log out":"Wyloguj","MByte":"MBajt","MByte/s":"MBajty/s","Maintenance":"Konserwacja","Manually type path":"Podaj ścieżkę ręcznie ","Max download speed":"Maksymalna szybkość pobierania","Max upload speed":"Maksymalna szybkość wysyłania","Menu":"Menu","Microsoft SQL Database:":"Baza danych Microsoft SQL:","Microsoft SQL Databases":"Bazy danych Microsoft SQL:","Minimum redundancy":"Minimalna redundancja","Minimum redundancy is 1.0":"Minimalna redundancja wynosi 1,0","Minutes":"Minuty","Missing name":"Brak nazwy","Missing passphrase":"Brak długiego hasła","Missing sources":"Brak źródła","Mon":"Pn","Months":"Miesiące","Move existing database":"Przenieś istniejącą bazę danych","Move failed:":"Nie udało się przenieść:","My Documents":"Moje Dokumenty","My Music":"Moja Muzyka","My Photos":"Moje Zdjęcia","My Pictures":"Moje Obrazy","Name":"Nazwa","Never":"Nigdy","New update found: {{message}}":"Znaleziono nowe uaktualnienie: {{message}}","New user name is {{user}}.\nUpdated credentials to use the new limited user":"Nowa nazwa użytkownika to {{user}}.\nUaktualniono uwierzytelnienia dla użytkownika o ograniczonym dostępie","Next":"Następny","Next scheduled run:":"Następne zaplanowane uruchomienie:","Next scheduled task:":"Następne zaplanowane zadanie:","Next task:":"Następne zadanie","Next time":"Następny raz","No":"Nie","No certificate was specified previously, please verify with the server administrator that the key is correct: {{key}} \n\nDo you want to approve the reported host key?":"Certyfikat nie został wcześniej określony, należy sprawdzić u administratora serwera czy klucz jest poprawny: {{key}} \n\nCzy akceptujesz podany klucz?","No editor found for the "{{backend}}" storage type":"Nie znaleziono edytora dla magazynu typu "{{backend}}"","No encryption":"Bez szyfrowania","No items selected":"Nie wybrano pozycji","No items to restore, please select one or more items":"Brak pozycji do odtworzenia, proszę wybrać jedną lub więcej pozycji.","No passphrase entered":"Nie wprowadzono długiego hasła","No scheduled tasks":"Brak zaplanowanych zadań","No, my machine has only a single account":"Nie, moje urządzenie ma tylko jedno konto","Non-matching passphrase":"Niepasujące długie hasła","None / disabled":"Żaden / wyłączone","OK":"OK","OSX":"OSX","OpenStack AuthURI":"OpenStack AuthURI","OpenStack Object Storage / Swift":"OpenStack Object Storage / Swift","Operation failed:":"Nie udało się wykonać operacji:","Operations:":"Operacje:","Optional authentication password":"Opcjonalne hasło uwierzytelnienia","Optional authentication username":"Opcjonalny użytkownik uwierzytelnienia","Options":"Opcje","Options added here are applied to all backups, but can be overridden in each individual backup":"Opcje dodane tutaj stosowane są do wszystkich kopii zapasowych, ale można je zmodyfikować w każdej indywidualnej kopii zapasowej","Original location":"Położenie oryginalne","Others":"Inne","Overwrite":"Nadpisz","Passphrase":"Długie hasło","Passphrase (if encrypted)":"Długie hasło (jeśli zaszyfrowane)","Passphrase changed":"Zmieniono długie hasło","Passphrases are not matching":"Długie hasła różnią się od siebie","Password":"Hasło","Passwords do not match":"Hasła różnią się od siebie","Patching files with local blocks ...":"Uzupełnianie plików z bloków lokalnych ...","Path not found":"Ścieżka nie znaleziona","Path on server":"Ścieżka na serwerze","Path or subfolder in the bucket":"Ścieżka lub podkatalog w zasobniku","Pause":"Wstrzymaj","Pause after startup or hibernation":"Wstrzymaj po uruchomieniu lub hibernacji","Pause options":"Opcje wstrzymania","Permissions":"Uprawnienia","Pick location":"Wybierz położenie","Point to your backup files and restore from there":"Wskaż pliki kopii zapasowej i odtwórz z nich","Port":"Port","Previous":"Poprzedni","ProjectID is optional if the bucket exist":"ProjectID jest opcjonalne jeśli zasobnik istnieje","Proprietary":"Własny","Purging files ...":"Czyszczenie plików ...","Rebuilding local database ...":"Przebudowywanie lokalnej bazy danych ...","Recreate (delete and repair)":"Odtworzenie (usunięcie i naprawienie)","Recreating database ...":"Odtwarzanie bazy danych ...","Registering temporary backup ...":"Rejestrowanie tymczasowej kopii ...","Relative paths not allowed":"Ścieżki względne nie są dopuszczalne","Reload":"Przeładuj","Remote":"Zdalny","Remove":"Usuń","Remove option":"Usuń opcję","Repair":"Napraw","Reparing ...":"Naprawianie ...","Repeat Passphrase":"Powtórz długie hasło","Reporting:":"Raportowanie:","Reset":"Resetuj","Restore":"Odtwórz","Restore files":"Odtwórz pliki","Restore files ...":"Odtwórz pliki ...","Restore files from {{backupname}}":"Odtwórz pliki z {{backupname}}","Restore from":"Odtwórz z","Restore from backup configuration":"Odtwórz z konfiguracji kopii","Restore from configuration ...":"Odtwórz z konfiguracji ...","Restore options":"Opcje odtwarzania","Restore read/write permissions":"Odtwórz uprawnienia odczytu/zapisu","Restoring files ...":"Odtwarzanie plików","Resume":"Wznów","Run again every":"Uruchom ponownie co","Run now":"Uruchom teraz","Running ...":"Uruchamianie ...","Running ....":"Uruchamianie ...","Running commandline entry":"Uruchamianie komend z linii poleceń","Running task:":"Uruchamianie zadania:","S3 Compatible":"Kompatybilny z S3","Same as the base install version: {{channelname}}":"Zgodny z bazową wersją instalacji: {{channelname}}","Sat":"So","Save":"Zapisz","Save and repair":"Zapisz i napraw","Save different versions with timestamp in file name":"Zapisz różne wersje z sygnaturą czasową w nazwie","Save immediately":"Zapisz niezwłocznie","Scanning existing files ...":"Przeglądanie istniejących plików ...","Scanning for local blocks ...":"Szukanie lokalnych bloków","Schedule":"Harmonogram","Search":"Szukaj","Search for files":"Szukaj plików","Seconds":"Sekundy","Select a log level and see messages as they happen:":"Wybierz zakres dziennika i zobacz co się wydarzyło:","Select files":"Wybierz pliki","Server":"Serwer","Server and port":"Serwer i port","Server hostname or IP":"Nazwa serwera lub IP","Server is currently paused,":"Serwer jest obecnie wstrzymany,","Server is currently paused, do you want to resume now?":"Serwer jest obecnie wstrzymany, czy chcesz teraz wznowić jego pracę?","Server password":"Hasło serwera","Server paused":"Serwer wstrzymany","Server state properties":"Właściwości stanu serwera","Settings":"Ustawienia","Show":"Pokaż","Show advanced editor":"Pokaż edytor zaawansowany","Show hidden folders":"Pokaż ukryte foldery","Show log":"Pokaż dziennik","Show log ...":"Pokaż dziennik ...","Show treeview":"Pokaż drzewo widoku","Sia server password":"Hasło serwera Sia","Some OpenStack providers allow an API key instead of a password and tenant name":"Niektórzy dostawcy OpenStack dopuszczają klucz API zamiast hasła i nazwy najemcy","Source Data":"Dane Źródłowe","Source data":"Dane źródłowe","Source folders":"Foldery źródłowe","Source:":"Źródło:","Specific builds for developers only.":"Specjalne kompilacje tylko dla developerów","Standard protocols":"Protokoły standardowe","Starting ...":"Uruchamianie ...","Starting the restore process ...":"Uruchamianie procesu odtwarzania ...","Stop after the current file":"Zatrzymaj po bieżącym pliku","Stop after upload":"Zatrzymaj po przesłaniu pliku","Stop now":"Zatrzymaj teraz","Stop running backup":"Zatrzymaj wykonywaną kopię","Stop running task":"Zatrzymaj wykonywane zadanie","Stopping after upload:":"Zatrzymaj po przesłaniu:","Stopping task:":"Zatrzymywanie zadania:","Storage Type":"Typ Magazynu","Storage class":"Klasa magazynu","Storage class for creating a bucket":"Klasa magazynu dla utworzenia zasobnika","Stored":"Zachowane","Strong":"Silne","Success":"Powodzenie","Sun":"Nie","Symbolic link":"Link symboliczny","System default ({{levelname}})":"System domyślny ({{levelname}})","System files":"Pliki systemowe","System info":"Informacja systemowa","System properties":"Właściwości systemowe","TByte":"TBajty","TByte/s":"TBajty/s","Target path, ie /backup":"Ścieżka docelowa, np. /backup","Task is running":"Zadanie jest wykonywane","Temporary files":"Pliki tymczasowe","Tenant Name":"Nazwa Dzierżawcy","Test connection":"Sprawdź połączenie","Testing ...":"Sprawdzanie ...","Testing connection ...":"Sprawdzanie połączenia ...","Testing permissions ...":"Sprawdzanie uprawnień ...","Testing permissions...":"Sprawdzanie uprawnień ...","The bucket name should be all lower-case, convert automatically?":"Nazwa zasobnika powinna być pisana wersalikami, zmienić automatycznie ?","The bucket name should start with your username, prepend automatically?":"Nazwa zasobnika powinna zaczynać się od nazwy użytkownika, dodać automatycznie ?","The connection to the server is lost, attempting again in {{time}} ...":"Utracono połączenie z serwerem, ponowna próba za {{time}} ...","The dark theme (by Michal)":"Ciemny schemat (wyk. Michal)","The default blue on white theme (by Alex)":"Domyślny schemat niebieski na białym (wyk. Alex)","The folder {{folder}} does not exist.\nCreate it now?":"Folder {{folder}} nie istnieje.\nUtworzyć go teraz?","The host key has changed, please check with the server administrator if this is correct, otherwise you could be the victim of a MAN-IN-THE-MIDDLE attack.\n\nDo you want to REPLACE your CURRENT host key \"{{prev}}\" with the REPORTED host key: {{key}}?":"Klucz komputera został zmieniony, proszę sprawdzić z administratorem serwera czy jest to poprawne, w przeciwnym razie możesz zostać ofiarą ataku typu MAN-IN--MIDDLE.\n\nCzy chcesz ZASTĄPIĆ twój BIEŻĄCY klucz komputera \"{{prev}}\" na PODANY klucz: {{klucz}}?","The path does not appear to exist, do you want to add it anyway?":"Wygląda, że ścieżka nie istnieje, czy mimo to chcesz ją dodać?","The path does not end with a '{{dirsep}}' character, which means that you include a file, not a folder.\n\nDo you want to include the specified file?":"Ścieżka nie kończy się znakiem \"{{dirsep}}\", co oznacza, że dołączasz plik, a nie folder.\n\nCzy chcesz dołączyć określony plik?","The path must be an absolute path, i.e. it must start with a forward slash '/'":"Ścieżka musi być ścieżką bezwzględną, tzn. musi rozpoczynać się prawym ukośnikiem '/'","The path should start with \"{{prefix1}}\" or \"{{prefix2}}\", otherwise you will not be able to see the files in the HubiC web interface.\n\nDo you want to add the prefix to the path automatically?":"Ścieżka powinna zaczynać się od \"{{prefix1}}\" lub \"{{prefix2}}\", w przeciwnym razie nie będzie widać plików w interfejsie internetowym HubiC.\n\nCzy chcesz dodać prefiks do ścieżki automatycznie?","The region parameter is only applied when creating a new bucket":"Parametr regionu jest stosowany tylko podczas tworzenia nowego zasobnika","The region parameter is only used when creating a bucket":"Parametr regionu jest używany tylko podczas tworzenia zasobnika","The server certificate could not be validated.\nDo you want to approve the SSL certificate with the hash: {{hash}}?":"Certyfikat serwera nie może być zweryfikowany.\nCzy aprobujesz certyfikat SSL z sygnaturą: {{hash}}?","The storage class affects the availability and price for a stored file":"Klasa magazynu danych ma wpływ na dostępność i cenę za przechowywany plik","The target folder contains encrypted files, please supply the passphrase":"Docelowy folder zawiera zaszyfrowane pliki, proszę podać długie hasło","The user has too many permissions. Do you want to create a new limited user, with only permissions to the selected path?":"Użytkownik ma za duże uprawnienia. Czy chcesz stworzyć nowego użytkownika z uprawnieniami ograniczonymi do wybranej ścieżki?","This backup was created on another operating system. Restoring files without specifying a destination folder can cause files to be restored in unexpected places. Are you sure you want to continue without choosing a destination folder?":"Ta kopia zapasowa została utworzona na innym systemie operacyjnym. Odzyskiwanie plików bez określania folderu docelowego może spowodować, że pliki zostaną przywrócone w nieoczekiwanych miejscach. Czy na pewno chcesz kontynuować bez wyboru folderu docelowego?","This month":"Bieżący miesiąc","This week":"Bieżący tydzień","Throttle settings":"Limity prędkości","Thu":"Czw","To File":"Do Pliku","To confirm you want to delete all remote files for \"{{name}}\", please enter the word you see below":"Aby potwierdzić, że chcesz skasować wszystkie zdalne pliki dla \"{{name}}\", proszę wprowadzić słowo zamieszczone poniżej","To export without a passphrase, uncheck the \"Encrypt file\" box":"Aby wyeksportować bez hasła, odznacz pole \"Szyfruj plik\"","Today":"Dzisiaj","Trust host certificate?":"Certyfikat zaufanego hosta?","Trust server certificate?":"Certyfikat zaufanego serwera?","Try out the new features we are working on. Don't use with important data.":"Wypróbuj nowe funkcjonalności nad którymi pracujemy. Nie używaj z ważnymi danymi.","Tue":"Wt","Type to highlight files":"Napisz by podświetlić pliki","Unknown backup size and versions":"Nieznany rozmiar kopii i wersje","Until resumed":"Do wznowienia","Update channel":"Kanał uaktualnień","Update failed:":"Nie udało się uaktualnić","Updating with existing database":"Uaktualnij z istniejącą bazą danych","Upload volume size":"Rozmiar przesłanych danych","Uploading verification file ...":"Przesyłanie pliku weryfikującego ...","Usage statistics":"Statystyki użycia","Usage statistics, warnings, errors, and crashes":"Statystyki użycia , ostrzeżenia, błędy i awarie","Use SSL":"Użyj SSL","Use existing database?":"Użyj istniejącej bazy danych","Use weak passphrase":"Użyj słabego długiego hasła","Useless":"Bezużyteczne","User data":"Dane użytkownika","User has too many permissions":"Użytkownik ma za duże uprawnienia","User interface settings":"Ustawienia interfejsu użytkownika","Username":"Nazwa użytkownika","Validating ...":"Potwierdzanie ...","Verify files":"Sprawdź pliki","Verifying ...":"Weryfikowanie ...","Verifying answer":"Weryfikacja odpowiedzi","Verifying backend data ...":"Weryfikowanie danych silnika ...","Verifying remote data ...":"Weryfikacja zdalnych danych ...","Verifying restored files ...":"Weryfikacja odtworzonych plików ...","Very strong":"Bardzo silne","Very weak":"Bardzo słabe","Visit us on":"Odwiedź nas na","WARNING: The remote database is found to be in use by the commandline library":"UWAGA: Wykryto, że zdalna baza danych jest używana przez bibliotekę wiersza poleceń.","WARNING: This will prevent you from restoring the data in the future.":"UWAGA: To uniemożliwi odtworzenie danych w przyszłości.","Waiting for task to begin":"Oczekiwanie na rozpoczęcie zadania","Waiting for task to start ....":"Oczekiwanie na uruchomienie zadania ...","Waiting for upload ...":"Oczekiwanie na przesłanie ...","Warnings, errors and crashes":"Ostrzeżenia, błędy i awarie","We accept donations via different services, such as OpenCollective, PayPal, BountySource and various crypto currencies.":"Przyjmujemy wsparcie za pośrednictwem różnych usług, takich jak OpenCollective, PayPal, BountySource i różne kryptowaluty.","We recommend that you encrypt all backups stored outside your system":"Zalecamy szyfrowanie wszystkich kopii przechowywanych poza twoim systemem","Weak":"Słabe","Weak passphrase":"Słabe długie hasło","Wed":"Śr","Weeks":"Tygodnie","Where do you want to restore from?":"Gdzie chcesz odtworzyć?","Where do you want to restore the files to?":"Gdzie chcesz odtworzyć pliki?","Windows":"Windows","Years":"Lata","Yes":"Tak","Yes, I have stored the passphrase safely":"Tak, długie hasło zostało bezpiecznie zachowane.","Yes, I'm brave!":"Tak. Jestem dzielny!","Yes, please break my backup!":"Tak, proszę zepsuj moją kopię!","Yesterday":"Wczoraj","You appear to be running Mono with no SSL certificates loaded.\nDo you want to import the list of trusted certificates from Mozilla?":"Wygląda na to, że uruchamiasz Mono bez załadowanego certyfikatu SSL.\nCzy chcesz zaimportować listę zaufanych certyfikatów z Mozilli?","You are changing the database path away from an existing database.\nAre you sure this is what you want?":"Zmieniłeś ścieżkę na nie prowadzącą do istniejącej bazy danych.\nCzy jesteś pewny, że takie było twoje rzeczywiste zamierzenie?","You are currently running {{appname}} {{version}}":"Aktualnie używasz {{appname}} {{version}}","You can stop the backup immediately, or stop after the current file has been uploaded.":"Możesz natychmiast przerwać tworzenie kopii zapasowej lub przerwać po przesłaniu bieżącego pliku.","You can stop the task immediately, or allow the process to continue its current file and the stop.":"Możesz natychmiast przerwać wykonywane zadanie lub przerwać po zakończeniu bieżącego pliku. ","You have changed the encryption mode. This may break stuff. You are encouraged to create a new backup instead":"Zmieniłeś tryb szyfrowania. Może to spowodować uszkodzenie zawartości. Zamiast tego zachęcamy do utworzenia nowej kopii zapasowej.","You have changed the passphrase, which is not supported. You are encouraged to create a new backup instead.":"Zmieniono hasło - zmiana hasła nie jest obsługiwana. Zachęcamy Cię zamiast tego do utworzenia nowej kopii zapasowej.","You have chosen not to encrypt the backup. Encryption is recommended for all data stored on a remote server.":"Wybrałeś opcję nieszyfrowania kopii zapasowej. Szyfrowanie jest zalecane dla wszystkich danych przechowywanych na serwerze zdalnym.","You have chosen to restore to a new location, but not entered one":"Możesz wybrać odtworzenie do nowej lokalizacji, ale nie tej wprowadzonej","You have generated a strong passphrase. Make sure you have made a safe copy of the passphrase, as the data cannot be recovered if you lose the passphrase.":"Wygenerowałeś silne hasło. Upewnij się, że wykonałeś bezpieczną kopię hasła, ponieważ danych nie będzie można odzyskać, jeśli utracisz hasło.","You must choose at least one source folder":"Musisz wybrać co najmniej jeden folder źródłowy","You must enter a name for the backup":"Musisz podać nazwę kopii zapasowej","You must enter a passphrase or disable encryption":"Musisz podać długie hasło lub wyłączyć szyfrowanie","You must enter a positive number of backups to keep":"Musisz podać dodatnią liczbę kopii do zachowania","You must enter a tenant name if you do not provide an API Key":"Musisz podać nazwę dzierżawcy jeśli nie podano Klucza API","You must enter a valid duration for the time to keep backups":"Musisz podać prawidłowy okres przechowywania kopii zapasowych","You must enter either a password or an API Key":"Musisz podać hasło lub Klucz API ","You must enter either a password or an API Key, not both":"Musisz podać jedno z dwóch hasło lub Klucz API, ale nie oba","You must fill in the password":"Musisz wypełnić pole hasło","You must fill in the server name or address":"Musisz wypełnić pole nazwa serwera lub adres","You must fill in the username":"Musisz wypełnić pole użytkownik","You must fill in {{field}}":"Musisz wypełnić pole {{field}}","You must select or fill in the AuthURI":"Musisz wybrać lub wypełnić pole AuthURI","You must select or fill in the server":"Musisz wybrać lub wypełnić pole serwer","You must specify a path":"Musisz podać ścieżkę","Your files and folders have been restored successfully.":"Twoje pliki i foldery zostały pomyślnie odtworzone.","Your passphrase is easy to guess. Consider changing passphrase.":"Twoje długie hasło jest łatwe do odgadnięcia. Rozważ zmianę długiego hasła.","bucket/folder/subfolder":"zasobnik/folder/podfolder","byte":"bajtów","byte/s":"bajtów/s","custom":"dostosowany","resume now":"wznów teraz","{{appname}} was primarily developed by {{dev1}} and {{dev2}}. {{appname}} can be downloaded from {{websitename}}. {{appname}} is licensed under the {{licensename}}.":"{{appname}} zostało opracowane głównie przez {{dev1}} i {{dev2}}. {{appname}} można pobrać z {{websitename}}. {{appname}} podlega licencji {{licensename}}.","{{files}} files ({{size}}) to go {{speed_txt}}":"{{files}} pliki ({{size}}), do zakończenia {{speed_txt}}","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Version":["{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Wersja","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Wersji","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Wersji","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Wersji"],"{{number}} Hour":"{{number}} Godzin","{{number}} Minutes":"{{number}} Minut","{{time}} (took {{duration}})":"{{time}} (trwało {{duration}})"}); gettextCatalog.setStrings('pt_BR', {"- pick an option -":"- selecione uma opção -","...loading...":"...carregando...","API Key":"Chave da API","AWS Access ID":"ID de acesso do AWS","AWS Access Key":"Chave de acesso do AWS","AWS IAM Policy":"Política de IAM do AWS","About":"Sobre","About {{appname}}":"Sobre {{appname}}","Access Key":"Chave de acesso","Access denied":"Acesso negado","Access to user interface":"Acesso à interface do usuário","Account name":"Nome do usuário","Activate":"Ativar","Activate failed:":"Falha na ativação:","Add a new backup":"Adicionar um novo backup","Add a path directly":"Adicione um caminho diretamente","Add advanced option":"Adicionar opção avançada","Add backup":"Adicionar backup","Add filter":"Adicionar filtro","Add path":"Adicionar caminho","Adjust bucket name?":"Ajustar o nome do bucket?","Adjust path name?":"Ajustar o nome do caminho?","Advanced Options":"Opções avançadas","Advanced options":"Opções avançadas","Advanced:":"Avançado:","All":"Todos","All Hyper-V Machines":"Todas as máquinas Hyper-V","All Microsoft SQL Databases":"Todas as bases Microsoft SQL","All usage reports are sent anonymously and do not contain any personal information. They contain information about hardware and operating system, the type of backend, backup duration, overall size of source data and similar data. They do not contain paths, filenames, usernames, passwords or similar sensitive information.":"Todos os relatórios de uso são enviados de forma anônima e não contêm dados pessoais. As informações contidas são sobre o hardware e o Sistema Operacional, o backend utilizado, a duração do backup, o tamanho total dos dados de origem e dados similares. Os relatórios não contêm caminhos, nomes de arquivos, usuários, senhas ou informações similares.","Allow remote access (requires restart)":"Permitir acesso remoto (restart necessário)","Allowed days":"Dias permitidos","An existing file was found at the new location":"Um arquivo foi encontrado no local escolhido","An existing file was found at the new location\nAre you sure you want the database to point to an existing file?":"Um arquivo foi encontrado no local escolhido\nVocê tem certeza que quer apontar a database para um arquivo existente?","An existing local database for the storage has been found.\nRe-using the database will allow the command-line and server instances to work on the same remote storage.\n\n Do you wish to use the existing database?":"Uma base local foi encontrada.\nReutilizar a basa permitirá que as ferramentas de linha de comando e as instâncias trabalhem no mesmo armazenamento remoto.\nGostaria de utilizar a base existente?","Anonymous usage reports":"Relatório anônimo de uso","As Command-line":"Como linha de comando","AuthID":"AuthID","Authentication password":"Senha de autenticação","Authentication username":"Usuário de autenticação","Autogenerated passphrase":"Senha gerada automaticamente","Automatically run backups.":"Executar backups automaticamente.","B2 Account ID":"B2 Account ID","B2 Application Key":"B2 Application Key","B2 Cloud Storage Account ID":"B2 Cloud Storage Account ID","B2 Cloud Storage Application Key":"B2 Cloud Storage Application Key","Back":"Voltar","Backend modules:":"Módulos:","Backup destination":"Destino do backup","Backup location":"Localização do backup","Backup:":"Backup:","Beta":"Beta","Broken access":"Acesso quebrado","Browse":"Navegar","Browser default":"Navegador padrão","Bucket Name":"Nome do Bucket","Bucket create location":"Localização do Bucket","Bucket create region":"Região do Bucket","Bucket name":"Nome do Bucket","Bucket storage class":"Classe de storage do Bucket","Building list of files to restore ...":"Construindo lista dos arquivos a serem recuperados ...","Building partial temporary database ...":"Criando base temporária parcial ...","Busy ...":"Ocupado ...","Canary":"Canary","Cancel":"Cancelar","Cannot move to existing file":"Não permitido mover para um arquivo existente","Changelog":"Changelog","Changelog for {{appname}} {{version}}":"Changelog para {{appname}} {{version}}","Check failed:":"Falha na verificação:","Check for updates now":"Buscar atualizações","Checking ...":"Verificando ...","Checking for updates ...":"Procurando atualizações ...","Chose a storage type to get started":"Para iniciar, escolha o tipo de armazenamento","Click the AuthID link to create an AuthID":"Clique no link AuthID para criar uma AuthID","Click to set throttle options":"Clique para definir opções de limite","Commandline ...":"Linha de comando","Compact now":"Compactar agora","Compacting remote data ...":"Compactando dados remotos","Completing backup ...":"Finalizando backup...","Completing previous backup ...":"Completando o backup anterior ...","Compression modules:":"Módulos de compressão:","Computer":"Computador","Configuration file:":"Arquivo de configuração:","Configuration:":"Configuração:","Configure a new backup":"Configurar novo backup","Confirm delete":"Confirmar remoção","Confirmation required":"Confirmação necessária","Connect":"Conectar","Connect now":"Conectar agora","Connecting to server ...":"Conectando ao servidor ...","Connecting to task ....":"Conectando-se à tarefa","Connecting...":"Conectando...","Connection lost":"Conexão perdida","Connection worked!":"Conexão estabelecida!","Container name":"Nome do Container","Container region":"Região do Container","Continue":"Continuar","Continue without encryption":"Continuar sem utilizar criptografia","Copied!":"Copiado!","Copy Destination URL to Clipboard":"Copiar URL do destino","Copy failed. Please manually copy the URL":"Falha na cópia. Copie a URL manualmente","Core options":"Opções básicas","Counting ({{files}} files found, {{size}})":"Contabilizando ({{files}} arquivos encontrados, {{size}})","Crashes only":"Somente falhas","Create bug report ...":"Criar relatório de falhas","Create folder?":"Criar diretório?","Created new limited user":"Criar novo usuário com limitações no acesso","Creating bug report ...":"Criando relatório de erros ...","Creating new user with limited access ...":"Criando novo usuário com limitações no acesso ...","Creating target folders ...":"Criando diretórios ...","Creating temporary backup ...":"Criando backup temporario ...","Creating user...":"Criando usuário...","Current version is {{versionname}} ({{versionnumber}})":"A versão atual é {{versionname}} ({{versionnumber}})","Custom S3 endpoint":"Endpoint S3 modificado","Custom authentication url":"URL de autenticação modificada","Custom location ({{server}})":"Localização personalizada ({{server}})","Custom region for creating buckets":"Região personalizada para a criação dos buckets","Custom region value ({{region}})":"Valor personalizado da region ({{region}})","Custom server url ({{server}})":"URL personalizada do servidor ({{server}})","Custom storage class ({{class}})":"Classe de armazenamento personalizada ({{class}})","Database ...":"Banco de dados","Days":"Dias","Default":"Padrão","Default ({{channelname}})":"Padrão ({{channelname}})","Default Filters":"Filtros padrões","Default options":"Opções padrão","Delete":"Remover","Delete ...":"Remover ...","Delete backup":"Remover backup","Delete local database":"Remover base local","Delete remote files":"Remover arquivos remotos","Delete the local database":"Remover a base local","Delete {{filecount}} files ({{filesize}}) from the remote storage?":"Remover {{filecount}} arquivos ({{filesize}}) do armazenamento remoto?","Deleting remote files ...":"Removendo arquivos remotos ...","Deleting unwanted files ...":"Removendo arquivos desnecessários ...","Desktop":"Área de Trabalho","Destination":"Destino","Did we help save your files? If so, please consider supporting Duplicati with a donation. We suggest {{smallamount}} for private use and {{largeamount}} for commercial use.":"Ajudamos a salvar seus arquivos? Caso afirmativo, ajude no desenvolvimento do Duplicati com uma doação. Sugerimos {{smallamount}} para usuários domésticos e {{largeamount}} para uso comercial.","Direct restore from backup files ...":"Restaure diretamente dos arquivos de backup...","Disabled":"Desabilitado","Dismiss":"Ok","Display and color theme":"Tela e cores do tema","Do you really want to delete the backup: \"{{name}}\" ?":"Deseja realmente remover o backup: \"{{name}}\" ?","Do you really want to delete the local database for: {{name}}":"Deseja realmente remover a base local para: {{name}}","Donate":"Doar","Donate with PayPal":"Doar com Paypal","Donate with crypto currency":"Doe com cripto moeda","Donation messages":"Sugestões de doação","Donation messages are hidden, click to show":"O lembrete de doação está escondido, clique para mostrá-lo","Donation messages are visible, click to hide":"O lembrete de doação está visível, clique para escondê-lo","Done":"Finalizado","Download":"Baixar","Downloading ...":"Baixando ...","Downloading files ...":"Baixando arquivos ...","Downloading update...":"Baixando update...","Duplicate option {{opt}}":"Duplicar opção {{opt}}","Duplicati Website":"Site do Duplicati","Duplicati forum":"Fórum do Duplicati","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\n When deleting a backup, you can also delete the local database without affecting the ability to restore the remote files.\n If you are using the local database for backups from the commandline, you should keep the database.":"Cada backup tem um banco de dados local associado a ele, que armazena informações sobre o backup remoto na máquina local.\n            Ao excluir um backup, você também pode excluir o banco de dados local sem afetar a capacidade de restaurar os arquivos remotos.\n            Se você estiver usando o banco de dados local para backups da linha de comando, é melhor manter o banco de dados.","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\\nThis makes it faster to perform many operations, and reduces the amount of data that needs to be downloaded for each operation.":"Cada backup possui uma base associada pra armazenar informações sobre o destino.\\nEsta base torna algumas operações mais rápidas, além de reduzir a quantidade de dados que precisam ser baixados para cada operação.","Edit ...":"Editar ...","Edit as list":"Editar como lista","Edit as text":"Editar como texto","Encrypt file":"Criptografar arquivo","Encryption":"Criptografia","Encryption changed":"A criptografia mudou","Encryption modules:":"Módulos de criptografia:","Enter URL":"Informe a URL","Enter access key":"Informe a chave de acesso","Enter account name":"Informe o nome da conta","Enter backup passphrase, if any":"Informe a senha do backup, caso exista","Enter configuration details":"Inserir detalhes da configuração","Enter container name":"Informe o nome do container","Enter encryption passphrase":"Informe a senha de criptografia","Enter expression here":"Informe a expressão aqui","Enter folder path name":"Informe o caminho completo do diretório","Enter one option per line in command-line format, eg. {0}":"Informe uma opção por linha do comando, ex. {0}","Enter the destination path":"Informe o caminho no destino","Error":"Erro","Error!":"Erro!","Errors and crashes":"Erros e problemas","Exclude":"Excluir","Exclude directories whose names contain":"Excluir diretórios que contenham","Exclude expression":"Excluir utilizando expressão","Exclude file":"Excluir arquivo","Exclude file extension":"Excluir arquivos com extensão","Exclude files whose names contain":"Excluir arquivos que contenham","Exclude folder":"Excluir diretório","Exclude regular expression":"Excluir utilizando expressão regular","Existing file found":"Excluir arquivo encontrado","Experimental":"Experimental","Export":"Exportar","Export ...":"Exportar ...","Export backup configuration":"Exportar configuração do backup","Export configuration":"Exportar configuração","Exporting ...":"Exportando ...","FTP (Alternative)":"FTP (alternativo)","Failed to build temporary database: {{message}}":"Falha ao construir base temporária: {{message}}","Failed to connect:":"Falha ao conectar:","Failed to connect: {{message}}":"Falha ao conectar: {{message}}","Failed to delete:":"Falha ao remover:","Failed to fetch path information: {{message}}":"Falha ao obter informação do caminho: {{message}}","Failed to import:":"Falha ao importar:","Failed to read backup defaults:":"Falha ao ler os padrões do backup","Failed to restore files: {{message}}":"Falha ao restaurar arquivos: {{message}}","Failed to save:":"Falha ao salvar:","Fetching path information ...":"Obtendo informação do caminho ...","File":"Arquivo","Files larger than:":"Arquivos maiores que:","Filters":"Filtros","Finished!":"Finalizado!","First run setup":"Configuração inicial","Folder":"Diretório","Folder path":"Caminho do diretório","Fri":"Sex","GByte":"GByte","GByte/s":"GByte/s","GCS Project ID":"ID do Projeto GCS","General":"Geral","General backup settings":"Configurações gerais de backup","General options":"Opções gerais","Generate":"Gerar","Generate IAM access policy":"Gerar política de acesso IAM","Getting file versions ...":"Obtendo versões de arquivos ...","Hidden files":"Arquivos ocultos","Hide":"Ocultar","Hide hidden folders":"Ocultar diretórios ocultos","Home":"Home","Hours":"Horas","How do you want to handle existing files?":"Como você quer lidar com arquivos existentes?","Hyper-V Machine":"Máquina Hyper-V","Hyper-V Machine:":"Máquina Hyper-V:","Hyper-V Machines":"Máquinas Hyper-V","ID:":"ID:","If a date was missed, the job will run as soon as possible.":"Caso um backup não ocorra na data específica, ele executará assim que possível.","If the backup and the remote storage is out of sync, Duplicati will require that you perform a repair operation to synchronize the database.\\nIf the repair is unsuccesful, you can delete the local database and re-generate.":"Caso o backup e o armazenamento remoto estejam dessincronizados, o Duplicati precisará de uma operação de reparo para realizar o sincronismo. \\nCaso o reparo não seja possível, você pode remover a base local e regenerá-la.","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"Se o arquivo de backup não foi baixado automaticamente, clique direito e escolha "Salvar como ... " ","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"Se o arquivo de backup não foi baixado automaticamente, clique direito e escolha "Salvar como ... " ","If you do not enter a path, all files will be stored in the login folder.\nAre you sure this is what you want?":"Se você não inserir um caminho, todos os arquivos serão armazenados na pasta de login.\nTem certeza de que isso é o que quer?","If you do not enter an API Key, the tenant name is required":"Se você não inserir uma chave de API, o nome do projeto é necessário","If you want to use the backup later, you can export the configuration before deleting it":"Se você quiser usar o backup mais tarde, você pode exportar a configuração antes de excluí-la","If your machine is in a multi-user environment (i.e. the machine has more than one account), you need to set a password to prevent other users from accessing data on your account.\nDo you want to set a password now?":"Se a sua máquina estiver em um ambiente multiusuário (ou seja, a máquina possui mais de uma conta), você precisa definir uma senha para impedir que outros usuários acessem dados de sua conta.\nDeseja configurar uma senha agora?","Import":"Importar","Import Destination URL":"Importar URL de destino","Import backup configuration":"Importar configuração de backup","Import completed, but no certificates were found after the import":"Importação completa, mas não foram encontrados certificados após a importação","Import failed":"Falha na importação","Import from a file":"Importar de um arquivo","Importing ...":"Importando ...","Include a file?":"Incluir um arquivo?","Include expression":"Incluir expressão","Include regular expression":"Incluir expressão regular","Incorrect answer, try again":"Resposta incorreta, tente novamente","Individual builds for developers only.":"Compilações individuais apenas para desenvolvedores.","Information":"Informação","Install":"Instalar","Install failed:":"Falha na instalação:","Invalid characters in path":"Caracteres inválidos no caminho","Invalid retention time":"Tempo de retenção inválido","It is possible to connect to some FTP without a password.\nAre you sure your FTP server supports password-less logins?":"É possível conectar em alguns servidores FTP sem utilizar senha.\nTem certeza que o seu servidor FTP suporta autenticação sem senha?","KByte":"KByte","KByte/s":"KByte/s","Keep this number of backups":"Manter esse número de backups","Language in user interface":"Idioma da interface do usuário","Last month":"Último mês","Last successful run:":"Última execução com sucesso:","Latest":"Mais recentes","Libraries":"Bibliotecas","Linux":"Linux","Listing backup dates ...":"Listando datas de backup ...","Listing remote files ...":"Listando arquivos remotos ...","Live":"Ao vivo","Load a configuration from an exported job or a storage provider":"Carregar uma configuração de um trabalho exportado ou de um provedor de armazenamento","Load destination from an exported job or a storage provider":"Carregar destino a partir de um trabalho exportado ou de um provedor de armazenamento","Load older data":"Abrir dados antigos","Loading ...":"Abrindo ...","Loading remote storage usage ...":"Carregando o uso de armazenamento remoto ...","Local database for":"Banco de dados local para","Local database path:":"Caminho do banco de dados local:","Local storage":"Armazenamento local","Location":"Localização","Location where buckets are created":"Local onde os compartimentos são criados","Log data for {{Backup.Backup.Name}}":"Grave log para {{Backup.Backup.Name}} ","Log data from the server":"Registrar dados do servidor","Log out":"Sair","MByte":"MByte","MByte/s":"MByte/s","Maintenance":"Manutenção","Manually type path":"Digite manualmente o caminho","Max download speed":"Velocidade de download máxima","Max upload speed":"Velocidade de upload máxima","Menu":"Menu","Microsoft SQL Database:":"Banco de dados Microsoft SQL:","Microsoft SQL Databases":"Banco de Dados Microsoft SQL","Minimum redundancy":"Redundância mínima","Minimum redundancy is 1.0":"Redundância mínima é 1.0","Minutes":"Minutos","Missing name":"Faltando o nome","Missing passphrase":"Faltando a frase de senha","Missing sources":"Faltando as origens","Mon":"Seg","Months":"Meses","Move existing database":"Mover o banco de dados existente","Move failed:":"Falha ao mover:","My Documents":"Meus Documentos","My Music":"Minhas Músicas","My Photos":"Minhas Fotos","My Pictures":"Minhas Imagens","Name":"Nome","Never":"Nunca","New update found: {{message}}":"Nova atualização encontrada: {{message}}","New user name is {{user}}.\nUpdated credentials to use the new limited user":"Nome nome de usuário é {{user}}\nAutorizações atualizadas para uso de um novo usuário limitado","Next":"Próximo","Next scheduled run:":"Próxima execução agendada:","Next scheduled task:":"Próxima tarefa agendada:","Next task:":"Próxima tarefa:","Next time":"Próxima vez","No":"Não","No certificate was specified previously, please verify with the server administrator that the key is correct: {{key}} \n\nDo you want to approve the reported host key?":"Nenhum certificado foi especificado anteriormente, verifique com o administrador do servidor se a chave está correta: {{key}}\n\nDeseja aprovar a chave de host relatada?","No editor found for the "{{backend}}" storage type":"Editor não encontrado para o "{{backend}}" tipo de armazenamento","No encryption":"Sem criptografia","No items selected":"Itens não selecionados","No items to restore, please select one or more items":"Sem itens para restaurar. por favor selecione um ou mais itens","No passphrase entered":"Nenhuma senha inserida","No scheduled tasks":"Sem tarefas agendadas","No, my machine has only a single account":"Não, minha máquina possui apenas uma conta","Non-matching passphrase":"Senha não correspondente","None / disabled":"Nenhum / desabilitado","OK":"OK","OSX":"OSX","OpenStack AuthURI":"OpenStack AuthURI","OpenStack Object Storage / Swift":"OpenStack Object Storage / Swift","Operation failed:":"Operação falhou:","Operations:":"Operações:","Optional authentication password":"Senha opcional de autenticação","Optional authentication username":"Usuário opcional de autenticação","Options":"Opções","Options added here are applied to all backups, but can be overridden in each individual backup":"As opções aqui adicionadas são aplicadas em todos os backups, mas podem ser substituídas em cada backup individual","Original location":"Localização original","Others":"Outros","Overwrite":"Sobrescrever","Passphrase":"Frase de segurança","Passphrase (if encrypted)":"Senha (se criptografado)","Passphrase changed":"Senha alterada","Passphrases are not matching":"Senhas não correspondem","Password":"Senha","Passwords do not match":"Senhas não conferem","Patching files with local blocks ...":"Aplicando patch nos arquivos com blocos locais ...","Path not found":"Caminho não encontrado","Path on server":"Caminho do servidor","Path or subfolder in the bucket":"Caminho ou subpasta no bucket","Pause":"Parar","Pause after startup or hibernation":"Pausa após a inicialização ou a hibernação","Pause options":"Interromper opções","Permissions":"Permissões","Pick location":"Escolher localização","Point to your backup files and restore from there":"Aponte para os arquivos de backup e restaure de lá","Port":"Porta","Previous":"Anterior","ProjectID is optional if the bucket exist":"ProjectID é opcional se o bucket já existe","Proprietary":"Proprietário","Purging files ...":"Limpando arquivos ...","Rebuilding local database ...":"Reconstruindo banco de dados local ...","Recreate (delete and repair)":"Recriar (excluir e reparar)","Recreating database ...":"Recriar banco de dados","Registering temporary backup ...":"Registrando cópia temporária ...","Relative paths not allowed":"Caminhos relativos não são permitidos","Reload":"Recarregar","Remote":"Remoto","Remove":"Remover","Remove option":"Remover opção","Repair":"Reparar","Reparing ...":"Reparando ...","Repeat Passphrase":"Repetir frase de segurança","Reporting:":"Relatórios:","Reset":"Redefinir","Restore":"Restaurar","Restore files":"Restaurar arquivos","Restore files ...":"Restaurar arquivos ...","Restore files from {{backupname}}":"Restaurar arquivos para {{backupname}}","Restore from":"Restaurar de","Restore from backup configuration":"Restaurar a partir da configuração de backup","Restore from configuration ...":"Restaurar a partir da configuração ...","Restore options":"Restaurar opções","Restore read/write permissions":"Restaurar permissões leitura/escrita","Restoring files ...":"Restaurando arquivos ...","Resume":"Continuar","Run again every":"Executar novamente a cada","Run now":"Executar agora","Running ...":"Executando ...","Running ....":"Executando ...","Running commandline entry":"Executando entrada de linha de comando","Running task:":"Executando tarefa:","S3 Compatible":"S3 Compatível","Same as the base install version: {{channelname}}":"Igual à versão de instalação base: {{channelname}}","Sat":"Sáb","Save":"Salvar","Save and repair":"Salvar e reparar","Save different versions with timestamp in file name":"Salve diferentes versões com marcas de horário no nome do arquivo","Save immediately":"Salvar imediatamente","Scanning existing files ...":"Verificando arquivos existentes ...","Scanning for local blocks ...":"Verificando blocos locais ...","Schedule":"Agendar","Search":"Buscar","Search for files":"Procurar por arquivos","Seconds":"Segundos","Select a log level and see messages as they happen:":"Selecione um nível de log e veja as mensagens conforme elas aparecem:","Select files":"Selecionar arquivos","Server":"Servidor","Server and port":"Servidor e porta","Server hostname or IP":"Nome do servidor ou IP","Server is currently paused,":"Servidor está atualmente parado,","Server is currently paused, do you want to resume now?":"Servidor está atualmente parado, você quer recomeçar agora?","Server password":"Senha do servidor","Server paused":"Servidor parado","Server state properties":"Propriedades do estado do servidor","Settings":"Configurações","Show":"Exibir","Show advanced editor":"Mostrar editor avançado","Show hidden folders":"Exibir pastas ocultas","Show log":"Exibir log","Show log ...":"Exibir log ...","Show treeview":"Mostrar hierarquia","Sia server password":"Senha do servidor Sia","Some OpenStack providers allow an API key instead of a password and tenant name":"Alguns provedores OpenStack permitem uma chave de API em vez de uma senha e nome de projeto","Source Data":"Dados de origem","Source data":"Dados de origem","Source folders":"Pasta de origem","Source:":"Origem:","Specific builds for developers only.":"Compilações específicas apenas para desenvolvedores.","Standard protocols":"Protocolos padrão","Starting ...":"Iniciando ...","Starting the restore process ...":"Iniciando o processo de restauração ...","Stop after the current file":"Parar após o arquivo atual","Stop after upload":"Parar após o envio","Stop now":"Parar agora","Stop running backup":"Parar de executar o backup","Stop running task":"Parar de executar a tarefa","Stopping after upload:":"Parando após o envio:","Stopping task:":"Tarefa de parada:","Storage Type":"Tipo de armazenamento","Storage class":"Classe de armazenamento","Storage class for creating a bucket":"Classe de armazenamento para criar um bucket","Stored":"Armazenado","Strong":"Forte","Success":"Sucesso","Sun":"Dom","Symbolic link":"Link simbólico","System default ({{levelname}})":"Sistema padrão ({{levelname}})","System files":"Arquivos do sistema","System info":"Informação do sistema","System properties":"Propriedades do sistema","TByte":"TByte","TByte/s":"TByte/s","Target path, ie /backup":"Caminho de destino, exemplo: /backup","Task is running":"Tarefa está executando","Temporary files":"Arquivos temporários","Tenant Name":"Nome do projeto","Test connection":"Teste de conexão","Testing ...":"Testando ...","Testing connection ...":"Testando conexão ...","Testing permissions ...":"Testando permissões ...","Testing permissions...":"Testando permissões...","The bucket name should be all lower-case, convert automatically?":"O nome do bucket deve ser todo em minúsculas. Converter automaticamente?","The bucket name should start with your username, prepend automatically?":"O nome do bucket deve começar com o seu nome de usuário, afixar automaticamente?","The connection to the server is lost, attempting again in {{time}} ...":"A conexão com o servidor foi perdida, tentando novamente em {{time}} ...","The dark theme (by Michal)":"O tema escuro (por Michal)","The default blue on white theme (by Alex)":"O tema padrão azul sobre branco (por Alex)","The folder {{folder}} does not exist.\nCreate it now?":"O diretório {{folder}} não existe.\nDeseja cria-lo agora?","The host key has changed, please check with the server administrator if this is correct, otherwise you could be the victim of a MAN-IN-THE-MIDDLE attack.\n\nDo you want to REPLACE your CURRENT host key \"{{prev}}\" with the REPORTED host key: {{key}}?":"A chave do host mudou, verifique com o administrador do servidor se está correta, caso contrário você poderia ser vítima de um ataque MAN-IN-THE MIDDLE.\n\nDeseja SUBSTITUIR a sua chave do host ATUAL \"{{prev}}\" com a chave do host REPORTADA: {{key}}?","The path does not appear to exist, do you want to add it anyway?":"O caminho não parece existir, você deseja adicioná-lo de qualquer maneira?","The path does not end with a '{{dirsep}}' character, which means that you include a file, not a folder.\n\nDo you want to include the specified file?":"O caminho não termina com um caractere '{{dirsep}}, o que significa que você inclui um arquivo, não uma pasta.\n\nDeseja incluir o arquivo especificado?","The path must be an absolute path, i.e. it must start with a forward slash '/'":"O caminho deve ser um caminho absoluto, ou seja, deve começar com uma barra progressiva '/'","The path should start with \"{{prefix1}}\" or \"{{prefix2}}\", otherwise you will not be able to see the files in the HubiC web interface.\n\nDo you want to add the prefix to the path automatically?":"O caminho deve começar com \"{{prefix1}}\" ou \"{{prefix2}}\", caso contrário você não poderá ver os arquivos na interface web do HubiC.\n\nDeseja adicionar o prefixo ao caminho automaticamente?","The region parameter is only applied when creating a new bucket":"O parâmetro de região só é aplicado ao criar um novo bucket","The region parameter is only used when creating a bucket":"O parâmetro de região só é usado na criação de um bucket","The server certificate could not be validated.\nDo you want to approve the SSL certificate with the hash: {{hash}}?":"O certificado do servidor não pôde ser validado.\nDeseja aprovar o certificado SSL com o hash: {{hash}}?","The storage class affects the availability and price for a stored file":"A classe de armazenamento afeta a disponibilidade e o preço de um arquivo armazenado","The target folder contains encrypted files, please supply the passphrase":"A pasta de destino contém arquivos criptografados. Forneça a senha","The user has too many permissions. Do you want to create a new limited user, with only permissions to the selected path?":"O usuário tem muitas permissões. Deseja criar um novo usuário limitado, com apenas permissões para o caminho selecionado?","This backup was created on another operating system. Restoring files without specifying a destination folder can cause files to be restored in unexpected places. Are you sure you want to continue without choosing a destination folder?":"Este backup foi criado em outro sistema operacional. A restauração de arquivos sem especificar uma pasta de destino pode fazer com que os arquivos sejam restaurados em locais inesperados. Tem certeza de que deseja continuar sem escolher uma pasta de destino?","This month":"Este mês","This week":"Esta semana","Throttle settings":"Configurações de limitação","Thu":"Qui","To File":"Para o arquivo","To confirm you want to delete all remote files for \"{{name}}\", please enter the word you see below":"Para confirmar que deseja excluir todos os arquivos remotos para \"{{nome}}\", insira a palavra abaixo","To export without a passphrase, uncheck the \"Encrypt file\" box":"Para exportar sem uma senha, desmarque a caixa \"Criptografar arquivo\"","Today":"Hoje","Trust host certificate?":"Confiar no certificado de host?","Trust server certificate?":"Confiar no certificado de servidor?","Try out the new features we are working on. Don't use with important data.":"Experimente os novos recursos em que estamos trabalhando. Não use com dados importantes.","Tue":"Ter","Type to highlight files":"Tipo para destacar arquivos","Unknown backup size and versions":"Tamanho do backup e versões desconhecidos","Until resumed":"Até retomar","Update channel":"Canal de atualização","Update failed:":"Atualização falhou:","Updating with existing database":"Atualizando com o banco de dados existente","Upload volume size":"Tamanho do volume de envio","Uploading verification file ...":"Enviando arquivo de verificação ...","Usage reports help us improve the user experience and evaluate impact of new features. We use them to generate public usage statistics":"Os relatórios de uso nos ajudam a melhorar a experiência do usuário e a avaliar o impacto de novos recursos. Usamos eles para gerar estatísticas de uso público ","Usage statistics":"Estatísticas de uso","Usage statistics, warnings, errors, and crashes":"Estatísticas de uso, avisos, erros e falhas","Use SSL":"Utilizar SSL","Use existing database?":"Usar um banco de dados existente?","Use weak passphrase":"Usar uma senha fraca","Useless":"Sem utilidade","User data":"Dados do usuário","User has too many permissions":"O usuário tem muitas permissões","User interface settings":"Configurações da interface do usuário","Username":"Nome de usuário","Validating ...":"Validando ...","Verify files":"Verificar arquivos","Verifying ...":"Verificando ...","Verifying answer":"Verificando pergunta","Verifying backend data ...":"Verificando os dados do backend ...","Verifying remote data ...":"Verificando dados remotos ...","Verifying restored files ...":"Verificando arquivos restaurados ...","Very strong":"Muito forte","Very weak":"Muito fraca","Visit us on":"Visite-nos em","WARNING: The remote database is found to be in use by the commandline library":"AVISO: o banco de dados remoto está sendo usado pela biblioteca de linha de comando","WARNING: This will prevent you from restoring the data in the future.":"AVISO: isso impedirá que você restaure os dados no futuro.","Waiting for task to begin":"Aguardando o início da tarefa","Waiting for task to start ....":"Aguardando a tarefa começar ...","Waiting for upload ...":"Aguardando pelo upload ...","Warnings, errors and crashes":"Avisos, erros e falhas","We accept donations via different services, such as OpenCollective, PayPal, BountySource and various crypto currencies.":"Aceitamos doações através de diferentes serviços, como OpenCollective, PayPal, BountySource e várias cripto moedas.","We recommend that you encrypt all backups stored outside your system":"Recomendamos que criptografe todos os backups armazenados fora do seu sistema","Weak":"Fraca","Weak passphrase":"Frase de segurança fraca","Wed":"Qua","Weeks":"Semanas","Where do you want to restore from?":"De onde você deseja restaurar?","Where do you want to restore the files to?":"Para onde você deseja restaurar os arquivos?","Windows":"Windows","Years":"Anos","Yes":"Sim","Yes, I have stored the passphrase safely":"Sim, eu tenho armazenado uma frase de acesso segura","Yes, I'm brave!":"Sim, sou corajoso!","Yes, please break my backup!":"Sim, corrompa meu backup!","Yesterday":"Ontem","You appear to be running Mono with no SSL certificates loaded.\nDo you want to import the list of trusted certificates from Mozilla?":"Você parece estar executando o Mono sem certificados SSL carregados.\nDeseja importar a lista de certificados confiáveis ​​da Mozilla?","You are changing the database path away from an existing database.\nAre you sure this is what you want?":"Você está mudando o caminho do banco de dados para longe de um banco de dados existente.\nTem certeza de que isso é o que deseja?","You are currently running {{appname}} {{version}}":"Você está atualmente executando {{appname}} {{version}}","You can stop the backup immediately, or stop after the current file has been uploaded.":"Você pode parar o backup imediatamente, ou parar após o arquivo atual ter sido enviado.","You can stop the task immediately, or allow the process to continue its current file and the stop.":"Você pode interromper a tarefa imediatamente ou permitir que o processo continue seu arquivo atual e então pare.","You have changed the encryption mode. This may break stuff. You are encouraged to create a new backup instead":"Você mudou o modo de criptografia. Isso pode estragar algo. É aconselhado criar um novo backup em vez disso","You have changed the passphrase, which is not supported. You are encouraged to create a new backup instead.":"Você alterou a senha, o que não é suportado. É aconselhado criar um novo backup.","You have chosen not to encrypt the backup. Encryption is recommended for all data stored on a remote server.":"Você escolheu não criptografar o backup. Encriptação é recomendada para todos dados armazenados em um servidor remoto.","You have chosen to restore to a new location, but not entered one":"Você escolheu restaurar para um novo local, mas não inseriu um","You have generated a strong passphrase. Make sure you have made a safe copy of the passphrase, as the data cannot be recovered if you lose the passphrase.":"Você gerou uma senha segura. Certifique-se de fazer um cópia da mesma, pois os dados não podem ser recuperados se você perder a senha.","You must choose at least one source folder":"Você deve escolher pelo menos uma pasta de origem","You must enter a name for the backup":"Você deve inserir um nome para o backup","You must enter a passphrase or disable encryption":"Você deve inserir uma senha ou desativar a criptografia","You must enter a positive number of backups to keep":"Você deve inserir um número positivo de backups para manter.","You must enter a tenant name if you do not provide an API Key":"Você deve inserir um nome de projeto se não fornecer uma chave de API","You must enter a valid duration for the time to keep backups":"Você deve inserir uma duração válida de tempo para manter os backups","You must enter either a password or an API Key":"Você deve inserir uma senha ou uma chave de API","You must enter either a password or an API Key, not both":"Você deve inserir uma senha OU uma chave de API, não ambas","You must fill in the password":"Você deve preencher a senha","You must fill in the server name or address":"Você deve preencher o nome do servidor ou endereço","You must fill in the username":"Você deve preencher o usuário","You must fill in {{field}}":"Você deve preencher {{field}}","You must select or fill in the AuthURI":"Você deve selecionar ou preencher a AuthURI","You must select or fill in the server":"Você deve selecionar ou preencher o servidor","You must specify a path":"Você deve especificar um caminho","Your files and folders have been restored successfully.":"Seus arquivos e pastas foram restaurados com êxito.","Your passphrase is easy to guess. Consider changing passphrase.":"Sua senha é fácil de adivinhar. Considere alterá-la.","a specific number":"um número específico","bucket/folder/subfolder":"bucket/pasta/subpasta","byte":"byte","byte/s":"byte/s","custom":"personalizado","resume now":"continuar agora","unlimited":"ilimitado","until they are older than":"até serem mais velhos que","{{appname}} was primarily developed by {{dev1}} and {{dev2}}. {{appname}} can be downloaded from {{websitename}}. {{appname}} is licensed under the {{licensename}}.":"{{appname}} foi desenvolvido inicialmente por {{dev1}} e{{dev2}}. {{appname}} pode ser baixado em {{websitename}}. {{appname}} é licenciado sob a {{licensename}}.","{{files}} files ({{size}}) to go {{speed_txt}}":"{{files}} arquivos ({{size}}) restantes {{speed_txt}}","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Version":["{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Versão","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Versões"],"{{number}} Hour":"{{number}} Hora","{{number}} Minutes":"{{number}} Minutos","{{time}} (took {{duration}})":"{{time}} (took {{duration}})"}); gettextCatalog.setStrings('pt', {"- pick an option -":"- escolha uma opção -","...loading...":"...a carregar...","API Key":"Chave API","AWS Access ID":"ID do acesso AWS","AWS Access Key":"Chave do acesso AWS","AWS IAM Policy":"Política de acesso e identidade AWS","About":"Acerca","About {{appname}}":"Acerca do {{appname}}","Access Key":"Chave de acesso","Access denied":"Acesso recusado","Access to user interface":"Acesso à interface","Account name":"Nome da conta","Activate":"Ativar","Activate failed:":"Falha ao ativar:","Add a new backup":"Adicionar novo backup","Add a path directly":"Digitar caminho","Add advanced option":"Adicionar opção avançada","Add backup":"Adicionar backup","Add filter":"Adicionar filtro","Add path":"Adicionar caminho","Adjust bucket name?":"Ajustar nome do 'bucket'?","Adjust path name?":"Ajustar nome do caminho?","Advanced Options":"Opções avançadas","Advanced options":"Opções avançadas","Advanced:":"Avançado:","All":"Tudo","All Hyper-V Machines":"Todas as máquinas Hyper-V","All Microsoft SQL Databases":"Todas as bases de dados Microsoft SQL","All usage reports are sent anonymously and do not contain any personal information. They contain information about hardware and operating system, the type of backend, backup duration, overall size of source data and similar data. They do not contain paths, filenames, usernames, passwords or similar sensitive information.":"Todos os relatórios de utilização são enviados de forma anónima. Contêm informação sobre o hardware, sobre o sistema operativo, o tipo de 'backend', a duração do backup, o tamanho dos dados e informações similares. Não contêm caminhos, ficheiros, utilizadores, palavras-passe ou quaisquer outras informações pessoais.","Allow remote access (requires restart)":"Permitir acesso remoto (tem que reiniciar)","Allowed days":"Dias permitidos","An existing file was found at the new location":"Encontrado um ficheiro na nova localização","An existing file was found at the new location\nAre you sure you want the database to point to an existing file?":"Foi encontrado um ficheiro na nova localização.\nTem a certeza de que deseja que a base de dados aponte para este ficheiro?","An existing local database for the storage has been found.\nRe-using the database will allow the command-line and server instances to work on the same remote storage.\n\n Do you wish to use the existing database?":"Foi encontrada uma base de dados local para o armazenamento.\nA reutilização da base de dados permite o funcionamento das instâncias do servidor e da linha de comandos no mesmo armazenamento remoto.\n\nDeseja reutilizar a base de dados existente?","Anonymous usage reports":"Relatório anónimos de utilização","As Command-line":"Como linha de comandos","AuthID":"AuthID","Authentication password":"Palavra-passe de autenticação","Authentication username":"Nome de utilizador de autenticação","Autogenerated passphrase":"Palavra-passe gerada automaticamente","Automatically run backups.":"Executar backups automaticamente.","B2 Account ID":"ID da conta B2","B2 Application Key":"Chave da aplicação B2","B2 Cloud Storage Account ID":"ID da conta B2 Cloud Storage","B2 Cloud Storage Application Key":"Chave da aplicação B2 Cloud Storage","Back":"Recuar","Backend modules:":"Módulos de 'backend':","Backup destination":"Destino do backup","Backup location":"Localização do backup","Backup:":"Backup:","Beta":"Beta","Broken access":"Acesso danificado","Browse":"Explorar","Browser default":"Navegador padrão","Bucket Name":"Nome do 'bucket'","Bucket create location":"Localização de criação do 'bucket'","Bucket create region":"Região de criação do 'bucket'","Bucket name":"Nome do 'bucket'","Bucket storage class":"Classe de armazenamento do 'bucket'","Building list of files to restore ...":"A criar lista de ficheiros a restaurar...","Building partial temporary database ...":"A criar base de dados temporária...","Busy ...":"Ocupado...","Canary":"Canary","Cancel":"Cancelar","Cannot move to existing file":"Incapaz de mover o ficheiro existente","Changelog":"Registo de alterações","Changelog for {{appname}} {{version}}":"Registo de alterações para {{appname}} {{version}}","Check failed:":"Falha de verificação:","Check for updates now":"Procurar atualizações agora","Checking ...":"A procurar...","Checking for updates ...":"A procurar atualizações...","Chose a storage type to get started":"Escolha o tipo de armazenamento para iniciar","Click the AuthID link to create an AuthID":"Clique na ligação para criar uma AuthID","Click to set throttle options":"Clique para definir as opções de velocidade","Commandline ...":"Linha de comandos...","Compact now":"Compactar agora","Compacting remote data ...":"A compactar dados remotos...","Completing backup ...":"A terminar backup...","Completing previous backup ...":"A terminar backup anterior...","Compression modules:":"Módulos de compressão:","Computer":"Computador","Configuration file:":"Ficheiro de configuração:","Configuration:":"Configuração:","Configure a new backup":"Configurar novo backup","Confirm delete":"Confirmação de eliminação","Confirmation required":"Requer confirmação","Connect":"Estabelecer ligação","Connect now":"Estabelecer ligação agora","Connecting to server ...":"A estabelecer ligação ao servidor...","Connecting to task ....":"A estabelecer ligação à tarefa...","Connecting...":"A estabelecer ligação...","Connection lost":"Ligação perdida","Connection worked!":"Ligação funcional!","Container name":"Nome do 'container'","Container region":"Região do 'container'","Continue":"Continuar","Continue without encryption":"Continuar sem encriptação","Copied!":"Copiada!","Copy Destination URL to Clipboard":"Copiar URL para a área de transferência","Copy failed. Please manually copy the URL":"Falha ao copiar. Copie o URL manualmente.","Core options":"Opções de core","Counting ({{files}} files found, {{size}})":"Encontrados ({{files}} ficheiros, {{size}})","Crashes only":"Apenas términos","Create bug report ...":"Criar relatório de erros...","Create folder?":"Criar pasta?","Created new limited user":"Criar utilizador com restrições","Creating bug report ...":"A criar relatório de erro...","Creating new user with limited access ...":"A criar novo utilizador com acesso limitado...","Creating target folders ...":"A criar pastas de destino....","Creating temporary backup ...":"A criar backup temporário...","Creating user...":"A criar utilizador...","Current version is {{versionname}} ({{versionnumber}})":"A versão atual é a {{versionname}} ({{versionnumber}})","Custom S3 endpoint":"URL S3 personalizado","Custom authentication url":"URL personalizado de autenticação","Custom location ({{server}})":"Localização personalizada ({{server}})","Custom region for creating buckets":"Região personalizada para a criação de 'buckets'","Custom region value ({{region}})":"Valor personalizado da região ({{region}})","Custom server url ({{server}})":"URL personalizado do servidor ({{server}})","Custom storage class ({{class}})":"Classe personalizada do armazenamento ({{class}})","Database ...":"Base de dados...","Days":"Dias","Default":"Padrão","Default ({{channelname}})":"Padrão ({{channelname}})","Default Filters":"Filtros padrão","Default options":"Opções padrão","Delete":"Apagar","Delete ...":"Apagar...","Delete backup":"Apagar backup","Delete local database":"Apagar base de dados local","Delete remote files":"Apagar ficheiros remotos","Delete the local database":"Apagar base de dados local","Delete {{filecount}} files ({{filesize}}) from the remote storage?":"Apagar {{filecount}} ficheiros ({{filesize}}) do armazenamento remoto?","Deleting remote files ...":"A apagar ficheiros remotos...","Deleting unwanted files ...":"A apagar ficheiros indesejados...","Desktop":"Ambiente de trabalho","Destination":"Destino","Did we help save your files? If so, please consider supporting Duplicati with a donation. We suggest {{smallamount}} for private use and {{largeamount}} for commercial use.":"Gostou da nossa aplicação? Se gostou, saiba que pode fazer uma doação. A nossa sugestão é de {{smallamount}} para particulares e de {{largeamount}} para organizações.","Direct restore from backup files ...":"Restauro a partir de ficheiros de backup...","Disabled":"Desativada","Dismiss":"Descartar","Display and color theme":"Exibição e cor do tema","Do you really want to delete the backup: \"{{name}}\" ?":"Tem a certeza de que deseja apagar o backup: \"{{name}}\"?","Do you really want to delete the local database for: {{name}}":"Tem a certeza de que deseja apagar a base de dados local para: {{name}}?","Donate":"Donativos","Donation messages":"Mensagens de donativo","Donation messages are hidden, click to show":"Mensagens de donativo ocultas... Clique para mostrar","Donation messages are visible, click to hide":"Mensagens de donativo mostradas... Clique para ocultar","Done":"Terminado","Download":"Descarregar","Downloading ...":"A descarregar...","Downloading files ...":"A descarregar ficheiros...","Downloading update...":"A descarregar atualização...","Duplicate option {{opt}}":"Opção duplicada {{opt}}","Duplicati Website":"Site do Duplicati","Duplicati forum":"Fórum","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\n When deleting a backup, you can also delete the local database without affecting the ability to restore the remote files.\n If you are using the local database for backups from the commandline, you should keep the database.":"Cada backup tem uma base de dados local associada e que armazena as informações sobre o backup remoto na sua máquina local.\nAo apagar um backup, também apaga a base de dados local e afetará a possibilidade de restaurar os ficheiros remotos.\nSe estiver a utilizar uma base de dados local para backups a partir da linha de comandos deve manter esta base de dados.","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\\nThis makes it faster to perform many operations, and reduces the amount of data that needs to be downloaded for each operation.":"Cada backup tem uma base de dados local associada e que armazena as informações sobre o backup remoto na sua máquina local.\\n Desta forma é mais fácil executar as operações e reduz a quantidade de dados que serão descarregados em cada operação.","Edit ...":"Editar","Edit as list":"Editar como lista...","Edit as text":"Editar como texto","Encrypt file":"Encriptar ficheiro","Encryption":"Encriptação","Encryption changed":"Encriptação alterada","Encryption modules:":"Módulos de encriptação:","Enter URL":"Digite o URL","Enter access key":"Digite a chave de acesso","Enter account name":"Digite o nome da conta","Enter backup passphrase, if any":"Digite a palavra-passe do backup, se existente","Enter configuration details":"Digite os detalhes da configuração","Enter container name":"Digite o nome do 'container'","Enter encryption passphrase":"Digite a palavra-passe de encriptação","Enter expression here":"Digite aqui a expressão","Enter folder path name":"Digite o nome do caminho da pasta","Enter one option per line in command-line format, eg. {0}":"Digite uma opção por linha no formato de linha de comandos, exemplo {0}","Enter the destination path":"Digite o caminho do destino","Error":"Erro","Error!":"Erro!","Errors and crashes":"Erros e términos","Exclude":"Excluir","Exclude directories whose names contain":"Excluir diretórios cujo nome contém","Exclude expression":"Expressão de exclusão","Exclude file":"Ficheiro de exclusão","Exclude file extension":"Tipo de ficheiro de exclusão","Exclude files whose names contain":"Excluir ficheiros cujo nome contém","Exclude folder":"Pasta de exclusão","Exclude regular expression":"Expressão regular de exclusão","Existing file found":"Encontrado ficheiro","Experimental":"Experimental","Export":"Exportar","Export ...":"Exportar...","Export backup configuration":"Exportar configuração de backup","Export configuration":"Exportar configuração","Exporting ...":"A exportar...","FTP (Alternative)":"FTP (Alternativo)","Failed to build temporary database: {{message}}":"Falha ao criar a base de dados temporária: {{message}}","Failed to connect:":"Falha ao estabelecer ligação:","Failed to connect: {{message}}":"Falha ao estabelecer ligação: {{message}}","Failed to delete:":"Falha ao apagar:","Failed to fetch path information: {{message}}":"Falha ao obter a informação do caminho: {{message}}","Failed to import:":"Falha ao importar:","Failed to read backup defaults:":"Falha ao ler as definições do backup:","Failed to restore files: {{message}}":"Falha ao restaurar os ficheiros: {{message}}","Failed to save:":"Falha ao guardar:","Fetching path information ...":"A obter informação do caminho:","File":"Ficheiro","Files larger than:":"Ficheiros maiores do que:","Filters":"Filtros","Finished!":"Terminado!","First run setup":"Configuração de primeira utilização","Folder":"Pasta","Folder path":"Caminho da pasta","Fri":"Sex","GByte":"GByte","GByte/s":"GByte/s","GCS Project ID":"ID do projeto GSC","General":"Geral","General backup settings":"Definições gerias de backup","General options":"Opções gerais","Generate":"Gerar","Generate IAM access policy":"Gerar política de acesso IAM","Getting file versions ...":"A obter versão dos ficheiros...","Hidden files":"Ficheiros ocultos","Hide":"Ocultar","Hide hidden folders":"Ocultar ficheiros ocultos","Home":"Página inicial","Hours":"Horas","How do you want to handle existing files?":"Como deseja gerir os ficheiros existentes?","Hyper-V Machine":"Máquina Hyper-V","Hyper-V Machine:":"Máquina Hyper-V:","Hyper-V Machines":"Máquinas Hyper-V","ID:":"ID:","If a date was missed, the job will run as soon as possible.":"Se não existir data, a tarefa será executada assim que possível.","If the backup and the remote storage is out of sync, Duplicati will require that you perform a repair operation to synchronize the database.\\nIf the repair is unsuccesful, you can delete the local database and re-generate.":"Se o backup e o servidor remoto não estiverem sincronizados, o Duplicati irá solicitar a reparação da base de dados.\\nSe não for possível a reparação, pode apagar a base dados local para a poder recriar.","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"Se o ficheiro do backup não for descarregado automaticamente, clique com o botão direito do rato e escolha "Guardar como..."","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"Se o ficheiro do backup não for descarregado automaticamente, clique com o botão direito do rato e escolha "Guardar como..."","If you do not enter a path, all files will be stored in the login folder.\nAre you sure this is what you want?":"Se não digitar o cominho, todos os ficheiros serão guardados na pasta raiz.\nTem a certeza de que é isto que deseja?","If you do not enter an API Key, the tenant name is required":"Se não digitar a chave API, será necessário o nome do 'tenant'.","If you want to use the backup later, you can export the configuration before deleting it":"Se quiser utilizar este backup posteriormente, pode exportar a configuração antes de o apagar.","If your machine is in a multi-user environment (i.e. the machine has more than one account), you need to set a password to prevent other users from accessing data on your account.\nDo you want to set a password now?":"Se a sua máquina tiver vários utilizadores (mais do que uma conta), terá que definir uma palavra-passe para impedir que os outros utilizadores acedam aos dados da sua conta.\nDeseja definir agora essa palavra-passe?","Import":"Importar","Import Destination URL":"Importar URL do destino","Import backup configuration":"Importar configuração do backup","Import completed, but no certificates were found after the import":"A importação foi terminada mas não foram encontrados certificados após a importação","Import failed":"Falha ao importar:","Import from a file":"Importar de um ficheiro","Importing ...":"A importar...","Include a file?":"Incluir um ficheiro?","Include expression":"Expressão de inclusão","Include regular expression":"Expressão regular de exclusão","Incorrect answer, try again":"Resposta errada, tente novamente.","Individual builds for developers only.":"Versões individuais para programadores.","Information":"Informação","Install":"Instalar","Install failed:":"Falha ao instalar:","Invalid characters in path":"Caracteres inválidos no caminho","Invalid retention time":"Tempo de retenção inválido","It is possible to connect to some FTP without a password.\nAre you sure your FTP server supports password-less logins?":"É possível estabelecer ligação a servidores FTP sem palavra-passe.\nTem a certeza de que o servidor FTP possui suporte a sessões no modo anónimo?","KByte":"KByte","KByte/s":"KByte/s","Language in user interface":"Idioma da interface de utilizador","Last month":"Último mês","Last successful run:":"Última execução com sucesso:","Latest":"Último","Libraries":"Bibliotecas","Linux":"Linux","Listing backup dates ...":"A listar datas dos backups...","Listing remote files ...":"A listar ficheiros remotos...","Live":"Live","Load a configuration from an exported job or a storage provider":"Carregar uma configuração de uma tarefa exportada ou de um fornecedor de armazenamento","Load destination from an exported job or a storage provider":"Carregar um destino de uma tarefa exportada ou de um fornecedor de armazenamento","Load older data":"Carregar dados antigos","Loading ...":"A carregar...","Loading remote storage usage ...":"A carregar utilização do armazenamento externo...","Local database for":"Base de dados local para","Local database path:":"Caminho da base de dados local:","Local storage":"Armazenamento local","Location":"Localização","Location where buckets are created":"Localização para a criação dos 'buckets'","Log data for {{Backup.Backup.Name}}":"Registo para {{Backup.Backup.Name}}","Log data from the server":"Registo a partir do servidor","Log out":"Terminar sessão","MByte":"MByte","MByte/s":"MByte/s","Maintenance":"Manutenção","Manually type path":"Digitar caminho manualmente","Max download speed":"Velocidade máxima para descargas","Max upload speed":"Velocidade máxima para envios","Menu":"Menu","Microsoft SQL Database:":"Base de dados Microsoft SQL:","Microsoft SQL Databases":"Bases de dados Microsoft SQL","Minimum redundancy":"Redundância mínima","Minimum redundancy is 1.0":"A redundância mínima é 1.0","Minutes":"Minutos","Missing name":"Nome em falta","Missing passphrase":"Palavra-passe inexistente","Missing sources":"Fontes em falta","Mon":"Seg","Months":"Meses","Move existing database":"Mover base de dados existente","Move failed:":"Falha ao mover:","My Documents":"Meus documentos","My Music":"Minhas músicas","My Photos":"Minhas fotos","My Pictures":"Minhas imagens","Name":"Nome","Never":"Nunca","New update found: {{message}}":"Atualização encontrada: {{message}}","New user name is {{user}}.\nUpdated credentials to use the new limited user":"O novo nome de utilizador é {{user}}.\nAs credenciais foram atualizadas para usar o utilizador limitado","Next":"Seguinte","Next scheduled run:":"Próximo agendamento:","Next scheduled task:":"Próxima tarefa agendada:","Next task:":"Próxima tarefa:","Next time":"Próxima hora","No":"Não","No encryption":"Sem encriptação","No items selected":"Nenhum item selecionado","No passphrase entered":"Palavra-passe não introduzida","No scheduled tasks":"Nenhuma tarefa agendada","No, my machine has only a single account":"Apenas existe uma conta na minha máquina","Non-matching passphrase":"Disparidade de palavras-passe","OK":"Aceitar","OSX":"OSX","OpenStack AuthURI":"OpenStack AuthURI","Operation failed:":"Falha de operação:","Operations:":"Operações:","Optional authentication password":"Palavra-passe opcional para autenticação","Optional authentication username":"Nome de utilizador opcional para autenticação","Options":"Opções","Original location":"Localização original","Others":"Outras","Overwrite":"Substituir","Passphrase":"Palavra-passe","Passphrase (if encrypted)":"Palavra-passe (se encriptado)","Passphrase changed":"Palavra-passe alterada","Passphrases are not matching":"Disparidade de palavras-passe","Password":"Palavra-passe","Passwords do not match":"Palavras-passe não coincidentes","Path not found":"Caminho não encontrado","Path on server":"Caminho no servidor","Path or subfolder in the bucket":"Caminho ou sub-pasta no 'bucket'","Pause":"Pausa","Pause after startup or hibernation":"Pausa após o arranque ou hibernação","Pause options":"Opções de pausa","Permissions":"Permissões","Pick location":"Escolher localização","Port":"Porta","Previous":"Anterior","Proprietary":"Proprietário","Purging files ...":"A purgar ficheiros...","Rebuilding local database ...":"A recriar base de dados local...","Recreate (delete and repair)":"Recriar (apagar e reparar)","Recreating database ...":"A recriar base de dados...","Registering temporary backup ...":"A registar backup temporário...","Relative paths not allowed":"Caminhos relativos não são permitidos","Reload":"Recarregar","Remote":"Remoto","Remove":"Remover","Remove option":"Remover opção","Repair":"Reparar","Reparing ...":"A reparar...","Repeat Passphrase":"Repetição de palavra-passe","Reporting:":"Reporte:","Reset":"Repor","Restore":"Restaurar","Restore files":"Restaurar ficheiros","Restore files ...":"Restaurar ficheiros...","Restore files from {{backupname}}":"Restaurar ficheiros de {{backupname}}","Restore from":"Restaurar de","Restore from backup configuration":"Restaurar de uma configuração de backup","Restore from configuration ...":"Restaurar de uma configuração...","Restore options":"Opções de restauro","Restore read/write permissions":"Restaurar permissões de leitura/escrita","Restoring files ...":"A restaurar ficheiros...","Resume":"Retomar","Run again every":"Executar a cada","Run now":"Executar agora","Running ...":"Em curso...","Running ....":"Em curso...","Running task:":"Tarefa em execução:","S3 Compatible":"Compatível com S3","Sat":"Sáb","Save":"Guardar","Save and repair":"Guardar e reparar","Save immediately":"Guardar imediatamente","Scanning existing files ...":"A analisar ficheiros existentes...","Scanning for local blocks ...":"A analisar blocos locais...","Schedule":"Agendamento","Search":"Pesquisa","Search for files":"Pesquisar ficheiros","Seconds":"Segundos","Select files":"Selecionar ficheiros","Server":"Servidor","Server and port":"Servidor e porta","Server hostname or IP":"Nome ou IP do servidor","Server is currently paused,":"O servidor está em pausa,","Server is currently paused, do you want to resume now?":"O servidor está em pausa, deseja continuar agora?","Server password":"Palavra-passe do servidor","Server paused":"Servidor em pausa","Server state properties":"Propriedades do estado do servidor","Settings":"Definições","Show":"Mostrar","Show advanced editor":"Mostrar editor avançado","Show hidden folders":"Mostrar pastas ocultas","Show log":"Mostrar registo","Show log ...":"Mostrar registo...","Show treeview":"Mostrar em árvore","Sia server password":"Palavra-passe do servidor Sia","Source Data":"Dados de origem","Source data":"Dados de origem","Source folders":"Pastas de origem","Source:":"Origem:","Specific builds for developers only.":"Versões específicas para programadores.","Standard protocols":"Protocolos padrão","Starting ...":"A iniciar...","Starting the restore process ...":"A iniciar o processo de restauro...","Stop after the current file":"Parar após o ficheiro atual","Stop after upload":"Parar depois de carregar","Stop now":"Parar agora","Stop running backup":"Parar backup em execução","Stop running task":"Parar tarefa em execução","Stopping after upload:":"Parar depois de carregar:","Stopping task:":"Parar tarefa:","Storage Type":"Tipo de armazenamento","Storage class":"Classe de armazenamento","Strong":"Forte","Success":"Sucesso","Sun":"Dom","Symbolic link":"Ligação simbólica","System default ({{levelname}})":"Predefinição ({{levelname}})","System files":"Ficheiros do sistema","System info":"Informações do sistema","System properties":"Propriedades do sistema","TByte":"TByte","TByte/s":"TByte/s","Target path, ie /backup":"Caminho do destino, isto é /backup","Task is running":"Tarefa em execução","Temporary files":"Ficheiros temporários","Tenant Name":"Nome do 'tenant'","Test connection":"Testar ligação","Testing ...":"A testar...","Testing connection ...":"A testar ligação...","Testing permissions ...":"A testar permissões...","Testing permissions...":"A testar permissões...","The dark theme (by Michal)":"Tema escuro (por Michal)","The default blue on white theme (by Alex)":"Azul em tema claro (by Alex)","This month":"Este mês","This week":"Esta semana","Throttle settings":"Definições de velocidade","Thu":"Qui","To File":"Para ficheiro","Today":"Hoje","Tue":"Terça","Type to highlight files":"Digite para destacar ficheiros","Until resumed":"Até retormar","Update channel":"Canal de atualização","Update failed:":"Falha ao atualizar:","Updating with existing database":"A atualizar base de dados existente","Usage statistics":"Estatísticas de utilização","Usage statistics, warnings, errors, and crashes":"Estatísticas de utilização, avisos e erros","Use SSL":"Usar SSL","Use existing database?":"Usar base de dados existente?","Use weak passphrase":"Utilizar palavra-passe fraca","Useless":"Inútil","User data":"Dados do utilizador","User has too many permissions":"Utilizador com demasiadas permissões","User interface settings":"Definições da interface","Username":"Nome de utilizador","Validating ...":"A validar...","Verify files":"A verificar ficheiros","Verifying ...":"A verificar...","Verifying answer":"A verificar resposta","Verifying backend data ...":"A verificar dados da infraestrutura...","Verifying remote data ...":"A verificar dados remotos...","Verifying restored files ...":"A verificar ficheiros restaurados...","Very strong":"Muito forte","Very weak":"Muito fraca","Visit us on":"Visite-nos em","Waiting for task to begin":"À espera para iniciar a tarefa","Waiting for task to start ....":"À espera para iniciar a tarefa...","Waiting for upload ...":"À espera para carregar...","Warnings, errors and crashes":"Avisos e erros","Weak":"Fraca","Weak passphrase":"Palavra-passe fraca","Wed":"Qua","Weeks":"Semanas","Where do you want to restore from?":"De onde deseja restaurar?","Where do you want to restore the files to?":"Para onde deseja restaurar os ficheiros?","Windows":"MS Windows","Years":"Anos","Yes":"Sim","Yesterday":"Ontem","You are currently running {{appname}} {{version}}":"Está a executar o {{appname}} {{version}}","You can stop the backup immediately, or stop after the current file has been uploaded.":"Pode parar o backup imediatamente ou parar depois de carregar o ficheiro atual.","You can stop the task immediately, or allow the process to continue its current file and the stop.":"Pode parar a tarefa imediatamente ou permitir que o ficheiro atual seja carregado.","You must choose at least one source folder":"Tem que escolher, pelo menos, uma pasta de origem","You must enter a name for the backup":"Tem que introduzir o nome para o backup","You must enter a positive number of backups to keep":"Tem que introduzir um número positivo para os backups a manter","You must enter either a password or an API Key":"Tem que preencher uma palavra-passe ou uma chave API","You must enter either a password or an API Key, not both":"Tem que preencher uma palavra-passe ou uma chave API mas não ambas","You must fill in the password":"Tem que preencher uma palavra-passe","You must fill in the server name or address":"Tem que preencher o nome ou endereço do servidor","You must fill in the username":"Tem que preencher o nome de utilizador","You must fill in {{field}}":"Tem que preencher {{field}}","You must select or fill in the AuthURI":"Tem que selecionar ou preencher o AuthURI","You must select or fill in the server":"Tem que selecionar ou preencher o servidor","You must specify a path":"Tem que especificar o caminho","Your files and folders have been restored successfully.":"Os seus ficheiros e pastas foram restaurados com sucesso.","Your passphrase is easy to guess. Consider changing passphrase.":"A sua palavra-passe é muito fraca. Deve alterar para uma mais forte.","bucket/folder/subfolder":"'bucket'/pasta/sub-pasta","byte":"byte","byte/s":"byte/s","custom":"personalizado","resume now":"retomar agora","{{appname}} was primarily developed by {{dev1}} and {{dev2}}. {{appname}} can be downloaded from {{websitename}}. {{appname}} is licensed under the {{licensename}}.":"{{appname}} foi inicialmente desenvolvido por {{dev1}} e {{dev2}}. {{appname}} pode ser descarregado em {{websitename}}. {{appname}} é licenciado nos termos da {{licensename}}.","{{files}} files ({{size}}) to go {{speed_txt}}":"{{files}} ficheiros ({{size}}) por enviar {{speed_txt}}","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Version":["{{item.Backup.Metadata.TargetSizeString}} / {{$count}} versão","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} versões"],"{{number}} Hour":"{{number}} hora","{{number}} Minutes":"{{number}} minutos","{{time}} (took {{duration}})":"{{time}} (demorou {{duration}})"}); @@ -18,6 +18,6 @@ angular.module('backupApp').run(['gettextCatalog', function (gettextCatalog) { gettextCatalog.setStrings('sr_RS', {"- pick an option -":"- odaberite opciju -","...loading...":"...učitavanje...","API Key":"API ključ","AWS Access ID":"AWS Access ID","AWS Access Key":"AWS Access Key","AWS IAM Policy":"AWS IAM Policy","About":"O nama","About {{appname}}":"O aplikaciji {{appname}}","Access Key":"Pristupni ključ - access key","Access denied":"Pristup odbijen","Access to user interface":"Pristup korisničkom interfejsu","Account name":"Korisničko ime","Activate":"Aktiviraj","Activate failed:":"Aktivacija nije uspešna:","Add a new backup":"Dodaj novi bekap","Add advanced option":"Dodaj naprednu opciju","Add backup":"Dodaj bekap","Add filter":"Dodaj filter","Add path":"Dodaj putanju","Adjust bucket name?":"Prilagodi ime kofice?","Adjust path name?":"Prilagodi ime putanje?","Advanced Options":"Napredne opcije","Advanced options":"Napredne opcije","Advanced:":"Napredno:","All Hyper-V Machines":"Sve Hyper-V mašine","All Microsoft SQL Databases":"Sve Microsoft SQL baze podataka","Allow remote access (requires restart)":"Dozvoli udaljeni pristup (zahteva restartovanje)","Allowed days":"Dozvoljeni dani","An existing file was found at the new location":"Postojeća datoteka je pronađena na novoj lokaciji","AuthID":"AuthID","Automatically run backups.":"Automatski pokreći backupove.","Back":"Nazad","Backend modules:":"Backend moduli:","Backup destination":"Backup odredište","Backup location":"Backup lokacija","Backup:":"Backup:","Beta":"Beta","Busy ...":"Zauzet ...","Canary":"Canary","Cancel":"Otkaži","Cannot move to existing file":"Nemoguće premestiti u postojeću datoteku","Check for updates now":"Proveri ažuriranja odmah","Checking ...":"Proveravanje ...","Checking for updates ...":"Proveravanje ažuriranja ...","Computer":"Računar","Configuration file:":"Datoteka sa podešavanjima:","Configuration:":"Podešavanja:","Confirm delete":"Potvrdi brisanje","Confirmation required":"Neophodna potvrda","Connect":"Poveži","Connect now":"Poveži odmah","Connecting to task ....":"Povezivanje na zadatak ....","Connecting...":"Povezivanje...","Connection lost":"Veza izgubljena","Connection worked!":"Veza je radila!","Continue":"Nastavi","Continue without encryption":"Nastavi bez šifrovanja","Copied!":"Prekopirano!","Copy Destination URL to Clipboard":"Kopiraj odredišni URL u privremenu memoriju","Copy failed. Please manually copy the URL":"Kopiranje nije uspelo. Molimo ručno kopiraj URL","Create folder?":"Napraviti fasciklu?","Created new limited user":"Napravljen novi ograničeni korisnik","Creating bug report ...":"Pravljenje izveštaja o grešci ...","Creating new user with limited access ...":"Pravljenje novog korisnika sa ograničenim pristupom ...","Creating temporary backup ...":"Pravljenje privremenog backupa ...","Creating user...":"Pravljenje korisnika...","Current version is {{versionname}} ({{versionnumber}})":"Trenutna verzija je {{versionname}} ({{versionnumber}})","Default":"Podrazumevano","Delete":"Obriši","Delete ...":"Brisanje ...","Delete backup":"Obriši backup","Delete local database":"Obriši lokalnu bazu podataka","Delete remote files":"Obriši udaljene datoteke","Delete the local database":"Obriši lokalnu bazu podataka","Delete {{filecount}} files ({{filesize}}) from the remote storage?":"Obrisati {{filecount}} datoteka ({{filesize}}) iz udaljenog skladišta?","Deleting remote files ...":"Brisanje udaljenih datoteka ...","Deleting unwanted files ...":"Brisanje nepoželjnih datoteka ...","Desktop":"Radna površina","Destination":"Odredište","Disabled":"Onemogućeno","Dismiss":"Odbaci","Do you really want to delete the backup: \"{{name}}\" ?":"Da li zaista želiš da obrišeš backup: \"{{name}}\" ?","Do you really want to delete the local database for: {{name}}":"Da li zaista želiš da obrišeš lokalnu bazu podataka za: {{name}}","Donate":"Doniraj","Done":"Završi","Download":"Preuzmi","Downloading ...":"Preuzimanje ...","Downloading files ...":"Preuzimanje datoteka ...","Downloading update...":"Preuzimanje ažuriranja...","Edit as list":"Izmeni kao listu","Edit as text":"Izmeni kao tekst","Encrypt file":"Šifruj datoteku","Encryption":"Šifrovanje","Encryption changed":"Šifrovanje promenjeno","Enter URL":"Unesi URL","Enter encryption passphrase":"Unesite lozinku šifrovanja","Error":"Greška","Error!":"Greška!","Export":"Izvezi","Export ...":"Izvoz ...","Export backup configuration":"Izvezi podešavanja backupa","Export configuration":"Izvezi podešavanja","File":"Datoteka","Files larger than:":"Datoteke veće od:","Finished!":"Završeno!","Folder":"Fascikla","Fri":"Pet","GByte":"GBajt","GByte/s":"GBajt/s","Hidden files":"Skrivene datoteke","Hide":"Sakrij","Hide hidden folders":"Sakrij skrivene fascikle","Home":"Glavna","Hours":"Sati","Hyper-V Machine":"Hyper-V mašina","Hyper-V Machine:":"Hyper-V mašina:","Hyper-V Machines":"Hyper-V mašine","ID:":"ID:","Incorrect answer, try again":"Netačan odgovor, pokušajte ponovo","Install":"Instalacija","Install failed:":"Instalacija nije uspela:","KByte":"KBajt","KByte/s":"KBajt/s","Language in user interface":"Jezik u korisničkom interfejsu","Last month":"Prošlog meseca","Libraries":"Biblioteke","Load older data":"Učitaj starije podatke","Loading ...":"Učitavanje ...","Local database for":"Lokalna baza podataka za","Local database path:":"Putanja lokalne baze podataka:","Local storage":"Lokalno skladište","Location":"Lokacija","Log out":"Odjavi se","MByte":"MBajt","MByte/s":"MBajt/s","Maintenance":"Održavanje","Manually type path":"Ručno unesite putanju","Menu":"Meni","Microsoft SQL Database:":"Microsoft SQL baza podataka:","Microsoft SQL Databases":"Microsoft SQL baze podataka","Minutes":"Minute","Missing name":"Nedostaje naziv","Missing passphrase":"Nedostaje lozinka","Mon":"Pon","Months":"Meseci","My Documents":"Moji dokumenti","My Music":"Moja muzika","My Photos":"Moje fotografije","My Pictures":"Moje slike","Name":"Naziv","Never":"Nikad","Next":"Sledeće","Next scheduled run:":"Sledeće zakazano pokretanje:","Next scheduled task:":"Sledeći zakazan zadatak:","Next task:":"Sledeći zadatak:","Next time":"Sledeći put","No":"Ne","No encryption":"Bez šifrovanja","No items selected":"Nema izabranih stavki","No passphrase entered":"Lozinka nije uneta","No scheduled tasks":"Nema zakazanih zadataka","OK":"U redu","Operation failed:":"Operacija neuspešna:","Operations:":"Operacije:","Options":"Opcije","Others":"Ostalo","Overwrite":"Prepiši","Passphrase":"Lozinka","Passphrase (if encrypted)":"Lozinka (ako je šifrovano)","Passphrase changed":"Lozinka promenjena","Passphrases are not matching":"Lozinke se ne poklapaju","Password":"Lozinka","Passwords do not match":"Lozinke se ne poklapaju","Path not found":"Putanja nije pronađena","Path on server":"Putanja na serveru","Pause":"Pauza","Pause after startup or hibernation":"Pauziraj nakon pokretanja ili hibernacije","Permissions":"Dozvole","Port":"Port","Previous":"Prethodno","Relative paths not allowed":"Relativne putanje nisu dozvoljene","Reload":"Učitaj ponovo","Remote":"Udaljeno","Remove":"Ukloni","Remove option":"Ukloni opciju","Repair":"Popravi","Reparing ...":"Popravka ...","Repeat Passphrase":"Ponovite lozinku","Reset":"Resetovanje","Restore":"Vrati","Restore files":"Vrati datoteke","Restore files ...":"Vraćanje datoteka ...","Restore files from {{backupname}}":"Povrati datoteke iz {{backupname}}","Restore from":"Vrati iz","Restore from backup configuration":"Vrati iz podešavanja backupa","Restore from configuration ...":"Vraćanje iz podešavanja ...","Restore options":"Vrati opcije","Restore read/write permissions":"Vrati dozvole za čitanje i upis","Restoring files ...":"Vraćanje datoteka ...","Resume":"Nastavi","Run again every":"Pokreni ponovo svaki","Run now":"Pokreni sad","Running ...":"Izvršavanje ...","Running ....":"Izvršavanje ....","Running commandline entry":"Izvrši unos komandne linije","Running task:":"Izvršavanje zadatka:","Sat":"Sub","Save":"Sačuvaj","Save and repair":"Snimi i popravi","Save different versions with timestamp in file name":"Snimi drugu verziju sa vremenom u nazivu datoteke","Save immediately":"Snimi odmah","Scanning existing files ...":"Pretraga postojećih datoteka ...","Scanning for local blocks ...":"Pretraga lokalnih blokova ...","Schedule":"Raspored","Search":"Pretraga","Search for files":"Pretraga datoteka","Seconds":"Sekunde","Select files":"Izaberite datoteke","Server":"Server","Server and port":"Server i port","Server hostname or IP":"Ime servera ili IP adresa","Server is currently paused,":"Server je trenutno pauziran,","Server is currently paused, do you want to resume now?":"Server je trenutno pauziran, da li želite da nastavite odmah?","Server paused":"Server je pauziran","Server state properties":"Opcije stanja servera","Settings":"Podešavanja","Show":"Prikaži","Show advanced editor":"Prikaži napredni editor","Show hidden folders":"Prikaži skrivene fascikle","Show log":"Prikaži dnevnik","Show log ...":"Prikaži dnevnik ...","Starting ...":"Pokretanje ...","Starting the restore process ...":"Pokretanje procesa vraćanja ...","Stop after the current file":"Zaustavi nakon trenutne datoteke","Stop now":"Zaustavi odmah","Stop running backup":"Zaustavi pokrenuti backup","Stop running task":"Zaustavi pokrenuti zadatak","Stopping task:":"Zaustavljanje zadatka:","Storage Type":"Tip skladišta","Storage class":"Klasa skladišta","Stored":"Uskladišteno","Strong":"Jaka","Success":"Uspešno","Sun":"Ned","Symbolic link":"Simbolička veza","System files":"Sistemske datoteke","System info":"Sistemski podaci","System properties":"Sistemske opcije","TByte":"TBajt","TByte/s":"TBajt/s","Task is running":"Zadatak se izvršava","Temporary files":"Privremene datoteke","Test connection":"Probaj vezu","Testing ...":"Proveravanje ...","Testing connection ...":"Proveravanje veze ...","Testing permissions ...":"Proveravanje dozvola ...","Testing permissions...":"Proveravanje dozvola...","The connection to the server is lost, attempting again in {{time}} ...":"Veza sa serverom je prekinuta, pokušavanje ponovo za {{time}} ...","The dark theme (by Michal)":"Tamna tema (napravio Michal)","The default blue on white theme (by Alex)":"Podrazumevana plavo na belom tema (napravio Alex)","The path does not appear to exist, do you want to add it anyway?":"Putanja izgleda ne postoji, da li svejedno želite da je dodate?","The server certificate could not be validated.\nDo you want to approve the SSL certificate with the hash: {{hash}}?":"Sertifikat servera nije mogao biti proveren.\nDa li želite da odobrite SSL sertifikat sa hešom: {{hash}}?","The storage class affects the availability and price for a stored file":"Klasa skladišta utiče na dostupnost i cenu za uskladištenu datoteku","The target folder contains encrypted files, please supply the passphrase":"Ciljana fasckla sadrži šifrovane datoteke, molimo unesite lozinku","The user has too many permissions. Do you want to create a new limited user, with only permissions to the selected path?":"Korisnik ima previše dozvola, Da li želite da napravite novog ograničenog korisnika, sa samo dozvolama za izabranu putanju?","This month":"Ovog meseca","This week":"Ove sedmice","Thu":"Čet","To File":"U datoteku","To confirm you want to delete all remote files for \"{{name}}\", please enter the word you see below":"Da potvrdite da želite obrisati sve udaljene datoteke sa imenom \"{{name}}\", molimo unesite reč koju vidite ispod","To export without a passphrase, uncheck the \"Encrypt file\" box":"Za izvoz bez lozinke, polje \"Šifruj datoteku\" ne treba da bude označeno","Today":"Danas","Trust server certificate?":"Veruj sertifikatu servera?","Try out the new features we are working on. Don't use with important data.":"Isprobajte nove mogućnosti na kojima radimo. Ne koristite sa važnim podacima.","Tue":"Uto","Update failed:":"Ažuriranje nije uspelo:","Updating with existing database":"Ažuriranje sa postojećom bazom podataka","Usage statistics":"Statistika upotrebe","Use SSL":"Koristi SSL","Use existing database?":"Koristi postojeću bazu podataka?","Use weak passphrase":"Koristi slabu lozinku","Useless":"Beskorisno","User data":"Podaci o korisniku","User has too many permissions":"Korisnik ima previše dozvola","User interface settings":"Podešavanja korisničkog interfejsa","Username":"Korisničko ime","Validating ...":"Proveravanje ...","Verify files":"Proveri datoteke","Verifying ...":"Proveravanje ...","Verifying answer":"Proveravanje odgovora","Verifying restored files ...":"Proveravanje vraćenih datoteka ..","Very strong":"Veoma jaka","Very weak":"Veoma slaba","Visit us on":"Posetite nas na","Waiting for task to begin":"Čekanje na početak zadatka","Waiting for task to start ....":"Čekanje na pokretanje zadatka ....","We recommend that you encrypt all backups stored outside your system":"Preporučujemo da šifrujete sve backup-ove uskladištene van Vašeg sistema","Weak":"Slaba","Weak passphrase":"Slaba lozinka","Wed":"Sre","Weeks":"Sedmica","Where do you want to restore from?":"Odakle želite da vratite?","Where do you want to restore the files to?":"Gde želite da vratite datoteke?","Years":"Godina","Yes":"Da","Yes, I have stored the passphrase safely":"Da, uskladištio sam lozinku bezbedno","Yes, I'm brave!":"Da, hrabar sam!","Yesterday":"Juče","You appear to be running Mono with no SSL certificates loaded.\nDo you want to import the list of trusted certificates from Mozilla?":"Izgleda da koristite Mono bez učitanih SSL sertifikata.\nDa li želite da uvezete listu poverljivih sertifikata od Mozille?","You are currently running {{appname}} {{version}}":"Trenutno koristite {{appname}} {{version}}","You must enter a name for the backup":"Morate uneti naziv za backup","You must enter a passphrase or disable encryption":"Morate uneti lozinku ili isključiti šifrovanje","You must enter either a password or an API Key":"Morate uneti ili lozinku ili API ključ","You must enter either a password or an API Key, not both":"Morate uneti ili lozinku ili API ključ, ne oboje","You must fill in the password":"Morate uneti lozinku","You must fill in the server name or address":"Morate uneti naziv servera ili adresu","You must fill in the username":"Morate uneti korisničko ime","You must fill in {{field}}":"Morate uneti {{field}}","You must select or fill in the AuthURI":"Morate izabrati ili uneti AuthURI","You must select or fill in the server":"Morate izabrati ili uneti server","You must specify a path":"Morate navesti putanju","Your files and folders have been restored successfully.":"Vaše datoteke i fascikle su uspešno vraćene.","Your passphrase is easy to guess. Consider changing passphrase.":"Vaša lozinka je laka za pogađanje. Razmislite o promeni lozinke.","byte":"bajt","byte/s":"bajt/s","resume now":"nastavi odmah","{{number}} Hour":"{{number}} sati","{{number}} Minutes":"{{number}} minuta"}); gettextCatalog.setStrings('zh_CN', {"- pick an option -":"- 选择一个选项 -","...loading...":"…载入中…","API Key":"API 密钥","AWS Access ID":"AWS 访问 ID","AWS Access Key":"AWS 访问密钥","AWS IAM Policy":"AWS IAM 策略","About":"关于","About {{appname}}":"关于 {{appname}}","Access Key":"访问密钥","Access denied":"访问被拒绝","Access to user interface":"访问控制","Account name":"帐户名","Activate":"激活","Activate failed:":"激活失败:","Add a new backup":"添加新备份","Add a path directly":"直接添加路径","Add advanced option":"添加高级选项","Add backup":"新增备份","Add filter":"添加过滤条件","Add path":"添加路径","Adjust bucket name?":"调整 bucket 名称?","Adjust path name?":"调整路径名称?","Advanced Options":"高级选项","Advanced options":"高级选项","Advanced:":"高级:","All":"所有","All Hyper-V Machines":"所有 Hyper-V 机器","All Microsoft SQL Databases":"所有 Microsoft SQL 数据库","All usage reports are sent anonymously and do not contain any personal information. They contain information about hardware and operating system, the type of backend, backup duration, overall size of source data and similar data. They do not contain paths, filenames, usernames, passwords or similar sensitive information.":"所有的使用情况报告都是匿名发送,不含任何个人信息。 其中包括硬件,操作系统,后端类型,备份时长,备份源大小以及类似数据,但不包括路径,文件名,用户名,密码或类似的敏感信息。","Allow remote access (requires restart)":"允许远程访问 (需要重启)","Allowed days":"日期规划","An existing file was found at the new location":"新位置已有文件","An existing file was found at the new location\nAre you sure you want the database to point to an existing file?":"新位置已有文件\n你确定要将数据库指向已存在的文件?","An existing local database for the storage has been found.\nRe-using the database will allow the command-line and server instances to work on the same remote storage.\n\n Do you wish to use the existing database?":"发现此存储在本地已存在数据库\n重新使用该数据库将使用命令行或服务器实例工作在相同的存储\n你希望使用已有的数据库吗?","Anonymous usage reports":"使用情况报告级别","As Command-line":"导出为命令行","AuthID":"授权 ID","Authentication password":"认证密码","Authentication username":"认证用户名","Autogenerated passphrase":"自动生成的密码","Automatically run backups.":"自动运行备份","B2 Account ID":"B2 帐户 ID","B2 Application Key":"B2 应用密钥","B2 Cloud Storage Account ID":"B2 云存储帐户 ID","B2 Cloud Storage Application Key":"B2 云存储应用密钥","Back":"返回","Backend modules:":"后端模块:","Backup destination":"备份保存位置","Backup location":"备份位置","Backup:":"备份数据:","Beta":" Beta","Broken access":"访问错误","Browse":"浏览","Browser default":"浏览器默认语言","Bucket Name":"Bucket 名称","Bucket create location":"Bucket 创建区域","Bucket create region":"Bucket 创建区域","Bucket name":"Bucket 名称","Bucket storage class":"Bucket 存储类型","Building list of files to restore ...":"正在构建文件还原列表…","Building partial temporary database ...":"正在构建局部临时数据库…","Busy ...":"忙碌中…","Canary":"Canary","Cancel":"取消","Cannot move to existing file":"不能移动到已有文件","Changelog":"更新日志","Changelog for {{appname}} {{version}}":"{{appname}} {{version}} 更新日志","Check failed:":"检查失败:","Check for updates now":"立即检查更新","Checking ...":"正在检查…","Checking for updates ...":"正在检查更新…","Chose a storage type to get started":"选择存储类型以开始","Click the AuthID link to create an AuthID":"点击\"授权 ID\"链接来创建一个授权 ID","Click to set throttle options":"点击配置限流","Commandline ...":"命令行...","Compact now":"立即压实","Compacting remote data ...":"正在压实远程数据…","Completing backup ...":"即将完成备份…","Completing previous backup ...":"即将完成前一备份…","Compression modules:":"压缩模块:","Computer":"计算机","Configuration file:":"配置文件:","Configuration:":"配置:","Configure a new backup":"配置新备份","Confirm delete":"确认删除","Confirmation required":"需要确认","Connect":"连接","Connect now":"立即连接","Connecting to server ...":"正在连接服务器…","Connecting to task ....":"正在连接至任务...","Connecting...":"正在连接…","Connection lost":"连接中断","Connection worked!":"连接正常!","Container name":"容器名称","Container region":"容器区域","Continue":"继续","Continue without encryption":"继续且不启用加密","Copied!":"已复制!","Copy Destination URL to Clipboard":"复制地址到剪贴板","Copy failed. Please manually copy the URL":"复制失败,请手动复制此地址","Core options":"核心选项","Counting ({{files}} files found, {{size}})":"正在计算 (已找到 {{files}} 个文件,{{size}})","Crashes only":"仅崩溃","Create bug report ...":"创建 bug 报告…","Create folder?":"创建文件夹?","Created new limited user":"受限用户已创建","Creating bug report ...":"正在创建 bug 报告…","Creating new user with limited access ...":"正在创建受限用户…","Creating target folders ...":"正在创建目标文件夹…","Creating temporary backup ...":"正在创建临时备份…","Creating user...":"正在创建用户…","Current version is {{versionname}} ({{versionnumber}})":"当前版本为 {{versionname}} ({{versionnumber}})","Custom S3 endpoint":"自定义 S3 端点","Custom authentication url":"自定义认证地址","Custom location ({{server}})":"自定义区域 ({{server}})","Custom region for creating buckets":"自定义创建 Bucket 的地区","Custom region value ({{region}})":"自定义地区 ({{region}})","Custom server url ({{server}})":"自定义服务器地址 ({{server}})","Custom storage class ({{class}})":"自定义存储类别 ({{class}})","Database ...":"数据库...","Days":"天","Default":"默认","Default ({{channelname}})":"默认 ({{channelname}})","Default Filters":"默认过滤条件","Default options":"默认选项","Delete":"删除","Delete ...":"删除…","Delete backup":"删除备份","Delete local database":"删除本地数据库","Delete remote files":"删除远程文件","Delete the local database":"删除本地数据库","Delete {{filecount}} files ({{filesize}}) from the remote storage?":"从远程存储中删除 {{filecount}} 个文件 ({{filesize}}) ?","Deleting remote files ...":"正在删除远程文件…","Deleting unwanted files ...":"正在删除多余文件…","Desktop":"桌面","Destination":"保存位置","Did we help save your files? If so, please consider supporting Duplicati with a donation. We suggest {{smallamount}} for private use and {{largeamount}} for commercial use.":"若 Duplicati 对你有所帮助,请考虑捐赠来支持我们。个人用途,建议捐赠 {{smallamount}},商业用途,建议捐赠 {{largeamount}}。","Direct restore from backup files ...":"直接从备份文件中恢复...","Disabled":"已禁用","Dismiss":"忽略","Display and color theme":"显示和颜色主题","Do you really want to delete the backup: \"{{name}}\" ?":"你确定要删除备份:\"{{name}}\"吗 ?","Do you really want to delete the local database for: {{name}}":"你确定要删除 \"{{name}}\" 的本地数据库吗 ?","Donate":"捐赠","Donation messages":"捐赠信息","Donation messages are hidden, click to show":"捐赠信息已隐藏,点击显示","Donation messages are visible, click to hide":"捐赠消息已显示,点击隐藏","Done":"完成","Download":"下载","Downloading ...":"正在下载…","Downloading files ...":"正在下载文件……","Downloading update...":"正在下载更新…","Duplicate option {{opt}}":"Duplicati 选项 {{opt}}","Duplicati Website":"Duplicati 网站","Duplicati forum":"Duplicati 论坛","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\n When deleting a backup, you can also delete the local database without affecting the ability to restore the remote files.\n If you are using the local database for backups from the commandline, you should keep the database.":"每个备份都有一个关联的本地数据库,用来存储远程备份相关的信息。\n删除一个备份时,你也可以删除其本地数据库,这不会影响从远程文件中恢复数据。\n但如果你通过命令行进行备份,你应当保留此数据库。","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\\nThis makes it faster to perform many operations, and reduces the amount of data that needs to be downloaded for each operation.":"每个备份都有一个关联的本地数据库,用来存储远程备份相关的信息。\\n这将加快许多操作的执行时间并减少操作时需要下载的数据量。","Edit ...":"编辑…","Edit as list":"以列表形式编辑","Edit as text":"以文本形式编辑","Encrypt file":"加密文件","Encryption":"加密方式","Encryption changed":"加密方式已更改","Encryption modules:":"加密模块:","Enter URL":"输入地址","Enter access key":"输入访问密钥","Enter account name":"输入帐户名称","Enter backup passphrase, if any":"输入备份密码 (若存在)","Enter configuration details":"进入详细配置","Enter container name":"输入容器名称","Enter encryption passphrase":"输入加密密码","Enter expression here":"在此输入表达式","Enter folder path name":"输入文件夹路径名","Enter one option per line in command-line format, eg. {0}":"以命令行格式,一行一个参数,例如 {0}","Enter the destination path":"输入目标路径","Error":"错误","Error!":"错误!","Errors and crashes":"错误,崩溃","Exclude":"排除","Exclude directories whose names contain":"排除文件夹,名称包括","Exclude expression":"排除表达式","Exclude file":"排除文件","Exclude file extension":"排除文件后缀","Exclude files whose names contain":"排除文件,名称包括","Exclude folder":"排除文件夹","Exclude regular expression":"排除正则表达式","Existing file found":"发现已存在文件","Experimental":"Experimental","Export":"导出","Export ...":"导出…","Export backup configuration":"导出备份配置","Export configuration":"导出配置","Exporting ...":"正在导出…","FTP (Alternative)":"FTP (备选)","Failed to build temporary database: {{message}}":"构建临时数据库失败: {{message}}","Failed to connect:":"连接失败:","Failed to connect: {{message}}":"连接失败:{{message}}","Failed to delete:":"删除失败:","Failed to fetch path information: {{message}}":"获取路径信息失败: {{message}}","Failed to import:":"导入失败:","Failed to read backup defaults:":"读取备份默认设置失败:","Failed to restore files: {{message}}":"恢复文件失败: {{message}}","Failed to save:":"保存失败:","Fetching path information ...":"获取路径信息…","File":"文件","Files larger than:":"文件大于","Filters":"过滤条件","Finished!":"已完成!","First run setup":"初始配置","Folder":"文件夹","Folder path":"文件夹路径","Fri":"周五","GByte":"GB","GByte/s":"GB/s","GCS Project ID":"GCS 项目 ID","General":"常规","General backup settings":"常规备份设置","General options":"常规选项","Generate":"生成","Generate IAM access policy":"生成 IAM 访问策略","Getting file versions ...":"正在读取文件版本...","Hidden files":"隐藏文件","Hide":"隐藏","Hide hidden folders":"隐藏被隐藏的文件夹","Home":"首页","Hours":"小时","How do you want to handle existing files?":"你想要怎样处理已存在的文件?","Hyper-V Machine":"Hyper-V 虚拟机","Hyper-V Machine:":"Hyper-V 虚拟机:","Hyper-V Machines":"Hyper-V 虚拟机","ID:":"ID:","If a date was missed, the job will run as soon as possible.":"如果时间错过,任务将尽快运行。","If the backup and the remote storage is out of sync, Duplicati will require that you perform a repair operation to synchronize the database.\\nIf the repair is unsuccesful, you can delete the local database and re-generate.":"如果备份和远程存储不同步,Duplicati 需要你执行修复操作来同步数据库。\\n如果修复失败,你可以删除本地数据库并重新生成。","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"如果备份文件没有自动下载,右键单击并选择 "另存为…" ","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"如果备份文件没有自动下载,右键单击并选择 "另存为…" ","If you do not enter a path, all files will be stored in the login folder.\nAre you sure this is what you want?":"如果你不输入路径,所有文件将存储在登录时的默认文件夹。\n你确定这是你想要的吗?","If you do not enter an API Key, the tenant name is required":"如果你不输入 API 密钥,则需要输入租户名称","If you want to use the backup later, you can export the configuration before deleting it":"如果你需要之后使用备份,你可以在删除它之前导出配置","If your machine is in a multi-user environment (i.e. the machine has more than one account), you need to set a password to prevent other users from accessing data on your account.\nDo you want to set a password now?":"如果你的机器处于多用户环境(比如机器上有多个帐户),你需要设定一个密码来防止其他帐户访问你的数据。\n你要现在设定密码吗?","Import":"导入","Import Destination URL":"导入地址","Import backup configuration":"导入备份配置","Import completed, but no certificates were found after the import":"导入完成,但是未能找到证书","Import failed":"导入失败","Import from a file":"从文件导入","Importing ...":"正在导入…","Include a file?":"包含一个文件?","Include expression":"包含表达式","Include regular expression":"包含正则表达式","Incorrect answer, try again":"验证失败,请重试","Individual builds for developers only.":"面向开发者的个人构建","Information":"信息","Install":"安装","Install failed:":"安装失败:","Invalid characters in path":"路径中包含无效字符","Invalid retention time":"无效的保留时间","It is possible to connect to some FTP without a password.\nAre you sure your FTP server supports password-less logins?":"某些 FTP 不需要密码\n你确定你的 FTP 服务器支持无密码登陆吗?","KByte":"KB","KByte/s":"KB/s","Language in user interface":"界面语言","Last month":"上月","Last successful run:":"上一次成功运行于:","Latest":"最新","Libraries":"第三方库","Linux":"hadoop01","Listing backup dates ...":"正在列举备份日期…","Listing remote files ...":"正在列举远程文件…","Live":"实时","Load a configuration from an exported job or a storage provider":"从已导出的任务文件或者存储提供商处载入配置","Load destination from an exported job or a storage provider":"从已导出的任务文件或存储提供商处载入目标位置","Load older data":"载入之前的数据","Loading ...":"载入中…","Loading remote storage usage ...":"正在载入远程存储使用量…","Local database for":"本地数据库","Local database path:":"本地数据库路径:","Local storage":"本地存储","Location":"位置","Location where buckets are created":"请指定 Bucket 创建区域","Log data for {{Backup.Backup.Name}}":"{{Backup.Backup.Name}} 的日志","Log data from the server":"Duplicati 服务器日志","Log out":"登出","MByte":"MB","MByte/s":"MB/s","Maintenance":"维护","Manually type path":"手动输入路径…","Max download speed":"最大下载速度","Max upload speed":"最大上传速度","Menu":"菜单","Microsoft SQL Database:":"Microsoft SQL 数据库:","Microsoft SQL Databases":"Microsoft SQL 数据库","Minimum redundancy":"最小冗余","Minimum redundancy is 1.0":"最小冗余为 1.0","Minutes":"分钟","Missing name":"缺少名称","Missing passphrase":"缺少密码","Missing sources":"缺少源数据","Mon":"周一","Months":"月","Move existing database":"移动已有数据库","Move failed:":"移动失败:","My Documents":"我的文档","My Music":"我的音乐","My Photos":"我的照片","My Pictures":"我的图片","Name":"名称","Never":"从不","New update found: {{message}}":"发现新版本: {{message}}","New user name is {{user}}.\nUpdated credentials to use the new limited user":"新用户名为 {{user}}\n已为新的受限用户更新证书","Next":"下一步","Next scheduled run:":"下一次计划运行于:","Next scheduled task:":"下一次计划任务:","Next task:":"下一次任务:","Next time":"下一次运行时间:","No":"否","No certificate was specified previously, please verify with the server administrator that the key is correct: {{key}} \n\nDo you want to approve the reported host key?":"未预先指定证书,请与服务器管理员确认密钥 {{key}} 是否正确\n\n你想要允许此主机密钥吗?","No editor found for the "{{backend}}" storage type":"未找到 "{{backend}}" 存储类型的编辑器","No encryption":"无加密","No items selected":"未选中项目","No items to restore, please select one or more items":"未恢复项目,请至少选择一项","No passphrase entered":"未输入密码","No scheduled tasks":"暂无计划任务","No, my machine has only a single account":"否,我的机器只有一个帐户","Non-matching passphrase":"密码不匹配","None / disabled":"无 / 禁用","OK":"确定","OSX":"OSX","OpenStack AuthURI":"OpenStack 认证地址","OpenStack Object Storage / Swift":"OpenStack 对象存储 / Swift","Operation failed:":"操作失败:","Operations:":"操作:","Optional authentication password":"如果需要,请输入认证密码","Optional authentication username":"如果需要,请输入认证用户名","Options":"选项","Options added here are applied to all backups, but can be overridden in each individual backup":"此处选项将对所有备份生效,但你可以单独设置备份来覆盖它","Original location":"原位置","Others":"其它","Overwrite":"覆盖","Passphrase":"密码","Passphrase (if encrypted)":"密码 (若启用加密)","Passphrase changed":"密码已更改","Passphrases are not matching":"密码不匹配","Password":"密码","Passwords do not match":"密码不匹配","Patching files with local blocks ...":"正在使用本地块修补文件…","Path not found":"路径未找到","Path on server":"服务器上路径","Path or subfolder in the bucket":" Bucket 中路径或子文件夹","Pause":"暂停","Pause after startup or hibernation":"开机或唤醒后暂缓","Pause options":"暂停选项","Permissions":"权限","Pick location":"选择位置","Point to your backup files and restore from there":"指向你的备份文件,将从中恢复","Port":"端口","Previous":"上一步","ProjectID is optional if the bucket exist":"若 Bucket 存在, 则项目ID 可选","Proprietary":"专有","Purging files ...":"正在清除文件...","Rebuilding local database ...":"正在重新构建本地数据库…","Recreate (delete and repair)":"重建 (删除并修复)","Recreating database ...":"正在重建数据库…","Registering temporary backup ...":"正在注册临时备份…","Relative paths not allowed":"不允许相对路径","Reload":"重新载入","Remote":"远程","Remove":"移除","Remove option":"移除选项","Repair":"修复","Reparing ...":"正在修复…","Repeat Passphrase":"重复密码","Reporting:":"报告:","Reset":"重置","Restore":"恢复文件","Restore files":"恢复文件","Restore files ...":"恢复文件…","Restore files from {{backupname}}":"从 {{backupname}} 恢复文件","Restore from":"恢复自","Restore from backup configuration":"从备份配置中恢复","Restore from configuration ...":"从配置中恢复...","Restore options":"恢复选项","Restore read/write permissions":"恢复读写权限","Restoring files ...":"正在恢复文件…","Resume":"恢复运行","Run again every":"重复运行每","Run now":"立即运行","Running ...":"正在运行…","Running ....":"正在运行...","Running commandline entry":"正在运行命令行","Running task:":"运行中的任务:","S3 Compatible":"S3 兼容","Same as the base install version: {{channelname}}":"与当前安装版本一致:{{channelname}}","Sat":"周六","Save":"保存","Save and repair":"保存并修复","Save different versions with timestamp in file name":"保存不同版本 (文件名中添加时间戳)","Save immediately":"立即保存","Scanning existing files ...":"正在扫描存在的文件…","Scanning for local blocks ...":"正在扫描本地文件块…","Schedule":"计划","Search":"搜索","Search for files":"搜索文件","Seconds":"秒","Select a log level and see messages as they happen:":"选择日志级别并实时查看","Select files":"选择文件","Server":"服务器","Server and port":"服务器与端口","Server hostname or IP":"服务器主机名或 IP","Server is currently paused,":"服务器暂停中,","Server is currently paused, do you want to resume now?":"Duplicati 服务器暂停中,你想要立即恢复运行吗?","Server password":"服务器密码","Server paused":"服务器已暂停","Server state properties":"Duplicati 服务器状态","Settings":"设置","Show":"查看","Show advanced editor":"显示高级编辑器","Show hidden folders":"显示隐藏文件夹","Show log":"日志","Show log ...":"查看日志…","Show treeview":"显示树状视图","Sia server password":"Sia 服务器密码","Some OpenStack providers allow an API key instead of a password and tenant name":"一些 OpenStack 提供商使用 API 密钥,而不是租户名称和密码","Source Data":"源数据","Source data":"源数据","Source folders":"源文件夹","Source:":"源数据:","Specific builds for developers only.":"面向开发者的特定构建","Standard protocols":"标准协议","Starting ...":"准备开始…","Starting the restore process ...":"正在开始恢复操作…","Stop after the current file":"当前文件完成后停止","Stop after upload":"上传完成后停止","Stop now":"立即停止","Stop running backup":"停止正在运行的备份","Stop running task":"停止正在运行的任务","Stopping after upload:":"于此完成后停止:","Stopping task:":"正在停止任务:","Storage Type":"存储类型","Storage class":"存储类别","Storage class for creating a bucket":"创建 Bucket 的存储类别","Stored":"存档","Strong":"强度高","Success":"成功","Sun":"周日","Symbolic link":"符号链接","System default ({{levelname}})":"默认 ({{levelname}})","System files":"系统文件","System info":"系统信息","System properties":"系统属性","TByte":"TB","TByte/s":"TB/s","Target path, ie /backup":"目标路径,例如 /backup","Task is running":"任务正在运行中","Temporary files":"临时文件","Tenant Name":"租户名称","Test connection":"测试连接","Testing ...":"正在测试…","Testing connection ...":"正在测试连接…","Testing permissions ...":"正在测试权限…","Testing permissions...":"正在测试权限…","The bucket name should be all lower-case, convert automatically?":"Bucket 名称应当是全小写,自动转换?","The bucket name should start with your username, prepend automatically?":"Bucket 名称应该以你的用户名开头,自动加上?","The connection to the server is lost, attempting again in {{time}} ...":"服务器连接中断,将在 {{time}} 后重新连接…","The dark theme (by Michal)":"黑色主题 (by Michal)","The default blue on white theme (by Alex)":"默认蓝白主题 (by Alex)","The host key has changed, please check with the server administrator if this is correct, otherwise you could be the victim of a MAN-IN-THE-MIDDLE attack.\n\nDo you want to REPLACE your CURRENT host key \"{{prev}}\" with the REPORTED host key: {{key}}?":"主机密钥已更改,请与服务器管理员确认其是否正确,否则你可能正在被中间人攻击。\n\n你想要把现有密钥 \"{{prev}}\" 替换为 {{key}} 吗?","The path does not appear to exist, do you want to add it anyway?":"路径似乎不存在,你确定要添加它吗?","The path does not end with a '{{dirsep}}' character, which means that you include a file, not a folder.\n\nDo you want to include the specified file?":"路径不应该以 '{{dirsep}}' 字符结尾,这意味你想要包含一个文件而不是文件夹。\n你想要包含指定文件吗?","The path must be an absolute path, i.e. it must start with a forward slash '/'":"路径必须为绝对路径,也就是以斜杠 '/' 开头","The path should start with \"{{prefix1}}\" or \"{{prefix2}}\", otherwise you will not be able to see the files in the HubiC web interface.\n\nDo you want to add the prefix to the path automatically?":"路径应当以 \"{{prefix1}}\" 或 \"{{prefix2}}\" 开头,否则你不会在 HubiC 网页界面上看到文件。\n你需要自动给路径添加上前缀吗?","The region parameter is only applied when creating a new bucket":"\"地区\"参数只在创建新 Bucket 时生效","The region parameter is only used when creating a bucket":"\"参数只在创建新 Bucket 时使用","The server certificate could not be validated.\nDo you want to approve the SSL certificate with the hash: {{hash}}?":"服务器证书验证失败\n你想要允许此 SSL证书吗?其哈希值为 {{hash}}","The storage class affects the availability and price for a stored file":"存储类别影响文件可用性和价格","The target folder contains encrypted files, please supply the passphrase":"目标文件夹包含加密文件,请提供密码","The user has too many permissions. Do you want to create a new limited user, with only permissions to the selected path?":"此用户权限太多,你想要创建一个只能访问所选路径的受限用户吗?","This backup was created on another operating system. Restoring files without specifying a destination folder can cause files to be restored in unexpected places. Are you sure you want to continue without choosing a destination folder?":"此备份创建于其他操作系统上。恢复时不指定目标文件夹可能会使文件恢复到未知的位置。你确定要继续吗?","This month":"本月","This week":"本周","Throttle settings":"限流设置","Thu":"周四","To File":"导出为文件","To confirm you want to delete all remote files for \"{{name}}\", please enter the word you see below":"为确认你想要删除 \"{{name}}\" 的所有远程文件,请输入以下单词","To export without a passphrase, uncheck the \"Encrypt file\" box":"如果不想使用密码加密导出的文件,请去除勾选\"加密文件\"","Today":"今天","Trust host certificate?":"信任主机证书?","Trust server certificate?":"信任服务器证书?","Try out the new features we are working on. Don't use with important data.":"尝试我们开发的新特性,注意不要使用在重要数据上","Tue":"周二","Type to highlight files":"输入以高亮文件","Unknown backup size and versions":"未知的备份大小和版本","Until resumed":"直到手动恢复运行","Update channel":"更新分支","Update failed:":"更新失败:","Updating with existing database":"正在更新存在的数据库","Upload volume size":"上传分卷大小","Uploading verification file ...":"正在上传校验文件…","Usage statistics":"使用情况统计","Usage statistics, warnings, errors, and crashes":"使用情况统计,警告,错误,崩溃","Use SSL":"启用 SSL","Use existing database?":"使用已存在的数据库?","Use weak passphrase":"确定使用弱密码","Useless":"无用","User data":"用户数据","User has too many permissions":"用户权限太多","User interface settings":"界面设置","Username":"用户名","Validating ...":"正在验证…","Verify files":"校验文件","Verifying ...":"正在校验…","Verifying answer":"正在验证","Verifying backend data ...":"正在校验后端数据…","Verifying remote data ...":"正在校验远程数据…","Verifying restored files ...":"正在校验恢复出的文件…","Very strong":"强度非常高","Very weak":"强度非常低","Visit us on":"了解我们","WARNING: The remote database is found to be in use by the commandline library":"警告:远程数据库正在被命令行库使用","WARNING: This will prevent you from restoring the data in the future.":"警告:这将使你以后不再能恢复数据","Waiting for task to begin":"等待任务开始…","Waiting for task to start ....":"正在等待任务开始...","Waiting for upload ...":"等待上传完成…","Warnings, errors and crashes":"警告,错误,崩溃","We recommend that you encrypt all backups stored outside your system":"我们推荐加密所有保存在第三方系统中的数据","Weak":"强度低","Weak passphrase":"弱密码","Wed":"周三","Weeks":"周","Where do you want to restore from?":"你想从哪里恢复呢?","Where do you want to restore the files to?":"你想把文件恢复到哪里?","Windows":"Windows","Years":"年","Yes":"是","Yes, I have stored the passphrase safely":"是,我已将密码安全保存","Yes, I'm brave!":"是,我无所谓","Yes, please break my backup!":"是,请清除我的备份","Yesterday":"昨天","You appear to be running Mono with no SSL certificates loaded.\nDo you want to import the list of trusted certificates from Mozilla?":"看起来 Mono 当前没有载入 SSL 证书。\n你想要从 Mozilla 导入可信任的证书吗?","You are changing the database path away from an existing database.\nAre you sure this is what you want?":"你正在改变数据库路径。\n你确定想要这么做吗?","You are currently running {{appname}} {{version}}":"当前正在运行 {{appname}} {{version}}","You can stop the backup immediately, or stop after the current file has been uploaded.":"你可以立即停止备份,也可以在当前文件完成上传后停止。","You can stop the task immediately, or allow the process to continue its current file and the stop.":"你可以立即停止任务,也可以在当前文件处理完成后停止。","You have changed the encryption mode. This may break stuff. You are encouraged to create a new backup instead":"你已经更改了加密方式,这可能破坏备份。你更应当创建新备份。","You have changed the passphrase, which is not supported. You are encouraged to create a new backup instead.":"你已经更改密码,这是不支持的操作。你更应当创建新备份。","You have chosen not to encrypt the backup. Encryption is recommended for all data stored on a remote server.":"你已选择不加密备份,推荐加密所有存储在远程服务器上的数据。","You have chosen to restore to a new location, but not entered one":"你选择了恢复到新位置,却没有指定具体位置","You have generated a strong passphrase. Make sure you have made a safe copy of the passphrase, as the data cannot be recovered if you lose the passphrase.":"你已经生成了一个强密码,确保你安全记录下了此密码,否则,万一你丢失了密码,数据将不能恢复。","You must choose at least one source folder":"你必须选择至少一个源文件夹","You must enter a name for the backup":"你必须输入备份名称","You must enter a passphrase or disable encryption":"你必须输入加密密码或禁用加密","You must enter a positive number of backups to keep":"你输入要保留的版本数必须为正","You must enter a tenant name if you do not provide an API Key":"如果你没有提供 API 密钥,你必须输入租户名称","You must enter a valid duration for the time to keep backups":"你必须输入有效的保留时长","You must enter either a password or an API Key":"你必须输入一个密码或 API 密钥","You must enter either a password or an API Key, not both":"你必须只输入一个密码或 API 密钥,而不是两者同时","You must fill in the password":"你必须填写密码","You must fill in the server name or address":"你必须填写服务器主机名或地址","You must fill in the username":"你必须填写用户名","You must fill in {{field}}":"你必须填写 {{field}}","You must select or fill in the AuthURI":"你必须选择或填写认证地址","You must select or fill in the server":"你必须选择或填写服务器","You must specify a path":"你必须指定路径","Your files and folders have been restored successfully.":"文件恢复成功!","Your passphrase is easy to guess. Consider changing passphrase.":"你的密码很容易被破解,请考虑更换一个强密码","bucket/folder/subfolder":"Bucket / 文件夹 / 子文件夹","byte":"B","byte/s":"B/s","custom":"自定义","resume now":"立即恢复运行","{{appname}} was primarily developed by {{dev1}} and {{dev2}}. {{appname}} can be downloaded from {{websitename}}. {{appname}} is licensed under the {{licensename}}.":"{{appname}} 主要由 {{dev1}} 和 {{dev2}} 开发. {{appname}} 可以从 {{websitename}} 下载. {{appname}} 采用 {{licensename}} 授权.","{{files}} files ({{size}}) to go {{speed_txt}}":"剩余 {{files}} 个文件 ({{size}}) {{speed_txt}}","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Version":"{{item.Backup.Metadata.TargetSizeString}} / {{$count}} 个版本","{{number}} Hour":"{{number}} 小时","{{number}} Minutes":"{{number}} 分钟","{{time}} (took {{duration}})":"{{time}} (耗时 {{duration}})"}); gettextCatalog.setStrings('zh_HK', {"- pick an option -":"選擇一個選項","...loading...":"...載入中...","API Key":"API Key","AWS IAM Policy":"AWS IAM 原則","About":"關於","About {{appname}}":"關於 {{appname}}","Access denied":"存取被拒","Account name":"用戶名","Activate":"啟動","Activate failed:":"啟動失敗:","Add a new backup":"加入新的備份","Add a path directly":"直接加入路徑","Add advanced option":"新增進階選項","Add backup":"新增備份","Add filter":"新增過濾器","Add path":"加入路徑","Advanced Options":"進階選項","Advanced options":"進階選項","Advanced:":"進階:","All Hyper-V Machines":"所有Hyper-V機器","All Microsoft SQL Databases":"所有Microsoft SQL數據庫","Allow remote access (requires restart)":"允許遠端存取(需要重新啟動)","Allowed days":"允許日子","An existing file was found at the new location":"在新的位置上發現有檔案存在","Anonymous usage reports":"匿名使用報告","AuthID":"AuthID","Authentication password":"認證密碼","Authentication username":"認證用戶名","Autogenerated passphrase":"自動產生密碼","Automatically run backups.":"自動執行備份","B2 Account ID":"B2 帳號 ID","Back":"返回","Backup destination":"備份目的地","Backup location":"備份位置","Backup:":"備份:","Beta":"Beta","Browse":"瀏覽","Browser default":"瀏覽預設","Bucket Name":"Bucket 名稱","Bucket create location":"Bucket 建立位置","Bucket create region":"Bucket 建立區域","Bucket name":"Bucket 名稱","Bucket storage class":"Bucket 儲存等級","Building list of files to restore ...":"建立還原的檔案清單中...","Building partial temporary database ...":"建立部分臨時資料庫中...","Busy ...":"忙碌...","Canary":"Canary","Cancel":"Cancel","Changelog":"更新日誌","Changelog for {{appname}} {{version}}":"{{appname}} {{version}} 更新日誌","Check failed:":"檢查失敗:","Check for updates now":"立即檢查更新","Checking ...":"檢查中...","Checking for updates ...":"檢查更新中...","Commandline ...":"命令列...","Compact now":"立即壓縮","Compacting remote data ...":"壓縮遠端資料中...","Completing backup ...":"正在完成備份...","Completing previous backup ...":"正在完成上次備份...","Compression modules:":"壓縮模組:","Computer":"電腦","Configuration file:":"設定檔案:","Configuration:":"設定:","Configure a new backup":"設定新備份","Confirm delete":"確認刪除","Confirmation required":"需要確認","Connect":"連接","Connect now":"立即連接","Connecting to server ...":"正在連接伺服器...","Connecting to task ....":"正在連接工作...","Connecting...":"連接中...","Connection lost":"連接中斷","Connection worked!":"連接成功!","Container name":"容器名稱","Container region":"容器區域","Continue":"繼續","Continue without encryption":"繼續但不加密","Copied!":"已複製!","Copy Destination URL to Clipboard":"複製目的地網址到剪貼簿","Copy failed. Please manually copy the URL":"複製失敗。請手動複製網址","Counting ({{files}} files found, {{size}})":"點算中(找到 {{files}} 個檔案,{{size}})","Create folder?":"建立資料夾?","Created new limited user":"已建立受限制的使用者","Creating new user with limited access ...":"建立受限制的使用者中...","Creating target folders ...":"建立目標資料夾中...","Creating temporary backup ...":"建立臨時備份中...","Creating user...":"建立使用者中...","Current version is {{versionname}} ({{versionnumber}})":"現時版本 {{versionname}} ({{versionnumber}})","Custom location ({{server}})":"自訂位置({{server}})","Custom server url ({{server}})":"自訂伺服器地址({{server}})","Database ...":"資料庫...","Days":"Days","Default":"預設","Default ({{channelname}})":"預設 ({{channelname}})","Default options":"預設選項","Delete":"刪除","Delete ...":"刪除...","Delete backup":"刪除備份","Delete local database":"刪除本地資料庫","Delete remote files":"刪除遠端檔案","Delete the local database":"刪除本地資料庫","Deleting remote files ...":"刪除遠端文件中...","Deleting unwanted files ...":"刪除不必要的文件中...","Desktop":"桌面","Destination":"目的地","Direct restore from backup files ...":"直接從備份檔案中還原...","Disabled":"已停用","Dismiss":"略過","Display and color theme":"顯示及顏色主題","Do you really want to delete the backup: \"{{name}}\" ?":"您真的確定要刪除備份: \"{{name}}\" ?","Do you really want to delete the local database for: {{name}}":"您真的確定要刪除 \"{{name}}\" 的本地數據庫?","Donate":"捐贈","Donation messages":"捐贈訊息","Donation messages are hidden, click to show":"捐贈訊息已隱藏,按此顯示。","Donation messages are visible, click to hide":"捐贈訊息顯示中,按此隱藏。","Done":"完成","Download":"下載","Downloading ...":"下載中...","Downloading files ...":"下載文件中...","Downloading update...":"下載更新中...","Duplicate option {{opt}}":"Duplicati 選項 {{opt}}","Duplicati Website":"Duplicati 網站","Duplicati forum":"Duplicati 討論區","Edit ...":"修改...","Encrypt file":"加密檔案","Encryption modules:":"加密模組:","Enter URL":"輸入網址","Enter access key":"輸入Access Key","Enter account name":"輸入帳戶名稱","Enter backup passphrase, if any":"輸入備份密碼(如有)","Enter container name":"輸入容器名稱","Enter encryption passphrase":"輸入加密密碼","Enter folder path name":"輸入資料夾路徑名稱","Enter the destination path":"輸入目的地路徑","Error":"錯誤","Error!":"錯誤!","Exclude":"排除","Exclude directories whose names contain":"排除含有此名稱的資料夾","Exclude expression":"排除表達式","Exclude file":"排除檔案","Exclude file extension":"排除副檔名","Exclude files whose names contain":"排除含有此名稱的檔案","Exclude folder":"排除資料夾","Exclude regular expression":"排除正規表達式","Existing file found":"找到已存在的檔案","Experimental":"實驗性","Export":"匯出","Export ...":"匯出...","Export backup configuration":"匯出備份設定","Export configuration":"匯出設定","Exporting ...":"匯出中...","FTP (Alternative)":"FTP(備用)","Failed to build temporary database: {{message}}":"建立臨時資籵庫失敗:{{message}}","Failed to connect:":"連接失敗:","Failed to connect: {{message}}":"連接失敗:{{message}}","Failed to delete:":"刪除失敗:","Failed to fetch path information: {{message}}":"無法取得路徑資料:{{message}}","Failed to import:":"匯入失敗","Failed to read backup defaults:":"讀取預設備份失敗:","Failed to restore files: {{message}}":"還原檔案失敗:{{message}}","Failed to save:":"儲存失敗:","Fetching path information ...":"取得路徑資料中...","File":"檔案","Files larger than:":"檔案大於","Filters":"過濾器","Finished!":"已完成!","Folder":"資籵夾","Folder path":"資料夾路徑","Fri":"星期五","GByte":"GByte","GByte/s":"GByte/s","GCS Project ID":"GCS Project ID","General":"一般","General backup settings":"一般備份設定","General options":"一般設定","Generate":"產生","Generate IAM access policy":"產生 IAM 存取原則","Getting file versions ...":"取得檔案版本中...","Hidden files":"隱藏的檔案","Hide":"隱藏","Hide hidden folders":"不顯示隱藏的資料夾","Home":"首頁","Hours":"小時","How do you want to handle existing files?":"您想怎樣處理已存在的檔案?","Hyper-V Machine":"Hyper-V 機器","Hyper-V Machine:":"Hyper-V 機器:","Hyper-V Machines":"Hyper-V 機器","ID:":"ID:","If a date was missed, the job will run as soon as possible.":"如果錯過了時間,將儘快執行工作。","Import":"匯入","Import Destination URL":"匯入目的地網址","Import backup configuration":"匯入備份設定","Import completed, but no certificates were found after the import":"匯入完成,但沒有找到證書","Import failed":"匯入失敗","Import from a file":"從檔案匯入","Importing ...":"匯入中...","Include a file?":"包括一個檔案?","Include expression":"包括表達式","Include regular expression":"包括正規表達式","Incorrect answer, try again":"答案錯誤,請重試","Information":"訊息","Install":"安裝","Install failed:":"安裝失敗:","Invalid characters in path":"路徑中有無效的字符","Invalid retention time":"無效的保留時間","KByte":"KByte","KByte/s":"KByte/s","Language in user interface":"界面語言","Last month":"上個月","Last successful run:":"上次成功執行:","Latest":"最新","Listing backup dates ...":"列出備份日期中...","Listing remote files ...":"列出遠端檔案中...","Live":"即時","Load older data":"載入舊資料","Loading ...":"載入中...","Loading remote storage usage ...":"載入遠端儲存使用量中...","Local database for":"本地資連庫","Local database path:":"本地資料庫路徑:","Local storage":"本地儲存","Location":"位置","Log data from the server":"來自伺服器的記錄","Log out":"登出","MByte":"MByte","MByte/s":"MByte/s","Maintenance":"維護","Manually type path":"手動輸入路徑","Max download speed":"最高下載速度","Max upload speed":"最高上傳速度","Menu":"選單","Microsoft SQL Database:":"Microsoft SQL 資料庫:","Microsoft SQL Databases":"Microsoft SQL 資料庫","Minutes":"分鐘","Missing name":"沒有名稱","Missing passphrase":"沒有密碼","Missing sources":"沒有來源","Mon":"星期一","Months":"月","Move existing database":"移動現時的資料庫","Move failed:":"移動失敗:","My Documents":"我的文件","My Music":"我的音樂","My Photos":"我的相片","My Pictures":"我的圖片","Name":"名稱","Never":"永不","New update found: {{message}}":"找到新版本:{{message}}","New user name is {{user}}.\nUpdated credentials to use the new limited user":"新用戶為 {{username}}。\n已更新憑證以使用該受管制用戶","Next":"下一步","Next scheduled run:":"下次預定報行的時間:","Next scheduled task:":"下次預定報行的工作:","Next task:":"下次的工作:","Next time":"下次執行時間:","No":"否","No certificate was specified previously, please verify with the server administrator that the key is correct: {{key}} \n\nDo you want to approve the reported host key?":"先前並未指定過證書,請與伺服管理員驗證此密匙是否正確:{key}}\n\n您要接受這個主題密匙嗎?","No encryption":"無加密","No items selected":"沒有選擇任何項目","No items to restore, please select one or more items":"沒有需要還原的項目,請擇一個或以上的項目","No passphrase entered":"沒有輸入密碼","No scheduled tasks":"沒有預定的工作","Non-matching passphrase":"密碼不正確","None / disabled":"沒有/已停用","OK":"確定","Options":"選項","Others":"Others","Overwrite":"覆蓋","Passphrase":"密碼","Passphrase (if encrypted)":"密碼(如已加密)","Passphrase changed":"已更改密碼","Passphrases are not matching":"密碼不相同","Password":"密碼","Passwords do not match":"密碼不正確","Path not found":"找不到路徑","Path on server":"伺服器上路徑","Pause":"暫停","Pause after startup or hibernation":"啟動或休眠後暫停","Pause options":"暫停選項","Permissions":"權限","Pick location":"選擇位置","Port":"埠","Previous":"Previous","Purging files ...":"清理檔案...","Rebuilding local database ...":"重建本機資料庫中...","Recreate (delete and repair)":"重建(刪除及修復)","Recreating database ...":"重建資料庫中...","Remote":"遠端","Remove":"移除","Remove option":"移除選項","Repair":"修復","Reparing ...":"修復中...","Repeat Passphrase":"重覆密碼","Reporting:":"報告︰","Reset":"重設","Restore":"還原","Restore files":"還原檔案","Restore files ...":"還原檔案...","Restore files from {{backupname}}":"從 {{backupname}} 還原檔案","Restore from":"從...還原檔案","Restore from backup configuration":"從備份設定還原","Restore from configuration ...":"從設定還原...","Restore options":"還原選項","Restoring files ...":"還原檔案中...","Resume":"繼續","Run again every":"每...重覆執行","Run now":"立即執行","Running ...":"執行中...","Running ....":"執行中...","Running task:":"正在執行工作:","S3 Compatible":"S3 相容","Sat":"星期六","Save":"儲存","Save and repair":"儲存並修復","Save immediately":"立即儲存","Scanning existing files ...":"正在掃描已存在檔案...","Schedule":"排程","Search":"搜尋","Search for files":"搜尋檔案","Seconds":"秒","Select files":"選擇檔案","Server":"伺服器","Server and port":"伺服器與連接埠","Server hostname or IP":"伺服器名稱或 IP","Server is currently paused,":"伺服器目前已暫停,","Server is currently paused, do you want to resume now?":"伺服器暫停中,您要現在立即繼續嗎?","Server password":"伺服器密碼","Server paused":"伺服器已暫停","Server state properties":"伺服器狀態","Settings":"設定","Show":"顯示","Show advanced editor":"顯示進階編輯","Show hidden folders":"顯示隱藏的資料夾","Show log":"顯示記錄","Show log ...":"顯示記錄...","Show treeview":"顯示樹狀檢視","Sia server password":"Sia 伺服器密碼","Source Data":"來源資料","Source data":"來源資料","Source folders":"來源資料夾","Source:":"來源:","Standard protocols":"標準通訊協定","Starting ...":"開始中...","Starting the restore process ...":"開始還原程序中...","Stop after the current file":"現時檔案完成後停止","Stop after upload":"上傳後停止","Stop now":"立即停止","Stop running backup":"停止正在進行的備份","Stop running task":"停止正在進行的工作","Stopping after upload:":"上傳後停止:","Stopping task:":"停止工作中:","Storage Type":"儲存類型","Storage class":"儲存等級","Stored":"已儲存","Strong":"強","Success":"成功","Sun":"星期日","Symbolic link":"符號連結","System default ({{levelname}})":"系統預設({{levelname}})","System files":"系統檔案","System info":"系統資訊","System properties":"系統內容","TByte":"TByte","TByte/s":"TByte/s","Target path, ie /backup":"目的地路徑,例如 /backup","Task is running":"工作執行中","Temporary files":"暫存檔案","Test connection":"測試連線","Testing ...":"測試中...","Testing connection ...":"測試連線中...","Testing permissions ...":"測試權限中...","Testing permissions...":"測試權限中...","The connection to the server is lost, attempting again in {{time}} ...":"伺服器連線中斷,{{time}} 後重試...","The dark theme (by Michal)":"深色主題(Michai設計)","The default blue on white theme (by Alex)":"預設的藍白色主題(Alexi設計)","This month":"本月","This week":"本週","Thu":"星期四","To File":"到檔案","Today":"今日","Trust server certificate?":"信任伺服器證書?","Tue":"星期二","Until resumed":"直至手動繼續","Update channel":"更新頻道","Update failed:":"更新失敗:","Use SSL":"使用 SSL","Use weak passphrase":"使用強度為弱的密碼","Useless":"不使用","Username":"使用者","Verify files":"驗證檔案","Verifying ...":"驗證中...","Verifying answer":"驗證答案中...","Verifying remote data ...":"驗證遠端資料中...","Verifying restored files ...":"驗證已還原的檔案中..","Very strong":"十分強","Very weak":"十分弱","Weak passphrase":"弱密碼","Wed":"星期三","Weeks":"星期","Years":"年","Yes":"是","Yesterday":"Yesterday","You have chosen not to encrypt the backup. Encryption is recommended for all data stored on a remote server.":"您選擇了不加密備份。建議備份所有儲存在遠端伺服器上資料。","You must fill in the server name or address":"您必須填寫伺服器名稱或地址","You must select or fill in the server":"您必須選擇或填寫伺服器","byte":"byte","byte/s":"byte/s","custom":"custom","resume now":"立即繼續","{{number}} Hour":"{{number}} 小時","{{number}} Minutes":"{{number}} 分鐘","{{time}} (took {{duration}})":"{{time}} (花費 {{duration}})"}); - gettextCatalog.setStrings('zh_TW', {"- pick an option -":"選擇一個選項","...loading...":"...載入中...","API Key":"API Key","AWS Access ID":"AWS Access ID","AWS Access Key":"AWS Access Key","AWS IAM Policy":"AWS IAM Policy","About":"關於","About {{appname}}":"關於 {{appname}}","Access Key":"Access Key","Access denied":"拒絕存取","Access to user interface":"進入使用者介面","Account name":"帳號名稱","Activate":"啟用","Activate failed:":"啟用失敗","Add a new backup":"新增備份","Add a path directly":"直接增加資料路徑","Add advanced option":"加入進階選項","Add backup":"加入備份","Add filter":"加入篩選條件","Add path":"加入路徑","Adjust bucket name?":"調整 bucket 名稱?","Adjust path name?":"調整 path 名稱?","Advanced Options":"進階選項","Advanced options":"進階選項","Advanced:":"進階:","All Hyper-V Machines":"全部 Hyper-V 主機","All Microsoft SQL Databases":"全部 Microsoft SQL 資料庫","All usage reports are sent anonymously and do not contain any personal information. They contain information about hardware and operating system, the type of backend, backup duration, overall size of source data and similar data. They do not contain paths, filenames, usernames, passwords or similar sensitive information.":"All usage reports are sent anonymously and do not contain any personal information. They contain information about hardware and operating system, the type of backend, backup duration, overall size of source data and similar data. They do not contain paths, filenames, usernames, passwords or similar sensitive information.","Allow remote access (requires restart)":"允許遠端存取(需要重新啟動)","Allowed days":"允許日","An existing file was found at the new location":"新的位置發現已既有檔案存在","An existing file was found at the new location\nAre you sure you want the database to point to an existing file?":"新的位置發現已既有檔案存在,您要將資料庫指向其中一個既有檔案嗎?","An existing local database for the storage has been found.\nRe-using the database will allow the command-line and server instances to work on the same remote storage.\n\n Do you wish to use the existing database?":"儲存區發現既有的的本機資料庫已存在。\n重新使用資料庫將可以讓您使用命令列和伺服器服務用在同樣的遠端儲存區。\n\n您希望使用既有的資料庫嗎?","Anonymous usage reports":"匿名使用報告","As Command-line":"如同 Command-Line","AuthID":"AuthID","Authentication password":"認證密碼","Authentication username":"認證名稱","Autogenerated passphrase":"自動產生密碼","Automatically run backups.":"自動執行備份","B2 Account ID":"B2 帳號 ID","B2 Application Key":"B2 Application Key","B2 Cloud Storage Account ID":"B2 Cloud Storage 帳號 ID","B2 Cloud Storage Application Key":"B2 Cloud Storage Application Key","Back":"返回","Backend modules:":"Backend 模組:","Backup destination":"備份目的地","Backup location":"備份位置","Backup:":"備份:","Beta":"測試版 (Beta)","Broken access":"故障連線","Browse":"瀏覽","Browser default":"瀏覽器預設","Bucket Name":"Bucket 名稱","Bucket create location":"Bucket 建立位置","Bucket create region":"Bucket 建立區域","Bucket name":"Bucket 名稱","Bucket storage class":"Bucket 儲存等級","Building list of files to restore ...":"正在建立還原的檔案清單 ...","Building partial temporary database ...":"正在建立部份暫存資料庫 ...","Busy ...":"忙碌 ...","Canary":"Canary","Cancel":"取消","Cannot move to existing file":"無法搬移已存在檔案","Changelog":"更新記錄","Changelog for {{appname}} {{version}}":"更新記錄:{{appname}} {{version}}","Check failed:":"檢查失敗:","Check for updates now":"現在檢查更新","Checking ...":"檢查中 ...","Checking for updates ...":"檢查更新中 ...","Chose a storage type to get started":"選擇儲存區類型,然後開始","Click the AuthID link to create an AuthID":"按下 AuthID 連結來建立一組 AuthID","Click to set throttle options":"點這裡進入頻寬限制設定","Commandline ...":"命令列 ...","Compact now":"立即緊密壓縮","Compacting remote data ...":"正在緊密壓縮遠端資料 ...","Completing backup ...":"正在完成備份 ...","Completing previous backup ...":"正在完成上一次備份 ...","Compression modules:":"壓縮模組:","Computer":"電腦","Configuration file:":"設定檔:","Configuration:":"設定:","Configure a new backup":"設定一個新備份","Confirm delete":"確認刪除","Confirmation required":"需要確認","Connect":"連線","Connect now":"立即連線","Connecting to server ...":"正在連線到伺服器 ...","Connecting to task ....":"正在連線到工作 ...","Connecting...":"連線中...","Connection lost":"連線失敗","Connection worked!":"連線已建立!","Container name":"容器名稱","Container region":"容器區域","Continue":"繼續","Continue without encryption":"不加密並繼續","Copied!":"已複製","Copy Destination URL to Clipboard":"複製目標 URL 至剪貼簿","Copy failed. Please manually copy the URL":"複製失敗。請手動複製 URL","Core options":"核心選項","Counting ({{files}} files found, {{size}})":"正在計算 ({{files}} 個檔案, {{size}})","Crashes only":"只有當機","Create bug report ...":"建立問題報告","Create folder?":"建立資料夾?","Created new limited user":"建立新的受限使用者","Creating bug report ...":"正在建立問題報告 ...","Creating new user with limited access ...":"正在建立有限制存取的新使用者 ...","Creating target folders ...":"正在建立目標資料夾 ...","Creating temporary backup ...":"正在建立暫存備份 ...","Creating user...":"正在建立使用者 ...","Current version is {{versionname}} ({{versionnumber}})":"目前版本 {{versionname}} ({{versionnumber}})","Custom S3 endpoint":"自訂 S3 進入點","Custom authentication url":"自訂授權 URL","Custom location ({{server}})":"自訂位置 ({{server}})","Custom region for creating buckets":"自定區域以建立 Bucket ","Custom region value ({{region}})":"自訂區域 Value ({{region}})","Custom server url ({{server}})":"自訂伺服器 URL ({{server}})","Custom storage class ({{class}})":"自訂儲存等級 ({{class}})","Database ...":"資料庫 ...","Days":"日","Default":"預設","Default ({{channelname}})":"預設 ({{channelname}})","Default options":"預設選項","Delete":"刪除","Delete ...":"刪除 ...","Delete backup":"刪除備份","Delete local database":"刪除本機資料庫","Delete remote files":"刪除遠端檔案","Delete the local database":"刪除本機資料庫","Delete {{filecount}} files ({{filesize}}) from the remote storage?":"刪除遠端儲存區的 {{filecount}} 個檔案 ({{filesize}}) 嗎?","Deleting remote files ...":"正在刪除遠端檔案 ...","Deleting unwanted files ...":"正在刪除不需要的檔案 ...","Desktop":"桌面","Destination":"目的地","Did we help save your files? If so, please consider supporting Duplicati with a donation. We suggest {{smallamount}} for private use and {{largeamount}} for commercial use.":"我們協助您保護您的檔案了嗎?如果是這樣,請考慮贊助支援 Duplicati。我們建議私人 {{smallamount}} 以及 {{largeamount}} 進行商業用途。","Direct restore from backup files ...":"直接從備份檔還原 ...","Disabled":"取消","Dismiss":"忽略","Display and color theme":"佈景主題設定","Do you really want to delete the backup: \"{{name}}\" ?":"您真的要刪除 \"{{name}}\" 這個備份?","Do you really want to delete the local database for: {{name}}":"您真的要刪除 {{name}} 這個本機資料庫?","Donate":"贊助","Donation messages":"贊助資訊","Donation messages are hidden, click to show":"贊助資訊已隱藏,點選可將之顯示","Donation messages are visible, click to hide":"贊助資訊已顯示,點選可將之隱藏","Done":"完成","Download":"下載","Downloading ...":"下載中 ...","Downloading files ...":"正在下載檔案 ...","Downloading update...":"正在下載更新 ...","Duplicate option {{opt}}":"重複選項 {{opt}}","Duplicati Website":"Duplicati 官方網站","Duplicati forum":"Duplicati 論壇","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\n When deleting a backup, you can also delete the local database without affecting the ability to restore the remote files.\n If you are using the local database for backups from the commandline, you should keep the database.":"Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\n When deleting a backup, you can also delete the local database without affecting the ability to restore the remote files.\n If you are using the local database for backups from the commandline, you should keep the database.","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\\nThis makes it faster to perform many operations, and reduces the amount of data that needs to be downloaded for each operation.":"Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\\nThis makes it faster to perform many operations, and reduces the amount of data that needs to be downloaded for each operation.","Edit ...":"編輯 ...","Edit as list":"編輯清單","Edit as text":"編輯文字內容","Encrypt file":"加密檔案","Encryption":"加密方式","Encryption changed":"加密方式已變更","Encryption modules:":"加密模組:","Enter URL":"輸入 URL","Enter access key":"輸入 access key","Enter account name":"輸入帳號名稱","Enter backup passphrase, if any":"輸入備份密碼,如果有的話","Enter configuration details":"進入設定細節","Enter container name":"輸入容器名稱","Enter encryption passphrase":"輸入加密密碼","Enter expression here":"在這裡輸入運算式","Enter folder path name":"輸入資料夾路徑名稱","Enter one option per line in command-line format, eg. {0}":"請輸入選項,每一行一個,如。{0}","Enter the destination path":"輸入目的地路徑","Error":"錯誤","Error!":"錯誤!","Errors and crashes":"錯誤與當機","Exclude":"例外","Exclude directories whose names contain":"排除目錄名稱含有","Exclude expression":"排除表示式","Exclude file":"例外檔案","Exclude file extension":"例外副檔名","Exclude files whose names contain":"排除檔案名稱包含有","Exclude folder":"例外資料夾","Exclude regular expression":"排除的正規表示式","Existing file found":"檔案已存在","Experimental":"實驗版 (Experimental)","Export":"匯出","Export ...":"匯出 ...","Export backup configuration":"匯出備份設定","Export configuration":"匯出設定","Exporting ...":"正在匯出 ...","FTP (Alternative)":"FTP (替代)","Failed to build temporary database: {{message}}":"建立暫存資料庫失敗:{{message}}","Failed to connect:":"連線失敗:","Failed to connect: {{message}}":"連線失敗:{{message}}","Failed to delete:":"刪除失敗:","Failed to fetch path information: {{message}}":"列取路徑資訊失敗: {{message}}","Failed to import:":"匯入失敗:","Failed to read backup defaults:":"讀取備份預設值失敗︰","Failed to restore files: {{message}}":"還原檔案失敗:{{message}}","Failed to save:":"儲存失敗:","Fetching path information ...":"正在列舉路徑資訊 ...","File":"檔案","Files larger than:":"檔案大小超過:","Filters":"篩選","Finished!":"已完成!","First run setup":"執行初始化設定","Folder":"資料夾","Folder path":"資料夾路徑","Fri":"週五","GByte":"GByte","GByte/s":"GByte/s","GCS Project ID":"GCS Project ID","General":"一般","General backup settings":"一般備份設定","General options":"一般選項","Generate":"產生","Generate IAM access policy":"產生 IAM access policy","Getting file versions ...":"正在取得檔案版本 ...","Hidden files":"隱藏檔案","Hide":"隱藏","Hide hidden folders":"隱藏目錄","Home":"首頁","Hours":"小時","How do you want to handle existing files?":"您如何處理既有檔案?","Hyper-V Machine":"Hyper-V 主機","Hyper-V Machine:":"Hyper-V 主機:","Hyper-V Machines":"Hyper-V 主機","ID:":"ID:","If a date was missed, the job will run as soon as possible.":"如果已錯過時間,將儘可能快速進行這個工作。","If the backup and the remote storage is out of sync, Duplicati will require that you perform a repair operation to synchronize the database.\\nIf the repair is unsuccesful, you can delete the local database and re-generate.":"如果備份與遠端儲存區不同步,Duplicati 需要您執行修復操作以讓資料庫重新同步。 \\n 如果修復不成功,您可以刪除本機資料庫並重新產生之。","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"如果備份檔案沒有自動下載,右鍵點選這裡 "另存 ..."","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"如果備份檔案沒有自動下載,右鍵點選這裡 "另存 ..."","If you do not enter a path, all files will be stored in the login folder.\nAre you sure this is what you want?":"如果沒有輸入路徑,將會儲存所有檔案在登入資料夾。\n確定這是您要的嗎?","If you do not enter an API Key, the tenant name is required":"If you do not enter an API Key, the tenant name is required","If you want to use the backup later, you can export the configuration before deleting it":"如果您以後還想要使用此備份,您可以在刪除之前先將設定匯出","If your machine is in a multi-user environment (i.e. the machine has more than one account), you need to set a password to prevent other users from accessing data on your account.\nDo you want to set a password now?":"如果你的主機是多使用者環境(例如這個主機不只有這一個使用者帳號),建議您設定一組密碼,以防址其它使用者存取您的 Duplicati 設定資料。\n您是否要立即前往設定密碼?","Import":"匯入","Import Destination URL":"匯入目的地 URL","Import backup configuration":"匯入備份設定","Import completed, but no certificates were found after the import":"匯入完成,但沒有在匯入時找到憑證","Import failed":"匯入失敗","Import from a file":"從檔案匯入","Importing ...":"正在匯入 ...","Include a file?":"包含檔案?","Include expression":"包含表示式","Include regular expression":"包含正則表示式","Incorrect answer, try again":"回應不正確,請重試一次","Individual builds for developers only.":"Individual builds for developers only.","Information":"資訊","Install":"安裝","Install failed:":"安裝失敗:","Invalid characters in path":"路徑有無法使用的字元","Invalid retention time":"保留時間無效","It is possible to connect to some FTP without a password.\nAre you sure your FTP server supports password-less logins?":"可以在無密碼的情況下連接到 FTP。\n您確定您的 FTP 伺服器支援無密碼登錄嗎?","KByte":"KByte","KByte/s":"KByte/s","Language in user interface":"使用者介面語言","Last month":"上個月","Last successful run:":"上一次成功執行:","Latest":"最新","Libraries":"Libraries","Listing backup dates ...":"正在列出備份日期 ...","Listing remote files ...":"正在列出遠端檔案 ...","Live":"即時","Load a configuration from an exported job or a storage provider":"從匯出的備份任務或儲存區來載入組態設定","Load destination from an exported job or a storage provider":"從匯出的備份任務或儲存區來載入備份目的地","Load older data":"載入較舊的資料","Loading ...":"載入中 ...","Loading remote storage usage ...":"正在載入遠端儲存區使用資訊 ...","Local database for":"本機資料庫","Local database path:":"本機資料庫路徑:","Local storage":"本機儲存區","Location":"位置","Location where buckets are created":"建立 Buckets 的位置","Log data for {{Backup.Backup.Name}}":"{{Backup.Backup.Name}} 的記錄資料","Log data from the server":"伺服器上的記錄","Log out":"登出","MByte":"MByte","MByte/s":"MByte/s","Maintenance":"維護","Manually type path":"手動輸入路徑","Max download speed":"最大下載速度","Max upload speed":"最大上傳速度","Menu":"功能","Microsoft SQL Database:":"Microsoft SQL 資料庫:","Microsoft SQL Databases":"Microsoft SQL 資料庫","Minimum redundancy":"Minimum redundancy","Minimum redundancy is 1.0":"Minimum redundancy is 1.0","Minutes":"分鐘","Missing name":"遺失名稱","Missing passphrase":"遺失密碼","Missing sources":"遺失來源","Mon":"週一","Months":"月","Move existing database":"搬移已存在資料庫","Move failed:":"搬移失敗:","My Documents":"My Documents","My Music":"My Music","My Photos":"My Photos","My Pictures":"My Pictures","Name":"名稱","Never":"從未","New update found: {{message}}":"發現最新版本:{{message}}","New user name is {{user}}.\nUpdated credentials to use the new limited user":"新使用者名稱是 {{user}}.\n更新憑證以使用新的受限使用者帳號","Next":"下一頁","Next scheduled run:":"下一次排程執行時間:","Next scheduled task:":"下一個排程工作:","Next task:":"下一個工作:","Next time":"下一次","No":"否","No certificate was specified previously, please verify with the server administrator that the key is correct: {{key}} \n\nDo you want to approve the reported host key?":"No certificate was specified previously, please verify with the server administrator that the key is correct: {{key}} \n\nDo you want to approve the reported host key?","No editor found for the "{{backend}}" storage type":"找不到 "{{backend}}" 儲存區類型","No encryption":"不加密","No items selected":"沒有選擇","No items to restore, please select one or more items":"沒有要還原的項目,請至少選擇一個項目","No passphrase entered":"沒有輸入密碼","No scheduled tasks":"沒有排程工作","No, my machine has only a single account":"不用,我的主機只有一個帳號在使用","Non-matching passphrase":"密碼不相符","None / disabled":"無 / 取消","OK":"確定","OpenStack AuthURI":"OpenStack AuthURI","OpenStack Object Storage / Swift":"OpenStack Object Storage / Swift","Operation failed:":"操作失敗:","Operations:":"操作:","Optional authentication password":"(非必要)認證密碼","Optional authentication username":"(非必要)認證帳號","Options":"選項","Options added here are applied to all backups, but can be overridden in each individual backup":"這裡的選項將適用所有備份任務,不過每個任務內可以再各自設定,它將會覆寫這裡的全域選項。","Original location":"原始位置","Others":"其它","Overwrite":"覆寫","Passphrase":"密碼","Passphrase (if encrypted)":"密碼 (如果已加密)","Passphrase changed":"密碼已變更","Passphrases are not matching":"密碼不相符","Password":"密碼","Passwords do not match":"密碼不符","Patching files with local blocks ...":"使用本機區塊修復檔案中 ...","Path not found":"找不到路徑","Path on server":"伺服器路徑","Path or subfolder in the bucket":"Bucket 裡的路徑或子資料夾","Pause":"暫停","Pause after startup or hibernation":"當啟動或休眠後暫停","Pause options":"暫停選項","Permissions":"權限","Pick location":"選擇位置","Point to your backup files and restore from there":"指向您的備份檔案,將會由此還原","Port":"連接埠","Previous":"上一頁","ProjectID is optional if the bucket exist":"ProjectID is optional if the bucket exist","Proprietary":"所有權","Purging files ...":"清理檔案 ...","Rebuilding local database ...":"正在重建本機資料庫 ...","Recreate (delete and repair)":"重新建立(刪除並修復)","Recreating database ...":"正在重建資料庫 ...","Registering temporary backup ...":"正在註冊暫時備份 ...","Relative paths not allowed":"不允許使用相對路徑","Reload":"重新載入","Remote":"入遠端","Remove":"移除","Remove option":"移除選項","Repair":"修復","Reparing ...":"正在修復 ...","Repeat Passphrase":"重複密碼","Reporting:":"報告︰","Reset":"重置","Restore":"還原","Restore files":"還原檔案","Restore files ...":"還原檔案 ...","Restore files from {{backupname}}":"從 {{backupname}} 還原檔案","Restore from":"還原檔案從 ","Restore from backup configuration":"從備份設定檔還原","Restore from configuration ...":"從設定檔還原 ...","Restore options":"還原選項","Restore read/write permissions":"還原讀/寫權限","Restoring files ...":"正在還原檔案 ...","Resume":"繼續","Run again every":"重複執行於每","Run now":"立即執行","Running ...":"正在執行 ...","Running ....":"執行中 ...","Running commandline entry":"Running commandline entry","Running task:":"正在執行工作:","S3 Compatible":"S3 相容","Same as the base install version: {{channelname}}":"Same as the base install version: {{channelname}}","Sat":"週六","Save":"儲存","Save and repair":"儲存並修復","Save different versions with timestamp in file name":"在檔案名稱中儲存不同版本的時間戳記","Save immediately":"立即儲存","Scanning existing files ...":"正在掃描已存在檔案 ...","Scanning for local blocks ...":"正在掃描本機區塊 ...","Schedule":"排程","Search":"搜尋","Search for files":"搜尋檔案","Seconds":"秒","Select a log level and see messages as they happen:":"選擇一個記錄等級以查看訊息︰","Select files":"選擇檔案","Server":"伺服器","Server and port":"伺服器與連接埠","Server hostname or IP":"伺服器名稱或 IP","Server is currently paused,":"伺服器目前已暫停,","Server is currently paused, do you want to resume now?":"伺服器目前已暫停,請問您現在要繼續嗎?","Server password":"伺服器密碼","Server paused":"伺服器目前已暫停","Server state properties":"伺服器狀態屬性","Settings":"設定","Show":"顯示","Show advanced editor":"顯示進階編輯器","Show hidden folders":"顯示隱藏資料夾","Show log":"顯示記錄","Show log ...":"顯示記錄 ...","Show treeview":"顯示樹狀清單","Sia server password":"Sia 伺服器密碼","Some OpenStack providers allow an API key instead of a password and tenant name":"某些 OpenStack 供應商允許 API Key 而不用密碼與 Tenant 名稱","Source Data":"來源資料","Source data":"來源資料","Source folders":"來源資料夾","Source:":"來源:","Specific builds for developers only.":"Specific builds for developers only.","Standard protocols":"標準通訊協定","Starting ...":"正在開始 ...","Starting the restore process ...":"正在開始還原程序 ...","Stop after the current file":"這個檔案完成後停止","Stop after upload":"上傳後停止","Stop now":"立即停止","Stop running backup":"停止正在進行的備份","Stop running task":"停止正在進行的工作","Stopping after upload:":"Stopping after upload:","Stopping task:":"正在停止工作:","Storage Type":"儲存區類型","Storage class":"儲存區等級","Storage class for creating a bucket":"建立 Bucket 的儲存類型","Stored":"儲存","Strong":"強","Success":"成功","Sun":"週日","Symbolic link":"符號連結","System default ({{levelname}})":"系統預設 ({{levelname}})","System files":"系統檔案","System info":"系統資訊","System properties":"系統屬性","TByte":"TByte","TByte/s":"TByte/s","Target path, ie /backup":"目的地路徑,例如 /backup","Task is running":"工作正在執行","Temporary files":"暫存檔案","Tenant Name":"Tenant 名稱","Test connection":"測試連線","Testing ...":"測試中 ...","Testing connection ...":"正在測試連線 ...","Testing permissions ...":"正在測試權限 ...","Testing permissions...":"正在測試權限 ...","The bucket name should be all lower-case, convert automatically?":"Bucket 名稱應該全部小寫,要自動轉換嗎?","The bucket name should start with your username, prepend automatically?":"Bucket 名稱應該以您的使用者名稱開頭,要自動加入嗎?","The connection to the server is lost, attempting again in {{time}} ...":"連接伺服器的失敗,再次嘗試 {{}}......","The dark theme (by Michal)":"深色主題 (by Michal)","The default blue on white theme (by Alex)":"預設白色主題 (by Alex)","The host key has changed, please check with the server administrator if this is correct, otherwise you could be the victim of a MAN-IN-THE-MIDDLE attack.\n\nDo you want to REPLACE your CURRENT host key \"{{prev}}\" with the REPORTED host key: {{key}}?":"主機金鑰已變更,如果是正確的請您與伺服器管理員聯繫,否則您可能已遭受中間人攻擊。\n\n你想要更換原先的主機金鑰 \"{{prev}}\" 到 {{key}} 嗎?","The path does not appear to exist, do you want to add it anyway?":"路徑似乎不存在,無論如何你都要加入嗎?","The path does not end with a '{{dirsep}}' character, which means that you include a file, not a folder.\n\nDo you want to include the specified file?":"The path does not end with a '{{dirsep}}' character, which means that you include a file, not a folder.\n\nDo you want to include the specified file?","The path must be an absolute path, i.e. it must start with a forward slash '/'":"必須是絕對路徑,也就是說必須以斜線開頭 '/'","The path should start with \"{{prefix1}}\" or \"{{prefix2}}\", otherwise you will not be able to see the files in the HubiC web interface.\n\nDo you want to add the prefix to the path automatically?":"The path should start with \"{{prefix1}}\" or \"{{prefix2}}\", otherwise you will not be able to see the files in the HubiC web interface.\n\nDo you want to add the prefix to the path automatically?","The region parameter is only applied when creating a new bucket":"區域參數只有在建立新 Bucket 時套用","The region parameter is only used when creating a bucket":"區域參數只使用在在建立新 Bucket 時","The server certificate could not be validated.\nDo you want to approve the SSL certificate with the hash: {{hash}}?":"伺服器無法驗證。\n您要使用這個 SSL 憑證 {{hash}} 嗎?","The storage class affects the availability and price for a stored file":"儲存區類型會影響到可用性以及... 價格","The target folder contains encrypted files, please supply the passphrase":"目的資料夾中包含加密檔案,請提供密碼","The user has too many permissions. Do you want to create a new limited user, with only permissions to the selected path?":"The user has too many permissions. Do you want to create a new limited user, with only permissions to the selected path?","This backup was created on another operating system. Restoring files without specifying a destination folder can cause files to be restored in unexpected places. Are you sure you want to continue without choosing a destination folder?":"This backup was created on another operating system. Restoring files without specifying a destination folder can cause files to be restored in unexpected places. Are you sure you want to continue without choosing a destination folder?","This month":"本月","This week":"本週","Throttle settings":"頻寬限制設定","Thu":"週四","To File":"到檔案","To confirm you want to delete all remote files for \"{{name}}\", please enter the word you see below":"確認要刪除所有的遠端檔案 \"{{name}}\",請輸入下面的單字","To export without a passphrase, uncheck the \"Encrypt file\" box":"若要無密碼匯出,請不要勾選\"加密檔案\"核取方塊","Today":"今天","Trust host certificate?":"信任主機憑證?","Trust server certificate?":"信任伺服器憑證?","Try out the new features we are working on. Don't use with important data.":"試試我們正在進行的新功能。不要使用在重要的資料上。","Tue":"週二","Type to highlight files":"Type to highlight files","Unknown backup size and versions":"未知的備份大小與版本","Until resumed":"手動繼續","Update channel":"更新分支","Update failed:":"更新失敗:","Updating with existing database":"正在更新已存在資料庫 ...","Upload volume size":"上傳區塊大小","Uploading verification file ...":"正在上傳驗證檔案 ...","Usage statistics":"使用統計","Usage statistics, warnings, errors, and crashes":"使用統計、警告、錯誤與當機","Use SSL":"使用 SSL","Use existing database?":"使用已存在資料庫?","Use weak passphrase":"使用低強度密碼","Useless":"不使用","User data":"使用者資料","User has too many permissions":"使用者有太多權限","User interface settings":"使用者介面設定","Username":"使用者","Validating ...":"確認中 ...","Verify files":"驗證檔案","Verifying ...":"驗證中 ...","Verifying answer":"驗證答案","Verifying backend data ...":"正在驗證後端資料 ...","Verifying remote data ...":"正在驗證遠端資料 ...","Verifying restored files ...":"正在驗證已還原檔案 ...","Very strong":"非常強","Very weak":"非常弱","Visit us on":"拜訪我們","WARNING: The remote database is found to be in use by the commandline library":"WARNING: The remote database is found to be in use by the commandline library","WARNING: This will prevent you from restoring the data in the future.":"警告︰ 這將會阻止您日後還原資料。","Waiting for task to begin":"正在等待工作開始","Waiting for task to start ....":"正在等待工作開始 ...","Waiting for upload ...":"正在等待上傳 ...","Warnings, errors and crashes":"警告、錯誤與當機","We recommend that you encrypt all backups stored outside your system":"我們建議,您將放在您自己控管系統以外的備份都進行加密","Weak":"弱","Weak passphrase":"弱密碼","Wed":"週三","Weeks":"週","Where do you want to restore from?":"您要從那裡還原?","Where do you want to restore the files to?":"您要還原檔案到哪裡?","Years":"年","Yes":"是","Yes, I have stored the passphrase safely":"是,我已安全的儲存密碼","Yes, I'm brave!":"是的,我敢!","Yes, please break my backup!":"是,請中斷我的備份!","Yesterday":"昨天","You appear to be running Mono with no SSL certificates loaded.\nDo you want to import the list of trusted certificates from Mozilla?":"您正在運行 Mono 似乎沒有載入 SSL 相關憑證。\n要從 Mozilla 匯入受信任的憑證清單嗎?","You are changing the database path away from an existing database.\nAre you sure this is what you want?":"您正在變更現有資料庫的路徑。\n您確定這是您想要的嗎?","You are currently running {{appname}} {{version}}":"您正在執行 {{appname}} {{version}}","You can stop the backup immediately, or stop after the current file has been uploaded.":"You can stop the backup immediately, or stop after the current file has been uploaded.","You can stop the task immediately, or allow the process to continue its current file and the stop.":"You can stop the task immediately, or allow the process to continue its current file and the stop.","You have changed the encryption mode. This may break stuff. You are encouraged to create a new backup instead":"您已變更加密模式。這可能導致資料損毀。我們建議您建立一個新的備份","You have changed the passphrase, which is not supported. You are encouraged to create a new backup instead.":"您變更加密密碼,這個動作不被支援。我們建議您建立一個新的備份。","You have chosen not to encrypt the backup. Encryption is recommended for all data stored on a remote server.":"您已選擇備份不加密。建議將存在遠端伺服器上的資料予以加密。","You have chosen to restore to a new location, but not entered one":"You have chosen to restore to a new location, but not entered one","You must choose at least one source folder":"您至少要選擇一個來源資料夾","You must enter a name for the backup":"您必須輸入備份名稱","You must enter a passphrase or disable encryption":"您必須輸入密碼或取消加密","You must enter a positive number of backups to keep":"您必須輸入正數,備份才能保存","You must enter a tenant name if you do not provide an API Key":"如果您不提供 API Key,您必須輸入 Tenant 名稱","You must enter a valid duration for the time to keep backups":"您必須輸入有效的起迄時間來保留備份","You must enter either a password or an API Key":"您必須輸入密碼或 API Key","You must enter either a password or an API Key, not both":"您必須輸入密碼或者 API Key,二擇一","You must fill in the password":"您必須輸入密碼","You must fill in the server name or address":"您必須填寫伺服器名稱或位址","You must fill in the username":"您必須填寫使用者名稱","You must fill in {{field}}":"您必須填寫 {{field}}","You must select or fill in the AuthURI":"您必須選擇或填寫 AuthURI","You must select or fill in the server":"您必須選擇或填寫伺服器","You must specify a path":"您必須指定一個路徑","Your files and folders have been restored successfully.":"您的檔案與資料夾已成功還原。","Your passphrase is easy to guess. Consider changing passphrase.":"您的密碼很容易被猜到。請考慮變更密碼。","bucket/folder/subfolder":"bucket/folder/subfolder","byte":"byte","byte/s":"byte/s","custom":"自訂","resume now":"立即繼續","{{appname}} was primarily developed by {{dev1}} and {{dev2}}. {{appname}} can be downloaded from {{websitename}}. {{appname}} is licensed under the {{licensename}}.":"{{appname}} was primarily developed by {{dev1}} and {{dev2}}. {{appname}} can be downloaded from {{websitename}}. {{appname}} is licensed under the {{licensename}}.","{{files}} files ({{size}}) to go {{speed_txt}}":"{{files}} 個檔案 ({{size}}) 正在傳輸 {{speed_txt}}","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Version":"{{item.Backup.Metadata.TargetSizeString}} / {{$count}} 個版本","{{number}} Hour":"{{number}} 小時","{{number}} Minutes":"{{number}} 分鐘","{{time}} (took {{duration}})":"{{time}} (花費 {{duration}})"}); + gettextCatalog.setStrings('zh_TW', {"- pick an option -":"選擇一個項目","...loading...":"...載入中...","API Key":"API Key","AWS Access ID":"AWS Access ID","AWS Access Key":"AWS Access Key","AWS IAM Policy":"AWS IAM Policy","About":"關於","About {{appname}}":"關於 {{appname}}","Access Key":"Access Key","Access denied":"拒絕存取","Access to user interface":"進入使用者介面","Account name":"帳號名稱","Activate":"啟用","Activate failed:":"啟用失敗","Add a new backup":"新增備份","Add a path directly":"直接增加資料路徑","Add advanced option":"加入進階選項","Add backup":"備份","Add filter":"加入篩選條件","Add path":"加入路徑","Adjust bucket name?":"調整 bucket 名稱?","Adjust path name?":"調整 path 名稱?","Advanced Options":"進階選項","Advanced options":"進階選項","Advanced:":"進階:","All":"全部","All Hyper-V Machines":"全部 Hyper-V 主機","All Microsoft SQL Databases":"全部 Microsoft SQL 資料庫","All usage reports are sent anonymously and do not contain any personal information. They contain information about hardware and operating system, the type of backend, backup duration, overall size of source data and similar data. They do not contain paths, filenames, usernames, passwords or similar sensitive information.":"All usage reports are sent anonymously and do not contain any personal information. They contain information about hardware and operating system, the type of backend, backup duration, overall size of source data and similar data. They do not contain paths, filenames, usernames, passwords or similar sensitive information.","Allow remote access (requires restart)":"允許遠端存取(需要重新啟動)","Allowed days":"允許日","An existing file was found at the new location":"新的位置發現已既有檔案存在","An existing file was found at the new location\nAre you sure you want the database to point to an existing file?":"新的位置發現已既有檔案存在,您要將資料庫指向其中一個既有檔案嗎?","An existing local database for the storage has been found.\nRe-using the database will allow the command-line and server instances to work on the same remote storage.\n\n Do you wish to use the existing database?":"儲存區發現既有的的本機資料庫已存在。\n重新使用資料庫將可以讓您使用命令列和伺服器服務用在同樣的遠端儲存區。\n\n您希望使用既有的資料庫嗎?","Anonymous usage reports":"匿名使用報告","As Command-line":"顯示為 Command-Line","AuthID":"AuthID","Authentication password":"認證密碼","Authentication username":"認證名稱","Autogenerated passphrase":"自動產生密碼","Automatically run backups.":"自動執行備份","B2 Account ID":"B2 帳號 ID","B2 Application Key":"B2 Application Key","B2 Cloud Storage Account ID":"B2 Cloud Storage 帳號 ID","B2 Cloud Storage Application Key":"B2 Cloud Storage Application Key","Back":"返回","Backend modules:":"Backend 模組:","Backup destination":"備份目的地","Backup location":"備份位置","Backup retention":"保留備份數目","Backup:":"備份:","Beta":"測試版 (Beta)","Broken access":"故障連線","Browse":"瀏覽","Browser default":"瀏覽器預設","Bucket Name":"Bucket 名稱","Bucket create location":"Bucket 建立位置","Bucket create region":"Bucket 建立區域","Bucket name":"Bucket 名稱","Bucket storage class":"Bucket 儲存等級","Building list of files to restore ...":"正在建立還原的檔案清單 ...","Building partial temporary database ...":"正在建立部份暫存資料庫 ...","Busy ...":"忙碌 ...","Canary":"Canary","Cancel":"取消","Cannot move to existing file":"無法搬移已存在檔案","Changelog":"更新記錄","Changelog for {{appname}} {{version}}":"更新記錄:{{appname}} {{version}}","Check failed:":"檢查失敗:","Check for updates now":"現在檢查更新","Checking ...":"檢查中 ...","Checking for updates ...":"檢查更新中 ...","Chose a storage type to get started":"選擇儲存區類型,然後開始","Click the AuthID link to create an AuthID":"按下 AuthID 連結來建立一組 AuthID","Click to set throttle options":"點這裡進入頻寬限制設定","Commandline ...":"命令列 ...","Compact now":"立即緊密壓縮","Compacting remote data ...":"正在緊密壓縮遠端資料 ...","Completing backup ...":"正在完成備份 ...","Completing previous backup ...":"正在完成上一次備份 ...","Compression modules:":"壓縮模組:","Computer":"電腦","Configuration file:":"設定檔:","Configuration:":"設定:","Configure a new backup":"設定一個新備份","Confirm delete":"確認刪除","Confirmation required":"需要確認","Connect":"連線","Connect now":"立即連線","Connecting to server ...":"正在連線到伺服器 ...","Connecting to task ....":"正在連線到工作 ...","Connecting...":"連線中...","Connection lost":"連線失敗","Connection worked!":"連線已建立!","Container name":"容器名稱","Container region":"容器區域","Continue":"繼續","Continue without encryption":"不加密並繼續","Copied!":"已複製","Copy":"複製","Copy Destination URL to Clipboard":"複製目標 URL 至剪貼簿","Copy failed. Please manually copy the URL":"複製失敗。請手動複製 URL","Core options":"核心選項","Counting ({{files}} files found, {{size}})":"正在計算 ({{files}} 個檔案, {{size}})","Crashes only":"只有當機","Create bug report ...":"建立問題報告","Create folder?":"建立資料夾?","Created new limited user":"建立新的受限使用者","Creating bug report ...":"正在建立問題報告 ...","Creating new user with limited access ...":"正在建立有限制存取的新使用者 ...","Creating target folders ...":"正在建立目標資料夾 ...","Creating temporary backup ...":"正在建立暫存備份 ...","Creating user...":"正在建立使用者 ...","Current version is {{versionname}} ({{versionnumber}})":"目前版本 {{versionname}} ({{versionnumber}})","Custom S3 endpoint":"自訂 S3 進入點","Custom authentication url":"自訂授權 URL","Custom backup retention":"自訂備份保留規則","Custom location ({{server}})":"自訂位置 ({{server}})","Custom region for creating buckets":"自定區域以建立 Bucket ","Custom region value ({{region}})":"自訂區域 Value ({{region}})","Custom server url ({{server}})":"自訂伺服器 URL ({{server}})","Custom storage class ({{class}})":"自訂儲存等級 ({{class}})","Database ...":"資料庫 ...","Days":"日","Default":"預設","Default ({{channelname}})":"預設 ({{channelname}})","Default Filters":"預設篩選條件","Default options":"預設選項","Delete":"刪除","Delete ...":"刪除 ...","Delete backup":"刪除備份","Delete backups that are older than":"刪除指定條件以前的備份","Delete local database":"刪除本機資料庫","Delete remote files":"刪除遠端檔案","Delete the local database":"刪除本機資料庫","Delete {{filecount}} files ({{filesize}}) from the remote storage?":"刪除遠端儲存區的 {{filecount}} 個檔案 ({{filesize}}) 嗎?","Deleting remote files ...":"正在刪除遠端檔案 ...","Deleting unwanted files ...":"正在刪除不需要的檔案 ...","Desktop":"桌面","Destination":"目的地","Did we help save your files? If so, please consider supporting Duplicati with a donation. We suggest {{smallamount}} for private use and {{largeamount}} for commercial use.":"我們協助您保護您的檔案了嗎?如果是這樣,請考慮贊助支援 Duplicati。我們建議私人 {{smallamount}} 以及 {{largeamount}} 進行商業用途。","Direct restore from backup files ...":"直接從備份檔還原 ...","Disabled":"取消","Dismiss":"忽略","Display and color theme":"佈景主題設定","Do you really want to delete the backup: \"{{name}}\" ?":"您真的要刪除 \"{{name}}\" 這個備份?","Do you really want to delete the local database for: {{name}}":"您真的要刪除 {{name}} 這個本機資料庫?","Donate":"贊助","Donation messages":"贊助資訊","Donation messages are hidden, click to show":"贊助資訊已隱藏,點選可將之顯示","Donation messages are visible, click to hide":"贊助資訊已顯示,點選可將之隱藏","Done":"完成","Download":"下載","Downloading ...":"下載中 ...","Downloading files ...":"正在下載檔案 ...","Downloading update...":"正在下載更新 ...","Duplicate option {{opt}}":"重複選項 {{opt}}","Duplicati Website":"Duplicati 官方網站","Duplicati forum":"Duplicati 論壇","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\n When deleting a backup, you can also delete the local database without affecting the ability to restore the remote files.\n If you are using the local database for backups from the commandline, you should keep the database.":"Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\n When deleting a backup, you can also delete the local database without affecting the ability to restore the remote files.\n If you are using the local database for backups from the commandline, you should keep the database.","Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\\nThis makes it faster to perform many operations, and reduces the amount of data that needs to be downloaded for each operation.":"Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\\nThis makes it faster to perform many operations, and reduces the amount of data that needs to be downloaded for each operation.","Edit ...":"編輯 ...","Edit as list":"編輯清單","Edit as text":"編輯文字內容","Encrypt file":"加密檔案","Encryption":"加密方式","Encryption changed":"加密方式已變更","Encryption modules:":"加密模組:","Enter URL":"輸入 URL","Enter a retention strategy manually. Placeholders are D/W/Y for days/weeks/years. The syntax is: 7D:1D,4W:1W,36M:1M. This example keeps one backup for each of the next 7 days, one for each of the next 4 weeks, and one for each of the next 36 months. This can also be written as 1W:1D,1M:1W,3Y:1M.":"手動輸入保留原則。可用關鍵字為 D/W/Y 分別代表 日/週/ 年。語法為:7D:1D,4W:1W,36M:1M。上述例子表示,每7日保留1份,每4週保留1份,每36個月保留1份。您也可以寫成 1W:1D,1M:1W,3Y:1M。","Enter access key":"輸入 access key","Enter account name":"輸入帳號名稱","Enter backup passphrase, if any":"輸入備份密碼,如果有的話","Enter configuration details":"進入設定細節","Enter container name":"輸入容器名稱","Enter encryption passphrase":"輸入加密密碼","Enter expression here":"在這裡輸入運算式","Enter folder path name":"輸入資料夾路徑名稱","Enter one option per line in command-line format, eg. {0}":"請輸入選項,每一行一個,如。{0}","Enter the destination path":"輸入目的地路徑","Error":"錯誤","Error!":"錯誤!","Errors and crashes":"錯誤與當機","Exclude":"例外","Exclude directories whose names contain":"排除目錄名稱含有","Exclude expression":"排除表示式","Exclude file":"例外檔案","Exclude file extension":"例外副檔名","Exclude files whose names contain":"排除檔案名稱包含有","Exclude folder":"例外資料夾","Exclude regular expression":"排除的正規表示式","Existing file found":"檔案已存在","Experimental":"實驗版 (Experimental)","Export":"匯出","Export ...":"匯出 ...","Export backup configuration":"匯出備份設定","Export configuration":"匯出設定","Exporting ...":"正在匯出 ...","External link":"外部連結","FTP (Alternative)":"FTP (替代)","Failed to build temporary database: {{message}}":"建立暫存資料庫失敗:{{message}}","Failed to connect:":"連線失敗:","Failed to connect: {{message}}":"連線失敗:{{message}}","Failed to delete:":"刪除失敗:","Failed to fetch path information: {{message}}":"列取路徑資訊失敗: {{message}}","Failed to import:":"匯入失敗:","Failed to read backup defaults:":"讀取備份預設值失敗︰","Failed to restore files: {{message}}":"還原檔案失敗:{{message}}","Failed to save:":"儲存失敗:","Fetching path information ...":"正在列舉路徑資訊 ...","File":"檔案","Files larger than:":"檔案大小超過:","Filters":"篩選","Finished!":"已完成!","First run setup":"執行初始化設定","Folder":"資料夾","Folder path":"資料夾路徑","Fri":"週五","GByte":"GByte","GByte/s":"GByte/s","GCS Project ID":"GCS Project ID","General":"一般","General backup settings":"一般備份設定","General options":"一般選項","Generate":"產生","Generate IAM access policy":"產生 IAM access policy","Getting file versions ...":"正在取得檔案版本 ...","Hidden files":"隱藏檔案","Hide":"隱藏","Hide hidden folders":"隱藏目錄","Home":"首頁","Hours":"小時","How do you want to handle existing files?":"您如何處理既有檔案?","Hyper-V Machine":"Hyper-V 主機","Hyper-V Machine:":"Hyper-V 主機:","Hyper-V Machines":"Hyper-V 主機","ID:":"ID:","If a date was missed, the job will run as soon as possible.":"如果已錯過時間,將儘可能快速進行這個工作。","If at least one newer backup is found, all backups older than this date are deleted.":"如果有更新的備份存在,則刪除比這個日期早的所有備份。","If the backup and the remote storage is out of sync, Duplicati will require that you perform a repair operation to synchronize the database.\\nIf the repair is unsuccesful, you can delete the local database and re-generate.":"如果備份與遠端儲存區不同步,Duplicati 需要您執行修復操作以讓資料庫重新同步。 \\n 如果修復不成功,您可以刪除本機資料庫並重新產生之。","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"如果備份檔案沒有自動下載,右鍵點選這裡 "另存 ..."","If the backup file was not downloaded automatically, right click and choose "Save as ..."":"如果備份檔案沒有自動下載,右鍵點選這裡 "另存 ..."","If you do not enter a path, all files will be stored in the login folder.\nAre you sure this is what you want?":"如果沒有輸入路徑,將會儲存所有檔案在登入資料夾。\n確定這是您要的嗎?","If you do not enter an API Key, the tenant name is required":"If you do not enter an API Key, the tenant name is required","If you want to use the backup later, you can export the configuration before deleting it":"如果您以後還想要使用此備份,您可以在刪除之前先將設定匯出","If your machine is in a multi-user environment (i.e. the machine has more than one account), you need to set a password to prevent other users from accessing data on your account.\nDo you want to set a password now?":"如果你的主機是多使用者環境(例如這個主機不只有這一個使用者帳號),建議您設定一組密碼,以防址其它使用者存取您的 Duplicati 設定資料。\n您是否要立即前往設定密碼?","Import":"匯入","Import Destination URL":"匯入目的地 URL","Import backup configuration":"匯入備份設定","Import completed, but no certificates were found after the import":"匯入完成,但沒有在匯入時找到憑證","Import failed":"匯入失敗","Import from a file":"從檔案匯入","Import metadata":"匯入 metadata","Importing ...":"正在匯入 ...","Include a file?":"包含檔案?","Include expression":"包含表示式","Include regular expression":"包含正則表示式","Incorrect answer, try again":"回應不正確,請重試一次","Individual builds for developers only.":"開發者專用個人版本,一般使用者請勿使用。","Information":"資訊","Install":"安裝","Install failed:":"安裝失敗:","Invalid characters in path":"路徑有無法使用的字元","Invalid retention time":"保留時間無效","It is possible to connect to some FTP without a password.\nAre you sure your FTP server supports password-less logins?":"可以在無密碼的情況下連接到 FTP。\n您確定您的 FTP 伺服器支援無密碼登錄嗎?","KByte":"KByte","KByte/s":"KByte/s","Keep a specific number of backups":"保留指定份數的備份","Keep all backups":"保留所有備份","Language in user interface":"使用者介面語言","Last month":"上個月","Last successful run:":"上一次成功執行:","Latest":"最新","Libraries":"函式庫","Linux":"Linux","Listing backup dates ...":"正在列出備份日期 ...","Listing remote files ...":"正在列出遠端檔案 ...","Live":"即時","Load a configuration from an exported job or a storage provider":"從匯出的備份任務或儲存區來載入組態設定","Load destination from an exported job or a storage provider":"從匯出的備份任務或儲存區來載入備份目的地","Load older data":"載入較舊的資料","Loading ...":"載入中 ...","Loading remote storage usage ...":"正在載入遠端儲存區使用資訊 ...","Local Repository":"本機 Repository","Local database for":"本機資料庫","Local database path:":"本機資料庫路徑:","Local repository":"本機 repository","Local storage":"本機儲存區","Location":"位置","Location where buckets are created":"建立 Buckets 的位置","Log data for {{Backup.Backup.Name}}":"{{Backup.Backup.Name}} 的記錄資料","Log data from the server":"伺服器上的記錄","Log out":"登出","MByte":"MByte","MByte/s":"MByte/s","Maintenance":"維護","Manually type path":"手動輸入路徑","Max download speed":"最大下載速度","Max upload speed":"最大上傳速度","Menu":"功能","Microsoft SQL Database:":"Microsoft SQL 資料庫:","Microsoft SQL Databases":"Microsoft SQL 資料庫","Minimum redundancy":"Minimum redundancy","Minimum redundancy is 1.0":"Minimum redundancy is 1.0","Minutes":"分鐘","Missing name":"遺失名稱","Missing passphrase":"遺失密碼","Missing sources":"遺失來源","Mon":"週一","Months":"月","Move existing database":"搬移已存在資料庫","Move failed:":"搬移失敗:","My Documents":"My Documents","My Music":"My Music","My Photos":"My Photos","My Pictures":"My Pictures","Name":"名稱","Never":"從未","New update found: {{message}}":"發現最新版本:{{message}}","New user name is {{user}}.\nUpdated credentials to use the new limited user":"新使用者名稱是 {{user}}.\n更新憑證以使用新的受限使用者帳號","Next":"下一頁","Next scheduled run:":"下一次排程執行:","Next scheduled task:":"下一個排程工作:","Next task:":"下一個工作:","Next time":"下一次","No":"否","No certificate was specified previously, please verify with the server administrator that the key is correct: {{key}} \n\nDo you want to approve the reported host key?":"No certificate was specified previously, please verify with the server administrator that the key is correct: {{key}} \n\nDo you want to approve the reported host key?","No editor found for the "{{backend}}" storage type":"找不到 "{{backend}}" 儲存區類型","No encryption":"不加密","No items selected":"沒有選擇","No items to restore, please select one or more items":"沒有要還原的項目,請至少選擇一個項目","No passphrase entered":"沒有輸入密碼","No scheduled tasks":"沒有排程工作","No, my machine has only a single account":"不用,我的主機只有一個帳號在使用","Non-matching passphrase":"密碼不相符","None / disabled":"無 / 取消","Nothing will be deleted. The backup size will grow with each change.":"什麼都不刪除。備份大小將隨著每次異動而持續增長。","OK":"確定","OSX":"OSX","Once there are more backups than the specified number, the oldest backups are deleted.":"當備份數量超過指定數目,最舊的備份將被刪除。","OpenStack AuthURI":"OpenStack AuthURI","OpenStack Object Storage / Swift":"OpenStack Object Storage / Swift","Operation failed:":"操作失敗:","Operations:":"操作:","Optional authentication password":"(非必要)認證密碼","Optional authentication username":"(非必要)認證帳號","Options":"選項","Options added here are applied to all backups, but can be overridden in each individual backup":"這裡的選項將適用所有備份任務,不過每個任務內可以再各自設定,它將會覆寫這裡的全域選項。","Original location":"原始位置","Others":"其它","Over time backups will be deleted automatically. There will remain one backup for each of the last 7 days, each of the last 4 weeks, each of the last 12 months. There will always be at least one remaining backup.":"智慧保留模式,兼具長時間保存與短時間份數考量。保留每7天、每4週、每12個月均有一份備份。","Overwrite":"覆寫","Passphrase":"密碼","Passphrase (if encrypted)":"密碼 (如果已加密)","Passphrase changed":"密碼已變更","Passphrases are not matching":"密碼不相符","Password":"密碼","Passwords do not match":"密碼不符","Patching files with local blocks ...":"使用本機區塊修復檔案中 ...","Path not found":"找不到路徑","Path on server":"伺服器路徑","Path or subfolder in the bucket":"Bucket 裡的路徑或子資料夾","Pause":"暫停","Pause after startup or hibernation":"當啟動或休眠後暫停","Pause options":"暫停選項","Permissions":"權限","Pick location":"選擇位置","Point to your backup files and restore from there":"指向您的備份檔案,將會由此還原","Port":"連接埠","Previous":"上一頁","ProjectID is optional if the bucket exist":"ProjectID is optional if the bucket exist","Proprietary":"雲端服務","Purging files ...":"清理檔案 ...","Rebuilding local database ...":"正在重建本機資料庫 ...","Recreate (delete and repair)":"重新建立(刪除並修復)","Recreating database ...":"正在重建資料庫 ...","Registering temporary backup ...":"正在註冊暫時備份 ...","Relative paths not allowed":"不允許使用相對路徑","Reload":"重新載入","Remote":"入遠端","Remote Path":"遠端 Path","Remote Repository":"遠端 Repository","Remote path":"遠端 path","Remote repository":"遠端 repository","Remove":"移除","Remove option":"移除選項","Repair":"修復","Reparing ...":"正在修復 ...","Repeat Passphrase":"重複密碼","Reporting:":"報告︰","Reset":"重置","Restore":"還原","Restore files":"還原檔案","Restore files ...":"還原檔案 ...","Restore files from {{backupname}}":"從 {{backupname}} 還原檔案","Restore from":"還原檔案從 ","Restore from backup configuration":"從備份設定檔還原","Restore from configuration ...":"從設定檔還原 ...","Restore options":"還原選項","Restore read/write permissions":"還原讀/寫權限","Restoring files ...":"正在還原檔案 ...","Resume":"繼續","Run again every":"重複執行於每","Run now":"立即執行","Running ...":"正在執行 ...","Running ....":"執行中 ...","Running commandline entry":"Running commandline entry","Running task:":"正在執行工作:","S3 Compatible":"S3 相容","Same as the base install version: {{channelname}}":"Same as the base install version: {{channelname}}","Sat":"週六","Save":"儲存","Save and repair":"儲存並修復","Save different versions with timestamp in file name":"在檔案名稱中儲存不同版本的時間戳記","Save immediately":"立即儲存","Scanning existing files ...":"正在掃描已存在檔案 ...","Scanning for local blocks ...":"正在掃描本機區塊 ...","Schedule":"排程","Search":"搜尋","Search for files":"搜尋檔案","Seconds":"秒","Select a log level and see messages as they happen:":"選擇一個記錄等級以查看訊息︰","Select files":"選擇檔案","Server":"伺服器","Server and port":"伺服器與連接埠","Server hostname or IP":"伺服器名稱或 IP","Server is currently paused,":"伺服器目前已暫停,","Server is currently paused, do you want to resume now?":"伺服器目前已暫停,請問您現在要繼續嗎?","Server password":"伺服器密碼","Server paused":"伺服器目前已暫停","Server state properties":"伺服器狀態屬性","Settings":"設定","Show":"顯示","Show advanced editor":"顯示進階編輯器","Show hidden folders":"顯示隱藏資料夾","Show log":"顯示記錄","Show log ...":"顯示記錄 ...","Show treeview":"顯示樹狀清單","Sia server password":"Sia 伺服器密碼","Smart backup retention":"智慧管理備份數","Some OpenStack providers allow an API key instead of a password and tenant name":"某些 OpenStack 供應商允許 API Key 而不用密碼與 Tenant 名稱","Source Data":"來源資料","Source data":"來源資料","Source folders":"來源資料夾","Source:":"來源:","Specific builds for developers only.":"開發者實驗正在開發中的新功能用,非開發者請勿使用。","Standard protocols":"標準通訊協定","Starting ...":"正在開始 ...","Starting the restore process ...":"正在開始還原程序 ...","Stop after the current file":"這個檔案完成後停止","Stop after upload":"上傳後停止","Stop now":"立即停止","Stop running backup":"停止正在進行的備份","Stop running task":"停止正在進行的工作","Stopping after upload:":"Stopping after upload:","Stopping task:":"正在停止工作:","Storage Type":"儲存區類型","Storage class":"儲存區等級","Storage class for creating a bucket":"建立 Bucket 的儲存類型","Stored":"儲存","Strong":"強","Success":"成功","Sun":"週日","Symbolic link":"符號連結","System default ({{levelname}})":"系統預設 ({{levelname}})","System files":"系統檔案","System info":"系統資訊","System properties":"系統屬性","TByte":"TByte","TByte/s":"TByte/s","Target path, ie /backup":"目的地路徑,例如 /backup","Task is running":"工作正在執行","Temporary files":"暫存檔案","Tenant Name":"Tenant 名稱","Test connection":"測試連線","Testing ...":"測試中 ...","Testing connection ...":"正在測試連線 ...","Testing permissions ...":"正在測試權限 ...","Testing permissions...":"正在測試權限 ...","The bucket name should be all lower-case, convert automatically?":"Bucket 名稱應該全部小寫,要自動轉換嗎?","The bucket name should start with your username, prepend automatically?":"Bucket 名稱應該以您的使用者名稱開頭,要自動加入嗎?","The connection to the server is lost, attempting again in {{time}} ...":"連接伺服器的失敗,再次嘗試 {{}}......","The dark theme (by Michal)":"深色主題 (by Michal)","The default blue on white theme (by Alex)":"預設白色主題 (by Alex)","The folder {{folder}} does not exist.\nCreate it now?":"資料夾 {{folder}} 不存在,是否立即建立?","The host key has changed, please check with the server administrator if this is correct, otherwise you could be the victim of a MAN-IN-THE-MIDDLE attack.\n\nDo you want to REPLACE your CURRENT host key \"{{prev}}\" with the REPORTED host key: {{key}}?":"主機金鑰已變更,如果是正確的請您與伺服器管理員聯繫,否則您可能已遭受中間人攻擊。\n\n你想要更換原先的主機金鑰 \"{{prev}}\" 到 {{key}} 嗎?","The path does not appear to exist, do you want to add it anyway?":"路徑似乎不存在,無論如何你都要加入嗎?","The path does not end with a '{{dirsep}}' character, which means that you include a file, not a folder.\n\nDo you want to include the specified file?":"The path does not end with a '{{dirsep}}' character, which means that you include a file, not a folder.\n\nDo you want to include the specified file?","The path must be an absolute path, i.e. it must start with a forward slash '/'":"必須是絕對路徑,也就是說必須以斜線開頭 '/'","The path should start with \"{{prefix1}}\" or \"{{prefix2}}\", otherwise you will not be able to see the files in the HubiC web interface.\n\nDo you want to add the prefix to the path automatically?":"The path should start with \"{{prefix1}}\" or \"{{prefix2}}\", otherwise you will not be able to see the files in the HubiC web interface.\n\nDo you want to add the prefix to the path automatically?","The region parameter is only applied when creating a new bucket":"區域參數只有在建立新 Bucket 時套用","The region parameter is only used when creating a bucket":"區域參數只使用在在建立新 Bucket 時","The server certificate could not be validated.\nDo you want to approve the SSL certificate with the hash: {{hash}}?":"伺服器無法驗證。\n您要使用這個 SSL 憑證 {{hash}} 嗎?","The storage class affects the availability and price for a stored file":"儲存區類型會影響到可用性以及... 價格","The target folder contains encrypted files, please supply the passphrase":"目的資料夾中包含加密檔案,請提供密碼","The user has too many permissions. Do you want to create a new limited user, with only permissions to the selected path?":"The user has too many permissions. Do you want to create a new limited user, with only permissions to the selected path?","This backup was created on another operating system. Restoring files without specifying a destination folder can cause files to be restored in unexpected places. Are you sure you want to continue without choosing a destination folder?":"This backup was created on another operating system. Restoring files without specifying a destination folder can cause files to be restored in unexpected places. Are you sure you want to continue without choosing a destination folder?","This month":"本月","This week":"本週","Throttle settings":"頻寬限制設定","Thu":"週四","To File":"到檔案","To confirm you want to delete all remote files for \"{{name}}\", please enter the word you see below":"確認要刪除所有的遠端檔案 \"{{name}}\",請輸入下面的單字","To export without a passphrase, uncheck the \"Encrypt file\" box":"若要無密碼匯出,請不要勾選\"加密檔案\"核取方塊","Today":"今天","Trust host certificate?":"信任主機憑證?","Trust server certificate?":"信任伺服器憑證?","Try out the new features we are working on. Don't use with important data.":"試試我們正在進行的新功能。請避免使用在重要的資料上。","Tue":"週二","Type to highlight files":"Type to highlight files","Unknown backup size and versions":"未知的備份大小與版本","Until resumed":"手動繼續","Update channel":"更新頻道","Update failed:":"更新失敗:","Updating with existing database":"正在更新既有資料庫 ...","Upload volume size":"上傳區塊大小","Uploading verification file ...":"正在上傳驗證檔案 ...","Usage reports help us improve the user experience and evaluate impact of new features. We use them to generate public usage statistics":"使用情況報告有助於我們改進使用者體驗並評估新功能的影響。 We use them to generate public usage statistics","Usage statistics":"使用統計","Usage statistics, warnings, errors, and crashes":"使用統計、警告、錯誤與當機","Use SSL":"使用 SSL","Use existing database?":"使用已存在資料庫?","Use weak passphrase":"使用低強度密碼","Useless":"不使用","User data":"使用者資料","User has too many permissions":"使用者有太多權限","User interface settings":"使用者介面設定","Username":"使用者","Validating ...":"確認中 ...","Verify files":"驗證檔案","Verifying ...":"驗證中 ...","Verifying answer":"驗證答案","Verifying backend data ...":"正在驗證後端資料 ...","Verifying remote data ...":"正在驗證遠端資料 ...","Verifying restored files ...":"正在驗證已還原檔案 ...","Very strong":"非常強","Very weak":"非常弱","Visit us on":"拜訪我們","WARNING: The remote database is found to be in use by the commandline library":"WARNING: The remote database is found to be in use by the commandline library","WARNING: This will prevent you from restoring the data in the future.":"警告︰ 這將會阻止您日後還原資料。","Waiting for task to begin":"正在等待工作開始","Waiting for task to start ....":"正在等待工作開始 ...","Waiting for upload ...":"正在等待上傳 ...","Warnings, errors and crashes":"警告、錯誤與當機","We accept donations via different services, such as OpenCollective, PayPal, BountySource and various crypto currencies.":"我們接受多種服務的贊助,例如 OpenCollective、PayPal、BountySource 以及多種加密貨幣。","We recommend that you encrypt all backups stored outside your system":"我們建議,您將放在您自己控管系統以外的備份都進行加密","Weak":"弱","Weak passphrase":"弱密碼","Wed":"週三","Weeks":"週","Where do you want to restore from?":"您要從那裡還原?","Where do you want to restore the files to?":"您要還原檔案到哪裡?","Windows":"Windows","Years":"年","Yes":"是","Yes, I have stored the passphrase safely":"是,我已安全的儲存密碼","Yes, I'm brave!":"是的,我敢!","Yes, please break my backup!":"是,請中斷我的備份!","Yesterday":"昨天","You appear to be running Mono with no SSL certificates loaded.\nDo you want to import the list of trusted certificates from Mozilla?":"您正在運行 Mono 似乎沒有載入 SSL 相關憑證。\n要從 Mozilla 匯入受信任的憑證清單嗎?","You are changing the database path away from an existing database.\nAre you sure this is what you want?":"您正在變更現有資料庫的路徑。\n您確定這是您想要的嗎?","You are currently running {{appname}} {{version}}":"您正在執行 {{appname}} {{version}}","You can stop the backup immediately, or stop after the current file has been uploaded.":"You can stop the backup immediately, or stop after the current file has been uploaded.","You can stop the task immediately, or allow the process to continue its current file and the stop.":"You can stop the task immediately, or allow the process to continue its current file and the stop.","You have changed the encryption mode. This may break stuff. You are encouraged to create a new backup instead":"您已變更加密模式。這可能導致資料損毀。我們建議您建立一個新的備份","You have changed the passphrase, which is not supported. You are encouraged to create a new backup instead.":"您變更加密密碼,這個動作不被支援。我們建議您建立一個新的備份。","You have chosen not to encrypt the backup. Encryption is recommended for all data stored on a remote server.":"您已選擇備份不加密。建議將存在遠端伺服器上的資料予以加密。","You have chosen to restore to a new location, but not entered one":"You have chosen to restore to a new location, but not entered one","You have generated a strong passphrase. Make sure you have made a safe copy of the passphrase, as the data cannot be recovered if you lose the passphrase.":"您已經產生足夠強度的密碼。請確保您已經另外備份好這組密碼,若您遺失這組密碼,您的資料將無法還原。","You must choose at least one source folder":"您至少要選擇一個來源資料夾","You must enter a name for the backup":"您必須輸入備份名稱","You must enter a passphrase or disable encryption":"您必須輸入密碼或取消加密","You must enter a positive number of backups to keep":"您必須輸入正數,備份才能保存","You must enter a tenant name if you do not provide an API Key":"如果您不提供 API Key,您必須輸入 Tenant 名稱","You must enter a valid duration for the time to keep backups":"您必須輸入有效的起迄時間來保留備份","You must enter a valid rentention policy string":"您必需輸入符合可用字串的備份保留原則","You must enter either a password or an API Key":"您必須輸入密碼或 API Key","You must enter either a password or an API Key, not both":"您必須輸入密碼或者 API Key,二擇一","You must fill in the password":"您必須輸入密碼","You must fill in the server name or address":"您必須填寫伺服器名稱或位址","You must fill in the username":"您必須填寫使用者名稱","You must fill in {{field}}":"您必須填寫 {{field}}","You must select or fill in the AuthURI":"您必須選擇或填寫 AuthURI","You must select or fill in the server":"您必須選擇或填寫伺服器","You must specify a path":"您必須指定一個路徑","Your files and folders have been restored successfully.":"您的檔案與資料夾已成功還原。","Your passphrase is easy to guess. Consider changing passphrase.":"您的密碼很容易被猜到。請考慮變更密碼。","bucket/folder/subfolder":"bucket/folder/subfolder","byte":"byte","byte/s":"byte/s","custom":"自訂","resume now":"立即繼續","{{appname}} was primarily developed by {{dev1}} and {{dev2}}. {{appname}} can be downloaded from {{websitename}}. {{appname}} is licensed under the {{licensename}}.":"{{appname}} was primarily developed by {{dev1}} and {{dev2}}. {{appname}} can be downloaded from {{websitename}}. {{appname}} is licensed under the {{licensename}}.","{{files}} files ({{size}}) to go {{speed_txt}}":"{{files}} 個檔案 ({{size}}) 正在傳輸 {{speed_txt}}","{{item.Backup.Metadata.TargetSizeString}} / {{$count}} Version":"{{item.Backup.Metadata.TargetSizeString}} / {{$count}} 個版本","{{number}} Hour":"{{number}} 小時","{{number}} Minutes":"{{number}} 分鐘","{{time}} (took {{duration}})":"{{time}} (花費 {{duration}})"}); /* jshint +W100 */ }]); \ No newline at end of file diff --git a/Duplicati/Server/webroot/ngax/scripts/controllers/EditBackupController.js b/Duplicati/Server/webroot/ngax/scripts/controllers/EditBackupController.js index a526cc70e..05af679ad 100644 --- a/Duplicati/Server/webroot/ngax/scripts/controllers/EditBackupController.js +++ b/Duplicati/Server/webroot/ngax/scripts/controllers/EditBackupController.js @@ -316,7 +316,7 @@ backupApp.controller('EditBackupController', function ($rootScope, $scope, $rout } // Retention options are mutual exclusive -> allow only one to be selected at a time - function resetAllRetentionOptionsExcept(optionToKeep = '') { + function resetAllRetentionOptionsExcept(optionToKeep) { ['keep-versions', 'keep-time', 'retention-policy'].forEach(function(entry) { if (entry != optionToKeep) { delete opts[entry]; @@ -351,7 +351,7 @@ backupApp.controller('EditBackupController', function ($rootScope, $scope, $rout return; } - if ($scope.KeepType == 'custom' && (opts['retention-policy'] || '').indexOf(':') <= 1) + if ($scope.KeepType == 'custom' && (opts['retention-policy'] || '').indexOf(':') <= 0) { DialogService.dialog(gettextCatalog.getString('Invalid retention time'), gettextCatalog.getString('You must enter a valid rentention policy string')); $scope.CurrentStep = 4; diff --git a/Duplicati/Server/webroot/ngax/scripts/directives/notificationArea.js b/Duplicati/Server/webroot/ngax/scripts/directives/notificationArea.js index 6353b947e..8fc6bc70b 100644 --- a/Duplicati/Server/webroot/ngax/scripts/directives/notificationArea.js +++ b/Duplicati/Server/webroot/ngax/scripts/directives/notificationArea.js @@ -37,6 +37,11 @@ backupApp.directive('notificationArea', function() { ); }; + $scope.doRepair = function(backupid) { + AppService.post('/backup/' + backupid + '/repair'); + $location.path('/'); + }; + $scope.doInstallUpdate = function(id) { AppService.post('/updates/install'); }; diff --git a/Duplicati/Server/webroot/ngax/styles/style.css b/Duplicati/Server/webroot/ngax/styles/style.css index 2c3ae55a7..e5f700597 100644 --- a/Duplicati/Server/webroot/ngax/styles/style.css +++ b/Duplicati/Server/webroot/ngax/styles/style.css @@ -1,4 +1,4 @@ @font-face{font-family:'Clear Sans';src:url(../fonts/ClearSans-Light-webfont.eot);src:url(../fonts/ClearSans-Light-webfont.eot?#iefix) format('embedded-opentype'),url(../fonts/ClearSans-Light-webfont.woff) format('woff'),url(../fonts/ClearSans-Light-webfont.ttf) format('truetype'),url(../fonts/ClearSans-Light-webfont.svg#clear_sans_lightregular) format('svg');font-weight:300;font-style:normal}@font-face{font-family:'Clear Sans';src:url(../fonts/ClearSans-Regular-webfont.eot);src:url(../fonts/ClearSans-Regular-webfont.eot?#iefix) format('embedded-opentype'),url(../fonts/ClearSans-Regular-webfont.woff) format('woff'),url(../fonts/ClearSans-Regular-webfont.ttf) format('truetype'),url(../fonts/ClearSans-Regular-webfont.svg#clear_sansregular) format('svg');font-weight:400;font-style:normal}@font-face{font-family:'Clear Sans';src:url(../fonts/ClearSans-Medium-webfont.eot);src:url(../fonts/ClearSans-Medium-webfont.eot?#iefix) format('embedded-opentype'),url(../fonts/ClearSans-Medium-webfont.woff) format('woff'),url(../fonts/ClearSans-Medium-webfont.ttf) format('truetype'),url(../fonts/ClearSans-Medium-webfont.svg#clear_sans_mediumregular) format('svg');font-weight:500;font-style:normal}@font-face{font-family:'Clear Sans';src:url(../fonts/ClearSans-Bold-webfont.eot);src:url(../fonts/ClearSans-Bold-webfont.eot?#iefix) format('embedded-opentype'),url(../fonts/ClearSans-Bold-webfont.woff) format('woff'),url(../fonts/ClearSans-Bold-webfont.ttf) format('truetype'),url(../fonts/ClearSans-Bold-webfont.svg#clear_sansbold) format('svg');font-weight:700;font-style:normal}form.styled div.leftflush input{width:auto;margin-top:10px}form.styled div.leftflush label{width:auto;min-width:190px}form.styled label{display:block;width:190px;float:left;line-height:37px}form.styled input,form.styled select,form.styled textarea{color:#8f8f8f;font-size:16px;font-weight:300;float:left;display:block;border:1px #d8d8d8 solid;border-radius:2px;width:420px}form.styled input:focus,form.styled select:focus,form.styled textarea:focus{border:1px #a5a5a5 solid}form.styled .input{padding-bottom:18px;overflow:hidden}form.styled .input.password input,form.styled .input.text input{height:35px;line-height:35px;padding:0 12px}form.styled .input.text.text-browse input{width:375px;border-top-right-radius:0;border-bottom-right-radius:0;border-right:0}form.styled .input.text.text-browse a.browse{width:45px;display:block;float:left;height:37px;border-radius:2px;border-top-left-radius:0;border-bottom-left-radius:0;color:#fff;background:#65b1dd;line-height:37px}form.styled .input.text.text-browse a.browse:hover{background:#2881b4}form.styled .input.textarea textarea{height:130px;padding:10px 12px}form.styled .input.select select{width:446px;padding:0 12px;-webkit-appearance:menulist-button;background:#fff;border-radius:2px;height:38px;line-height:38px}form.styled .buttons{overflow:hidden;float:right}form.styled .buttons a,form.styled .buttons input{display:block;background:#65b1dd;color:#fff!important;padding:5px 15px;float:right;margin-left:10px;cursor:pointer;width:auto;border:none;font-family:'Clear Sans',sans-serif;font-size:16px;font-weight:300;border-radius:0}form.styled .buttons input{padding:4px 15px}form.styled .buttons a:hover,form.styled .buttons input:hover{background:#23729f}@media (max-width:480px){form.styled input,form.styled select,form.styled textarea{font-size:15px}}/*! * Font Awesome 4.5.0 by @davegandy - http://fontawesome.io - @fontawesome * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */@font-face{font-family:FontAwesome;src:url(../fonts/fontawesome-webfont.eot?v=4.5.0);src:url(../fonts/fontawesome-webfont.eot?#iefix&v=4.5.0) format('embedded-opentype'),url(../fonts/fontawesome-webfont.woff2?v=4.5.0) format('woff2'),url(../fonts/fontawesome-webfont.woff?v=4.5.0) format('woff'),url(../fonts/fontawesome-webfont.ttf?v=4.5.0) format('truetype'),url(../fonts/fontawesome-webfont.svg?v=4.5.0#fontawesomeregular) format('svg');font-weight:400;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1,1);-ms-transform:scale(-1,1);transform:scale(-1,1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1,-1);-ms-transform:scale(1,-1);transform:scale(1,-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-rotate-90{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-close:before,.fa-remove:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-cog:before,.fa-gear:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-repeat:before,.fa-rotate-right:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-exclamation-triangle:before,.fa-warning:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-cogs:before,.fa-gears:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-floppy-o:before,.fa-save:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-sort:before,.fa-unsorted:before{content:"\f0dc"}.fa-sort-desc:before,.fa-sort-down:before{content:"\f0dd"}.fa-sort-asc:before,.fa-sort-up:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-gavel:before,.fa-legal:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-bolt:before,.fa-flash:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-clipboard:before,.fa-paste:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-chain-broken:before,.fa-unlink:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:"\f150"}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:"\f151"}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:"\f152"}.fa-eur:before,.fa-euro:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-inr:before,.fa-rupee:before{content:"\f156"}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:"\f157"}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:"\f158"}.fa-krw:before,.fa-won:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-try:before,.fa-turkish-lira:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-bank:before,.fa-institution:before,.fa-university:before{content:"\f19c"}.fa-graduation-cap:before,.fa-mortar-board:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:"\f1c5"}.fa-file-archive-o:before,.fa-file-zip-o:before{content:"\f1c6"}.fa-file-audio-o:before,.fa-file-sound-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before{content:"\f1d0"}.fa-empire:before,.fa-ge:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-hacker-news:before,.fa-y-combinator-square:before,.fa-yc-square:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-paper-plane:before,.fa-send:before{content:"\f1d8"}.fa-paper-plane-o:before,.fa-send-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-futbol-o:before,.fa-soccer-ball-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-ils:before,.fa-shekel:before,.fa-sheqel:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-bed:before,.fa-hotel:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-y-combinator:before,.fa-yc:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-paper-o:before,.fa-hand-stop-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-television:before,.fa-tv:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}*{font-family:'Clear Sans',sans-serif}body,html{margin:0;padding:0;height:100%}h1,h2{font-weight:300;color:#81c401}h1{margin:10px 0}h3{font-weight:400}a{text-decoration:none}ul{list-style:none;margin:0;padding:0}hr{border:none;border-bottom:1px #ddd solid}textarea{max-width:94%}.external-link-image{display:inline-block;margin-left:8px;margin-right:8px;height:16px;width:16px;background:url(../img/external-link-hover.png);background-size:16px}a .external-link-image{background:url(../img/external-link.png);background-size:16px}.header a:hover .external-link-image{background:url(../img/external-link-hover.png);background-size:16px}.button{display:block;background:#65b1dd;color:#fff!important;padding:5px 15px;float:right;margin-left:10px;cursor:pointer;width:auto;border:none;font-family:'Clear Sans',sans-serif;font-size:16px;font-weight:300;border-radius:0}.button:hover{background:#3b9cd4}#folder_path_picker,#restore_file_picker,.step3 source-folder-picker{display:block;border:1px solid #d3d3d3;padding:2px;height:100%;overflow:auto}.not-clickable{cursor:default!important}.not-clickable div,.not-clickable span,.not-clickable>a{cursor:default!important}.ui-match{font-weight:700;color:#006400}wait-area{min-width:350px;text-align:center;display:block}.prewrapped-text{white-space:pre-wrap}.exceptiontext{background-color:#d3d3d3;color:#000}ul.tabs{margin-bottom:10px}ul.tabs>li{display:inline;margin-right:10px;border:1px solid #65b1dd;padding:5px}ul.tabs>li.active{background-color:#65b1dd;color:#fff}ul.tabs>li.active>a{background-color:#65b1dd;color:#fff}ul.tabs>li.active.disabled{border:1px solid #d3d3d3;background-color:#d3d3d3;color:grey;cursor:default}ul.tabs>li.active.disabled>a{background-color:#d3d3d3;color:grey;cursor:default}.licenses>ul{list-style:initial;margin:10px;margin-left:20px}.licenses li{margin-bottom:10px}.licenses a.itemlink{font-weight:700}.logpage ul.entries{list-style:initial;margin:10px;margin-left:20px}.logpage .entries div.entryline{cursor:pointer}.logpage .entries.livedata li{height:1.2em}.logpage .entries.livedata li.expanded{height:auto;overflow:auto}.logpage .button{text-align:center;margin-right:10px;border:1px solid #65b1dd;padding:5px;background-color:#65b1dd;color:#fff;cursor:pointer}.exportpage .checkbox input{width:auto;margin-top:10px}.exportpage .commandline div{background-color:#d3d3d3;color:#000}.themelink{margin-left:20px}ul.notification{position:fixed;bottom:0;left:0;right:0;margin:auto;width:480px}.notification .title{border:1px solid #65b1dd;background-color:#65b1dd;border-top-left-radius:5px;border-top-right-radius:5px;border-bottom-left-radius:0;border-bottom-right-radius:0;padding:2px;padding-left:5px;padding-right:5px;font-weight:700;color:#d3d3d3;width:100%;text-align:center;clear:both}.notification .content{background-color:#fff;border:1px solid #65b1dd;border-top-left-radius:0;border-top-right-radius:0;border-bottom-left-radius:5px;border-bottom-right-radius:5px;padding:2px;padding-left:5px;padding-right:5px;width:100%}.notification .message{width:100%;color:#000}.notification .button{padding:2px 10px;margin-top:6px}.notification .clear{clear:right;height:1px}.notification .error .title{border-color:red;background-color:red}.notification .error .content{border-color:red}.notification .error .button{border-color:red;background-color:red}.notification .warning .title{background-color:orange;border-color:orange}.notification .warning .button{background-color:orange;border-color:orange}.notification .warning .content{border-color:orange}.filepicker{height:200px}.resizable{margin-bottom:6px;max-width:100%}.advanced-toggle{float:right;margin-right:25px;line-height:37px}.advancedoptions li{clear:both;margin-bottom:10px;padding:10px 0;border-top:1px #d3d3d3 solid}.advancedentry .multiple{display:inline}.advancedentry .shortname{font-weight:700}.advancedentry input[type=text]{width:300px}.advancedentry select{width:300px}.advancedentry input[type=checkbox]{margin-top:13px;width:auto}.advancedentry .longdescription{margin-left:190px;clear:both;font-style:italic}.settings div.sublabel{clear:both;padding:0 31px;font-style:italic}.logo img.mainlogo{height:64px;width:64px;float:left;padding-right:8px;padding-top:2px}.logo div.logotext{float:left}.logo a{float:left;display:block;line-height:normal}.logo div.build-suffix{clear:both;display:inline;float:left;font-size:16px;line-height:16px}.logo div.powered-by{font-size:16px;margin:0;line-height:16px;float:left;padding:0;margin-left:5px}.fixed-width-font{font-family:monospace}.warning{margin:10px;font-style:italic;color:#f49b42}div.captcha .details{padding-top:10px;margin-left:auto;margin-right:auto;width:180px}.centered-text{text-align:center}body{color:#8f8f8f}body .container{min-height:100%;position:relative}body .container .header{line-height:70px;background:#ededed;overflow:hidden;height:70px;position:fixed;top:0;left:0;right:0;z-index:100}body .container .header a{color:#65b1dd}body .container .header a.active,body .container .header a:hover{color:#4f4f4f}body .container .header .logo{font-size:30px;font-weight:700;float:left;padding-left:40px}body .container .header .statepadding{padding-right:90px;margin-left:320px}body .container .header .state{float:left;color:#609101;width:580px;padding:13px 15px;margin:10px 20px;border:1px #609101 solid;font-weight:300;font-size:18px;overflow:hidden;line-height:normal;display:inline-block;background-color:#fff;text-overflow:ellipsis;position:relative;height:25px}body .container .header .state strong{display:inline;margin-right:10px}body .container .header .state span{display:inline}body .container .header .state .button{position:static;margin-top:70px}body .container .header .state .content{position:relative;z-index:10;margin-right:40px;display:block;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}body .container .header .state .buttons{position:absolute;right:0;top:0;bottom:0;width:26px;margin:13px 15px}body .container .header .state .buttons .stop{display:block;width:26px;height:26px;background:url(../img/progress-stop.png);background-size:26px;cursor:pointer}body .container .header .state .buttons .resume{display:block;width:26px;height:26px;background:url(../img/progress-resume.png);background-size:26px;cursor:pointer}body .container .header .state .progress-bar{position:absolute;top:0;bottom:0;left:0;background:rgba(129,196,1,.25);z-index:5}body .container .header .action-icons{display:inline-block;line-height:normal;margin:10px 0;padding:13px 0;float:left}body .container .header .action-icons-small{display:none;float:right;margin-top:21px;line-height:normal}body .container .header .action-icons-small>.pause,body .container .header .action-icons>.pause{width:26px;height:26px;display:inline-block;cursor:pointer;background:url(../img/pause.png)}body .container .header .action-icons-small>.pause.active,body .container .header .action-icons>.pause.active{background:url(../img/resume.png)}body .container .header .action-icons-small>.throttle,body .container .header .action-icons>.throttle{width:26px;height:26px;display:inline-block;cursor:pointer;background:url(../img/throttle.png)}body .container .header .action-icons-small>.throttle.inactive,body .container .header .action-icons>.throttle.inactive{opacity:.5}body .container .header .about-header{float:right;padding-right:20px;overflow:hidden}body .container .header .about-header ul{overflow:hidden;list-style:none}body .container .header .about-header ul li{float:right;padding-right:20px}body .container .header .donate{float:right}body .container .header .donate ul{overflow:hidden;float:right;padding-left:20px;padding-right:10px}body .container .header .donate ul li{float:right;margin-right:10px;padding-top:5px}body .container .header .donate img{opacity:.6}body .container .header .donate img:hover{opacity:1}body .container .body{width:100%;overflow:hidden;min-height:500px;padding-top:120px;padding-bottom:70px}body .container .body a{color:#65b1dd}body .container .body .mainmenu{width:260px;padding-left:40px;float:left;position:fixed}body .container .body .mainmenu>ul>li{position:relative}body .container .body .mainmenu>ul>li>a{font-size:22px;font-weight:300;padding:5px 10px 5px 55px;display:block}body .container .body .mainmenu>ul>li>a:hover{color:#fff}body .container .body .mainmenu>ul>li>a.active{color:#fff}body .container .body .mainmenu>ul>li>a.add{background:url(../img/mainmenu/add.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.restore{background:url(../img/mainmenu/restore.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.pause{background:url(../img/mainmenu/pause.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.resume{background:url(../img/mainmenu/resume.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.settings{background:url(../img/mainmenu/settings.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.log{background:url(../img/mainmenu/log.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.logout{background:url(../img/mainmenu/logout.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.home{background:url(../img/mainmenu/home.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.about{background:url(../img/mainmenu/about.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.pause>span{padding-right:25px;background:url(../img/mainmenu/arrow_right.png) right center no-repeat}body .container .body .mainmenu>ul>li>a.home.active{background:#a4d1eb url(../img/mainmenu/over/home.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.add.active{background:#a4d1eb url(../img/mainmenu/over/add.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.restore.active{background:#a4d1eb url(../img/mainmenu/over/restore.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.pause.active{background:#a4d1eb url(../img/mainmenu/over/pause.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.resume.active{background:#a4d1eb url(../img/mainmenu/over/resume.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.settings.active{background:#a4d1eb url(../img/mainmenu/over/settings.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.log.active{background:#a4d1eb url(../img/mainmenu/over/log.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.about.active{background:#a4d1eb url(../img/mainmenu/over/about.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.pause.open.active>span{background:url(../img/mainmenu/over/arrow_down.png) right center no-repeat}body .container .body .mainmenu>ul>li>a.add:hover{background:#65b1dd url(../img/mainmenu/over/add.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.restore:hover{background:#65b1dd url(../img/mainmenu/over/restore.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.pause:hover{background:#65b1dd url(../img/mainmenu/over/pause.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.pause:hover>span{background:url(../img/mainmenu/over/arrow_right.png) right center no-repeat}body .container .body .mainmenu>ul>li>a.pause.open:hover>span{background:url(../img/mainmenu/over/arrow_down.png) right center no-repeat}body .container .body .mainmenu>ul>li>a.pause.open>span{background:url(../img/mainmenu/arrow_down.png) right center no-repeat}body .container .body .mainmenu>ul>li>a.resume:hover{background:#65b1dd url(../img/mainmenu/over/resume.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.settings:hover{background:#65b1dd url(../img/mainmenu/over/settings.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.log:hover{background:#65b1dd url(../img/mainmenu/over/log.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.logout:hover{background:#65b1dd url(../img/mainmenu/over/logout.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.home:hover{background:#65b1dd url(../img/mainmenu/over/home.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.about:hover{background:#65b1dd url(../img/mainmenu/over/about.png) no-repeat 8px 7px}body .container .body .mainmenu>ul li.hr-top{padding-top:25px;margin-top:25px;border-top:1px #ededed solid}body .container .body div.contextmenu_container{position:relative}body .container .body .contextmenu{display:none;position:absolute;background:#fff;border:1px #ededed solid;box-shadow:0 4px 8px rgba(0,0,0,.3);z-index:200;padding:5px}body .container .body .contextmenu li a{color:#65b1dd;font-size:15px;font-weight:400;padding:0;display:block;min-width:200px;padding:4px 10px;white-space:nowrap;padding-left:45px;overflow:hidden;text-overflow:ellipsis}body .container .body .contextmenu li a:hover{background:#65b1dd;color:#fff}body .container .body .contextmenu.open{display:block}body .container .body .content{float:left;padding-left:350px;padding-bottom:50px;max-width:700px}body .container .body .content ul.tabs>li{display:inline-block}body .container .body .content .tasks .tasklist .task{border-top:1px solid #eee;padding-top:20px;margin-bottom:25px}body .container .body .content .tasks .tasklist .task:last-child{border-bottom:1px solid #eee;padding-bottom:20px}body .container .body .content .tasks .tasklist .task:first-child{padding-top:0;border-top:0 none}body .container .body .content .tasks .tasklist a{font-size:30px;padding-left:55px;background:url(../img/backup.png) no-repeat 5px 6px;font-weight:300;display:inline-block}body .container .body .content .tasks .tasklist a.action-link{font-size:14px;background:0 0;padding-left:0}body .container .body .content .tasks .tasklist dl{padding-left:55px;overflow:hidden;font-size:14px}body .container .body .content .tasks .tasklist dl dd,body .container .body .content .tasks .tasklist dl dt{display:block;float:left}body .container .body .content .tasks .tasklist dl dt{clear:both;font-weight:500;margin-bottom:5px}body .container .body .content .tasks .tasklist dl dd{margin-left:10px}body .container .body .content .tasks .tasklist dl.taskmenu p{display:inline;margin-right:10px;color:#65b1dd;cursor:pointer}body .container .body .content .tasks .tasklist dl.taskmenu dt{float:left;margin-right:10px;margin-bottom:0;padding:5px 8px;color:#8f8f8f;cursor:pointer;clear:none}body .container .body .content .tasks .tasklist dl.taskmenu dd{clear:both;float:none;padding-bottom:8px;border-bottom:1px #ddd solid;margin-bottom:5px}body .container .body .content div.add .steps,body .container .body .content div.restore .steps{width:100%;overflow:hidden}body .container .body .content div.add .steps .step,body .container .body .content div.restore .steps .step{float:left;background:url(../img/steps/line-out.png) no-repeat top left;color:#c7e5f6}body .container .body .content div.add .steps .step span,body .container .body .content div.restore .steps .step span{display:block;border:4px #c7e5f6 solid;background:#fff;border-radius:50%;width:35px;height:35px;text-align:center;font-size:22px;line-height:35px;cursor:pointer}body .container .body .content div.add .steps .step.active,body .container .body .content div.restore .steps .step.active{color:#65b1dd}body .container .body .content div.add .steps .step.active span,body .container .body .content div.restore .steps .step.active span{border:4px #65b1dd solid;background:#65b1dd;color:#fff}body .container .body .content div.add .steps .step.active h2,body .container .body .content div.restore .steps .step.active h2{color:#65b1dd}body .container .body .content div.add .steps .step:first-child,body .container .body .content div.restore .steps .step:first-child{padding-left:0;background:0 0}body .container .body .content div.add .steps-legend,body .container .body .content div.restore .steps-legend{overflow:hidden;padding-bottom:50px;list-style:none;margin:0}body .container .body .content div.add .steps-legend li,body .container .body .content div.restore .steps-legend li{color:#c7e5f6;font-size:18px;text-align:center;float:left;padding-top:10px;cursor:pointer}body .container .body .content div.add .steps-legend li.active,body .container .body .content div.restore .steps-legend li.active{color:#65b1dd}body .container .body .content div.add .steps-boxes,body .container .body .content div.restore .steps-boxes{padding-left:40px}body .container .body .content div.add .steps-boxes .step,body .container .body .content div.restore .steps-boxes .step{display:none}body .container .body .content div.add .steps-boxes .step.active,body .container .body .content div.restore .steps-boxes .step.active{display:block}body .container .body .content div.add .steps-boxes .box.browser .checklinks a,body .container .body .content div.restore .steps-boxes .box.browser .checklinks a{float:left;margin-left:20px;color:#8f8f8f}body .container .body .content div.add .steps-boxes .box.browser .checklinks a i,body .container .body .content div.restore .steps-boxes .box.browser .checklinks a i{border:2px solid;border-color:#8f8f8f;border-radius:2px;font-size:18px;height:18px;vertical-align:top;width:18px}body .container .body .content div.add .steps-boxes .box.browser .checklinks a.inactive,body .container .body .content div.restore .steps-boxes .box.browser .checklinks a.inactive{color:#c2c2c2;cursor:default}body .container .body .content div.add .steps-boxes .box.browser .checklinks a.inactive i,body .container .body .content div.restore .steps-boxes .box.browser .checklinks a.inactive i{border-color:#c2c2c2}body .container .body .content div.add .steps-boxes .box.browser .checklinks a:first-child,body .container .body .content div.restore .steps-boxes .box.browser .checklinks a:first-child{margin-left:0}body .container .body .content div.add .steps-boxes .box.browser .input.overlayButton,body .container .body .content div.restore .steps-boxes .box.browser .input.overlayButton{padding-top:10px;max-width:100%}body .container .body .content div.add .steps-boxes .box.browser .input.overlayButton input#sourcePath,body .container .body .content div.restore .steps-boxes .box.browser .input.overlayButton input#sourcePath{width:100%;box-sizing:border-box;height:37px}body .container .body .content div.add .steps-boxes .box.browser .input.overlayButton a.button,body .container .body .content div.restore .steps-boxes .box.browser .input.overlayButton a.button{top:10px}body .container .body .content div.add .steps-boxes .box.filters .input.link a,body .container .body .content div.restore .steps-boxes .box.filters .input.link a{color:#8f8f8f}body .container .body .content div.add .steps-boxes .box.filters .input.link a i,body .container .body .content div.restore .steps-boxes .box.filters .input.link a i{border:2px solid;border-color:#8f8f8f;border-radius:2px;font-size:18px;height:18px;vertical-align:top;width:18px}body .container .body .content div.add .steps-boxes .box.filters ul#simplefilterlist,body .container .body .content div.restore .steps-boxes .box.filters ul#simplefilterlist{overflow:hidden;padding-bottom:15px}body .container .body .content div.add .steps-boxes .box.filters ul#simplefilterlist li,body .container .body .content div.restore .steps-boxes .box.filters ul#simplefilterlist li{overflow:hidden;clear:both;padding-bottom:5px}body .container .body .content div.add .steps-boxes .box.filters ul#simplefilterlist li select,body .container .body .content div.restore .steps-boxes .box.filters ul#simplefilterlist li select{width:200px;margin-right:5px;height:36px;line-height:36px}body .container .body .content div.add .steps-boxes .box.filters ul#simplefilterlist li input,body .container .body .content div.restore .steps-boxes .box.filters ul#simplefilterlist li input{width:280px;padding:5px}body .container .body .content div.add .steps-boxes .step1 li.strength.score-0,body .container .body .content div.restore .steps-boxes .step1 li.strength.score-0{color:red}body .container .body .content div.add .steps-boxes .step1 li.strength.score-1,body .container .body .content div.restore .steps-boxes .step1 li.strength.score-1{color:#f70}body .container .body .content div.add .steps-boxes .step1 li.strength.score-2,body .container .body .content div.restore .steps-boxes .step1 li.strength.score-2{color:#aa0}body .container .body .content div.add .steps-boxes .step1 li.strength.score-3,body .container .body .content div.restore .steps-boxes .step1 li.strength.score-3{color:#070}body .container .body .content div.add .steps-boxes .step1 li.strength.score-4,body .container .body .content div.restore .steps-boxes .step1 li.strength.score-4{color:#427e27}body .container .body .content div.add .steps-boxes .step1 li.strength.score-x,body .container .body .content div.restore .steps-boxes .step1 li.strength.score-x{color:red}body .container .body .content div.add .steps-boxes .step5 div.input.keepBackups input.number,body .container .body .content div.add .steps-boxes .step5 div.input.maxSize input.number,body .container .body .content div.restore .steps-boxes .step5 div.input.keepBackups input.number,body .container .body .content div.restore .steps-boxes .step5 div.input.maxSize input.number{width:60px}body .container .body .content div.add .steps-boxes .step5 .hint,body .container .body .content div.add .steps-boxes .step5 .retention-options,body .container .body .content div.restore .steps-boxes .step5 .hint,body .container .body .content div.restore .steps-boxes .step5 .retention-options{clear:both;margin-left:190px;margin-top:50px;font-style:italic}body .container .body .content div.add .steps-boxes .step5 .retention-options input,body .container .body .content div.restore .steps-boxes .step5 .retention-options input{margin-bottom:10px}body .container .body .content div.add .steps-boxes .step5 .advancedoptions,body .container .body .content div.restore .steps-boxes .step5 .advancedoptions{padding-top:15px;clear:both}body .container .body .content div.add .steps-boxes .step5 .advancedoptions li,body .container .body .content div.restore .steps-boxes .step5 .advancedoptions li{border-top:none}body .container .body .content div.add .steps-boxes .step5 .advancedoptions li>a,body .container .body .content div.restore .steps-boxes .step5 .advancedoptions li>a{display:block;background:#65b1dd;color:#fff!important;padding:5px 15px;float:right;margin-left:10px;cursor:pointer;width:auto;border:none;font-family:'Clear Sans',sans-serif;font-size:16px;font-weight:300;border-radius:0}body .container .body .content div.add .steps-boxes .step5 .advancedoptions li.advancedentry,body .container .body .content div.restore .steps-boxes .step5 .advancedoptions li.advancedentry{border-bottom:1px solid #d3d3d3}body .container .body .content div.add .steps-boxes .step5 .advancedoptions li:last-child,body .container .body .content div.restore .steps-boxes .step5 .advancedoptions li:last-child{padding-top:0}body .container .body .content div.add .steps-boxes .step5 .advancedoptions li:last-child select,body .container .body .content div.restore .steps-boxes .step5 .advancedoptions li:last-child select{max-width:400px}body .container .body .content div.add .steps-boxes .step5 .advancedoptions label,body .container .body .content div.restore .steps-boxes .step5 .advancedoptions label{line-height:normal}body .container .body .content div.add .steps-boxes .step5 .advancedoptions input,body .container .body .content div.add .steps-boxes .step5 .advancedoptions select,body .container .body .content div.restore .steps-boxes .step5 .advancedoptions input,body .container .body .content div.restore .steps-boxes .step5 .advancedoptions select{width:auto;max-width:100%;box-sizing:border-box}body .container .body .content div.add .steps-boxes .step5 .advancedoptions .longdescription,body .container .body .content div.restore .steps-boxes .step5 .advancedoptions .longdescription{margin-top:10px}body .container .body .content div.add .steps-boxes .step5 .advanced-toggle,body .container .body .content div.restore .steps-boxes .step5 .advanced-toggle{color:#8f8f8f;line-height:normal;margin-top:16px;clear:both;float:left}body .container .body .content div.add .steps-boxes .step5 .advanced-toggle i.fa,body .container .body .content div.restore .steps-boxes .step5 .advanced-toggle i.fa{border:2px solid;border-color:#8f8f8f;border-radius:2px;font-size:18px;height:18px;vertical-align:top;width:18px}body .container .body .content div.add .steps-boxes .step5 textarea,body .container .body .content div.restore .steps-boxes .step5 textarea{box-sizing:border-box;clear:both;margin-top:15px;width:100%}body .container .body .content div.add form,body .container .body .content div.restore form{padding-bottom:50px;overflow:hidden}body .container .body .content div.add form .input.password .tools,body .container .body .content div.restore form .input.password .tools{clear:both;padding-left:190px;padding-top:10px}body .container .body .content div.add form .input.password .tools ul,body .container .body .content div.restore form .input.password .tools ul{overflow:hidden}body .container .body .content div.add form .input.password .tools ul li,body .container .body .content div.restore form .input.password .tools ul li{float:left;padding-right:7px}body .container .body .content div.add form .input.password .tools ul li.strength.useless,body .container .body .content div.restore form .input.password .tools ul li.strength.useless{color:red}body .container .body .content div.add form .input.password .tools ul li.strength.average,body .container .body .content div.restore form .input.password .tools ul li.strength.average{color:#ff0}body .container .body .content div.add form .input.password .tools ul li.strength.good,body .container .body .content div.restore form .input.password .tools ul li.strength.good{color:#65b1dd}body .container .body .content div.add form .input.multiple input,body .container .body .content div.add form .input.multiple select,body .container .body .content div.restore form .input.multiple input,body .container .body .content div.restore form .input.multiple select{width:auto;margin-right:5px}body .container .body .content div.add form .input.multiple select,body .container .body .content div.restore form .input.multiple select{padding:5px 12px}body .container .body .content div.add form .input.overlayButton,body .container .body .content div.restore form .input.overlayButton{overflow:hidden;position:relative;max-width:446px}body .container .body .content div.add form .input.overlayButton input,body .container .body .content div.restore form .input.overlayButton input{width:347px}body .container .body .content div.add form .input.overlayButton a.button,body .container .body .content div.restore form .input.overlayButton a.button{position:absolute;top:0;right:0;padding:7px 12px 8px}body .container .body .content div.add form .input.checkbox.multiple strong,body .container .body .content div.restore form .input.checkbox.multiple strong{display:block;padding-bottom:5px}body .container .body .content div.add form .input.checkbox.multiple label,body .container .body .content div.restore form .input.checkbox.multiple label{display:inline-block;float:none;width:auto;padding-right:10px}body .container .body .content div.add form .input.checkbox.multiple input,body .container .body .content div.restore form .input.checkbox.multiple input{width:auto;display:inline-block;float:none}body .container .body .content div.add form .buttons,body .container .body .content div.restore form .buttons{float:none;width:635px;padding-top:30px}body .container .body .content div.add .steps{margin-left:48.5px}body .container .body .content div.add .steps .step{padding-left:97px}body .container .body .content div.add .steps-legend{padding-left:0}body .container .body .content div.add .steps-legend li{width:140px}body .container .body .content div.restore .steps{margin-left:153.5px}body .container .body .content div.restore .steps .step{padding-left:307px}body .container .body .content div.restore .steps-legend{padding-left:0}body .container .body .content div.restore .steps-legend li{width:350px}body .container .body .content div.restore.restore-direct .steps{margin-left:66px}body .container .body .content div.restore.restore-direct .steps .step{padding-left:132px}body .container .body .content div.restore.restore-direct .steps-legend{padding-left:0}body .container .body .content div.restore.restore-direct .steps-legend li{width:175px}body .container .body .content div.restore.restore-direct .step:first-child{padding-left:0;background:0 0}body .container .body .content div.restore.restore-direct .steps-legend{padding-left:20px}body .container .body .content div.headerthreedotmenu{margin:20px 0 20px 0}body .container .body .content div.headerthreedotmenu h2{display:inline}body .container .body .content div.headerthreedotmenu .contextmenu_container{float:right}body .container .body .content div.headerthreedotmenu .contextmenu{left:auto;right:0;top:auto}body .container .body .content div.headerthreedotmenu .threedotmenubutton{padding:5px}body .container .body .content .expandable{margin:20px 0 20px 0}body .container .body .content .expandable h2{display:inline}body .container .body .content .expandable img{padding:0 6px}body .container .body .content div.settings .input.checkbox input.checkbox,body .container .body .content div.settings .input.mixed.multiple input.checkbox{width:auto}body .container .body .content div.settings .input.checkbox select,body .container .body .content div.settings .input.mixed.multiple select{width:auto;margin-right:5px}body .container .body .content div.settings .input.checkbox label,body .container .body .content div.settings .input.mixed.multiple label{line-height:normal;padding:0 15px;width:auto}body .container .body .content .logpage ul.tabs{padding:15px 0}body .container .body .content .logpage ul.entries li{padding-top:30px}body .container .body .content .prewrapped-text{white-space:pre-wrap;overflow-x:auto}body .container .footer{background:#ededed;min-height:70px;line-height:70px;overflow:hidden;position:absolute;bottom:0;width:100%}body .container .footer a{color:#65b1dd}body .container .footer .about-footer{float:left;overflow:hidden;padding-right:20px;display:none}body .container .footer .about-footer span{display:block;float:left;padding-left:20px}body .container .footer .about-footer ul{float:left}body .container .footer .about-footer li{float:left;padding-left:20px}body .container .footer .donate{display:none;float:right;padding-right:40px;overflow:hidden}body .container .footer .donate ul{overflow:hidden;float:right}body .container .footer .donate ul li{float:left;margin-left:10px}body .container .footer .donate ul li a img{margin-top:24px;display:inline-block;opacity:.6}body .container .footer .donate ul li a img:hover{opacity:1}body .container .footer .donate>a{float:left}body .container .footer .social{float:right}body .container .footer .social ul{overflow:hidden;float:right;padding-left:20px;padding-right:10px}body .container .footer .social ul li{float:right;margin-right:10px;padding-top:5px}body .container .footer .social ul li img{opacity:.6}body .container .footer .social ul li img:hover{opacity:1}body .container .footer .themelink{float:right;padding-right:20px}body #modal-menu{max-width:400px}body #modal-menu a{color:#65b1dd;font-size:20px;line-height:40px}.remodal{padding:30px;box-shadow:0 2px 7px rgba(0,0,0,.3);background:#fff;display:none}.remodal form .buttons{float:none}.remodal-wrapper .remodal{display:block}span.info{font-size:10px;font-weight:500;display:inline-block;background:#65b1dd;border-radius:50%;width:15px;height:15px;vertical-align:super;color:#fff;line-height:15px;margin-left:5px;text-align:center}.hidden{display:none}.clear{clear:both}.nofloat{float:none!important}div.blocker,div.connection-lost,div.modal-dialog{position:fixed;top:0;left:0;right:0;bottom:0;margin:auto}div.blocker{z-index:5000;background-color:#000;opacity:.65}#connection-lost-blocker{z-index:5100}#connection-lost-dialog{z-index:5200}div.connection-lost,div.modal-dialog{z-index:5001;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-box-pack:center;-moz-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-box-align:center;-moz-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center}div.connection-lost div.info,div.modal-dialog div.info{min-width:310px;max-width:650px;margin:5px}div.connection-lost div.title,div.modal-dialog div.title{border:1px solid #65b1dd;background-color:#65b1dd;border-radius:5px 5px 0 0;padding:10px 20px;font-weight:700;color:#d3d3d3;text-align:center}div.connection-lost div.content,div.modal-dialog div.content{background-color:#fff;border:1px solid #fff;padding:20px}div.connection-lost .buttons,div.modal-dialog .buttons{border-radius:0 0 5px 5px;padding-top:10px;overflow:auto}div.connection-lost form,div.modal-dialog form{margin-top:15px}div.connection-lost form textarea,div.modal-dialog form textarea{height:130px;width:420px;padding:10px 12px;border:1px #d8d8d8 solid;border-radius:2px;color:#8f8f8f;font-size:16px;font-weight:300}div.connection-lost form input,div.modal-dialog form input{height:35px;line-height:35px;padding:0 12px}div.modal-dialog .content.buttons ul{float:right}div.modal-dialog .content.buttons .tooltipped{position:relative}div.modal-dialog .content.buttons .tooltipped:after{position:absolute;z-index:1000000;display:none;padding:5px 8px;font:normal normal 11px/1.5 Helvetica,arial,nimbussansl,liberationsans,freesans,clean,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";color:#fff;text-align:center;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-wrap:break-word;white-space:pre;pointer-events:none;content:attr(aria-label);background:rgba(0,0,0,.8);border-radius:3px;-webkit-font-smoothing:subpixel-antialiased}div.modal-dialog .content.buttons .tooltipped:before{position:absolute;z-index:1000001;display:none;width:0;height:0;color:rgba(0,0,0,.8);pointer-events:none;content:"";border:5px solid transparent}div.modal-dialog .content.buttons .tooltipped:active:after,div.modal-dialog .content.buttons .tooltipped:active:before,div.modal-dialog .content.buttons .tooltipped:focus:after,div.modal-dialog .content.buttons .tooltipped:focus:before,div.modal-dialog .content.buttons .tooltipped:hover:after,div.modal-dialog .content.buttons .tooltipped:hover:before{display:inline-block;text-decoration:none}div.modal-dialog .content.buttons .tooltipped-w:after{right:100%;bottom:50%;margin-right:5px;-webkit-transform:translateY(50%);-ms-transform:translateY(50%);transform:translateY(50%)}div.modal-dialog .content.buttons .tooltipped-w:before{top:50%;bottom:50%;left:-5px;margin-top:-5px;border-left-color:rgba(0,0,0,.8)}.importpage form.styled input{margin-top:11px;margin-bottom:11px}.addwizard form.styled ul,.restorewizard form.styled ul{margin:20px;margin-left:0}.addwizard form.styled input[type=radio],.restorewizard form.styled input[type=radio]{width:20px;margin-left:5px;margin-right:5px}.addwizard form.styled label,.restorewizard form.styled label{width:auto;line-height:normal}.addwizard form.styled div.subtext,.restorewizard form.styled div.subtext{clear:both;margin-left:30px;padding-top:5px;color:#d3d3d3}.pauseoptions form.styled li{line-height:normal;padding:0}.pauseoptions form.styled li input{height:auto;margin-top:8px;margin-right:8px;width:auto}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress{position:relative;min-height:25px}.progress>span{vertical-align:middle;display:block;width:100%;height:100%;text-align:center;z-index:100;padding-top:2px}.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress .progress-bar{float:left;width:0;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease;height:100%;position:absolute}.progress .progress-bar.active{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.tree-view{list-style-type:none;margin-left:10px;padding-bottom:5px}.tree-view ul{margin-left:16px}.tree-view span.nodeLabel{cursor:pointer}.tree-view span.nodeLabel.selected{border:1px solid #aaa;background-color:#ddd;padding:1px 3px}.tree-view li .node{padding-bottom:5px}.tree-view li div.selected{border-color:#add8e6;background-color:#add8e6}.tree-view li>ul{display:none}.tree-view li>ul.expanded{display:block}.tree-view li a.nav{cursor:pointer;display:inline-block;width:16px;height:16px;vertical-align:middle;background-image:url(../img/treeicons.png);background-repeat:no-repeat;background-position:-80px 0}.tree-view li a.nav.leaf{background:0 0}.tree-view li a.nav.expanded{background-position:-80px -16px}.tree-view li a.type{cursor:auto;display:inline-block;width:16px;height:16px;vertical-align:middle;background-image:url(../img/treeicons.png);background-repeat:no-repeat;background-position:0 -16px}.tree-view li a.type.invisible{background-position:0 -32px}.tree-view li a.type.loading{cursor:progress;background-image:url(../img/loader-16.gif);background-repeat:no-repeat;background-position:0 0}.tree-view li a.type.x-tree-icon-drive{background-position:-16px -16px}.tree-view li a.type.x-tree-icon-leaf{background-position:-32px -16px}.tree-view li a.type.x-tree-icon-symlink{background-position:-48px -16px}.tree-view li a.type.x-tree-icon-userdata{background-position:-16px -48px}.tree-view li a.type.x-tree-icon-locked{background-position:-64px -16px}.tree-view li a.type.x-tree-icon-broken{background-position:-64px -16px}.tree-view li a.type.x-tree-icon-computer{background-position:0 -48px}.tree-view li a.type.x-tree-icon-hyperv{background-position:-96px -16px}.tree-view li a.type.x-tree-icon-hypervmachine{background-position:-96px 0}.tree-view li a.type.x-tree-icon-mssql{background-position:-96px -32px}.tree-view li a.type.x-tree-icon-mssqldb{background-position:-80px -32px}.tree-view li a.type.x-tree-icon-mydocuments{background-position:-32px -48px}.tree-view li a.type.x-tree-icon-mymusic{background-position:-48px -48px}.tree-view li a.type.x-tree-icon-mypictures{background-position:-64px -48px}.tree-view li a.type.x-tree-icon-desktop{background-position:-80px -48px}.tree-view li a.type.x-tree-icon-home{background-position:-96px -48px}.tree-view li a.type.x-tree-icon-drive.invisible{background-position:-16px -32px}.tree-view li a.type.x-tree-icon-leaf.invisible{background-position:-32px -32px}.tree-view li a.type.x-tree-icon-symlink.invisible{cursor:auto;background-position:-48px -32px}.tree-view li a.type.x-tree-icon-locked.invisible{background-position:-64px -32px}.tree-view li a.check{height:16px;width:16px;display:inline-block;cursor:pointer;background-image:url(../img/treeicons.png);background-repeat:no-repeat;background-position:0 0;vertical-align:middle}.tree-view li a.partial{background-position:-32px 0}.tree-view li a.include{background-position:-16px 0}.tree-view li a.exclude{background-position:-48px 0}.tree-view li a.root{background:0 0;display:none}.throttlesettings div.multiple select{width:auto;margin-right:5px}.throttlesettings div.multiple input{width:100px}.throttlesettings div.multiple input.checkbox{width:auto}.throttlesettings div.multiple label{line-height:35px;padding:0 15px;width:auto;min-width:150px}.throttlesettings .disabled{color:#cfcfcf}.throttlesettings .disabled input,.throttlesettings .disabled select{color:#cfcfcf}@media (max-width:1150px){body .container .header{height:140px}body .container .header .statepadding{padding-right:90px;margin-left:0}body .container .header .state{width:100%;margin:10px 40px;clear:left;float:left}body .container .header .action-icons{display:none}body .container .header .action-icons-small{display:inline-block}body .container .header .menubutton{display:block;font-size:18px;padding-right:50px;margin-top:5px;margin-right:15px;background:url(../img/menu.png) no-repeat right top;position:relative;height:40px;line-height:40px;color:#8f8f8f;float:right;top:10px;padding-left:20px;text-transform:uppercase;text-align:right}body .container .header .menubutton.active{background-image:url(../img/menu_active.png);color:#65b1dd}body .container .header .donate{display:none}body .container .body{position:relative;padding-top:140px}body .container .body .mainmenu{display:none;position:fixed;background:none repeat scroll 0 0 #fff;box-shadow:0 4px 8px rgba(0,0,0,.3);left:10px;padding:20px;top:60px}body .container .body .mainmenu.mobile-open{display:block;left:auto;right:0;top:0;z-index:1000}body .container .body .contextmenu{left:0;top:auto}body .container .body .content{float:none;padding:20px 20px;margin:0 auto 30px auto}body .container .body .content .state{width:auto}body .container .mobileOpen{display:block!important}}@media (max-width:768px){body .container .body .content .tasks .tasklist a{font-size:20px;background-size:24px;background-position:0 4px;padding-left:35px}body .container .body .content .tasks .tasklist dl{padding-left:35px}body .container .header .logo{padding-left:10px}body .container .header .statepadding{padding-right:50px}body .container .header .state{margin-left:10px}body .container .header .menubutton{margin-right:5px}body .container .body .content div.add .steps,body .container .body .content div.restore .steps,body .container .body .content div.settings .steps{display:none}body .container .body .content div.add .steps-legend,body .container .body .content div.restore .steps-legend,body .container .body .content div.settings .steps-legend{list-style:decimal;padding-left:20px;border-bottom:1px solid #eee;margin-bottom:30px;padding-bottom:20px}body .container .body .content div.add .steps-legend li,body .container .body .content div.restore .steps-legend li,body .container .body .content div.settings .steps-legend li{float:none;font-weight:500;width:auto!important;padding-right:0!important}body .container .body .content div.add .steps-boxes,body .container .body .content div.restore .steps-boxes,body .container .body .content div.settings .steps-boxes{padding-left:0}body .container .body .content div.add form.styled .input input,body .container .body .content div.add form.styled .input select,body .container .body .content div.add form.styled .input textarea,body .container .body .content div.restore form.styled .input input,body .container .body .content div.restore form.styled .input select,body .container .body .content div.restore form.styled .input textarea,body .container .body .content div.settings form.styled .input input,body .container .body .content div.settings form.styled .input select,body .container .body .content div.settings form.styled .input textarea{max-width:100%;box-sizing:border-box}body .container .body .content div.add form.styled .input.select select,body .container .body .content div.restore form.styled .input.select select,body .container .body .content div.settings form.styled .input.select select{width:420px}body .container .body .content div.add form.styled .buttons,body .container .body .content div.restore form.styled .buttons,body .container .body .content div.settings form.styled .buttons{max-width:100%;width:auto}body .container .body .content div.add form.styled .tools,body .container .body .content div.restore form.styled .tools,body .container .body .content div.settings form.styled .tools{padding-left:0!important}body .container .body .content div.add form.styled .input.checkbox.multiple,body .container .body .content div.restore form.styled .input.checkbox.multiple,body .container .body .content div.settings form.styled .input.checkbox.multiple{padding-bottom:5px}body .container .body .content div.add form.styled .input.checkbox.multiple input,body .container .body .content div.add form.styled .input.checkbox.multiple label,body .container .body .content div.restore form.styled .input.checkbox.multiple input,body .container .body .content div.restore form.styled .input.checkbox.multiple label,body .container .body .content div.settings form.styled .input.checkbox.multiple input,body .container .body .content div.settings form.styled .input.checkbox.multiple label{display:block!important;float:left!important;line-height:normal}body .container .body .content div.add form.styled .input.checkbox.multiple input,body .container .body .content div.restore form.styled .input.checkbox.multiple input,body .container .body .content div.settings form.styled .input.checkbox.multiple input{clear:both}body .container .body .content div.add form.styled .input.text.multiple input,body .container .body .content div.restore form.styled .input.text.multiple input,body .container .body .content div.settings form.styled .input.text.multiple input{max-width:48%!important}}@media (max-width:640px){body h2{font-size:20px;text-align:center}body .container .body{padding-bottom:10px}body .container .body .content{margin:0 auto}body .container .body .content div.add form .input.overlayButton,body .container .body .content div.restore form .input.overlayButton{padding-top:8px;padding-bottom:30px;margin-bottom:10px}body .container .body .content div.add form .input.overlayButton a.button,body .container .body .content div.restore form .input.overlayButton a.button{padding:7px 10px;right:1px;top:9px}body .container .body .content div.add form .input.checkbox.multiple div,body .container .body .content div.restore form .input.checkbox.multiple div{display:block}body .container .body .content div.add form .input.select.multiple input#exclude-larger-than-number,body .container .body .content div.restore form .input.select.multiple input#exclude-larger-than-number{width:75px}body .container .body .content div.add form .input.select.multiple select#exclude-larger-than-multiplier,body .container .body .content div.restore form .input.select.multiple select#exclude-larger-than-multiplier{width:140px}body .container .body .content div.add form .filters .input.textarea,body .container .body .content div.restore form .filters .input.textarea{padding-bottom:10px}body .container .body .content div.add form .filters h3,body .container .body .content div.restore form .filters h3{margin:5px 0}body .container .body .content div.add form .input.text.select.multiple.repeat label,body .container .body .content div.restore form .input.text.select.multiple.repeat label{float:none}body .container .body .content div.add form .input.text.select.multiple.repeat input#repeatRunNumber,body .container .body .content div.restore form .input.text.select.multiple.repeat input#repeatRunNumber{width:70px}body .container .body .content div.add form .input.text.select.multiple.repeat select#repeatRunMultiplier,body .container .body .content div.restore form .input.text.select.multiple.repeat select#repeatRunMultiplier{width:100px}body .container .body .content div.add form .input.multiple.text.select.maxSize input,body .container .body .content div.restore form .input.multiple.text.select.maxSize input{width:70px}body .container .body .content div.add form .input.multiple.text.select.maxSize select,body .container .body .content div.restore form .input.multiple.text.select.maxSize select{width:100px}body .container .body .content div.add form .input.multiple.text.select.keepBackups select,body .container .body .content div.restore form .input.multiple.text.select.keepBackups select{width:85px;padding:4px 6px}body .container .body .content div.add form .input.multiple.text.select.keepBackups input,body .container .body .content div.restore form .input.multiple.text.select.keepBackups input{width:60px}body .container .footer{position:static;padding:15px;line-height:normal;text-align:left;box-sizing:border-box}body .container .footer *{float:none!important;text-align:center;box-sizing:border-box}body .container .footer .about-footer{padding-right:0;display:block}body .container .footer .about-footer span{padding-left:0;padding-bottom:5px}body .container .footer .about-footer li{padding-left:0;float:none;display:inline-block;height:32px;width:32px;background-size:28px!important;border-bottom:none}body .container .footer .about-footer li.support{background:url(../img/support.png) no-repeat center center}body .container .footer .about-footer li.about{background:url(../img/about.png) no-repeat center center}body .container .footer .about-footer li:first-child{padding-bottom:0}body .container .footer .about-footer li:last-child{padding-bottom:20px}body .container .footer .about-footer,body .container .footer .donate,body .container .footer .social,body .container .footer li{padding:8px 0;border-bottom:1px #ddd solid}body .container .footer .donate{display:block}body .container .footer .donate ul li{display:inline-block;border:none;margin:0 5px}body .container .footer .donate ul li a img{margin-top:0}body .container .footer .social li{display:inline-block;border:none}body .container .footer .themelink{padding:5px 0}}@media (max-width:580px){.advancedentry .longdescription{margin-left:0}}@media (max-width:492px){ul.notification{width:auto}}@media (max-width:480px){body{font-size:15px}body .container .header .logo{padding-left:5px}body .container .header .menubutton{margin-right:5px}body .container .header .state{margin-left:5px}body .container .header .statepadding{padding-right:40px}body .container .header .menubutton{padding-left:10px}body .container .body .mainmenu{width:280px;box-sizing:border-box}body .container .body .mainmenu ul li a{font-size:22px}body .container .body .content{padding:15px}body .container .body .content div.add form .input.password .tools ul li,body .container .body .content div.restore form .input.password .tools ul li{font-size:14px}body .container .body .content div.add form .buttons a,body .container .body .content div.restore form .buttons a{float:none;text-align:center;margin-bottom:5px}body .container .body .content div.add .steps-boxes .box.browser .checklinks a,body .container .body .content div.restore .steps-boxes .box.browser .checklinks a{float:none;margin-bottom:8px;display:block}}@media (max-width:400px){body{font-size:15px}body .container .header .menubutton{margin-right:0;padding-left:0;padding-right:40px}body .container .header .menubutton span{display:none}}@media (max-width:325px){body{font-size:15px}body .container .header .logo div{display:none}}@media (max-width:200px){body{font-size:15px}body .container .header .menubutton{position:static;margin-top:0}body .container .header .action-icons-small{clear:right;margin-top:0}} \ No newline at end of file + */@font-face{font-family:FontAwesome;src:url(../fonts/fontawesome-webfont.eot?v=4.5.0);src:url(../fonts/fontawesome-webfont.eot?#iefix&v=4.5.0) format('embedded-opentype'),url(../fonts/fontawesome-webfont.woff2?v=4.5.0) format('woff2'),url(../fonts/fontawesome-webfont.woff?v=4.5.0) format('woff'),url(../fonts/fontawesome-webfont.ttf?v=4.5.0) format('truetype'),url(../fonts/fontawesome-webfont.svg?v=4.5.0#fontawesomeregular) format('svg');font-weight:400;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1,1);-ms-transform:scale(-1,1);transform:scale(-1,1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1,-1);-ms-transform:scale(1,-1);transform:scale(1,-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-rotate-90{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-close:before,.fa-remove:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-cog:before,.fa-gear:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-repeat:before,.fa-rotate-right:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-exclamation-triangle:before,.fa-warning:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-cogs:before,.fa-gears:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-floppy-o:before,.fa-save:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-sort:before,.fa-unsorted:before{content:"\f0dc"}.fa-sort-desc:before,.fa-sort-down:before{content:"\f0dd"}.fa-sort-asc:before,.fa-sort-up:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-gavel:before,.fa-legal:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-bolt:before,.fa-flash:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-clipboard:before,.fa-paste:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-chain-broken:before,.fa-unlink:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:"\f150"}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:"\f151"}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:"\f152"}.fa-eur:before,.fa-euro:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-inr:before,.fa-rupee:before{content:"\f156"}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:"\f157"}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:"\f158"}.fa-krw:before,.fa-won:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-try:before,.fa-turkish-lira:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-bank:before,.fa-institution:before,.fa-university:before{content:"\f19c"}.fa-graduation-cap:before,.fa-mortar-board:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:"\f1c5"}.fa-file-archive-o:before,.fa-file-zip-o:before{content:"\f1c6"}.fa-file-audio-o:before,.fa-file-sound-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before{content:"\f1d0"}.fa-empire:before,.fa-ge:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-hacker-news:before,.fa-y-combinator-square:before,.fa-yc-square:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-paper-plane:before,.fa-send:before{content:"\f1d8"}.fa-paper-plane-o:before,.fa-send-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-futbol-o:before,.fa-soccer-ball-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-ils:before,.fa-shekel:before,.fa-sheqel:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-bed:before,.fa-hotel:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-y-combinator:before,.fa-yc:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-paper-o:before,.fa-hand-stop-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-television:before,.fa-tv:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}*{font-family:'Clear Sans',sans-serif}body,html{margin:0;padding:0;height:100%}h1,h2{font-weight:300;color:#81c401}h1{margin:10px 0}h3{font-weight:400}a{text-decoration:none}ul{list-style:none;margin:0;padding:0}hr{border:none;border-bottom:1px #ddd solid}textarea{max-width:94%}.external-link-image{display:inline-block;margin-left:8px;margin-right:8px;height:16px;width:16px;background:url(../img/external-link-hover.png);background-size:16px}a .external-link-image{background:url(../img/external-link.png);background-size:16px}.header a:hover .external-link-image{background:url(../img/external-link-hover.png);background-size:16px}.button{display:block;background:#65b1dd;color:#fff!important;padding:5px 15px;float:right;margin-left:10px;cursor:pointer;width:auto;border:none;font-family:'Clear Sans',sans-serif;font-size:16px;font-weight:300;border-radius:0}.button:hover{background:#3b9cd4}#folder_path_picker,#restore_file_picker,.step3 source-folder-picker{display:block;border:1px solid #d3d3d3;padding:2px;height:100%;overflow:auto}.not-clickable{cursor:default!important}.not-clickable div,.not-clickable span,.not-clickable>a{cursor:default!important}.ui-match{font-weight:700;color:#006400}wait-area{min-width:350px;text-align:center;display:block}.prewrapped-text{white-space:pre-wrap}.exceptiontext{background-color:#d3d3d3;color:#000}ul.tabs{margin-bottom:10px}ul.tabs>li{display:inline;margin-right:10px;border:1px solid #65b1dd;padding:5px}ul.tabs>li.active{background-color:#65b1dd;color:#fff}ul.tabs>li.active>a{background-color:#65b1dd;color:#fff}ul.tabs>li.active.disabled{border:1px solid #d3d3d3;background-color:#d3d3d3;color:grey;cursor:default}ul.tabs>li.active.disabled>a{background-color:#d3d3d3;color:grey;cursor:default}.licenses>ul{list-style:initial;margin:10px;margin-left:20px}.licenses li{margin-bottom:10px}.licenses a.itemlink{font-weight:700}.logpage ul.entries{list-style:initial;margin:10px;margin-left:20px}.logpage .entries div.entryline.clickable{cursor:pointer}.logpage .entries.livedata li.expanded{height:auto}.logpage .button{text-align:center;margin-right:10px;border:1px solid #65b1dd;padding:5px;background-color:#65b1dd;color:#fff;cursor:pointer}.exportpage .checkbox input{width:auto;margin-top:10px}.exportpage .commandline div{background-color:#d3d3d3;color:#000}.themelink{margin-left:20px}ul.notification{position:fixed;bottom:0;left:0;right:0;margin:auto;width:480px}.notification .title{border:1px solid #65b1dd;background-color:#65b1dd;border-top-left-radius:5px;border-top-right-radius:5px;border-bottom-left-radius:0;border-bottom-right-radius:0;padding:2px;padding-left:5px;padding-right:5px;font-weight:700;color:#d3d3d3;width:100%;text-align:center;clear:both}.notification .content{background-color:#fff;border:1px solid #65b1dd;border-top-left-radius:0;border-top-right-radius:0;border-bottom-left-radius:5px;border-bottom-right-radius:5px;padding:2px;padding-left:5px;padding-right:5px;width:100%}.notification .message{width:100%;color:#000}.notification .button{padding:2px 10px;margin-top:6px}.notification .clear{clear:right;height:1px}.notification .error .title{border-color:red;background-color:red}.notification .error .content{border-color:red}.notification .error .button{border-color:red;background-color:red}.notification .warning .title{background-color:orange;border-color:orange}.notification .warning .button{background-color:orange;border-color:orange}.notification .warning .content{border-color:orange}.filepicker{height:200px}.resizable{margin-bottom:6px;max-width:100%}.advanced-toggle{float:right;margin-right:25px;line-height:37px}.advancedoptions li{clear:both;margin-bottom:10px;padding:10px 0;border-top:1px #d3d3d3 solid}.advancedentry .multiple{display:inline}.advancedentry .shortname{font-weight:700}.advancedentry input[type=text]{width:300px}.advancedentry select{width:300px}.advancedentry input[type=checkbox]{margin-top:13px;width:auto}.advancedentry .longdescription{margin-left:190px;clear:both;font-style:italic}.settings div.sublabel{clear:both;padding:0 31px;font-style:italic}.logo img.mainlogo{height:64px;width:64px;float:left;padding-right:8px;padding-top:2px}.logo div.logotext{float:left}.logo a{float:left;display:block;line-height:normal}.logo div.build-suffix{clear:both;display:inline;float:left;font-size:16px;line-height:16px}.logo div.powered-by{font-size:16px;margin:0;line-height:16px;float:left;padding:0;margin-left:5px}.fixed-width-font{font-family:monospace}.warning{margin:10px;font-style:italic;color:#f49b42}div.captcha .details{padding-top:10px;margin-left:auto;margin-right:auto;width:180px}.centered-text{text-align:center}body{color:#8f8f8f}body .container{min-height:100%;position:relative}body .container .header{line-height:70px;background:#ededed;overflow:hidden;height:70px;position:fixed;top:0;left:0;right:0;z-index:100}body .container .header a{color:#65b1dd}body .container .header a.active,body .container .header a:hover{color:#4f4f4f}body .container .header .logo{font-size:30px;font-weight:700;float:left;padding-left:40px}body .container .header .statepadding{padding-right:90px;margin-left:320px}body .container .header .state{float:left;color:#609101;width:580px;padding:13px 15px;margin:10px 20px;border:1px #609101 solid;font-weight:300;font-size:18px;overflow:hidden;line-height:normal;display:inline-block;background-color:#fff;text-overflow:ellipsis;position:relative;height:25px}body .container .header .state strong{display:inline;margin-right:10px}body .container .header .state span{display:inline}body .container .header .state .button{position:static;margin-top:70px}body .container .header .state .content{position:relative;z-index:10;margin-right:40px;display:block;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}body .container .header .state .buttons{position:absolute;right:0;top:0;bottom:0;width:26px;margin:13px 15px}body .container .header .state .buttons .stop{display:block;width:26px;height:26px;background:url(../img/progress-stop.png);background-size:26px;cursor:pointer}body .container .header .state .buttons .resume{display:block;width:26px;height:26px;background:url(../img/progress-resume.png);background-size:26px;cursor:pointer}body .container .header .state .progress-bar{position:absolute;top:0;bottom:0;left:0;background:rgba(129,196,1,.25);z-index:5}body .container .header .action-icons{display:inline-block;line-height:normal;margin:10px 0;padding:13px 0;float:left}body .container .header .action-icons-small{display:none;float:right;margin-top:21px;line-height:normal}body .container .header .action-icons-small>.pause,body .container .header .action-icons>.pause{width:26px;height:26px;display:inline-block;cursor:pointer;background:url(../img/pause.png)}body .container .header .action-icons-small>.pause.active,body .container .header .action-icons>.pause.active{background:url(../img/resume.png)}body .container .header .action-icons-small>.throttle,body .container .header .action-icons>.throttle{width:26px;height:26px;display:inline-block;cursor:pointer;background:url(../img/throttle.png)}body .container .header .action-icons-small>.throttle.inactive,body .container .header .action-icons>.throttle.inactive{opacity:.5}body .container .header .about-header{float:right;padding-right:20px;overflow:hidden}body .container .header .about-header ul{overflow:hidden;list-style:none}body .container .header .about-header ul li{float:right;padding-right:20px}body .container .header .donate{float:right}body .container .header .donate ul{overflow:hidden;float:right;padding-left:20px;padding-right:10px}body .container .header .donate ul li{float:right;margin-right:10px;padding-top:5px}body .container .header .donate img{opacity:.6}body .container .header .donate img:hover{opacity:1}body .container .body{width:100%;overflow:hidden;min-height:500px;padding-top:120px;padding-bottom:70px}body .container .body a{color:#65b1dd}body .container .body .mainmenu{width:260px;padding-left:40px;float:left;position:fixed}body .container .body .mainmenu>ul>li{position:relative}body .container .body .mainmenu>ul>li>a{font-size:22px;font-weight:300;padding:5px 10px 5px 55px;display:block}body .container .body .mainmenu>ul>li>a:hover{color:#fff}body .container .body .mainmenu>ul>li>a.active{color:#fff}body .container .body .mainmenu>ul>li>a.add{background:url(../img/mainmenu/add.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.restore{background:url(../img/mainmenu/restore.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.pause{background:url(../img/mainmenu/pause.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.resume{background:url(../img/mainmenu/resume.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.settings{background:url(../img/mainmenu/settings.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.log{background:url(../img/mainmenu/log.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.logout{background:url(../img/mainmenu/logout.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.home{background:url(../img/mainmenu/home.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.about{background:url(../img/mainmenu/about.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.pause>span{padding-right:25px;background:url(../img/mainmenu/arrow_right.png) right center no-repeat}body .container .body .mainmenu>ul>li>a.home.active{background:#a4d1eb url(../img/mainmenu/over/home.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.add.active{background:#a4d1eb url(../img/mainmenu/over/add.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.restore.active{background:#a4d1eb url(../img/mainmenu/over/restore.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.pause.active{background:#a4d1eb url(../img/mainmenu/over/pause.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.resume.active{background:#a4d1eb url(../img/mainmenu/over/resume.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.settings.active{background:#a4d1eb url(../img/mainmenu/over/settings.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.log.active{background:#a4d1eb url(../img/mainmenu/over/log.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.about.active{background:#a4d1eb url(../img/mainmenu/over/about.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.pause.open.active>span{background:url(../img/mainmenu/over/arrow_down.png) right center no-repeat}body .container .body .mainmenu>ul>li>a.add:hover{background:#65b1dd url(../img/mainmenu/over/add.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.restore:hover{background:#65b1dd url(../img/mainmenu/over/restore.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.pause:hover{background:#65b1dd url(../img/mainmenu/over/pause.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.pause:hover>span{background:url(../img/mainmenu/over/arrow_right.png) right center no-repeat}body .container .body .mainmenu>ul>li>a.pause.open:hover>span{background:url(../img/mainmenu/over/arrow_down.png) right center no-repeat}body .container .body .mainmenu>ul>li>a.pause.open>span{background:url(../img/mainmenu/arrow_down.png) right center no-repeat}body .container .body .mainmenu>ul>li>a.resume:hover{background:#65b1dd url(../img/mainmenu/over/resume.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.settings:hover{background:#65b1dd url(../img/mainmenu/over/settings.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.log:hover{background:#65b1dd url(../img/mainmenu/over/log.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.logout:hover{background:#65b1dd url(../img/mainmenu/over/logout.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.home:hover{background:#65b1dd url(../img/mainmenu/over/home.png) no-repeat 8px 7px}body .container .body .mainmenu>ul>li>a.about:hover{background:#65b1dd url(../img/mainmenu/over/about.png) no-repeat 8px 7px}body .container .body .mainmenu>ul li.hr-top{padding-top:25px;margin-top:25px;border-top:1px #ededed solid}body .container .body div.contextmenu_container{position:relative}body .container .body .contextmenu{display:none;position:absolute;background:#fff;border:1px #ededed solid;box-shadow:0 4px 8px rgba(0,0,0,.3);z-index:200;padding:5px}body .container .body .contextmenu li a{color:#65b1dd;font-size:15px;font-weight:400;padding:0;display:block;min-width:200px;padding:4px 10px;white-space:nowrap;padding-left:45px;overflow:hidden;text-overflow:ellipsis}body .container .body .contextmenu li a:hover{background:#65b1dd;color:#fff}body .container .body .contextmenu.open{display:block}body .container .body .content{float:left;padding-left:350px;padding-bottom:50px;max-width:700px}body .container .body .content ul.tabs>li{display:inline-block}body .container .body .content .tasks .tasklist .task{border-top:1px solid #eee;padding-top:20px;margin-bottom:25px}body .container .body .content .tasks .tasklist .task:last-child{border-bottom:1px solid #eee;padding-bottom:20px}body .container .body .content .tasks .tasklist .task:first-child{padding-top:0;border-top:0 none}body .container .body .content .tasks .tasklist a{font-size:30px;padding-left:55px;background:url(../img/backup.png) no-repeat 5px 6px;font-weight:300;display:inline-block}body .container .body .content .tasks .tasklist a.action-link{font-size:14px;background:0 0;padding-left:0}body .container .body .content .tasks .tasklist dl{padding-left:55px;overflow:hidden;font-size:14px}body .container .body .content .tasks .tasklist dl dd,body .container .body .content .tasks .tasklist dl dt{display:block;float:left}body .container .body .content .tasks .tasklist dl dt{clear:both;font-weight:500;margin-bottom:5px}body .container .body .content .tasks .tasklist dl dd{margin-left:10px}body .container .body .content .tasks .tasklist dl.taskmenu p{display:inline;margin-right:10px;color:#65b1dd;cursor:pointer}body .container .body .content .tasks .tasklist dl.taskmenu dt{float:left;margin-right:10px;margin-bottom:0;padding:5px 8px;color:#8f8f8f;cursor:pointer;clear:none}body .container .body .content .tasks .tasklist dl.taskmenu dd{clear:both;float:none;padding-bottom:8px;border-bottom:1px #ddd solid;margin-bottom:5px}body .container .body .content div.add .steps,body .container .body .content div.restore .steps{width:100%;overflow:hidden}body .container .body .content div.add .steps .step,body .container .body .content div.restore .steps .step{float:left;background:url(../img/steps/line-out.png) no-repeat top left;color:#c7e5f6}body .container .body .content div.add .steps .step span,body .container .body .content div.restore .steps .step span{display:block;border:4px #c7e5f6 solid;background:#fff;border-radius:50%;width:35px;height:35px;text-align:center;font-size:22px;line-height:35px;cursor:pointer}body .container .body .content div.add .steps .step.active,body .container .body .content div.restore .steps .step.active{color:#65b1dd}body .container .body .content div.add .steps .step.active span,body .container .body .content div.restore .steps .step.active span{border:4px #65b1dd solid;background:#65b1dd;color:#fff}body .container .body .content div.add .steps .step.active h2,body .container .body .content div.restore .steps .step.active h2{color:#65b1dd}body .container .body .content div.add .steps .step:first-child,body .container .body .content div.restore .steps .step:first-child{padding-left:0;background:0 0}body .container .body .content div.add .steps-legend,body .container .body .content div.restore .steps-legend{overflow:hidden;padding-bottom:50px;list-style:none;margin:0}body .container .body .content div.add .steps-legend li,body .container .body .content div.restore .steps-legend li{color:#c7e5f6;font-size:18px;text-align:center;float:left;padding-top:10px;cursor:pointer}body .container .body .content div.add .steps-legend li.active,body .container .body .content div.restore .steps-legend li.active{color:#65b1dd}body .container .body .content div.add .steps-boxes,body .container .body .content div.restore .steps-boxes{padding-left:40px}body .container .body .content div.add .steps-boxes .step,body .container .body .content div.restore .steps-boxes .step{display:none}body .container .body .content div.add .steps-boxes .step.active,body .container .body .content div.restore .steps-boxes .step.active{display:block}body .container .body .content div.add .steps-boxes .box.browser .checklinks a,body .container .body .content div.restore .steps-boxes .box.browser .checklinks a{float:left;margin-left:20px;color:#8f8f8f}body .container .body .content div.add .steps-boxes .box.browser .checklinks a i,body .container .body .content div.restore .steps-boxes .box.browser .checklinks a i{border:2px solid;border-color:#8f8f8f;border-radius:2px;font-size:18px;height:18px;vertical-align:top;width:18px}body .container .body .content div.add .steps-boxes .box.browser .checklinks a.inactive,body .container .body .content div.restore .steps-boxes .box.browser .checklinks a.inactive{color:#c2c2c2;cursor:default}body .container .body .content div.add .steps-boxes .box.browser .checklinks a.inactive i,body .container .body .content div.restore .steps-boxes .box.browser .checklinks a.inactive i{border-color:#c2c2c2}body .container .body .content div.add .steps-boxes .box.browser .checklinks a:first-child,body .container .body .content div.restore .steps-boxes .box.browser .checklinks a:first-child{margin-left:0}body .container .body .content div.add .steps-boxes .box.browser .input.overlayButton,body .container .body .content div.restore .steps-boxes .box.browser .input.overlayButton{padding-top:10px;max-width:100%}body .container .body .content div.add .steps-boxes .box.browser .input.overlayButton input#sourcePath,body .container .body .content div.restore .steps-boxes .box.browser .input.overlayButton input#sourcePath{width:100%;box-sizing:border-box;height:37px}body .container .body .content div.add .steps-boxes .box.browser .input.overlayButton a.button,body .container .body .content div.restore .steps-boxes .box.browser .input.overlayButton a.button{top:10px}body .container .body .content div.add .steps-boxes .box.filters .input.link a,body .container .body .content div.restore .steps-boxes .box.filters .input.link a{color:#8f8f8f}body .container .body .content div.add .steps-boxes .box.filters .input.link a i,body .container .body .content div.restore .steps-boxes .box.filters .input.link a i{border:2px solid;border-color:#8f8f8f;border-radius:2px;font-size:18px;height:18px;vertical-align:top;width:18px}body .container .body .content div.add .steps-boxes .box.filters ul#simplefilterlist,body .container .body .content div.restore .steps-boxes .box.filters ul#simplefilterlist{overflow:hidden;padding-bottom:15px}body .container .body .content div.add .steps-boxes .box.filters ul#simplefilterlist li,body .container .body .content div.restore .steps-boxes .box.filters ul#simplefilterlist li{overflow:hidden;clear:both;padding-bottom:5px}body .container .body .content div.add .steps-boxes .box.filters ul#simplefilterlist li select,body .container .body .content div.restore .steps-boxes .box.filters ul#simplefilterlist li select{width:200px;margin-right:5px;height:36px;line-height:36px}body .container .body .content div.add .steps-boxes .box.filters ul#simplefilterlist li input,body .container .body .content div.restore .steps-boxes .box.filters ul#simplefilterlist li input{width:280px;padding:5px}body .container .body .content div.add .steps-boxes .step1 li.strength.score-0,body .container .body .content div.restore .steps-boxes .step1 li.strength.score-0{color:red}body .container .body .content div.add .steps-boxes .step1 li.strength.score-1,body .container .body .content div.restore .steps-boxes .step1 li.strength.score-1{color:#f70}body .container .body .content div.add .steps-boxes .step1 li.strength.score-2,body .container .body .content div.restore .steps-boxes .step1 li.strength.score-2{color:#aa0}body .container .body .content div.add .steps-boxes .step1 li.strength.score-3,body .container .body .content div.restore .steps-boxes .step1 li.strength.score-3{color:#070}body .container .body .content div.add .steps-boxes .step1 li.strength.score-4,body .container .body .content div.restore .steps-boxes .step1 li.strength.score-4{color:#427e27}body .container .body .content div.add .steps-boxes .step1 li.strength.score-x,body .container .body .content div.restore .steps-boxes .step1 li.strength.score-x{color:red}body .container .body .content div.add .steps-boxes .step5 div.input.keepBackups input.number,body .container .body .content div.add .steps-boxes .step5 div.input.maxSize input.number,body .container .body .content div.restore .steps-boxes .step5 div.input.keepBackups input.number,body .container .body .content div.restore .steps-boxes .step5 div.input.maxSize input.number{width:60px}body .container .body .content div.add .steps-boxes .step5 .hint,body .container .body .content div.add .steps-boxes .step5 .retention-options,body .container .body .content div.restore .steps-boxes .step5 .hint,body .container .body .content div.restore .steps-boxes .step5 .retention-options{clear:both;margin-left:190px;margin-top:50px;font-style:italic}body .container .body .content div.add .steps-boxes .step5 .retention-options input,body .container .body .content div.restore .steps-boxes .step5 .retention-options input{margin-bottom:10px}body .container .body .content div.add .steps-boxes .step5 .advancedoptions,body .container .body .content div.restore .steps-boxes .step5 .advancedoptions{padding-top:15px;clear:both}body .container .body .content div.add .steps-boxes .step5 .advancedoptions li,body .container .body .content div.restore .steps-boxes .step5 .advancedoptions li{border-top:none}body .container .body .content div.add .steps-boxes .step5 .advancedoptions li>a,body .container .body .content div.restore .steps-boxes .step5 .advancedoptions li>a{display:block;background:#65b1dd;color:#fff!important;padding:5px 15px;float:right;margin-left:10px;cursor:pointer;width:auto;border:none;font-family:'Clear Sans',sans-serif;font-size:16px;font-weight:300;border-radius:0}body .container .body .content div.add .steps-boxes .step5 .advancedoptions li.advancedentry,body .container .body .content div.restore .steps-boxes .step5 .advancedoptions li.advancedentry{border-bottom:1px solid #d3d3d3}body .container .body .content div.add .steps-boxes .step5 .advancedoptions li:last-child,body .container .body .content div.restore .steps-boxes .step5 .advancedoptions li:last-child{padding-top:0}body .container .body .content div.add .steps-boxes .step5 .advancedoptions li:last-child select,body .container .body .content div.restore .steps-boxes .step5 .advancedoptions li:last-child select{max-width:400px}body .container .body .content div.add .steps-boxes .step5 .advancedoptions label,body .container .body .content div.restore .steps-boxes .step5 .advancedoptions label{line-height:normal}body .container .body .content div.add .steps-boxes .step5 .advancedoptions input,body .container .body .content div.add .steps-boxes .step5 .advancedoptions select,body .container .body .content div.restore .steps-boxes .step5 .advancedoptions input,body .container .body .content div.restore .steps-boxes .step5 .advancedoptions select{width:auto;max-width:100%;box-sizing:border-box}body .container .body .content div.add .steps-boxes .step5 .advancedoptions .longdescription,body .container .body .content div.restore .steps-boxes .step5 .advancedoptions .longdescription{margin-top:10px}body .container .body .content div.add .steps-boxes .step5 .advanced-toggle,body .container .body .content div.restore .steps-boxes .step5 .advanced-toggle{color:#8f8f8f;line-height:normal;margin-top:16px;clear:both;float:left}body .container .body .content div.add .steps-boxes .step5 .advanced-toggle i.fa,body .container .body .content div.restore .steps-boxes .step5 .advanced-toggle i.fa{border:2px solid;border-color:#8f8f8f;border-radius:2px;font-size:18px;height:18px;vertical-align:top;width:18px}body .container .body .content div.add .steps-boxes .step5 textarea,body .container .body .content div.restore .steps-boxes .step5 textarea{box-sizing:border-box;clear:both;margin-top:15px;width:100%}body .container .body .content div.add form,body .container .body .content div.restore form{padding-bottom:50px;overflow:hidden}body .container .body .content div.add form .input.password .tools,body .container .body .content div.restore form .input.password .tools{clear:both;padding-left:190px;padding-top:10px}body .container .body .content div.add form .input.password .tools ul,body .container .body .content div.restore form .input.password .tools ul{overflow:hidden}body .container .body .content div.add form .input.password .tools ul li,body .container .body .content div.restore form .input.password .tools ul li{float:left;padding-right:7px}body .container .body .content div.add form .input.password .tools ul li.strength.useless,body .container .body .content div.restore form .input.password .tools ul li.strength.useless{color:red}body .container .body .content div.add form .input.password .tools ul li.strength.average,body .container .body .content div.restore form .input.password .tools ul li.strength.average{color:#ff0}body .container .body .content div.add form .input.password .tools ul li.strength.good,body .container .body .content div.restore form .input.password .tools ul li.strength.good{color:#65b1dd}body .container .body .content div.add form .input.multiple input,body .container .body .content div.add form .input.multiple select,body .container .body .content div.restore form .input.multiple input,body .container .body .content div.restore form .input.multiple select{width:auto;margin-right:5px}body .container .body .content div.add form .input.multiple select,body .container .body .content div.restore form .input.multiple select{padding:5px 12px}body .container .body .content div.add form .input.overlayButton,body .container .body .content div.restore form .input.overlayButton{overflow:hidden;position:relative;max-width:446px}body .container .body .content div.add form .input.overlayButton input,body .container .body .content div.restore form .input.overlayButton input{width:347px}body .container .body .content div.add form .input.overlayButton a.button,body .container .body .content div.restore form .input.overlayButton a.button{position:absolute;top:0;right:0;padding:7px 12px 8px}body .container .body .content div.add form .input.checkbox.multiple strong,body .container .body .content div.restore form .input.checkbox.multiple strong{display:block;padding-bottom:5px}body .container .body .content div.add form .input.checkbox.multiple label,body .container .body .content div.restore form .input.checkbox.multiple label{display:inline-block;float:none;width:auto;padding-right:10px}body .container .body .content div.add form .input.checkbox.multiple input,body .container .body .content div.restore form .input.checkbox.multiple input{width:auto;display:inline-block;float:none}body .container .body .content div.add form .buttons,body .container .body .content div.restore form .buttons{float:none;width:635px;padding-top:30px}body .container .body .content div.add .steps{margin-left:48.5px}body .container .body .content div.add .steps .step{padding-left:97px}body .container .body .content div.add .steps-legend{padding-left:0}body .container .body .content div.add .steps-legend li{width:140px}body .container .body .content div.restore .steps{margin-left:153.5px}body .container .body .content div.restore .steps .step{padding-left:307px}body .container .body .content div.restore .steps-legend{padding-left:0}body .container .body .content div.restore .steps-legend li{width:350px}body .container .body .content div.restore.restore-direct .steps{margin-left:66px}body .container .body .content div.restore.restore-direct .steps .step{padding-left:132px}body .container .body .content div.restore.restore-direct .steps-legend{padding-left:0}body .container .body .content div.restore.restore-direct .steps-legend li{width:175px}body .container .body .content div.restore.restore-direct .step:first-child{padding-left:0;background:0 0}body .container .body .content div.restore.restore-direct .steps-legend{padding-left:20px}body .container .body .content div.headerthreedotmenu{margin:20px 0 20px 0}body .container .body .content div.headerthreedotmenu h2{display:inline}body .container .body .content div.headerthreedotmenu .contextmenu_container{float:right}body .container .body .content div.headerthreedotmenu .contextmenu{left:auto;right:0;top:auto}body .container .body .content div.headerthreedotmenu .threedotmenubutton{padding:5px}body .container .body .content .expandable{margin:20px 0 20px 0}body .container .body .content .expandable h2{display:inline}body .container .body .content .expandable img{padding:0 6px}body .container .body .content div.settings .input.checkbox input.checkbox,body .container .body .content div.settings .input.mixed.multiple input.checkbox{width:auto}body .container .body .content div.settings .input.checkbox select,body .container .body .content div.settings .input.mixed.multiple select{width:auto;margin-right:5px}body .container .body .content div.settings .input.checkbox label,body .container .body .content div.settings .input.mixed.multiple label{line-height:normal;padding:0 15px;width:auto}body .container .body .content .logpage ul.tabs{padding:15px 0}body .container .body .content .logpage ul.entries li{padding-top:10px}body .container .body .content .prewrapped-text{white-space:pre-wrap;overflow-x:auto}body .container .footer{background:#ededed;min-height:70px;line-height:70px;overflow:hidden;position:absolute;bottom:0;width:100%}body .container .footer a{color:#65b1dd}body .container .footer .about-footer{float:left;overflow:hidden;padding-right:20px;display:none}body .container .footer .about-footer span{display:block;float:left;padding-left:20px}body .container .footer .about-footer ul{float:left}body .container .footer .about-footer li{float:left;padding-left:20px}body .container .footer .donate{display:none;float:right;padding-right:40px;overflow:hidden}body .container .footer .donate ul{overflow:hidden;float:right}body .container .footer .donate ul li{float:left;margin-left:10px}body .container .footer .donate ul li a img{margin-top:24px;display:inline-block;opacity:.6}body .container .footer .donate ul li a img:hover{opacity:1}body .container .footer .donate>a{float:left}body .container .footer .social{float:right}body .container .footer .social ul{overflow:hidden;float:right;padding-left:20px;padding-right:10px}body .container .footer .social ul li{float:right;margin-right:10px;padding-top:5px}body .container .footer .social ul li img{opacity:.6}body .container .footer .social ul li img:hover{opacity:1}body .container .footer .themelink{float:right;padding-right:20px}body #modal-menu{max-width:400px}body #modal-menu a{color:#65b1dd;font-size:20px;line-height:40px}.remodal{padding:30px;box-shadow:0 2px 7px rgba(0,0,0,.3);background:#fff;display:none}.remodal form .buttons{float:none}.remodal-wrapper .remodal{display:block}span.info{font-size:10px;font-weight:500;display:inline-block;background:#65b1dd;border-radius:50%;width:15px;height:15px;vertical-align:super;color:#fff;line-height:15px;margin-left:5px;text-align:center}.hidden{display:none}.clear{clear:both}.nofloat{float:none!important}div.blocker,div.connection-lost,div.modal-dialog{position:fixed;top:0;left:0;right:0;bottom:0;margin:auto}div.blocker{z-index:5000;background-color:#000;opacity:.65}#connection-lost-blocker{z-index:5100}#connection-lost-dialog{z-index:5200}div.connection-lost,div.modal-dialog{z-index:5001;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-box-pack:center;-moz-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-box-align:center;-moz-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center}div.connection-lost div.info,div.modal-dialog div.info{min-width:310px;max-width:650px;margin:5px}div.connection-lost div.title,div.modal-dialog div.title{border:1px solid #65b1dd;background-color:#65b1dd;border-radius:5px 5px 0 0;padding:10px 20px;font-weight:700;color:#d3d3d3;text-align:center}div.connection-lost div.content,div.modal-dialog div.content{background-color:#fff;border:1px solid #fff;padding:20px}div.connection-lost .buttons,div.modal-dialog .buttons{border-radius:0 0 5px 5px;padding-top:10px;overflow:auto}div.connection-lost form,div.modal-dialog form{margin-top:15px}div.connection-lost form textarea,div.modal-dialog form textarea{height:130px;width:420px;padding:10px 12px;border:1px #d8d8d8 solid;border-radius:2px;color:#8f8f8f;font-size:16px;font-weight:300}div.connection-lost form input,div.modal-dialog form input{height:35px;line-height:35px;padding:0 12px}div.modal-dialog .content.buttons ul{float:right}div.modal-dialog .content.buttons .tooltipped{position:relative}div.modal-dialog .content.buttons .tooltipped:after{position:absolute;z-index:1000000;display:none;padding:5px 8px;font:normal normal 11px/1.5 Helvetica,arial,nimbussansl,liberationsans,freesans,clean,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";color:#fff;text-align:center;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-wrap:break-word;white-space:pre;pointer-events:none;content:attr(aria-label);background:rgba(0,0,0,.8);border-radius:3px;-webkit-font-smoothing:subpixel-antialiased}div.modal-dialog .content.buttons .tooltipped:before{position:absolute;z-index:1000001;display:none;width:0;height:0;color:rgba(0,0,0,.8);pointer-events:none;content:"";border:5px solid transparent}div.modal-dialog .content.buttons .tooltipped:active:after,div.modal-dialog .content.buttons .tooltipped:active:before,div.modal-dialog .content.buttons .tooltipped:focus:after,div.modal-dialog .content.buttons .tooltipped:focus:before,div.modal-dialog .content.buttons .tooltipped:hover:after,div.modal-dialog .content.buttons .tooltipped:hover:before{display:inline-block;text-decoration:none}div.modal-dialog .content.buttons .tooltipped-w:after{right:100%;bottom:50%;margin-right:5px;-webkit-transform:translateY(50%);-ms-transform:translateY(50%);transform:translateY(50%)}div.modal-dialog .content.buttons .tooltipped-w:before{top:50%;bottom:50%;left:-5px;margin-top:-5px;border-left-color:rgba(0,0,0,.8)}.importpage form.styled input{margin-top:11px;margin-bottom:11px}.addwizard form.styled ul,.restorewizard form.styled ul{margin:20px;margin-left:0}.addwizard form.styled input[type=radio],.restorewizard form.styled input[type=radio]{width:20px;margin-left:5px;margin-right:5px}.addwizard form.styled label,.restorewizard form.styled label{width:auto;line-height:normal}.addwizard form.styled div.subtext,.restorewizard form.styled div.subtext{clear:both;margin-left:30px;padding-top:5px;color:#d3d3d3}.pauseoptions form.styled li{line-height:normal;padding:0}.pauseoptions form.styled li input{height:auto;margin-top:8px;margin-right:8px;width:auto}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress{position:relative;min-height:25px}.progress>span{vertical-align:middle;display:block;width:100%;height:100%;text-align:center;z-index:100;padding-top:2px}.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress .progress-bar{float:left;width:0;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease;height:100%;position:absolute}.progress .progress-bar.active{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.tree-view{list-style-type:none;margin-left:10px;padding-bottom:5px}.tree-view ul{margin-left:16px}.tree-view span.nodeLabel{cursor:pointer}.tree-view span.nodeLabel.selected{border:1px solid #aaa;background-color:#ddd;padding:1px 3px}.tree-view li .node{padding-bottom:5px}.tree-view li div.selected{border-color:#add8e6;background-color:#add8e6}.tree-view li>ul{display:none}.tree-view li>ul.expanded{display:block}.tree-view li a.nav{cursor:pointer;display:inline-block;width:16px;height:16px;vertical-align:middle;background-image:url(../img/treeicons.png);background-repeat:no-repeat;background-position:-80px 0}.tree-view li a.nav.leaf{background:0 0}.tree-view li a.nav.expanded{background-position:-80px -16px}.tree-view li a.type{cursor:auto;display:inline-block;width:16px;height:16px;vertical-align:middle;background-image:url(../img/treeicons.png);background-repeat:no-repeat;background-position:0 -16px}.tree-view li a.type.invisible{background-position:0 -32px}.tree-view li a.type.loading{cursor:progress;background-image:url(../img/loader-16.gif);background-repeat:no-repeat;background-position:0 0}.tree-view li a.type.x-tree-icon-drive{background-position:-16px -16px}.tree-view li a.type.x-tree-icon-leaf{background-position:-32px -16px}.tree-view li a.type.x-tree-icon-symlink{background-position:-48px -16px}.tree-view li a.type.x-tree-icon-userdata{background-position:-16px -48px}.tree-view li a.type.x-tree-icon-locked{background-position:-64px -16px}.tree-view li a.type.x-tree-icon-broken{background-position:-64px -16px}.tree-view li a.type.x-tree-icon-computer{background-position:0 -48px}.tree-view li a.type.x-tree-icon-hyperv{background-position:-96px -16px}.tree-view li a.type.x-tree-icon-hypervmachine{background-position:-96px 0}.tree-view li a.type.x-tree-icon-mssql{background-position:-96px -32px}.tree-view li a.type.x-tree-icon-mssqldb{background-position:-80px -32px}.tree-view li a.type.x-tree-icon-mydocuments{background-position:-32px -48px}.tree-view li a.type.x-tree-icon-mymusic{background-position:-48px -48px}.tree-view li a.type.x-tree-icon-mypictures{background-position:-64px -48px}.tree-view li a.type.x-tree-icon-desktop{background-position:-80px -48px}.tree-view li a.type.x-tree-icon-home{background-position:-96px -48px}.tree-view li a.type.x-tree-icon-drive.invisible{background-position:-16px -32px}.tree-view li a.type.x-tree-icon-leaf.invisible{background-position:-32px -32px}.tree-view li a.type.x-tree-icon-symlink.invisible{cursor:auto;background-position:-48px -32px}.tree-view li a.type.x-tree-icon-locked.invisible{background-position:-64px -32px}.tree-view li a.check{height:16px;width:16px;display:inline-block;cursor:pointer;background-image:url(../img/treeicons.png);background-repeat:no-repeat;background-position:0 0;vertical-align:middle}.tree-view li a.partial{background-position:-32px 0}.tree-view li a.include{background-position:-16px 0}.tree-view li a.exclude{background-position:-48px 0}.tree-view li a.root{background:0 0;display:none}.throttlesettings div.multiple select{width:auto;margin-right:5px}.throttlesettings div.multiple input{width:100px}.throttlesettings div.multiple input.checkbox{width:auto}.throttlesettings div.multiple label{line-height:35px;padding:0 15px;width:auto;min-width:150px}.throttlesettings .disabled{color:#cfcfcf}.throttlesettings .disabled input,.throttlesettings .disabled select{color:#cfcfcf}@media (max-width:1150px){body .container .header{height:140px}body .container .header .statepadding{padding-right:90px;margin-left:0}body .container .header .state{width:100%;margin:10px 40px;clear:left;float:left}body .container .header .action-icons{display:none}body .container .header .action-icons-small{display:inline-block}body .container .header .menubutton{display:block;font-size:18px;padding-right:50px;margin-top:5px;margin-right:15px;background:url(../img/menu.png) no-repeat right top;position:relative;height:40px;line-height:40px;color:#8f8f8f;float:right;top:10px;padding-left:20px;text-transform:uppercase;text-align:right}body .container .header .menubutton.active{background-image:url(../img/menu_active.png);color:#65b1dd}body .container .header .donate{display:none}body .container .body{position:relative;padding-top:140px}body .container .body .mainmenu{display:none;position:fixed;background:none repeat scroll 0 0 #fff;box-shadow:0 4px 8px rgba(0,0,0,.3);left:10px;padding:20px;top:60px}body .container .body .mainmenu.mobile-open{display:block;left:auto;right:0;top:0;z-index:1000}body .container .body .contextmenu{left:0;top:auto}body .container .body .content{float:none;padding:20px 20px;margin:0 auto 30px auto}body .container .body .content .state{width:auto}body .container .mobileOpen{display:block!important}}@media (max-width:768px){body .container .body .content .tasks .tasklist a{font-size:20px;background-size:24px;background-position:0 4px;padding-left:35px}body .container .body .content .tasks .tasklist dl{padding-left:35px}body .container .header .logo{padding-left:10px}body .container .header .statepadding{padding-right:50px}body .container .header .state{margin-left:10px}body .container .header .menubutton{margin-right:5px}body .container .body .content div.add .steps,body .container .body .content div.restore .steps,body .container .body .content div.settings .steps{display:none}body .container .body .content div.add .steps-legend,body .container .body .content div.restore .steps-legend,body .container .body .content div.settings .steps-legend{list-style:decimal;padding-left:20px;border-bottom:1px solid #eee;margin-bottom:30px;padding-bottom:20px}body .container .body .content div.add .steps-legend li,body .container .body .content div.restore .steps-legend li,body .container .body .content div.settings .steps-legend li{float:none;font-weight:500;width:auto!important;padding-right:0!important}body .container .body .content div.add .steps-boxes,body .container .body .content div.restore .steps-boxes,body .container .body .content div.settings .steps-boxes{padding-left:0}body .container .body .content div.add form.styled .input input,body .container .body .content div.add form.styled .input select,body .container .body .content div.add form.styled .input textarea,body .container .body .content div.restore form.styled .input input,body .container .body .content div.restore form.styled .input select,body .container .body .content div.restore form.styled .input textarea,body .container .body .content div.settings form.styled .input input,body .container .body .content div.settings form.styled .input select,body .container .body .content div.settings form.styled .input textarea{max-width:100%;box-sizing:border-box}body .container .body .content div.add form.styled .input.select select,body .container .body .content div.restore form.styled .input.select select,body .container .body .content div.settings form.styled .input.select select{width:420px}body .container .body .content div.add form.styled .buttons,body .container .body .content div.restore form.styled .buttons,body .container .body .content div.settings form.styled .buttons{max-width:100%;width:auto}body .container .body .content div.add form.styled .tools,body .container .body .content div.restore form.styled .tools,body .container .body .content div.settings form.styled .tools{padding-left:0!important}body .container .body .content div.add form.styled .input.checkbox.multiple,body .container .body .content div.restore form.styled .input.checkbox.multiple,body .container .body .content div.settings form.styled .input.checkbox.multiple{padding-bottom:5px}body .container .body .content div.add form.styled .input.checkbox.multiple input,body .container .body .content div.add form.styled .input.checkbox.multiple label,body .container .body .content div.restore form.styled .input.checkbox.multiple input,body .container .body .content div.restore form.styled .input.checkbox.multiple label,body .container .body .content div.settings form.styled .input.checkbox.multiple input,body .container .body .content div.settings form.styled .input.checkbox.multiple label{display:block!important;float:left!important;line-height:normal}body .container .body .content div.add form.styled .input.checkbox.multiple input,body .container .body .content div.restore form.styled .input.checkbox.multiple input,body .container .body .content div.settings form.styled .input.checkbox.multiple input{clear:both}body .container .body .content div.add form.styled .input.text.multiple input,body .container .body .content div.restore form.styled .input.text.multiple input,body .container .body .content div.settings form.styled .input.text.multiple input{max-width:48%!important}}@media (max-width:640px){body h2{font-size:20px;text-align:center}body .container .body{padding-bottom:10px}body .container .body .content{margin:0 auto}body .container .body .content div.add form .input.overlayButton,body .container .body .content div.restore form .input.overlayButton{padding-top:8px;padding-bottom:30px;margin-bottom:10px}body .container .body .content div.add form .input.overlayButton a.button,body .container .body .content div.restore form .input.overlayButton a.button{padding:7px 10px;right:1px;top:9px}body .container .body .content div.add form .input.checkbox.multiple div,body .container .body .content div.restore form .input.checkbox.multiple div{display:block}body .container .body .content div.add form .input.select.multiple input#exclude-larger-than-number,body .container .body .content div.restore form .input.select.multiple input#exclude-larger-than-number{width:75px}body .container .body .content div.add form .input.select.multiple select#exclude-larger-than-multiplier,body .container .body .content div.restore form .input.select.multiple select#exclude-larger-than-multiplier{width:140px}body .container .body .content div.add form .filters .input.textarea,body .container .body .content div.restore form .filters .input.textarea{padding-bottom:10px}body .container .body .content div.add form .filters h3,body .container .body .content div.restore form .filters h3{margin:5px 0}body .container .body .content div.add form .input.text.select.multiple.repeat label,body .container .body .content div.restore form .input.text.select.multiple.repeat label{float:none}body .container .body .content div.add form .input.text.select.multiple.repeat input#repeatRunNumber,body .container .body .content div.restore form .input.text.select.multiple.repeat input#repeatRunNumber{width:70px}body .container .body .content div.add form .input.text.select.multiple.repeat select#repeatRunMultiplier,body .container .body .content div.restore form .input.text.select.multiple.repeat select#repeatRunMultiplier{width:100px}body .container .body .content div.add form .input.multiple.text.select.maxSize input,body .container .body .content div.restore form .input.multiple.text.select.maxSize input{width:70px}body .container .body .content div.add form .input.multiple.text.select.maxSize select,body .container .body .content div.restore form .input.multiple.text.select.maxSize select{width:100px}body .container .body .content div.add form .input.multiple.text.select.keepBackups select,body .container .body .content div.restore form .input.multiple.text.select.keepBackups select{width:85px;padding:4px 6px}body .container .body .content div.add form .input.multiple.text.select.keepBackups input,body .container .body .content div.restore form .input.multiple.text.select.keepBackups input{width:60px}body .container .footer{position:static;padding:15px;line-height:normal;text-align:left;box-sizing:border-box}body .container .footer *{float:none!important;text-align:center;box-sizing:border-box}body .container .footer .about-footer{padding-right:0;display:block}body .container .footer .about-footer span{padding-left:0;padding-bottom:5px}body .container .footer .about-footer li{padding-left:0;float:none;display:inline-block;height:32px;width:32px;background-size:28px!important;border-bottom:none}body .container .footer .about-footer li.support{background:url(../img/support.png) no-repeat center center}body .container .footer .about-footer li.about{background:url(../img/about.png) no-repeat center center}body .container .footer .about-footer li:first-child{padding-bottom:0}body .container .footer .about-footer li:last-child{padding-bottom:20px}body .container .footer .about-footer,body .container .footer .donate,body .container .footer .social,body .container .footer li{padding:8px 0;border-bottom:1px #ddd solid}body .container .footer .donate{display:block}body .container .footer .donate ul li{display:inline-block;border:none;margin:0 5px}body .container .footer .donate ul li a img{margin-top:0}body .container .footer .social li{display:inline-block;border:none}body .container .footer .themelink{padding:5px 0}}@media (max-width:580px){.advancedentry .longdescription{margin-left:0}}@media (max-width:492px){ul.notification{width:auto}}@media (max-width:480px){body{font-size:15px}body .container .header .logo{padding-left:5px}body .container .header .menubutton{margin-right:5px}body .container .header .state{margin-left:5px}body .container .header .statepadding{padding-right:40px}body .container .header .menubutton{padding-left:10px}body .container .body .mainmenu{width:280px;box-sizing:border-box}body .container .body .mainmenu ul li a{font-size:22px}body .container .body .content{padding:15px}body .container .body .content div.add form .input.password .tools ul li,body .container .body .content div.restore form .input.password .tools ul li{font-size:14px}body .container .body .content div.add form .buttons a,body .container .body .content div.restore form .buttons a{float:none;text-align:center;margin-bottom:5px}body .container .body .content div.add .steps-boxes .box.browser .checklinks a,body .container .body .content div.restore .steps-boxes .box.browser .checklinks a{float:none;margin-bottom:8px;display:block}}@media (max-width:400px){body{font-size:15px}body .container .header .menubutton{margin-right:0;padding-left:0;padding-right:40px}body .container .header .menubutton span{display:none}}@media (max-width:325px){body{font-size:15px}body .container .header .logo div{display:none}}@media (max-width:200px){body{font-size:15px}body .container .header .menubutton{position:static;margin-top:0}body .container .header .action-icons-small{clear:right;margin-top:0}} \ No newline at end of file diff --git a/Duplicati/Server/webroot/ngax/templates/addoredit.html b/Duplicati/Server/webroot/ngax/templates/addoredit.html index 4b32e2d3c..bf7f68e38 100755 --- a/Duplicati/Server/webroot/ngax/templates/addoredit.html +++ b/Duplicati/Server/webroot/ngax/templates/addoredit.html @@ -335,7 +335,7 @@
- Enter a retention strategy manually. Placeholders are D/W/Y for days/weeks/years. The syntax is: 7D:1D,4W:1W,36M:1M. This example keeps one backup for each of the next 7 days, one for each of the next 4 weeks, and one for each of the next 36 months. This can also be written as 1W:1D,1M:1W,3Y:1M. + Enter a retention strategy manually. Placeholders are D/W/Y for days/weeks/years and U for unlimited. The syntax is: 7D:1D,4W:1W,36M:1M. This example keeps one backup for each of the next 7 days, one for each of the next 4 weeks, and one for each of the next 36 months. This can also be written as 1W:1D,1M:1W,3Y:1M.
diff --git a/Duplicati/Server/webroot/ngax/templates/notificationarea.html b/Duplicati/Server/webroot/ngax/templates/notificationarea.html index 1bcfdb3b1..3514f3756 100644 --- a/Duplicati/Server/webroot/ngax/templates/notificationarea.html +++ b/Duplicati/Server/webroot/ngax/templates/notificationarea.html @@ -11,6 +11,8 @@ Show + Repair + Download
diff --git a/Duplicati/Service/Runner.cs b/Duplicati/Service/Runner.cs index ae4300815..c45bb458b 100644 --- a/Duplicati/Service/Runner.cs +++ b/Duplicati/Service/Runner.cs @@ -30,7 +30,7 @@ namespace Duplicati.Service private Action m_onStoppedAction; private Action m_reportMessage; - private object m_writelock = new object(); + private readonly object m_writelock = new object(); private readonly string[] m_cmdargs; diff --git a/Duplicati/UnitTest/BasicSetupHelper.cs b/Duplicati/UnitTest/BasicSetupHelper.cs index 8636df956..4dad6bc42 100644 --- a/Duplicati/UnitTest/BasicSetupHelper.cs +++ b/Duplicati/UnitTest/BasicSetupHelper.cs @@ -105,7 +105,7 @@ namespace Duplicati.UnitTest opts["passphrase"] = "123456"; opts["debug-output"] = ""; - opts["log-level"] = "profiling"; + opts["log-file-log-level"] = nameof(Library.Logging.LogMessageType.Profiling); opts["log-file"] = LOGFILE; opts["dblock-size"] = "10mb"; opts["dbpath"] = DBFILE; diff --git a/Duplicati/UnitTest/BorderTests.cs b/Duplicati/UnitTest/BorderTests.cs index 27bbf2f0b..e3eacad35 100644 --- a/Duplicati/UnitTest/BorderTests.cs +++ b/Duplicati/UnitTest/BorderTests.cs @@ -206,7 +206,6 @@ namespace Duplicati.UnitTest private void RunCommands(int blocksize, int basedatasize = 0, Action> modifyOptions = null) { var testopts = TestOptions; - testopts["verbose"] = "true"; testopts["blocksize"] = blocksize.ToString() + "b"; if (modifyOptions != null) modifyOptions(testopts); diff --git a/Duplicati/UnitTest/CommandLineOperationsTests.cs b/Duplicati/UnitTest/CommandLineOperationsTests.cs index 1019def92..a3e0f3cb8 100644 --- a/Duplicati/UnitTest/CommandLineOperationsTests.cs +++ b/Duplicati/UnitTest/CommandLineOperationsTests.cs @@ -25,6 +25,10 @@ namespace Duplicati.UnitTest { public class CommandLineOperationsTests : BasicSetupHelper { + /// + /// The log tag + /// + private static readonly string LOGTAG = Library.Logging.Log.LogTagFromType(); /// /// The folder that contains all the source data which the test is based on /// @@ -82,12 +86,12 @@ namespace Duplicati.UnitTest var size = Directory.EnumerateFiles(targetfolder, "*", SearchOption.AllDirectories).Select(x => new FileInfo(x).Length).Sum(); ProgressWriteLine("Running backup with {0} data added ...", Duplicati.Library.Utility.Utility.FormatSizeString(size)); - using(new Library.Logging.Timer(string.Format("Backup with {0} data added", Duplicati.Library.Utility.Utility.FormatSizeString(size)))) + using(new Library.Logging.Timer(LOGTAG, "BackupWithDataAdded", string.Format("Backup with {0} data added", Duplicati.Library.Utility.Utility.FormatSizeString(size)))) Duplicati.CommandLine.Program.RealMain(backupargs); } ProgressWriteLine("Running unchanged backup ..."); - using(new Library.Logging.Timer("Unchanged backup")) + using(new Library.Logging.Timer(LOGTAG, "UnchangedBackupe", "Unchanged backup")) Duplicati.CommandLine.Program.RealMain(backupargs); var datafolders = Directory.EnumerateDirectories(DATAFOLDER); @@ -98,7 +102,7 @@ namespace Duplicati.UnitTest Directory.Move(f, Path.Combine(Path.GetDirectoryName(f), Path.GetFileName(f) + "-renamed")); ProgressWriteLine("Running backup with renamed folder..."); - using(new Library.Logging.Timer("Backup with renamed folder")) + using(new Library.Logging.Timer(LOGTAG, "BackupWithRenamedFolder", "Backup with renamed folder")) Duplicati.CommandLine.Program.RealMain(backupargs); datafolders = Directory.EnumerateDirectories(DATAFOLDER); @@ -115,11 +119,11 @@ namespace Duplicati.UnitTest File.Delete(n); ProgressWriteLine("Running backup with deleted data..."); - using(new Library.Logging.Timer("Backup with deleted data")) + using(new Library.Logging.Timer(LOGTAG, "BackupWithDeletedData", "Backup with deleted data")) Duplicati.CommandLine.Program.RealMain(backupargs); ProgressWriteLine("Testing the compare method ..."); - using(new Library.Logging.Timer("Compare method")) + using(new Library.Logging.Timer(LOGTAG, "CompareMethod", "Compare method")) Duplicati.CommandLine.Program.RealMain((new string[] { "compare", target, "0", "1" }.Union(opts)).ToArray()); for(var i = 0; i < 5; i++) @@ -127,12 +131,12 @@ namespace Duplicati.UnitTest ProgressWriteLine("Running backup with changed logfile {0} of {1} ...", i + 1, 5); File.Copy(LOGFILE, Path.Combine(SOURCEFOLDER, Path.GetFileName(LOGFILE)), true); - using(new Library.Logging.Timer(string.Format("Backup with logfilechange {0}", i + 1))) + using(new Library.Logging.Timer(LOGTAG, "BackupWithLogfileChange", string.Format("Backup with logfilechange {0}", i + 1))) Duplicati.CommandLine.Program.RealMain(backupargs); } - ProgressWriteLine("Compacting data ..."); - using(new Library.Logging.Timer("Compacting")) + ProgressWriteLine(LOGTAG, "CompactingData", "Compacting data ..."); + using(new Library.Logging.Timer(LOGTAG, "Compacting", "Compacting")) Duplicati.CommandLine.Program.RealMain((new string[] { "compact", target, "--small-file-max-count=2" }.Union(opts)).ToArray()); @@ -143,33 +147,33 @@ namespace Duplicati.UnitTest Directory.Delete(RESTOREFOLDER, true); ProgressWriteLine("Partial restore of {0} ...", Path.GetFileName(rf)); - using(new Library.Logging.Timer("Partial restore")) + using(new Library.Logging.Timer(LOGTAG, "PartialRestore", "Partial restore")) Duplicati.CommandLine.Program.RealMain((new string[] { "restore", target, rf + "*", "--restore-path=\"" + RESTOREFOLDER + "\"" }.Union(opts)).ToArray()); ProgressWriteLine("Verifying partial restore ..."); - using (new Library.Logging.Timer("Verification of partial restored files")) + using (new Library.Logging.Timer(LOGTAG, "VerifiationOfPartialRestore", "Verification of partial restored files")) TestUtils.VerifyDir(rf, RESTOREFOLDER, true); if (Directory.Exists(RESTOREFOLDER)) Directory.Delete(RESTOREFOLDER, true); ProgressWriteLine("Partial restore of {0} without local db...", Path.GetFileName(rf)); - using(new Library.Logging.Timer("Partial restore without local db")) + using(new Library.Logging.Timer(LOGTAG, "PartialRestoreWithoutLocalDb", "Partial restore without local db")) Duplicati.CommandLine.Program.RealMain((new string[] { "restore", target, rf + "*", "--restore-path=\"" + RESTOREFOLDER + "\"", "--no-local-db" }.Union(opts)).ToArray()); ProgressWriteLine("Verifying partial restore ..."); - using (new Library.Logging.Timer("Verification of partial restored files")) + using (new Library.Logging.Timer(LOGTAG, "VerificationOfPartialRestore", "Verification of partial restored files")) TestUtils.VerifyDir(rf, RESTOREFOLDER, true); if (Directory.Exists(RESTOREFOLDER)) Directory.Delete(RESTOREFOLDER, true); ProgressWriteLine("Full restore ..."); - using(new Library.Logging.Timer("Full restore")) + using(new Library.Logging.Timer(LOGTAG, "FullRestore", "Full restore")) Duplicati.CommandLine.Program.RealMain((new string[] { "restore", target, "*", "--restore-path=\"" + RESTOREFOLDER + "\"" }.Union(opts)).ToArray()); ProgressWriteLine("Verifying full restore ..."); - using (new Library.Logging.Timer("Verification of restored files")) + using (new Library.Logging.Timer(LOGTAG, "VerificationOfFullRestore", "Verification of restored files")) foreach(var s in Directory.EnumerateDirectories(DATAFOLDER)) TestUtils.VerifyDir(s, Path.Combine(RESTOREFOLDER, Path.GetFileName(s)), true); @@ -177,16 +181,16 @@ namespace Duplicati.UnitTest Directory.Delete(RESTOREFOLDER, true); ProgressWriteLine("Full restore without local db..."); - using(new Library.Logging.Timer("Full restore without local db")) + using(new Library.Logging.Timer(LOGTAG, "FullRestoreWithoutDb", "Full restore without local db")) Duplicati.CommandLine.Program.RealMain((new string[] { "restore", target, "*", "--restore-path=\"" + RESTOREFOLDER + "\"", "--no-local-db" }.Union(opts)).ToArray()); ProgressWriteLine("Verifying full restore ..."); - using (new Library.Logging.Timer("Verification of restored files")) + using (new Library.Logging.Timer(LOGTAG, "VerificationOfFullRestoreWithoutDb", "Verification of restored files")) foreach(var s in Directory.EnumerateDirectories(DATAFOLDER)) TestUtils.VerifyDir(s, Path.Combine(RESTOREFOLDER, Path.GetFileName(s)), true); ProgressWriteLine("Testing data ..."); - using (new Library.Logging.Timer("Test remote data")) + using (new Library.Logging.Timer(LOGTAG, "TestRemoteData", "Test remote data")) if (Duplicati.CommandLine.Program.RealMain((new string[] { "test", target, "all" }.Union(opts)).ToArray()) != 0) throw new Exception("Failed during final remote verification"); diff --git a/Duplicati/UnitTest/Issue1410.cs b/Duplicati/UnitTest/Issue1410.cs index 513aaefac..d610daa19 100644 --- a/Duplicati/UnitTest/Issue1410.cs +++ b/Duplicati/UnitTest/Issue1410.cs @@ -38,7 +38,6 @@ namespace Duplicati.UnitTest public void RunCommands() { var testopts = TestOptions; - testopts["verbose"] = "true"; var data = new byte[1024 * 1024 * 10]; File.WriteAllBytes(Path.Combine(DATAFOLDER, "a"), data); diff --git a/Duplicati/UnitTest/Issue1723.cs b/Duplicati/UnitTest/Issue1723.cs index 7a7cb76c8..c805fb75e 100644 --- a/Duplicati/UnitTest/Issue1723.cs +++ b/Duplicati/UnitTest/Issue1723.cs @@ -36,7 +36,6 @@ namespace Duplicati.UnitTest public void RunCommands() { var testopts = TestOptions; - testopts["verbose"] = "true"; testopts["no-backend-verification"] = "true"; var data = new byte[1024 * 1024 * 10]; diff --git a/Duplicati/UnitTest/PurgeTesting.cs b/Duplicati/UnitTest/PurgeTesting.cs index 8c090a78a..ac4387b94 100644 --- a/Duplicati/UnitTest/PurgeTesting.cs +++ b/Duplicati/UnitTest/PurgeTesting.cs @@ -42,7 +42,6 @@ namespace Duplicati.UnitTest var basedatasize = 0; var testopts = TestOptions; - testopts["verbose"] = "true"; testopts["blocksize"] = blocksize.ToString() + "b"; var filenames = BorderTests.WriteTestFilesToFolder(DATAFOLDER, blocksize, basedatasize).Select(x => "a" + x.Key).ToList(); @@ -170,7 +169,6 @@ namespace Duplicati.UnitTest var basedatasize = 0; var testopts = TestOptions; - testopts["verbose"] = "true"; testopts["blocksize"] = blocksize.ToString() + "b"; var filenames = BorderTests.WriteTestFilesToFolder(DATAFOLDER, blocksize, basedatasize).Select(x => "a" + x.Key).ToList(); diff --git a/Duplicati/UnitTest/RandomErrorBackend.cs b/Duplicati/UnitTest/RandomErrorBackend.cs index 4151a8622..d714f7920 100644 --- a/Duplicati/UnitTest/RandomErrorBackend.cs +++ b/Duplicati/UnitTest/RandomErrorBackend.cs @@ -23,6 +23,13 @@ namespace Duplicati.UnitTest public RandomErrorBackend() { } public RandomErrorBackend(string url, Dictionary options) { var u = new Library.Utility.Uri(url).SetScheme(WrappedBackend).ToString(); m_backend = (IStreamingBackend)Library.DynamicLoader.BackendLoader.GetBackend(u, options); } private void ThrowErrorRandom() { if (random.NextDouble() > 0.90) throw new Exception("Random upload failure"); } - #region IStreamingBackend implementation public void Put(string remotename, Stream stream) { var uploadError = random.NextDouble() > 0.9; using(var f = new Library.Utility.ProgressReportingStream(stream, stream.Length, x => { if (uploadError && stream.Position > stream.Length / 2) throw new Exception("Random upload failure"); })) m_backend.Put(remotename, f); ThrowErrorRandom(); } public void Get(string remotename, Stream stream) { ThrowErrorRandom(); m_backend.Get(remotename, stream); ThrowErrorRandom(); } #endregion #region IBackend implementation public IEnumerable List() { return m_backend.List(); } public void Put(string remotename, string filename) { ThrowErrorRandom(); m_backend.Put(remotename, filename); ThrowErrorRandom(); } public void Get(string remotename, string filename) { ThrowErrorRandom(); m_backend.Get(remotename, filename); ThrowErrorRandom(); } public void Delete(string remotename) { ThrowErrorRandom(); m_backend.Delete(remotename); ThrowErrorRandom(); } public void Test() { m_backend.Test(); } public void CreateFolder() { m_backend.CreateFolder(); } public string DisplayName { get { return "Random Error Backend"; } } public string ProtocolKey { get { return "randomerror"; } } public IList SupportedCommands { get { if (m_backend == null) try { return Duplicati.Library.DynamicLoader.BackendLoader.GetSupportedCommands(WrappedBackend + "://"); } catch { } return m_backend.SupportedCommands; } } public string Description { get { return "A testing backend that randomly fails"; } } #endregion #region IDisposable implementation public void Dispose() { if (m_backend != null) try { m_backend.Dispose(); } finally { m_backend = null; } } #endregion } + #region IStreamingBackend implementation public void Put(string remotename, Stream stream) { var uploadError = random.NextDouble() > 0.9; using(var f = new Library.Utility.ProgressReportingStream(stream, stream.Length, x => { if (uploadError && stream.Position > stream.Length / 2) throw new Exception("Random upload failure"); })) m_backend.Put(remotename, f); ThrowErrorRandom(); } public void Get(string remotename, Stream stream) { ThrowErrorRandom(); m_backend.Get(remotename, stream); ThrowErrorRandom(); } #endregion #region IBackend implementation public IEnumerable List() { return m_backend.List(); } public void Put(string remotename, string filename) { ThrowErrorRandom(); m_backend.Put(remotename, filename); ThrowErrorRandom(); } public void Get(string remotename, string filename) { ThrowErrorRandom(); m_backend.Get(remotename, filename); ThrowErrorRandom(); } public void Delete(string remotename) { ThrowErrorRandom(); m_backend.Delete(remotename); ThrowErrorRandom(); } public void Test() { m_backend.Test(); } public void CreateFolder() { m_backend.CreateFolder(); } + public string[] DNSName + { + get + { + return m_backend.DNSName; + } + } public string DisplayName { get { return "Random Error Backend"; } } public string ProtocolKey { get { return "randomerror"; } } public IList SupportedCommands { get { if (m_backend == null) try { return Duplicati.Library.DynamicLoader.BackendLoader.GetSupportedCommands(WrappedBackend + "://"); } catch { } return m_backend.SupportedCommands; } } public string Description { get { return "A testing backend that randomly fails"; } } #endregion #region IDisposable implementation public void Dispose() { if (m_backend != null) try { m_backend.Dispose(); } finally { m_backend = null; } } #endregion } } diff --git a/Duplicati/UnitTest/SVNCheckoutsTest.cs b/Duplicati/UnitTest/SVNCheckoutsTest.cs index 146086dce..1dfad2608 100644 --- a/Duplicati/UnitTest/SVNCheckoutsTest.cs +++ b/Duplicati/UnitTest/SVNCheckoutsTest.cs @@ -35,10 +35,15 @@ namespace Duplicati.UnitTest ///
public class SVNCheckoutTest { + /// + /// The log tag + /// + private static readonly string LOGTAG = Library.Logging.Log.LogTagFromType(); + /// /// A helper class to write debug messages to the log file /// - private class LogHelper : StreamLog + private class LogHelper : StreamLogDestination { private string m_backupset; @@ -57,13 +62,13 @@ namespace Duplicati.UnitTest this.Backupset = "none"; } - public override void WriteMessage(string message, LogMessageType type, Exception exception) + public override void WriteMessage(LogEntry entry) { - if (type == LogMessageType.Error) + if (entry.Level == LogMessageType.Error) System.Threading.Interlocked.Increment(ref ErrorCount); - else if (type == LogMessageType.Warning) + else if (entry.Level == LogMessageType.Warning) System.Threading.Interlocked.Increment(ref WarningCount); - base.WriteMessage(this.Backupset + ", " + message, type, exception); + base.WriteMessage(entry); } } @@ -90,9 +95,8 @@ namespace Duplicati.UnitTest } using (var log = new LogHelper(logfilename)) - using (Log.StartScope(log)) + using (Log.StartScope(log, LogMessageType.Profiling)) { - Log.LogLevel = Duplicati.Library.Logging.LogMessageType.Profiling; //Filter empty entries, commonly occuring with copy/paste and newlines folders = (from x in folders @@ -115,7 +119,7 @@ namespace Duplicati.UnitTest options["prefix"] = "duplicati_unittest"; //We want all messages in the log - options["log-level"] = LogMessageType.Profiling.ToString(); + options["log-file-log-level"] = LogMessageType.Profiling.ToString(); //We cannot rely on USN numbering, but we can use USN enumeration //options["disable-usn-diff-check"] = "true"; @@ -156,7 +160,7 @@ namespace Duplicati.UnitTest var verifymetadata = !Utility.ParseBoolOption(options, "skip-metadata"); - using (new Timer("Total unittest")) + using (new Timer(LOGTAG, "UnitTest", "Total unittest")) using (TempFolder tf = new TempFolder()) { options["dbpath"] = System.IO.Path.Combine(tempdir, "unittest.sqlite"); @@ -175,7 +179,7 @@ namespace Duplicati.UnitTest tmp["force"] = ""; tmp["allow-full-removal"] = ""; - using (new Timer("Cleaning up any existing backups")) + using (new Timer(LOGTAG, "CleanupExisting", "Cleaning up any existing backups")) try { using (var bk = Duplicati.Library.DynamicLoader.BackendLoader.GetBackend(target, options)) @@ -228,11 +232,12 @@ namespace Duplicati.UnitTest { string msg = string.Format("The file {0} is {1} bytes larger than allowed", fe.Name, fe.Size - opts.VolumeSize); BasicSetupHelper.ProgressWriteLine(msg); - Log.WriteMessage(msg, LogMessageType.Error); + Log.WriteErrorMessage(LOGTAG, "RemoteTargetSize", null, msg); } IList entries; - using (var i = new Duplicati.Library.Main.Controller(target, options, new CommandLine.ConsoleOutput(Console.Out, options))) + using (var console = new CommandLine.ConsoleOutput(Console.Out, options)) + using (var i = new Duplicati.Library.Main.Controller(target, options, console)) entries = (from n in i.List().Filesets select n.Time.ToLocalTime()).ToList(); if (entries.Count != folders.Length) @@ -261,10 +266,11 @@ namespace Duplicati.UnitTest using (TempFolder ptf = new TempFolder()) { List testfiles = new List(); - using (new Timer("Extract list of files from" + folders[i])) + using (new Timer(LOGTAG, "ExtractFileList", "Extract list of files from" + folders[i])) { List sourcefiles; - using (var inst = new Library.Main.Controller(target, options, new CommandLine.ConsoleOutput(Console.Out, options))) + using (var console = new CommandLine.ConsoleOutput(Console.Out, options)) + using (var inst = new Library.Main.Controller(target, options, console)) sourcefiles = (from n in inst.List("*").Files select n.Path).ToList(); //Remove all folders from list @@ -364,7 +370,7 @@ namespace Duplicati.UnitTest if (s.StartsWith(Utility.AppendDirSeparator(tf), StringComparison.Ordinal)) continue; - Log.WriteMessage(string.Format("Found left-over temp file: {0}", s.Substring(tempdir.Length)), LogMessageType.Warning); + Log.WriteWarningMessage(LOGTAG, "LeftOverTempFile", null, "Found left-over temp file: {0}", s.Substring(tempdir.Length)); BasicSetupHelper.ProgressWriteLine("Found left-over temp file: {0} -> {1}", s.Substring(tempdir.Length), #if DEBUG TempFile.GetStackTraceForTempFile(System.IO.Path.GetFileName(s)) @@ -377,7 +383,7 @@ namespace Duplicati.UnitTest foreach (string s in Utility.EnumerateFolders(tempdir)) if (!s.StartsWith(Utility.AppendDirSeparator(tf), StringComparison.Ordinal) && Utility.AppendDirSeparator(s) != Utility.AppendDirSeparator(tf) && Utility.AppendDirSeparator(s) != Utility.AppendDirSeparator(tempdir)) { - Log.WriteMessage(string.Format("Found left-over temp folder: {0}", s.Substring(tempdir.Length)), LogMessageType.Warning); + Log.WriteWarningMessage(LOGTAG, "LeftOverTempFolder", null, "Found left-over temp folder: {0}", s.Substring(tempdir.Length)); BasicSetupHelper.ProgressWriteLine("Found left-over temp folder: {0}", s.Substring(tempdir.Length)); } } @@ -395,7 +401,7 @@ namespace Duplicati.UnitTest private static void VerifyPartialRestore(string source, IEnumerable testfiles, string[] actualfolders, string tempfolder, string rootfolder, bool verifymetadata) { - using (new Timer("Verification of partial restore from " + source)) + using (new Timer(LOGTAG, "PartialRestoreVerify", "Verification of partial restore from " + source)) foreach (string s in testfiles) { string restoredname; @@ -415,21 +421,21 @@ namespace Duplicati.UnitTest if (!System.IO.File.Exists(restoredname)) { - Log.WriteMessage("Partial restore missing file: " + restoredname, LogMessageType.Error); + Log.WriteErrorMessage(LOGTAG, "PartialRestoreMissingFile", null, "Partial restore missing file: {0}", restoredname); BasicSetupHelper.ProgressWriteLine("Partial restore missing file: " + restoredname); } else { if (!System.IO.File.Exists(sourcename)) { - Log.WriteMessage("Partial restore missing file: " + sourcename, LogMessageType.Error); + Log.WriteErrorMessage(LOGTAG, "PartialRestoreMissingFile", null, "Partial restore missing file: {0}", sourcename); BasicSetupHelper.ProgressWriteLine("Partial restore missing file: " + sourcename); throw new Exception("Unittest is broken"); } if (!TestUtils.CompareFiles(sourcename, restoredname, s, verifymetadata)) { - Log.WriteMessage("Partial restore file differs: " + s, LogMessageType.Error); + Log.WriteErrorMessage(LOGTAG, "PartialRestoreWrongFile", null, "Partial restore file differs: {0}", s); BasicSetupHelper.ProgressWriteLine("Partial restore file differs: " + s); } } @@ -438,7 +444,7 @@ namespace Duplicati.UnitTest private static void VerifyFullRestore(string source, string[] actualfolders, string[] restorefoldernames, bool verifymetadata) { - using (new Timer("Verification of " + source)) + using (new Timer(LOGTAG, "SourceVerification", "Verification of " + source)) { for (int j = 0; j < actualfolders.Length; j++) TestUtils.VerifyDir(actualfolders[j], restorefoldernames[j], verifymetadata); @@ -448,27 +454,30 @@ namespace Duplicati.UnitTest private static void RunBackup(string source, string target, Dictionary options, string sourcename) { BasicSetupHelper.ProgressWriteLine("Backing up the copy: " + sourcename); - using (new Timer("Backup of " + sourcename)) - using(var i = new Duplicati.Library.Main.Controller(target, options, new CommandLine.ConsoleOutput(Console.Out, options))) - Log.WriteMessage(i.Backup(source.Split(System.IO.Path.PathSeparator)).ToString(), LogMessageType.Information); + using (new Timer(LOGTAG, "BackupRun", "Backup of " + sourcename)) + using (var console = new CommandLine.ConsoleOutput(Console.Out, options)) + using(var i = new Duplicati.Library.Main.Controller(target, options, console)) + Log.WriteInformationMessage(LOGTAG, "BackupOutput", i.Backup(source.Split(System.IO.Path.PathSeparator)).ToString()); } private static void RunRestore(string source, string target, string tempfolder, Dictionary options) { var tops = new Dictionary(options); tops["restore-path"] = tempfolder; - using (new Timer("Restore of " + source)) - using(var i = new Duplicati.Library.Main.Controller(target, tops, new CommandLine.ConsoleOutput(Console.Out, options))) - Log.WriteMessage(i.Restore(null).ToString(), LogMessageType.Information); + using (new Timer(LOGTAG, "RestoreRun", "Restore of " + source)) + using (var console = new CommandLine.ConsoleOutput(Console.Out, options)) + using(var i = new Duplicati.Library.Main.Controller(target, tops, console)) + Log.WriteInformationMessage(LOGTAG, "RestoreOutput", i.Restore(null).ToString()); } private static void RunPartialRestore(string source, string target, string tempfolder, Dictionary options, string[] files) { var tops = new Dictionary(options); tops["restore-path"] = tempfolder; - using (new Timer("Partial restore of " + source)) - using(var i = new Duplicati.Library.Main.Controller(target, tops, new CommandLine.ConsoleOutput(Console.Out, options))) - Log.WriteMessage(i.Restore(files).ToString(), LogMessageType.Information); + using (new Timer(LOGTAG, "PartialRestore", "Partial restore of " + source)) + using (var console = new CommandLine.ConsoleOutput(Console.Out, options)) + using(var i = new Duplicati.Library.Main.Controller(target, tops, console)) + Log.WriteInformationMessage(LOGTAG, "PartialRestoreOutput", i.Restore(files).ToString()); } } } diff --git a/Duplicati/UnitTest/SizeOmittingBackend.cs b/Duplicati/UnitTest/SizeOmittingBackend.cs index baba42555..9f3cb95bf 100644 --- a/Duplicati/UnitTest/SizeOmittingBackend.cs +++ b/Duplicati/UnitTest/SizeOmittingBackend.cs @@ -78,6 +78,13 @@ namespace Duplicati.UnitTest { m_backend.CreateFolder(); } + public string[] DNSName + { + get + { + return m_backend.DNSName; + } + } public string DisplayName { get diff --git a/Duplicati/UnitTest/TestUtils.cs b/Duplicati/UnitTest/TestUtils.cs index 8e72dd99e..273147882 100644 --- a/Duplicati/UnitTest/TestUtils.cs +++ b/Duplicati/UnitTest/TestUtils.cs @@ -26,6 +26,11 @@ namespace Duplicati.UnitTest { public static class TestUtils { + /// + /// The log tag + /// + private static readonly string LOGTAG = Library.Logging.Log.LogTagFromType(typeof(TestUtils)); + public static Dictionary DefaultOptions { get @@ -158,7 +163,7 @@ namespace Duplicati.UnitTest int ix = IndexOf(folders2, target); if (ix < 0) { - Log.WriteMessage("Missing folder: " + relpath, LogMessageType.Error); + Log.WriteErrorMessage(LOGTAG, "MissingFolder", null, "Missing folder: {0}", relpath); Console.WriteLine("Missing folder: " + relpath); anymissing = true; } @@ -168,7 +173,7 @@ namespace Duplicati.UnitTest foreach (string s in folders2) { - Log.WriteMessage("Extra folder: " + s.Substring(f2.Length), LogMessageType.Error); + Log.WriteErrorMessage(LOGTAG, "ExtraFolder", null, "Extra folder: {0}", s.Substring(f2.Length)); Console.WriteLine("Extra folder: " + s.Substring(f2.Length)); } @@ -181,7 +186,7 @@ namespace Duplicati.UnitTest int ix = IndexOf(files2, target); if (ix < 0) { - Log.WriteMessage("Missing file: " + relpath, LogMessageType.Error); + Log.WriteErrorMessage(LOGTAG, "MissingFile", null, "Missing file: {0}", relpath); Console.WriteLine("Missing file: " + relpath); anymissing = true; } @@ -190,7 +195,7 @@ namespace Duplicati.UnitTest files2.RemoveAt(ix); if (!CompareFiles(s, target, relpath, verifymetadata)) { - Log.WriteMessage("File differs: " + relpath, LogMessageType.Error); + Log.WriteErrorMessage(LOGTAG, "FileDiffers", null, "File differs: {0}", relpath); Console.WriteLine("File differs: " + relpath); } } @@ -198,7 +203,7 @@ namespace Duplicati.UnitTest foreach (string s in files2) { - Log.WriteMessage("Extra file: " + s.Substring(f2.Length), LogMessageType.Error); + Log.WriteErrorMessage(LOGTAG, "ExtraFile", null, "Extra file: {0}", s.Substring(f2.Length)); Console.WriteLine("Extra file: " + s.Substring(f2.Length)); } @@ -219,7 +224,7 @@ namespace Duplicati.UnitTest using (System.IO.FileStream fs2 = System.IO.File.OpenRead(f2)) if (fs1.Length != fs2.Length) { - Log.WriteMessage("Lengths differ: " + display + ", " + fs1.Length.ToString() + " vs. " + fs2.Length.ToString(), LogMessageType.Error); + Log.WriteErrorMessage(LOGTAG, "LengthsDiffer", null, "Lengths differ: {0}, {1} vs {2}", display, fs1.Length.ToString(), fs2.Length.ToString()); Console.WriteLine("Lengths differ: " + display + ", " + fs1.Length.ToString() + " vs. " + fs2.Length.ToString()); return false; } @@ -234,7 +239,7 @@ namespace Duplicati.UnitTest for(long l = 0; l < len; l++) if (fs1.ReadByte() != fs2.ReadByte()) { - Log.WriteMessage("Mismatch in byte " + l.ToString() + " in file " + display, LogMessageType.Error); + Log.WriteErrorMessage(LOGTAG, "MismatchInFile", null, "Mismatch in byte {0} in file {1}", l.ToString(), display); Console.WriteLine("Mismatch in byte " + l.ToString() + " in file " + display); return false; } @@ -245,13 +250,13 @@ namespace Duplicati.UnitTest { if (System.IO.File.GetLastWriteTime(f1) != System.IO.File.GetLastWriteTime(f2)) { - Log.WriteMessage("Mismatch in lastmodified for " + f2 + ", " + System.IO.File.GetLastWriteTimeUtc(f1) + " vs. " + System.IO.File.GetLastWriteTimeUtc(f2), LogMessageType.Warning); + Log.WriteWarningMessage(LOGTAG, "MismatchInLastModified", null, "Mismatch in lastmodified for {0}, {1} vs {2}", f2, System.IO.File.GetLastWriteTimeUtc(f1), System.IO.File.GetLastWriteTimeUtc(f2)); Console.WriteLine("Mismatch in lastmodified for " + f2 + ", " + System.IO.File.GetLastWriteTimeUtc(f1) + " vs. " + System.IO.File.GetLastWriteTimeUtc(f2)); } if (System.IO.File.GetCreationTimeUtc(f1) != System.IO.File.GetCreationTimeUtc(f2)) { - Log.WriteMessage("Mismatch in create-time for " + f2 + ", " + System.IO.File.GetCreationTimeUtc(f1) + " vs. " + System.IO.File.GetCreationTimeUtc(f2), LogMessageType.Warning); + Log.WriteWarningMessage(LOGTAG, "MismatchInCreateTime", null, "Mismatch in create-time for {0}, {1} vs {2}", f2, System.IO.File.GetCreationTimeUtc(f1), System.IO.File.GetCreationTimeUtc(f2)); Console.WriteLine("Mismatch in create-time for " + f2 + ", " + System.IO.File.GetCreationTimeUtc(f1) + " vs. " + System.IO.File.GetCreationTimeUtc(f2)); } } diff --git a/Installer/Docker/build-images.sh b/Installer/Docker/build-images.sh index 33500ee77..1aace28dc 100755 --- a/Installer/Docker/build-images.sh +++ b/Installer/Docker/build-images.sh @@ -69,3 +69,5 @@ for arch in ${ARCHITECTURES}; do docker push ${REPOSITORY}:${tag} done done + +rm -rf "${DIRNAME}" diff --git a/Installer/OSX/make-dmg.sh b/Installer/OSX/make-dmg.sh index 49f18fa9c..0ac4e23ef 100644 --- a/Installer/OSX/make-dmg.sh +++ b/Installer/OSX/make-dmg.sh @@ -16,7 +16,7 @@ CODESIGN_IDENTITY=2S6R28R577 SHOW_USAGE_ERROR= -TEMPLATE_DMG_BZ2=`echo "$TEMPLATE_DMG.bz2"` +TEMPLATE_DMG_BZ2=$(echo "$TEMPLATE_DMG.bz2") DELETE_DMG=0 if [ -f "$TEMPLATE_DMG_BZ2" ]; then @@ -38,7 +38,7 @@ if [ ! -f "$1" ]; then exit fi -VERSION_NUMBER=`echo "$1" | awk -F- '{print $2}' | awk -F_ '{print $1}'` +VERSION_NUMBER=$(echo "$1" | awk -F- '{print $2}' | awk -F_ '{print $1}') VERSION_NAME="Duplicati" if [ -e "${OUTPUT_DMG}" ]; then @@ -64,8 +64,8 @@ mkdir "Duplicati.app/Contents/Resources" unzip -q "$1" -d "Duplicati.app/Contents/Resources" # Install the Info.plist and icon -SHORT_VERSION_NUMBER=`echo ${VERSION_NUMBER} | awk -F. '{printf $1; printf "."; printf $2; printf "."; print $3}'` -PLIST=`cat "Info.plist"` +SHORT_VERSION_NUMBER=$(echo ${VERSION_NUMBER} | awk -F. '{printf $1; printf "."; printf $2; printf "."; print $3}') +PLIST=$(cat "Info.plist") PLIST=${PLIST/!LONG_VERSION!/${VERSION_NUMBER}} PLIST=${PLIST/!SHORT_VERSION!/${SHORT_VERSION_NUMBER}} echo ${PLIST} > "Duplicati.app/Contents/Info.plist" @@ -121,7 +121,7 @@ if [ "x${CODESIGN_IDENTITY}" != "x" ]; then echo "Codesigning application bundle" #Do a poke to get sudo prompt up before the long-running sign-process - UNUSED=`sudo ls` + UNUSED=$(sudo ls) # Codesign all resources in bundle (i.e. the actual code) # Not required, but nice-to-have diff --git a/Installer/OSX/run-with-mono.sh b/Installer/OSX/run-with-mono.sh index ae4890d0b..a954b4123 100644 --- a/Installer/OSX/run-with-mono.sh +++ b/Installer/OSX/run-with-mono.sh @@ -30,7 +30,7 @@ DOWNLOAD_URL="http://www.mono-project.com/download/stable/#download-mac" # Try to find system default Mono if an override was not supplied if [ "z${MONO_BIN}" == "z" ]; then - MONO_BIN=`which mono` + MONO_BIN=$(which mono) # If the result is broken, don't use it if [ ! -f "${MONO_BIN}" ]; then diff --git a/Installer/Synology/make-binary-package.sh b/Installer/Synology/make-binary-package.sh index 33b612631..9bad51722 100644 --- a/Installer/Synology/make-binary-package.sh +++ b/Installer/Synology/make-binary-package.sh @@ -5,10 +5,10 @@ if [ ! -f "$1" ]; then exit fi -FILENAME=`basename $1` -DIRNAME=`echo "${FILENAME}" | cut -d "_" -f 1` -VERSION=`echo "${DIRNAME}" | cut -d "-" -f 2` -DATE_STAMP=`LANG=C date -R` +FILENAME=$(basename $1) +DIRNAME=$(echo "${FILENAME}" | cut -d "_" -f 1) +VERSION=$(echo "${DIRNAME}" | cut -d "-" -f 2) +DATE_STAMP=$(LANG=C date -R) BASE_FILE_NAME="${FILENAME%.*}" TMPDIRNAME="${BASE_FILE_NAME}-extract" MONO=/Library/Frameworks/Mono.framework/Commands/mono @@ -85,7 +85,7 @@ rm -rf ./licenses/gpg cp -R ../web-extra/* webroot/ cp ../dsm.duplicati.conf . -DIRSIZE_KB=`BLOCKSIZE=1024 du -s | cut -d '.' -f 1` +DIRSIZE_KB=$(BLOCKSIZE=1024 du -s | cut -d '.' -f 1) let "DIRSIZE=DIRSIZE_KB*1024" tar cf ../package.tgz ./* @@ -98,7 +98,7 @@ ICON_256=$(openssl base64 -A -in PACKAGE_ICON_256.PNG) git checkout INFO echo "version=\"${VERSION}\"" >> "INFO" -MD5=`md5 "package.tgz" | awk -F ' ' '{print $NF}'` +MD5=$(md5 "package.tgz" | awk -F ' ' '{print $NF}') echo "checksum=\"${MD5}\"" >> "INFO" echo "extractsize=\"${DIRSIZE_KB}\"" >> "INFO" echo "package_icon=\"${ICON_72}\"" >> "INFO" @@ -118,13 +118,13 @@ if [ -f "${GPG_KEYFILE}" ]; then echo fi - GPGDATA=`"${MONO}" "../../BuildTools/AutoUpdateBuilder/bin/Debug/SharpAESCrypt.exe" d "${KEYFILE_PASSWORD}" "${GPG_KEYFILE}"` + GPGDATA=$("${MONO}" "../../BuildTools/AutoUpdateBuilder/bin/Debug/SharpAESCrypt.exe" d "${KEYFILE_PASSWORD}" "${GPG_KEYFILE}") if [ ! $? -eq 0 ]; then echo "Decrypting GPG keyfile failed" exit 1 fi - GPGID=`echo "${GPGDATA}" | head -n 1` - GPGKEY=`echo "${GPGDATA}" | head -n 2 | tail -n 1` + GPGID=$(echo "${GPGDATA}" | head -n 1) + GPGKEY=$(echo "${GPGDATA}" | head -n 2 | tail -n 1) else echo "No GPG keyfile found, skipping gpg signing" fi @@ -142,7 +142,7 @@ if [ "z${GPGID}" != "z" ]; then rm "${BASE_FILE_NAME}.signature" rm "${BASE_FILE_NAME}.spk" - tar cf "${BASE_FILE_NAME}.spk" -C "${TMPDIRNAME}" `ls -1 ${TMPDIRNAME}` + tar cf "${BASE_FILE_NAME}.spk" -C "${TMPDIRNAME}" $(ls -1 ${TMPDIRNAME}) rm -rf "${TMPDIRNAME}" fi diff --git a/Installer/debian/build-package.sh b/Installer/debian/build-package.sh index 3a0fbfa41..f0ab0d3c3 100755 --- a/Installer/debian/build-package.sh +++ b/Installer/debian/build-package.sh @@ -1,10 +1,10 @@ #!/bin/bash -DATE=`date +%Y%m%d` -VERSION=`git describe --tags | cut -d '-' -f 1 | cut -d 'v' -f 2` -GITTAG=`git rev-parse --short HEAD` -RELEASETYPE=`git describe --tags | cut -d '_' -f 2` -BUILDTAG=`git describe --tags | cut -d '-' -f 2-4` +DATE=$(date +%Y%m%d) +VERSION=$(git describe --tags | cut -d '-' -f 1 | cut -d 'v' -f 2) +GITTAG=$(git rev-parse --short HEAD) +RELEASETYPE=$(git describe --tags | cut -d '_' -f 2) +BUILDTAG=$(git describe --tags | cut -d '-' -f 2-4) DIRNAME="duplicati-$VERSION" diff --git a/Installer/debian/docker-build-binary.sh b/Installer/debian/docker-build-binary.sh index 24a5b5c8e..8da81e7d9 100644 --- a/Installer/debian/docker-build-binary.sh +++ b/Installer/debian/docker-build-binary.sh @@ -5,10 +5,10 @@ if [ ! -f "$1" ]; then exit fi -FILENAME=`basename $1` -DIRNAME=`echo "${FILENAME}" | cut -d "_" -f 1` -VERSION=`echo "${DIRNAME}" | cut -d "-" -f 2` -DATE_STAMP=`LANG=C date -R` +FILENAME=$(basename $1) +DIRNAME=$(echo "${FILENAME}" | cut -d "_" -f 1) +VERSION=$(echo "${DIRNAME}" | cut -d "-" -f 2) +DATE_STAMP=$(LANG=C date -R) if [ -d "${DIRNAME}" ]; then rm -rf "${DIRNAME}" diff --git a/Installer/debian/docker-build-package.sh b/Installer/debian/docker-build-package.sh index 9c7312fef..b1d2957bc 100755 --- a/Installer/debian/docker-build-package.sh +++ b/Installer/debian/docker-build-package.sh @@ -1,13 +1,13 @@ #!/bin/bash -DATE=`date +%Y%m%d` -VERSION=`git describe --tags | cut -d '-' -f 1 | cut -d 'v' -f 2` -GITTAG=`git rev-parse --short HEAD` -RELEASETYPE=`git describe --tags | cut -d '_' -f 2` -BUILDTAG=`git describe --tags | cut -d '-' -f 2-4` +DATE=$(date +%Y%m%d) +VERSION=$(git describe --tags | cut -d '-' -f 1 | cut -d 'v' -f 2) +GITTAG=$(git rev-parse --short HEAD) +RELEASETYPE=$(git describe --tags | cut -d '_' -f 2) +BUILDTAG=$(git describe --tags | cut -d '-' -f 2-4) DIRNAME="duplicati-$VERSION" -CWD=`pwd` +CWD=$(pwd) git pull bash duplicati-make-git-snapshot.sh "${GITTAG}" "${DATE}" "${VERSION}" "${RELEASETYPE}" "${BUILDTAG}-${GITTAG}" diff --git a/Installer/debian/duplicati-make-git-snapshot.sh b/Installer/debian/duplicati-make-git-snapshot.sh index 2b3cfe20d..b7586f058 100755 --- a/Installer/debian/duplicati-make-git-snapshot.sh +++ b/Installer/debian/duplicati-make-git-snapshot.sh @@ -6,32 +6,32 @@ # Point env var REF to a local duplicati repo to reduce clone time. if [ -z $2 ]; then - DATE=`date +%Y%m%d` + DATE=$(date +%Y%m%d) else DATE=$2 fi if [ -z $3 ]; then - VERSION=`git describe --tags | cut -d '-' -f 1 | cut -d 'v' -f 2` + VERSION=$(git describe --tags | cut -d '-' -f 1 | cut -d 'v' -f 2) else VERSION=$3 fi if [ -z $4 ]; then - RELEASETYPE=`git describe --tags | cut -d '_' -f 2` + RELEASETYPE=$(git describe --tags | cut -d '_' -f 2) else RELEASETYPE=$4 fi if [ -z $5 ]; then - BUILDTAG=`git describe --tags | cut -d '-' -f 2-4` + BUILDTAG=$(git describe --tags | cut -d '-' -f 2-4) else BUILDTAG=$5 fi DIRNAME="duplicati-$VERSION" -DATE_STAMP=`LANG=C date -R` +DATE_STAMP=$(LANG=C date -R) UPDATE_URLS="http://updates.duplicati.com/${RELEASETYPE}/latest.manifest;http://alt.updates.duplicati.com/${RELEASETYPE}/latest.manifest" echo REF ${REF:+--reference $REF} diff --git a/Installer/debian/make-binary-package.sh b/Installer/debian/make-binary-package.sh index b88c349ed..98b31a4b1 100644 --- a/Installer/debian/make-binary-package.sh +++ b/Installer/debian/make-binary-package.sh @@ -5,10 +5,10 @@ if [ ! -f "$1" ]; then exit fi -FILENAME=`basename $1` -DIRNAME=`echo "${FILENAME}" | cut -d "_" -f 1` -VERSION=`echo "${DIRNAME}" | cut -d "-" -f 2` -DATE_STAMP=`LANG=C date -R` +FILENAME=$(basename $1) +DIRNAME=$(echo "${FILENAME}" | cut -d "_" -f 1) +VERSION=$(echo "${DIRNAME}" | cut -d "-" -f 2) +DATE_STAMP=$(LANG=C date -R) if [ -d "${DIRNAME}" ]; then rm -rf "${DIRNAME}" diff --git a/Installer/fedora/build-package.sh b/Installer/fedora/build-package.sh index 1c7162c35..4b4621df4 100644 --- a/Installer/fedora/build-package.sh +++ b/Installer/fedora/build-package.sh @@ -2,11 +2,11 @@ git pull -DATE=`date +%Y%m%d` -VERSION=`git describe --tags | cut -d '-' -f 1 | cut -d 'v' -f 2` -GITTAG=`git rev-parse --short HEAD` -RELEASETYPE=`git describe --tags | cut -d '_' -f 2` -BUILDTAG=`git describe --tags | cut -d '-' -f 2-4` +DATE=$(date +%Y%m%d) +VERSION=$(git describe --tags | cut -d '-' -f 1 | cut -d 'v' -f 2) +GITTAG=$(git rev-parse --short HEAD) +RELEASETYPE=$(git describe --tags | cut -d '_' -f 2) +BUILDTAG=$(git describe --tags | cut -d '-' -f 2-4) bash duplicati-make-git-snapshot.sh "${GITTAG}" "${DATE}" "${VERSION}" "${RELEASETYPE}" "${BUILDTAG}-${GITTAG}" diff --git a/Installer/fedora/docker-build-binary.sh b/Installer/fedora/docker-build-binary.sh index 87401fba4..a35cc2c49 100644 --- a/Installer/fedora/docker-build-binary.sh +++ b/Installer/fedora/docker-build-binary.sh @@ -5,13 +5,13 @@ if [ ! -f "$1" ]; then exit fi -FILENAME=`basename $1` -DIRNAME=`echo "${FILENAME}" | cut -d "_" -f 1` -VERSION=`echo "${DIRNAME}" | cut -d "-" -f 2` -BUILDDATE=`date +%Y%m%d` -BUILDTAG_RAW=`echo "${FILENAME}" | cut -d "." -f 1-4 | cut -d "-" -f 2-4` +FILENAME=$(basename $1) +DIRNAME=$(echo "${FILENAME}" | cut -d "_" -f 1) +VERSION=$(echo "${DIRNAME}" | cut -d "-" -f 2) +BUILDDATE=$(date +%Y%m%d) +BUILDTAG_RAW=$(echo "${FILENAME}" | cut -d "." -f 1-4 | cut -d "-" -f 2-4) BUILDTAG="${BUILDTAG_RAW//-}" -CWD=`pwd` +CWD=$(pwd) echo "BUILDTAG: ${BUILDTAG}" echo "Version: ${VERSION}" diff --git a/Installer/fedora/docker-build-package.sh b/Installer/fedora/docker-build-package.sh index 4c032cc7c..a2cb69f24 100644 --- a/Installer/fedora/docker-build-package.sh +++ b/Installer/fedora/docker-build-package.sh @@ -2,12 +2,12 @@ git pull -DATE=`date +%Y%m%d` -VERSION=`git describe --tags | cut -d '-' -f 1 | cut -d 'v' -f 2` -GITTAG=`git rev-parse --short HEAD` -RELEASETYPE=`git describe --tags | cut -d '_' -f 2` -BUILDTAG=`git describe --tags | cut -d '-' -f 2-4` -CWD=`pwd` +DATE=$(date +%Y%m%d) +VERSION=$(git describe --tags | cut -d '-' -f 1 | cut -d 'v' -f 2) +GITTAG=$(git rev-parse --short HEAD) +RELEASETYPE=$(git describe --tags | cut -d '_' -f 2) +BUILDTAG=$(git describe --tags | cut -d '-' -f 2-4) +CWD=$(pwd) bash duplicati-make-git-snapshot.sh "${GITTAG}" "${DATE}" "${VERSION}" "${RELEASETYPE}" "${BUILDTAG}-${GITTAG}" diff --git a/Installer/fedora/duplicati-make-git-snapshot.sh b/Installer/fedora/duplicati-make-git-snapshot.sh index 5d09356e8..75e0a360d 100644 --- a/Installer/fedora/duplicati-make-git-snapshot.sh +++ b/Installer/fedora/duplicati-make-git-snapshot.sh @@ -6,25 +6,25 @@ # Point env var REF to a local duplicati repo to reduce clone time. if [ -z $2 ]; then - DATE=`date +%Y%m%d` + DATE=$(date +%Y%m%d) else DATE=$2 fi if [ -z $3 ]; then - VERSION=`git describe --tags | cut -d '-' -f 1 | cut -d 'v' -f 2` + VERSION=$(git describe --tags | cut -d '-' -f 1 | cut -d 'v' -f 2) else VERSION=$3 fi if [ -z $4 ]; then - RELEASETYPE=`git describe --tags | cut -d '_' -f 2` + RELEASETYPE=$(git describe --tags | cut -d '_' -f 2) else RELEASETYPE=$4 fi if [ -z $5 ]; then - BUILDTAG=`git describe --tags | cut -d '-' -f 2-4` + BUILDTAG=$(git describe --tags | cut -d '-' -f 2-4) else BUILDTAG=$5 fi @@ -42,7 +42,7 @@ echo BUILDTAG ${BUILDTAG} rm -rf $DIRNAME git clone ${REF:+--reference $REF} \ - `git config --get remote.origin.url` $DIRNAME + $(git config --get remote.origin.url) $DIRNAME cd "$DIRNAME" git checkout -b fedora-build ${1:-HEAD} diff --git a/Installer/fedora/make-binary-package.sh b/Installer/fedora/make-binary-package.sh index 5fe766421..4446f5604 100644 --- a/Installer/fedora/make-binary-package.sh +++ b/Installer/fedora/make-binary-package.sh @@ -5,11 +5,11 @@ if [ ! -f "$1" ]; then exit fi -FILENAME=`basename $1` -DIRNAME=`echo "${FILENAME}" | cut -d "_" -f 1` -VERSION=`echo "${DIRNAME}" | cut -d "-" -f 2` -BUILDDATE=`date +%Y%m%d` -BUILDTAG_RAW=`echo "${FILENAME}" | cut -d "." -f 1-4 | cut -d "-" -f 2-4` +FILENAME=$(basename $1) +DIRNAME=$(echo "${FILENAME}" | cut -d "_" -f 1) +VERSION=$(echo "${DIRNAME}" | cut -d "-" -f 2) +BUILDDATE=$(date +%Y%m%d) +BUILDTAG_RAW=$(echo "${FILENAME}" | cut -d "." -f 1-4 | cut -d "-" -f 2-4) BUILDTAG="${BUILDTAG_RAW//-}" echo "BUILDTAG: ${BUILDTAG}" diff --git a/Localizations/duplicati/localization-cs.mo b/Localizations/duplicati/localization-cs.mo index dc1b547a4..dfe561264 100644 Binary files a/Localizations/duplicati/localization-cs.mo and b/Localizations/duplicati/localization-cs.mo differ diff --git a/Localizations/duplicati/localization-cs.po b/Localizations/duplicati/localization-cs.po index e853cdbb6..14d4ee035 100644 --- a/Localizations/duplicati/localization-cs.po +++ b/Localizations/duplicati/localization-cs.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-01-18 11:11+0100\n" +"POT-Creation-Date: 2018-02-12 07:39+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Lukáš Tyrychtr , 2017\n" "Language-Team: Czech (https://www.transifex.com/duplicati/teams/67655/cs/)\n" @@ -48,15 +48,60 @@ msgstr "" msgid "--{0}: {1}" msgstr "--{0}: {1}" -#: Server/Strings.cs:15 +#: Server/Strings.cs:15 CommandLine/Strings.cs:21 +#, csharp-format +msgid "" +"This option can be used to store some or all of the options given to the " +"commandline client. The file must be a plain text file, UTF-8 encoding is " +"preferred. Each line in the file should be of the format --option=value. The" +" special options --{0} and --{1} can be used to override the localpath and " +"the remote destination uri, respectively. The options in this file take " +"precedence over the options provided on the commandline. You cannot specify " +"filters in both the file and on the commandline. Instead, you can use the " +"special --{2}, --{3}, or --{4} options to specify filters inside the " +"parameter file. Each filter must be prefixed with either a + or a -, and " +"multiple filters must be joined with {5} " +msgstr "" +"Tuto volbu je možné použít pro ukládání některých nebo všech voleb zadaných " +"klientovi pro příkazový řádek. Je třeba, aby soubor byl čistě textový, " +"nejlépe se znakovou sadou UTF-8. Každý řádek souboru by měl mít podobu " +"--volba=hodnota. Pro přepsání místního popisu umístění a uri adresy " +"vzdáleného cíle je možné použít speciální volby --{0} a --{1}. Volby v tomto" +" souboru mají přednost před volbami zadanými na příkazovém řádku. U filtrů " +"není možné, aby byly zadaná jak v souboru, tak na příkazovém řádku zároveň. " +"Namísto toho je možné pro zadání filtrů uvnitř souboru s parametry použít " +"zvláštní volby --{2}, --{3}, nebo --{4}. Je třeba, aby každý z filtrů byl " +"předeslán buď + nebo - a vícero filtrů bylo spojeno pomocí {5}" + +#: Server/Strings.cs:16 CommandLine/Strings.cs:22 +msgid "Path to a file with parameters" +msgstr "Popis umístění souboru s parametry" + +#: Server/Strings.cs:17 CommandLine/Strings.cs:19 +#, csharp-format +msgid "" +"Filters cannot be specified on the commandline if filters are also present " +"in the parameter file. Use the special --{0}, --{1}, or --{2} options to " +"specify filters inside the parameter file. Each filter must be prefixed with" +" either a + or a -, and multiple filters must be joined with {3}" +msgstr "" +"Pokud se filtry nacházejí už v souboru s parametry, není možné je zadávat zároveň i na příkazovém řádku. Pro zadání filtrů uvnitř souboru s parametry použijte zvláštní volby --{0}, --{1}, nebo --{2}.\n" +"Každý filtr je třeba předeslat buď + nebo - a vícero filtrů je třeba spojit pomocí {3}" + +#: Server/Strings.cs:18 CommandLine/Strings.cs:18 +#, csharp-format +msgid "Unable to read the parameters file \"{0}\", reason: {1}" +msgstr "Nedaří se číst soubor s parametry „{0}“, důvod: {1}" + +#: Server/Strings.cs:20 msgid "Outputs log information to the file given" msgstr "Zapíše záznam událostí do zadaného souboru" -#: Server/Strings.cs:16 +#: Server/Strings.cs:21 msgid "Determines the amount of information written in the log file" msgstr "Určuje množství informací zapsaných do souboru se záznamem udáslotí" -#: Server/Strings.cs:17 +#: Server/Strings.cs:22 msgid "" "Activates portable mode where the database is placed below the program " "executable" @@ -64,29 +109,29 @@ msgstr "" "Aktivuje přenosný režim, v němž je databáze umístěna vedle spustitelného " "souboru" -#: Server/Strings.cs:18 +#: Server/Strings.cs:23 #, csharp-format msgid "A serious error occurred in Duplicati: {0}" msgstr "V Duplicati došlo k závažné chybě: {0}" -#: Server/Strings.cs:19 +#: Server/Strings.cs:24 #, csharp-format msgid "" "Unable to start up, perhaps another process is already running?\n" "Error message: {0}" msgstr "Spuštění se nepodařilo, možná běží jiný proces?" -#: Server/Strings.cs:21 +#: Server/Strings.cs:26 msgid "Disables database encryption" msgstr "Vypíná šifrování databáze" -#: Server/Strings.cs:22 +#: Server/Strings.cs:27 #, csharp-format msgid "Unsupported version of SQLite detected ({0}), must be {1} or higher" msgstr "" "Zjištěna nepodporovaná verze SQLite ({0}), je třeba, aby byla {1} a vyšší" -#: Server/Strings.cs:23 +#: Server/Strings.cs:28 msgid "" "The path to the folder where the static files for the webserver is present. " "The folder must be located beneath the installation folder" @@ -94,7 +139,7 @@ msgstr "" "Popis umístění složky ve které se nacházejí neměnné soubory pro webový " "server. Je třeba, aby se složka nacházela pod instalační složkou" -#: Server/Strings.cs:24 +#: Server/Strings.cs:29 msgid "" "The port the webserver listens on. Multiple values may be supplied with a " "comma in between." @@ -102,7 +147,7 @@ msgstr "" "Port na kterém webový server bude očekávat spojení. Je možné zadat vícero " "hodnot oddělovaných čárkou." -#: Server/Strings.cs:25 +#: Server/Strings.cs:30 msgid "" "The certificate and key file in PKCS #12 format the webserver use for SSL. " "Only RSA/DSA keys are supported." @@ -110,11 +155,11 @@ msgstr "" "Certifikát a klíč ve formátu PKCS #12 které webový server použije pro SSL. " "Jsou podporovány pouze klíče RSA/DSA." -#: Server/Strings.cs:26 +#: Server/Strings.cs:31 msgid "The password for decryption of certificate PKCS #12 file." msgstr "Heslo k dešifrování PKCS12 souboru s certifikátem." -#: Server/Strings.cs:27 +#: Server/Strings.cs:32 msgid "" "The interface the webserver listens on. The special values \"*\" and \"any\"" " means any interface. The special value \"loopback\" means the loopback " @@ -124,7 +169,7 @@ msgstr "" "„any“ (libovolné) znamená libovolné rozhraní. Speciální hodnota „loopback“ " "znamená zpětnou smyčku (loopback)." -#: Server/Strings.cs:28 +#: Server/Strings.cs:33 msgid "" "The password required to access the webserver. This option is saved so you " "do not need to set it on each run. Setting an empty value disables the " @@ -134,11 +179,11 @@ msgstr "" "takže ji nebude třeba zadávat při každém spuštění. Pokud není zadáno, je " "heslo vypnut." -#: Server/Strings.cs:29 +#: Server/Strings.cs:34 msgid "Enables the ping-pong responder" msgstr "Zapne odpovídání na ping" -#: Server/Strings.cs:30 +#: Server/Strings.cs:35 msgid "" "When running as a server, the service daemon must verify that the process is" " responding. If this option is enabled, the server reads stdin and writes a " @@ -148,19 +193,19 @@ msgstr "" "odpovídá. Pokud je tato volba zapnutá, server čte standardní vstup a " "zapisuje odpověď na každé načtení řádku" -#: Server/Strings.cs:31 Library/Main/Strings.cs:218 +#: Server/Strings.cs:36 Library/Main/Strings.cs:220 msgid "Clean up old log data" msgstr "Odstranit staré záznamy událostí" -#: Server/Strings.cs:32 Library/Main/Strings.cs:219 +#: Server/Strings.cs:37 Library/Main/Strings.cs:221 msgid "Set the time after which log data will be purged from the database." msgstr "Nastavte čas, po kterém budou data protokolu smazána z databáze." -#: Server/Strings.cs:33 +#: Server/Strings.cs:38 msgid "Sets the folder where settings are stored" msgstr "Nastavuje složku ve které jsou ukládána nastavení" -#: Server/Strings.cs:34 +#: Server/Strings.cs:39 #, csharp-format msgid "" "Duplicati needs to store a small database with all settings. Use this option" @@ -171,11 +216,11 @@ msgstr "" "této předvolby zvolíte kam jsou nastavení ukládána. Tuto předvolbu je možné " "také nastavit pomocí proměnné prostředí {0}." -#: Server/Strings.cs:35 +#: Server/Strings.cs:40 msgid "Sets the database encryption key" msgstr "Nastavuje klíč pro šifrování databáze" -#: Server/Strings.cs:36 +#: Server/Strings.cs:41 #, csharp-format msgid "" "This option sets the encryption key used to scramble the local settings " @@ -186,7 +231,7 @@ msgstr "" "nastaveními. Tuto volbu je možné nastavit také pomocí proměnné prostředí " "{0}. Pomocí volby --{1} je možné pomíchání databáze vypnout." -#: Server/Strings.cs:39 +#: Server/Strings.cs:44 #, csharp-format msgid "" "Unable to find a valid date, given the start date {0}, the repetition " @@ -195,12 +240,12 @@ msgstr "" "Nedaří se nalézt platné datum pro dané počáteční datum {0}, interval " "opakování {1} a dny, kdy je umožněno {2}" -#: Server/Strings.cs:44 +#: Server/Strings.cs:49 #, csharp-format msgid "Server has started and is listening on {0}, port {1}" msgstr "Server je spuštěn a očekává spojení na {0}, portu {1}" -#: Server/Strings.cs:45 +#: Server/Strings.cs:50 #, csharp-format msgid "" "Unable to create SSL certificate using provided parameters. Exception " @@ -209,7 +254,7 @@ msgstr "" "S poskytnutými parametry není možné vytvořit SSL certifikát. Podrobnosti " "výjimky: {0}" -#: Server/Strings.cs:46 +#: Server/Strings.cs:51 #, csharp-format msgid "Unable to open a socket for listening, tried ports: {0}" msgstr "Nedaří se otevřít soket pro očekávání spojení, vyzkoušené porty: {0}" @@ -962,6 +1007,18 @@ msgstr "" msgid "Google Drive" msgstr "Google Drive" +#: Library/Backend/GoogleServices/Strings.cs:48 +msgid "Hide team drives" +msgstr "Skrýt týmové jednotky" + +#: Library/Backend/GoogleServices/Strings.cs:49 +msgid "" +"This option disables the team drives, showing only files and folders " +"accesible with the account itself" +msgstr "" +"Tato volba skryje týmové jednotky, zobrazeny budou pouze soubory a složky " +"přístupné účtu samotnému" + #: Library/Backend/CloudFiles/Strings.cs:4 #, csharp-format msgid "" @@ -1510,6 +1567,66 @@ msgstr "" "doby natrvalo vymazán. Tímto příkazem je možné vynutit přímo trvalé " "vymazání." +#: Library/Backend/Rclone/Strings.cs:6 +msgid "Rclone" +msgstr "Rclone" + +#: Library/Backend/Rclone/Strings.cs:7 +msgid "This backend can read and write data to Rclone." +msgstr "Tato podpůrná vrstva (backend) umožňuje čtení a zápis dat na rclone." + +#: Library/Backend/Rclone/Strings.cs:8 +msgid "Local repository" +msgstr "Místní repozitář" + +#: Library/Backend/Rclone/Strings.cs:9 +msgid "" +"Local repository for Rclone. Make sure it is configured as a local drive, as" +" it needs access to the files generated by Duplicati." +msgstr "" +"Lokální repozitář pro Rclone. Ověřte že je nastavený na místní jednotku, " +"protože potřebuje přístup k souborům vytvořeným Duplicati." + +#: Library/Backend/Rclone/Strings.cs:10 +msgid "Remote repository" +msgstr "Vzdálený repozitář" + +#: Library/Backend/Rclone/Strings.cs:11 +msgid "" +"Remote repository for Rclone. This can be any of the backends provided by " +"Rclone. More info available on https://rclone.org/." +msgstr "" +"Vzdálený repozitář pro Rclone. Může to být libovolná z podpůrných vrstev " +"(backend) poskytovaná Rclone. Více informací je k dispozici na " +"https://rclone.org/." + +#: Library/Backend/Rclone/Strings.cs:12 +msgid "Remote path" +msgstr "Vzdálené umístění" + +#: Library/Backend/Rclone/Strings.cs:13 +msgid "Path on the Remote repository. " +msgstr "Umístění vzdáleného repozitáře." + +#: Library/Backend/Rclone/Strings.cs:14 +msgid "Rclone options." +msgstr "Předvolby pro Rclone." + +#: Library/Backend/Rclone/Strings.cs:15 +msgid "Options will be transferred to rclone." +msgstr "Předvolby budou předány rclone" + +#: Library/Backend/Rclone/Strings.cs:16 +msgid "Rclone executable" +msgstr "Spustitelný soubor rclone" + +#: Library/Backend/Rclone/Strings.cs:17 +msgid "" +"Full path to the rclone executable. Only needed if it's not in your path." +msgstr "" +"Úplný popis umístění pro spustitelný soubor s rclone. Je třeba pouze pokud " +"se nenachází v proměnné PATH vašeho prostředí." + #: Library/Backend/File/Strings.cs:4 #, csharp-format msgid "" @@ -2340,31 +2457,6 @@ msgid "" "Database is NOT upgraded." msgstr "Nepodařilo se provést SQL: {0}" -#: Library/Main/Database/ExtensionMethods.cs:48 -#, csharp-format -msgid "ExecuteNonQuery: {0}" -msgstr "ExecuteNonQuery: {0}" - -#: Library/Main/Database/ExtensionMethods.cs:64 -#, csharp-format -msgid "ExecuteScalar: {0}" -msgstr "ExecuteScalar: {0}" - -#: Library/Main/Database/ExtensionMethods.cs:90 -#, csharp-format -msgid "ExecuteScalarInt64: {0}" -msgstr "ExecuteScalarInt64: {0}" - -#: Library/Main/Database/ExtensionMethods.cs:110 -#, csharp-format -msgid "ExecuteReader: {0}" -msgstr "ExecuteReader: {0}" - -#: Library/Main/Database/ExtensionMethods.cs:200 -#, csharp-format -msgid "{0} records" -msgstr "{0} záznamů" - #: Library/Main/Strings.cs:8 #, csharp-format msgid "Hash mismatch on file \"{0}\", recorded hash: {1}, actual hash {2}" @@ -3141,6 +3233,24 @@ msgid "A reported maximum storage" msgstr "Nahlášená kapacita úložiště" #: Library/Main/Strings.cs:122 +msgid "" +"Sets a threshold for when to warn about the backend quota being nearly " +"exceeded. It is given as a percentage, and a warning is generated if the " +"amount of available quota is less that this percentage of the total backup " +"size. If the backend does not report the quota information, this value will " +"be ignored" +msgstr "" +"Nastavuje práh po jehož dosažení varovat o blížícím se překročení kvóty na " +"podpůrné vrstvě (backend). Zadává se jako procento a varování je vytvořeno " +"pokud množství zbývající kvóty je nižší než toto procento celkové velikosti " +"zálohy. Pokud podpůrná vrstva (backend) nehlásí informace o kvótě, tato " +"hodnota bude ignorována" + +#: Library/Main/Strings.cs:123 +msgid "Threshold for warning about low quota" +msgstr "Práh varování před vyčerpáním kvóty" + +#: Library/Main/Strings.cs:124 #, csharp-format msgid "" "Exclude files that match the given filter sets. Which default filter sets " @@ -3153,15 +3263,15 @@ msgstr "" "tento parametr není nastaven, pak je použita sada pro stávající operační " "systém." -#: Library/Main/Strings.cs:123 +#: Library/Main/Strings.cs:125 msgid "Default filter sets" msgstr "Výchozí sady filtrů" -#: Library/Main/Strings.cs:124 +#: Library/Main/Strings.cs:126 msgid "Symlink handling" msgstr "Zacházení se symbolickými odkazy (symlink)" -#: Library/Main/Strings.cs:125 +#: Library/Main/Strings.cs:127 #, csharp-format msgid "" "Use this option to handle symlinks differently. The \"{0}\" option will " @@ -3178,11 +3288,11 @@ msgstr "" "používaly nastavení „{2}“, které způsobuje že soubory na které je odkazováno" " budou zahrnuty a obnoveny jako běžné soubory." -#: Library/Main/Strings.cs:126 +#: Library/Main/Strings.cs:128 msgid "Hardlink handling" msgstr "Zacházení se symbolickými odkazy (hardlink)" -#: Library/Main/Strings.cs:127 +#: Library/Main/Strings.cs:129 #, csharp-format msgid "" "Use this option to handle hardlinks (only works on Linux/OSX). The \"{0}\" " @@ -3198,11 +3308,11 @@ msgstr "" "se. Volba „{2}“ bude ignorovat všechny pevné odkazy s více než jedním " "odkazem." -#: Library/Main/Strings.cs:128 +#: Library/Main/Strings.cs:130 msgid "Exclude files by attribute" msgstr "Vynechávat soubory na základě atributů" -#: Library/Main/Strings.cs:129 +#: Library/Main/Strings.cs:131 #, csharp-format msgid "" "Use this option to exclude files with certain attributes. Use a comma " @@ -3213,7 +3323,7 @@ msgstr "" "zadání více než jednoho použijte čárkou oddělovaný seznam. Možné hodnoty " "jsou: {0}" -#: Library/Main/Strings.cs:130 +#: Library/Main/Strings.cs:132 msgid "" "Activate this option to map VSS snapshots to a drive (similar to SUBST, " "using Win32 DefineDosDevice). This will create temporary drives that are " @@ -3225,11 +3335,11 @@ msgstr "" "které slouží k přístupu k obsahu zachyceného stavu. Toto obejití problému " "může zrychlit přístup k souborů pod systémem Windows XP." -#: Library/Main/Strings.cs:131 +#: Library/Main/Strings.cs:133 msgid "Map snapshots to a drive (Windows only)" msgstr "Namapovat zachycené stavy jako disky (pouze Windows)" -#: Library/Main/Strings.cs:132 +#: Library/Main/Strings.cs:134 msgid "" "A display name that is attached to this backup. Can be used to identify the " "backup when sending mail or running scripts." @@ -3237,11 +3347,11 @@ msgstr "" "Zobrazovaný název který je připojen k této záloze. Je možné ho použít pro " "identifikaci zálohy při posílání e-mailu nebo spouštění skriptů." -#: Library/Main/Strings.cs:133 +#: Library/Main/Strings.cs:135 msgid "Name of the backup" msgstr "Název zálohy" -#: Library/Main/Strings.cs:134 +#: Library/Main/Strings.cs:136 #, csharp-format msgid "" "This property can be used to point to a text file where each line contains a" @@ -3259,12 +3369,12 @@ msgstr "" "mezera je považována za konec přípony. Je poskytován výchozí soubor, který " "slouží jako ukázka. Výchozí soubor se nachází v {0}." -#: Library/Main/Strings.cs:135 +#: Library/Main/Strings.cs:137 msgid "Manage non-compressible file extensions" msgstr "Spravovat přípony souborů, které nelze komprimovat" -#: Library/Main/Strings.cs:136 Library/Main/Strings.cs:146 -#: Library/Main/Strings.cs:155 +#: Library/Main/Strings.cs:138 Library/Main/Strings.cs:148 +#: Library/Main/Strings.cs:157 msgid "" "A fragment of memory is used to reduce database lookups. You should not " "change this value unless you get warnings in the log." @@ -3273,11 +3383,11 @@ msgstr "" "byste neměli měnit dokud vás k tomu nepřiměje varování v záznamu událostí " "(log)." -#: Library/Main/Strings.cs:137 +#: Library/Main/Strings.cs:139 msgid "Memory used by the block hash" msgstr "Paměť využívaná kontrolními součty bloků" -#: Library/Main/Strings.cs:138 +#: Library/Main/Strings.cs:140 msgid "" "The block size determines how files are fragmented. Choosing a large value " "will cause a larger overhead on file changes, choosing a small value will " @@ -3289,11 +3399,11 @@ msgstr "" "seznamů souborů. Mějte na paměti, že po vytvoření souboru na protějšku už s " "touto hodnotou nelze hýbat." -#: Library/Main/Strings.cs:139 +#: Library/Main/Strings.cs:141 msgid "Block size used in hashing" msgstr "Velikost bloků pro kontrolní součty" -#: Library/Main/Strings.cs:140 +#: Library/Main/Strings.cs:142 msgid "" "This option can be used to limit the scan to only files that are known to " "have changed. This is usually only activated in combination with a " @@ -3303,20 +3413,20 @@ msgstr "" "se ví, že byly změněny. Toto je obvykle zapínáno pouze v kombinaci se " "sledováním změn v souborovém systému které zaznamenává změny v souborech." -#: Library/Main/Strings.cs:141 +#: Library/Main/Strings.cs:143 msgid "List of files to examine for changes" msgstr "Seznam souborů u kterých zkoumat změny" -#: Library/Main/Strings.cs:142 +#: Library/Main/Strings.cs:144 msgid "" "Path to the file containing the local cache of the remote file database" msgstr "Cesta k souboru s místní mezipamětí vzdálené databáze souborů" -#: Library/Main/Strings.cs:143 +#: Library/Main/Strings.cs:145 msgid "Path to the local state database" msgstr "Umístění místní stavové databáze" -#: Library/Main/Strings.cs:144 +#: Library/Main/Strings.cs:146 #, csharp-format msgid "" "This option can be used to supply a list of deleted files. This option will " @@ -3325,15 +3435,15 @@ msgstr "" "Pomocí této předvolby je možné poskytnout seznam smazaných souborů. Je ovšem" " ignorována pokud není zadaná také předvolba --{0}." -#: Library/Main/Strings.cs:145 +#: Library/Main/Strings.cs:147 msgid "List of deleted files" msgstr "Seznam smazaných souborů" -#: Library/Main/Strings.cs:147 +#: Library/Main/Strings.cs:149 msgid "Memory used by the file hash" msgstr "Paměť využívaná kontrolními součty souborů" -#: Library/Main/Strings.cs:148 +#: Library/Main/Strings.cs:150 msgid "" "This option can be used to reduce the memory footprint by not keeping paths " "and modification timestamps in memory" @@ -3341,22 +3451,22 @@ msgstr "" "Tato předvolba může být použita pro snížení spotřeby kapacity operační " "paměti tím, že v ní nebudou uchovávány popisy umístění a časové značky úprav" -#: Library/Main/Strings.cs:149 +#: Library/Main/Strings.cs:151 msgid "Reduce memory footprint by disabling in-memory lookups" msgstr "Snížit využití paměti zakázáním vyhledávání v paměti" -#: Library/Main/Strings.cs:150 +#: Library/Main/Strings.cs:152 msgid "" "This option can be used to increase speed in exchange for extra memory use." msgstr "" "Pomocí této předvolby je možné zvýšit rychlost za cenu vyšší spotřeby " "operační paměti." -#: Library/Main/Strings.cs:151 +#: Library/Main/Strings.cs:153 msgid "Store an in-memory block cache" msgstr "Udržovat mezipaměť bloků v operační paměti" -#: Library/Main/Strings.cs:152 +#: Library/Main/Strings.cs:154 msgid "" "Stores metadata, such as file timestamps and attributes. This increases the " "required storage space as well as the processing time." @@ -3364,21 +3474,21 @@ msgstr "" "Uchovává metadata, jako například časové značky a atributy. To zvyšuje " "požadavky na úložný prostor a prodlužuje dobu potřebnou pro zpracování." -#: Library/Main/Strings.cs:153 +#: Library/Main/Strings.cs:155 msgid "Enables storing file metadata" msgstr "Ukládat metadata souborů" -#: Library/Main/Strings.cs:154 +#: Library/Main/Strings.cs:156 msgid "This option is no longer used as metadata is now stored by default" msgstr "" "Tato předvolba už není používána protože metadata jsou nyní ukládána už ve " "výchozím nastavení" -#: Library/Main/Strings.cs:156 +#: Library/Main/Strings.cs:158 msgid "Memory used by the metadata hash" msgstr "Paměť využitá tabulkou metadat" -#: Library/Main/Strings.cs:157 +#: Library/Main/Strings.cs:159 msgid "" "If this flag is set, the local database is not compared to the remote " "filelist on startup. The intended usage for this option is to work correctly" @@ -3389,11 +3499,11 @@ msgstr "" "předvolby je správné fungování v případech kdy je seznam souborů poškozený " "nebo není k dispozici." -#: Library/Main/Strings.cs:158 +#: Library/Main/Strings.cs:160 msgid "Do not query backend at startup" msgstr "Při spuštění se backendu nedotazovat" -#: Library/Main/Strings.cs:159 +#: Library/Main/Strings.cs:161 msgid "" "The index files are used to limit the need for downloading dblock files when" " there is no local database present. The more information is recorded in the" @@ -3407,11 +3517,11 @@ msgstr "" "databáze. Daní za to je že velké indexové soubory zabírají více místa na " "vzdáleném úložišti a přitom nemusí být nikdy použity." -#: Library/Main/Strings.cs:160 +#: Library/Main/Strings.cs:162 msgid "Determines usage of index files" msgstr "Určuje použití indexových souborů" -#: Library/Main/Strings.cs:161 +#: Library/Main/Strings.cs:163 msgid "" "As files are changed, some data stored at the remote destination may not be " "required. This option controls how much wasted space the destination can " @@ -3423,11 +3533,11 @@ msgstr "" "bude uvolněn. Tato hodnota je procento z každého ze svazků a celkového " "úložiště." -#: Library/Main/Strings.cs:162 +#: Library/Main/Strings.cs:164 msgid "The maximum wasted space in percent" msgstr "Maximum zbytečného místa v procentech" -#: Library/Main/Strings.cs:163 +#: Library/Main/Strings.cs:165 msgid "" "This option can be used to experiment with different settings and observe " "the outcome without changing actual files." @@ -3435,11 +3545,11 @@ msgstr "" "Pomocí této předvolby je možné experimentovat s různými nastaveními a " "sledovat výsledek aniž by byly měněny skutečné soubory." -#: Library/Main/Strings.cs:164 +#: Library/Main/Strings.cs:166 msgid "Does not perform any modifications" msgstr "Neprovádět žádné úpravy" -#: Library/Main/Strings.cs:165 +#: Library/Main/Strings.cs:167 msgid "" "This is a very advanced option! This option can be used to select a block " "hash algorithm with smaller or larger hash size, for performance or storage " @@ -3449,11 +3559,11 @@ msgstr "" "tvorbu otisků (hash) bloků podle délky výsledného otisku (z důvodů výkonu a " "místa)." -#: Library/Main/Strings.cs:166 +#: Library/Main/Strings.cs:168 msgid "The hash algorithm used on blocks" msgstr "Hashovací algoritmus použitý na bloky" -#: Library/Main/Strings.cs:167 +#: Library/Main/Strings.cs:169 msgid "" "This is a very advanced option! This option can be used to select a file " "hash algorithm with smaller or larger hash size, for performance or storage " @@ -3463,11 +3573,11 @@ msgstr "" "tvorbu otisků (hash) souborů podle délky výsledného otisku (z důvodů výkonu " "a místa)." -#: Library/Main/Strings.cs:168 +#: Library/Main/Strings.cs:170 msgid "The hash algorithm used on files" msgstr "Hashovací algoritmus použitý na soubory" -#: Library/Main/Strings.cs:169 +#: Library/Main/Strings.cs:171 msgid "" "If a large number of small files are detected during a backup, or wasted " "space is found after deleting backups, the remote data will be compacted. " @@ -3479,11 +3589,11 @@ msgstr "" " Pomocí této předvolby toto automatické zkompaktňování vypnete a bude se dít" " pouze ručním spouštěním příkazu compact." -#: Library/Main/Strings.cs:170 +#: Library/Main/Strings.cs:172 msgid "Disable automatic compacting" msgstr "Zakázat automatické zmenšení" -#: Library/Main/Strings.cs:171 +#: Library/Main/Strings.cs:173 msgid "" "When examining the size of a volume in consideration for compacting, a small" " tolerance value is used, by default 20 percent of the volume size. This " @@ -3495,11 +3605,11 @@ msgstr "" "zajistí, že velké svazky které mohou mít pár bajtů ztraceného prostoru " "nejsou stahovány a přepisovány." -#: Library/Main/Strings.cs:172 +#: Library/Main/Strings.cs:174 msgid "Volume size threshold" msgstr "Velikost svazku může být nejvýše" -#: Library/Main/Strings.cs:173 +#: Library/Main/Strings.cs:175 msgid "" "To avoid filling the remote storage with small files, this value can force " "grouping small files. The small volumes will always be combined when they " @@ -3509,11 +3619,11 @@ msgstr "" " vynutit seskupení malých souborů. Malé objemy budou vždy kombinovány když " "mohou zaplnit celý svazek." -#: Library/Main/Strings.cs:174 +#: Library/Main/Strings.cs:176 msgid "Maximum number of small volumes" msgstr "Malých svazků nejvýše" -#: Library/Main/Strings.cs:175 +#: Library/Main/Strings.cs:177 msgid "" "Enable this option to look into other files on this machine to find existing" " blocks. This is a fairly slow operation but can limit the size of " @@ -3523,15 +3633,15 @@ msgstr "" " a hledat existující bloky. To je dost pomalá operace ale může snížit objem " "stahovaných dat." -#: Library/Main/Strings.cs:176 +#: Library/Main/Strings.cs:178 msgid "Use local file data when restoring" msgstr "Při obnově použít místní údaje o souborech" -#: Library/Main/Strings.cs:177 +#: Library/Main/Strings.cs:179 msgid "Disables the local database" msgstr "Vypne místní databázi" -#: Library/Main/Strings.cs:178 +#: Library/Main/Strings.cs:180 msgid "" "When listing contents or when restoring files, the local database can be " "skipped. This is usually slower, but can be used to verify the actual " @@ -3541,11 +3651,11 @@ msgstr "" "přeskočit. Toto je obvykle pomalejší, ale může být použito k ověření " "skutečného obsahu vzdáleného úložiště" -#: Library/Main/Strings.cs:179 +#: Library/Main/Strings.cs:181 msgid "Keep a number of versions" msgstr "Uchovávat verzí nazpět" -#: Library/Main/Strings.cs:180 +#: Library/Main/Strings.cs:182 msgid "" "Use this option to set number of versions to keep, supply -1 to keep all " "versions" @@ -3553,52 +3663,52 @@ msgstr "" "Pomocí této předvolby nastavte počet verzí které ponechat, zadáním -1 budou " "ponechány všechny" -#: Library/Main/Strings.cs:181 +#: Library/Main/Strings.cs:183 msgid "Keep all versions within a timespan" msgstr "Zachovat všechny verze v časovém období" -#: Library/Main/Strings.cs:182 +#: Library/Main/Strings.cs:184 msgid "Use this option to set the timespan in which backups are kept." msgstr "" "Tuto volbu použijte k nastavení časového období, po které mají být " "uchovávány zálohy." -#: Library/Main/Strings.cs:183 +#: Library/Main/Strings.cs:185 msgid "Reduce number of versions by deleting old intermediate backups" msgstr "Snížit počet verzí smazáním starých mezidobých záloh" -#: Library/Main/Strings.cs:184 +#: Library/Main/Strings.cs:186 msgid "" "Use this option to reduce the number of versions that are kept with " "increasing version age by deleting most of the old backups. The expected " -"format is a comma seperated list of collon sperated time frame and interval " +"format is a comma separated list of colon separated time frame and interval " "pairs. For example the value \"7D:0s,3M:1D,10Y:2M\" means \"For 7 day keep " -"all backups, for 3 months keep one backup per day and for 10 years one " -"backup every 2nd month" +"all backups, for 3 months keep one backup every day, for 10 years one backup" +" every 2nd month and delete every backup older than this.\"" msgstr "" -"Pomocí této volby je možné snížit počet verzí které jsou uchovávány se " -"zvyšujícím se stářím verze smazáním těch nejstarších záloh. Očekávaný formát" -" je čárkou oddělovaný seznam dvojic časových oken (spojovaných dvojtečkou). " -"Například hodnota „7D:0s,3M:1D,10Y:2M“ znamená „Ponechat úplně všechny " -"zálohy z minulých sedmi dnů (týden), poté za minulé tři měsíce ponechat " -"jednu zálohu z každého dne a následně po dobu deseti let ponechat jednu " -"zálohu z každého druhého dne v měsíci“." +"Tuto volbu použijte pro snížení počtu verzí které jsou ponechávány při " +"zvyšováním stáří verze pomocí mazání nejstarších záloh. Očekávaný formát je " +"čárkou oddělovaný seznam dvojtečkou oddělovaných dvojic časový rámec a čas. " +"Například hodnota „7D:0s,3M:1D,10Y:2M“ znamená „Po 7 dnů ponechat všechny " +"zálohy, po 3 měsíce ponechat jednu zálohu z každého dne, po 10 let ponechat " +"jednu zálohu z každého druhého měsíce a smazat všechny zálohy starší než " +"tyto.“" -#: Library/Main/Strings.cs:185 +#: Library/Main/Strings.cs:187 msgid "Ignore missing source elements" msgstr "Ignorovat chybějící zdrojové prvky" -#: Library/Main/Strings.cs:186 +#: Library/Main/Strings.cs:188 msgid "Use this option to continue even if some source entries are missing." msgstr "" "Toto volbu použijte, pokud chcete pokračovat i v případě, že chybí některé " "zdrojové záznamy." -#: Library/Main/Strings.cs:187 +#: Library/Main/Strings.cs:189 msgid "Overwrite files when restoring" msgstr "Při obnovování přepsat soubory" -#: Library/Main/Strings.cs:188 +#: Library/Main/Strings.cs:190 msgid "" "Use this option to overwrite target files when restoring, if this option is " "not set the files will be restored with a timestamp and a number appended." @@ -3607,11 +3717,11 @@ msgstr "" "tato předvolba není nastavená, soubory budou obnoveny s názvy ke kterým je " "připojena časová značka a číslo." -#: Library/Main/Strings.cs:189 +#: Library/Main/Strings.cs:191 msgid "Output more progress information" msgstr "Vypisovat více informací o průběhu" -#: Library/Main/Strings.cs:190 +#: Library/Main/Strings.cs:192 msgid "" "Use this option to increase the amount of output generated when running an " "option. Generally this option will produce a line for each file processed." @@ -3619,11 +3729,11 @@ msgstr "" "Pomocí této předvolby zvyšte množství výstupu vytvářeného při spouštění " "volby. Obecně tato předvolba vytvoří řádek pro každý zpracovaný soubor." -#: Library/Main/Strings.cs:191 +#: Library/Main/Strings.cs:193 msgid "Output full results" msgstr "Vypsat plné výsledky" -#: Library/Main/Strings.cs:192 +#: Library/Main/Strings.cs:194 msgid "" "Use this option to increase the amount of output generated as the result of " "the operation, including all filenames." @@ -3631,11 +3741,11 @@ msgstr "" "Pomocí této předvolby je možné zvýšit množství výstupu vytvářeného jako " "výsledek operace, včetně všech názvů souborů." -#: Library/Main/Strings.cs:193 +#: Library/Main/Strings.cs:195 msgid "Determine if verification files are uploaded" msgstr "Určit, zda mají být nahrány ověřovací soubory" -#: Library/Main/Strings.cs:194 +#: Library/Main/Strings.cs:196 msgid "" "Use this option to upload a verification file after changing the remote " "storage. The file is not encrypted and contains the size and SHA256 hashes " @@ -3647,11 +3757,11 @@ msgstr "" "všech vzdálených souborů a může být použit pro ověření neporušenosti " "souborů." -#: Library/Main/Strings.cs:195 +#: Library/Main/Strings.cs:197 msgid "The number of samples to test after a backup" msgstr "Množství vzorků které otestovat po provedení zálohy" -#: Library/Main/Strings.cs:196 +#: Library/Main/Strings.cs:198 #, csharp-format msgid "" "After a backup is completed, some files are selected for verification on the" @@ -3663,11 +3773,11 @@ msgstr "" "hodnota nastavená na 0 (nula) nebo je nastavena předvolba --{0}, nejsou " "ověřený žádné vzdálené soubory" -#: Library/Main/Strings.cs:197 +#: Library/Main/Strings.cs:199 msgid "Activates in-depth verification of files" msgstr "Zapíná hloubkové ověřování souborů" -#: Library/Main/Strings.cs:198 +#: Library/Main/Strings.cs:200 #, csharp-format msgid "" "After a backup is completed, some files are selected for verification on the" @@ -3684,22 +3794,22 @@ msgstr "" " předvolba --{0}, nejsou ověřovány žádné vzdálené soubory. Tato předvolba je" " nastavena automaticky v případě přímého ověřování." -#: Library/Main/Strings.cs:199 +#: Library/Main/Strings.cs:201 msgid "Size of the file read buffer" msgstr "Velikost vyrovnávací paměti čtení" -#: Library/Main/Strings.cs:200 +#: Library/Main/Strings.cs:202 msgid "" "Use this size to control how many bytes a read from a file before processing" msgstr "" "Nastavením této velikosti je možné řídit kolik bajtů číst ze souboru před " "zpracováním" -#: Library/Main/Strings.cs:201 +#: Library/Main/Strings.cs:203 msgid "Allow the passphrase to change" msgstr "Umožnit změnu heslové fráze" -#: Library/Main/Strings.cs:202 +#: Library/Main/Strings.cs:204 msgid "" "Use this option to allow the passphrase to change, note that this option is " "not permitted for a backup or repair operation" @@ -3707,11 +3817,11 @@ msgstr "" "Pomocí této předvolby je možné umožnit změnu heslové fráze. Poznamenejme, že" " tato předvolba není přístupná při zálohovacích a opravných operacích" -#: Library/Main/Strings.cs:203 +#: Library/Main/Strings.cs:205 msgid "List only filesets" msgstr "Vypsat pouze sady souborů" -#: Library/Main/Strings.cs:204 +#: Library/Main/Strings.cs:206 msgid "" "Use this option to only list filesets and avoid traversing file names and " "other metadata which slows down the process" @@ -3719,11 +3829,11 @@ msgstr "" "Pomocí této předvolby vypíšete pouze sady souborů a vyhnete se tak " "procházení názvů souborů a dalších metadat, což by proces zpomalilo" -#: Library/Main/Strings.cs:206 +#: Library/Main/Strings.cs:208 msgid "Don't store metadata" msgstr "Neuchovávat metadata" -#: Library/Main/Strings.cs:207 +#: Library/Main/Strings.cs:209 msgid "" "Use this option to disable the storage of metadata, such as file timestamps." " Disabling metadata storage will speed up the backup and restore operations," @@ -3733,11 +3843,11 @@ msgstr "" "souborů. Vypnutí ukládání metadat zrychlí operaci zálohování a obnovy, ale " "velikost záloh příliš neovlivní." -#: Library/Main/Strings.cs:208 +#: Library/Main/Strings.cs:210 msgid "Restore file permissions" msgstr "Obnovit přístupová práva souboru" -#: Library/Main/Strings.cs:209 +#: Library/Main/Strings.cs:211 msgid "" "By default permissions are not restored as they might prevent you from " "accessing your files. Use this option to restore the permissions as well." @@ -3746,11 +3856,11 @@ msgstr "" "bránit v přístupu k souborům. Pomocí této předvolby budou obnovena i " "přístupová práva." -#: Library/Main/Strings.cs:210 +#: Library/Main/Strings.cs:212 msgid "Skip restored file check" msgstr "Přeskočit kontrolu obnoveného souboru" -#: Library/Main/Strings.cs:211 +#: Library/Main/Strings.cs:213 msgid "" "After restoring files, the file hash of all restored files are checked to " "verify that the restore was successful. Use this option to disable the check" @@ -3760,21 +3870,21 @@ msgstr "" "tak, že vše proběhlo úspěšně. Pomocí této předvolby kontrolu vypnete a " "vyhnete se tak čekání na toto ověření." -#: Library/Main/Strings.cs:212 +#: Library/Main/Strings.cs:214 msgid "Activate caches" msgstr "Zapnout mezipaměti" -#: Library/Main/Strings.cs:213 +#: Library/Main/Strings.cs:215 msgid "Activate in-memory caches, which are now off by default" msgstr "" "Aktivovat mezipaměti v operační paměti, které jsou nyní ve výchozím stavu " "vypnuté" -#: Library/Main/Strings.cs:214 +#: Library/Main/Strings.cs:216 msgid "Do not use local data" msgstr "Nepoužívat místní data" -#: Library/Main/Strings.cs:215 +#: Library/Main/Strings.cs:217 msgid "" "Duplicati will attempt to use data from source files to minimize the amount " "of downloaded data. Use this option to skip this optimization and only use " @@ -3784,11 +3894,11 @@ msgstr "" "objem stahovaných dat. Pomocí této předvolby tuto optimalizaci přeskočíte a " "použijete pouze vzdálená data." -#: Library/Main/Strings.cs:216 +#: Library/Main/Strings.cs:218 msgid "Check block hashes" msgstr "Zkontrolovat hashe bloků" -#: Library/Main/Strings.cs:217 +#: Library/Main/Strings.cs:219 msgid "" "Use this option to increase verification by checking the hash of blocks read" " from a volume before patching restored files with the data." @@ -3796,11 +3906,11 @@ msgstr "" "Pomocí této předvolby zvýšíte důkladnost ověřování kontrolováním otisku " "(hash) bloků načítaných ze svazku před vkládáním dat do obnovených souborů." -#: Library/Main/Strings.cs:220 +#: Library/Main/Strings.cs:222 msgid "Repair database with paths" msgstr "Opravit databázi s cestami" -#: Library/Main/Strings.cs:221 +#: Library/Main/Strings.cs:223 msgid "" "Use this option to build a searchable local database which only contains " "path information. This option is usable for quickly building a database to " @@ -3813,11 +3923,11 @@ msgstr "" "všechny informace. Výslednou databázi lze prohledávat, ale nelze ji použít " "pro obnovení dat." -#: Library/Main/Strings.cs:222 +#: Library/Main/Strings.cs:224 msgid "Force the locale setting" msgstr "Vynutit místní a jazyková nastavení" -#: Library/Main/Strings.cs:223 +#: Library/Main/Strings.cs:225 msgid "" "By default, your system locale and culture settings will be used. In some " "cases you may prefer to run with another locale, for example to get messages" @@ -3829,13 +3939,13 @@ msgstr "" "zpráv v jiném jazyce. Pomocí této volby je možné nastavit místní a jazyková " "nastavení. Zadáním prázdného řetězce zvolíte „neměnnou kulturu“-" -#: Library/Main/Strings.cs:224 +#: Library/Main/Strings.cs:226 msgid "Handle file communication with backend using threaded pipes" msgstr "" "Obsluhovat souborovou komunikaci s podpůrnou vrstvou (backend) pomocí " "vláknovaných rour (pipe)" -#: Library/Main/Strings.cs:225 +#: Library/Main/Strings.cs:227 msgid "" "Use this option to disable multithreaded handling of up- and downloads, that" " can significantly speed up backend operations depending on the hardware " @@ -3845,11 +3955,11 @@ msgstr "" "stahování, což může významně zrychlit operace na podpůrné vrstvě (backend) v" " závislosti na hardware, který provozujete a přenosové rychlosti." -#: Library/Main/Strings.cs:226 +#: Library/Main/Strings.cs:228 msgid "Perform backup of Hyper-V machines (Windows only)" msgstr "Zazálohovat Hyper-V stroje (pouze Windows)" -#: Library/Main/Strings.cs:227 +#: Library/Main/Strings.cs:229 msgid "" "Use this option to specify the IDs of machines to include in the backup. " "Specify multiple machine IDs with a semicolon separator. (You can use this " @@ -3859,7 +3969,7 @@ msgstr "" " zálohy. Vícero identifikátorů oddělujte středníkem. (Identifikátor zjistíte" " tímto příkazem v Powershell „Get-VM | ft VMName“, ID)" -#: Library/Main/Strings.cs:228 +#: Library/Main/Strings.cs:230 msgid "" "If Duplicati detects that the previous backup did not complete, it will " "generate a filelist that is a merge of the last completed backup and the " @@ -3869,11 +3979,11 @@ msgstr "" " souborů, který je sloučením minulé kompletní zálohy a obsahu který byl " "nahrán při nekompletní zálohovací relaci." -#: Library/Main/Strings.cs:229 +#: Library/Main/Strings.cs:231 msgid "Disables synthetic filelist" msgstr "Vypíná syntetický seznam souborů" -#: Library/Main/Strings.cs:230 +#: Library/Main/Strings.cs:232 msgid "" "This flag instructs Duplicati to not look at metadata or filesize when " "deciding to scan a file for changes. Use this option if you have a large " @@ -3885,15 +3995,15 @@ msgstr "" "pokud máte velké množství souborů a pozorujete, že skenování souborů trvá i " "u nezměněných souborů dlouho." -#: Library/Main/Strings.cs:231 +#: Library/Main/Strings.cs:233 msgid "Checks only file lastmodified" msgstr "Kontroluje pouze poslední změnu souboru" -#: Library/Main/Strings.cs:232 +#: Library/Main/Strings.cs:234 msgid "Disables path compresion on restore" msgstr "Vypne stlačení popisu umístění při obnově" -#: Library/Main/Strings.cs:233 +#: Library/Main/Strings.cs:235 msgid "" "When restore a subset of a backup into a new folder, the shortest possible " "path is used to avoid generating deep paths with empty folders. Use this " @@ -3906,11 +4016,11 @@ msgstr "" " čímž bude zachována původní struktura složky, včetně prázdných složek na " "vyšší úrovni." -#: Library/Main/Strings.cs:234 +#: Library/Main/Strings.cs:236 msgid "Allow removing all filesets" msgstr "Povolit odstranění všech množin souborů" -#: Library/Main/Strings.cs:235 +#: Library/Main/Strings.cs:237 msgid "" "By default, the last fileset cannot be removed. This is a safeguard to make " "sure that all remote data is not deleted by a configuration mistake. Use " @@ -3921,12 +4031,12 @@ msgstr "" "Pomocí tohoto příznaku je možné tuto ochranu vypnout a mohou tak být smazány" " všechny sady souborů." -#: Library/Main/Strings.cs:236 +#: Library/Main/Strings.cs:238 msgid "Allow automatic rebuilding of local database to save space." msgstr "" "Umožnit automatické znovuvytváření místní databáze a šetřit tak prostor." -#: Library/Main/Strings.cs:237 +#: Library/Main/Strings.cs:239 msgid "" "Some operations that manipulate the local database leave unused entries " "behind. These entries are not deleted from a hard drive until a VACUUM " @@ -3941,7 +4051,23 @@ msgstr "" "vytvořit kopii všech platných položek v databázi. Nastavením tohoto umožní " "Duplicati provádět operaci VACUUM dle potřeby." -#: Library/Main/Strings.cs:242 +#: Library/Main/Strings.cs:240 +msgid "Disable the read-ahead scanner" +msgstr "Vypnout skener načítání dopředu" + +#: Library/Main/Strings.cs:241 +msgid "" +"When this flag is enabled, the scanner that computes the size of source " +"files is disabled, and instead the reported size is read from the database. " +"Using this flag can speed up the backup by reducing disk access, but will " +"give a less accurate progress indicator." +msgstr "" +"Když je tento příznak zapnutý, skener který počítá velikost zdrojových " +"souborů je vypnut a namísto toho je hlášená velikost načítána z databáze. " +"Použitím tohoto příznaku je možné zrychlit zálohování snížením počtu " +"přístupů k úložišti, ale za cenu méně přesného ukazatele stavu průběhu." + +#: Library/Main/Strings.cs:246 #, csharp-format msgid "" "The cryptolibrary does not support re-usable transforms for the hash " @@ -3950,18 +4076,18 @@ msgstr "" "Kryptografická knihovna nepodporuje znovupoužitelné transformace pro " "hashovací algoritmus {0}" -#: Library/Main/Strings.cs:243 +#: Library/Main/Strings.cs:247 #, csharp-format msgid "The cryptolibrary does not support the hash algorithm {0}" msgstr "" "Kryptografická knihovna nepodporuje tento algoritmus tvorby otisku (hash) " "{0}" -#: Library/Main/Strings.cs:244 +#: Library/Main/Strings.cs:248 msgid "The passphrase cannot be changed for an existing backup" msgstr "Heslo existující zálohy nemůže být změněno" -#: Library/Main/Strings.cs:245 +#: Library/Main/Strings.cs:249 #, csharp-format msgid "Failed to create a snapshot: {0}" msgstr "Zachycený stav se nepodařilo vytvořit: {0}" @@ -4787,22 +4913,6 @@ msgstr "" msgid "Supported generic modules:" msgstr "Podporované obecné moduly:" -#: CommandLine/Strings.cs:18 -#, csharp-format -msgid "Unable to read the parameters file \"{0}\", reason: {1}" -msgstr "Nedaří se číst soubor s parametry „{0}“, důvod: {1}" - -#: CommandLine/Strings.cs:19 -#, csharp-format -msgid "" -"Filters cannot be specified on the commandline if filters are also present " -"in the parameter file. Use the special --{0}, --{1}, or --{2} options to " -"specify filters inside the parameter file. Each filter must be prefixed with" -" either a + or a -, and multiple filters must be joined with {3}" -msgstr "" -"Pokud se filtry nacházejí už v souboru s parametry, není možné je zadávat zároveň i na příkazovém řádku. Pro zadání filtrů uvnitř souboru s parametry použijte zvláštní volby --{0}, --{1}, nebo --{2}.\n" -"Každý filtr je třeba předeslat buď + nebo - a vícero filtrů je třeba spojit pomocí {3}" - #: CommandLine/Strings.cs:20 #, csharp-format msgid "" @@ -4812,35 +4922,6 @@ msgstr "" "Byla zadána volba --{0}, ale ta je vyhrazena pro použití v rámci aplikace a " "neměla by být zadávána na příkazovém řádku" -#: CommandLine/Strings.cs:21 -#, csharp-format -msgid "" -"This option can be used to store some or all of the options given to the " -"commandline client. The file must be a plain text file, UTF-8 encoding is " -"preferred. Each line in the file should be of the format --option=value. The" -" special options --{0} and --{1} can be used to override the localpath and " -"the remote destination uri, respectively. The options in this file take " -"precedence over the options provided on the commandline. You cannot specify " -"filters in both the file and on the commandline. Instead, you can use the " -"special --{2}, --{3}, or --{4} options to specify filters inside the " -"parameter file. Each filter must be prefixed with either a + or a -, and " -"multiple filters must be joined with {5} " -msgstr "" -"Tuto volbu je možné použít pro ukládání některých nebo všech voleb zadaných " -"klientovi pro příkazový řádek. Je třeba, aby soubor byl čistě textový, " -"nejlépe se znakovou sadou UTF-8. Každý řádek souboru by měl mít podobu " -"--volba=hodnota. Pro přepsání místního popisu umístění a uri adresy " -"vzdáleného cíle je možné použít speciální volby --{0} a --{1}. Volby v tomto" -" souboru mají přednost před volbami zadanými na příkazovém řádku. U filtrů " -"není možné, aby byly zadaná jak v souboru, tak na příkazovém řádku zároveň. " -"Namísto toho je možné pro zadání filtrů uvnitř souboru s parametry použít " -"zvláštní volby --{2}, --{3}, nebo --{4}. Je třeba, aby každý z filtrů byl " -"předeslán buď + nebo - a vícero filtrů bylo spojeno pomocí {5}" - -#: CommandLine/Strings.cs:22 -msgid "Path to a file with parameters" -msgstr "Popis umístění souboru s parametry" - #: CommandLine/Strings.cs:23 #, csharp-format msgid "An error occured: {0}" diff --git a/Localizations/duplicati/localization-da.mo b/Localizations/duplicati/localization-da.mo index 64348c5ce..af05681fb 100644 Binary files a/Localizations/duplicati/localization-da.mo and b/Localizations/duplicati/localization-da.mo differ diff --git a/Localizations/duplicati/localization-da.po b/Localizations/duplicati/localization-da.po index 00acdac50..9d6063d67 100644 --- a/Localizations/duplicati/localization-da.po +++ b/Localizations/duplicati/localization-da.po @@ -1527,7 +1527,7 @@ msgstr "" #: Library/Backend/Rclone/Strings.cs:12 msgid "Remote path" -msgstr "" +msgstr "Fjernvej" #: Library/Backend/Rclone/Strings.cs:13 msgid "Path on the Remote repository. " @@ -1760,7 +1760,7 @@ msgstr "" #: Library/Backend/Sia/Strings.cs:10 msgid "Backup path" -msgstr "" +msgstr "Backup sti" #: Library/Backend/Sia/Strings.cs:11 msgid "Target path, ie /backup" @@ -1906,7 +1906,7 @@ msgstr "Ikke gyldigt mount givet" #: Library/Backend/Jottacloud/Strings.cs:16 msgid "Supplies the backup device to use" -msgstr "" +msgstr "Leverer den backupenhed, der skal bruges" #: Library/Backend/Jottacloud/Strings.cs:17 #, csharp-format @@ -1916,6 +1916,10 @@ msgid "" "When you specify a custom device you should also specify the mount point to " "use on this device with the \"{0}\" option." msgstr "" +"Den backup enhed, der skal bruges. Bliver oprettet, hvis den ikke allerede " +"eksisterer. Du kan styre dine enheder fra backuppanelet i Jottacloud's web-" +"interface. Når du angiver en brugerdefineret enhed, skal du også angive det " +"mount point, der skal bruges til denne enhed, med indstillingen \"{0}\"." #: Library/Backend/Jottacloud/Strings.cs:18 msgid "Supplies the mount point to use on the server" @@ -1973,6 +1977,8 @@ msgid "" "Use this option to have files moved to the recycle bin folder instead of " "removing them permanently when compacting or deleting backups." msgstr "" +"Brug denne indstilling til at få filer flyttet til papirkurv mappen i stedet" +" for at fjerne dem permanent, når du komprimerer eller sletter backups." #: Library/Backend/SharePoint/Strings.cs:15 msgid "Move deleted files to the recycle bin" @@ -2256,6 +2262,11 @@ msgid "" "This is likely caused by upgrading to a newer version and then downgrading.\n" "If this is the case, there is likely a backup file of the previous database version in the folder {2}." msgstr "" +"\n" +"Databasen har version {0}, men den største understøttede version er {1}.\n" +"\n" +"Dette skyldes sandsynligvis opgradering til en nyere version og derefter nedgradering.\n" +"Hvis dette er tilfældet, er der sandsynligvis en backupfil af den tidligere databaseversion i mappen {2}." #: Library/SQLiteHelper/Strings.cs:11 msgid "Unknown table layout detected" diff --git a/Localizations/duplicati/localization-it.mo b/Localizations/duplicati/localization-it.mo index 8145a3bce..a9db5066e 100644 Binary files a/Localizations/duplicati/localization-it.mo and b/Localizations/duplicati/localization-it.mo differ diff --git a/Localizations/duplicati/localization-it.po b/Localizations/duplicati/localization-it.po index 081fc40e7..5fdc807e4 100644 --- a/Localizations/duplicati/localization-it.po +++ b/Localizations/duplicati/localization-it.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-01-18 11:11+0100\n" +"POT-Creation-Date: 2018-02-12 07:39+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Massimo Piceni , 2017\n" "Language-Team: Italian (https://www.transifex.com/duplicati/teams/67655/it/)\n" @@ -48,15 +48,63 @@ msgstr "" msgid "--{0}: {1}" msgstr "--{0}: {1}" -#: Server/Strings.cs:15 +#: Server/Strings.cs:15 CommandLine/Strings.cs:21 +#, csharp-format +msgid "" +"This option can be used to store some or all of the options given to the " +"commandline client. The file must be a plain text file, UTF-8 encoding is " +"preferred. Each line in the file should be of the format --option=value. The" +" special options --{0} and --{1} can be used to override the localpath and " +"the remote destination uri, respectively. The options in this file take " +"precedence over the options provided on the commandline. You cannot specify " +"filters in both the file and on the commandline. Instead, you can use the " +"special --{2}, --{3}, or --{4} options to specify filters inside the " +"parameter file. Each filter must be prefixed with either a + or a -, and " +"multiple filters must be joined with {5} " +msgstr "" +"Questa opzione può essere utilizzata per memorizzare alcune o tutte le " +"opzioni fornite al client Riga di comando. Il file deve essere un file di " +"testo normale, la codifica UTF-8 è preferibile. Ogni riga nel file deve " +"essere del formato -option=value. Le opzioni speciali -{0} e --{1} possono " +"essere utilizzate per sovrascrivere rispettivamente il LocalPath e l'URI di " +"destinazione remota. Le opzioni in questo file hanno la precedenza sulle " +"opzioni fornite dalla riga di comando. Non è possibile specificare filtri " +"sia nel file sia nella riga di comando. È invece possibile utilizzare le " +"opzioni speciali --{2}, --{3}, o --{4} per specificare i filtri all'interno " +"del file dei parametri. Ogni filtro deve essere preceduto con un + o un -, e" +" più filtri devono essere uniti con {5}" + +#: Server/Strings.cs:16 CommandLine/Strings.cs:22 +msgid "Path to a file with parameters" +msgstr "Percorso di un file con parametri" + +#: Server/Strings.cs:17 CommandLine/Strings.cs:19 +#, csharp-format +msgid "" +"Filters cannot be specified on the commandline if filters are also present " +"in the parameter file. Use the special --{0}, --{1}, or --{2} options to " +"specify filters inside the parameter file. Each filter must be prefixed with" +" either a + or a -, and multiple filters must be joined with {3}" +msgstr "" +"I filtri non possono essere specificati dalla riga di comando se sono " +"presenti anche nel file parametri. Usa le opzioni speciali --{0}, --{1}, o " +"--{2} per specificare i filtri all'interno del file parametri. Ogni filtro " +"deve avere un prefisso + o un -, e più filtri devono essere uniti con {3}" + +#: Server/Strings.cs:18 CommandLine/Strings.cs:18 +#, csharp-format +msgid "Unable to read the parameters file \"{0}\", reason: {1}" +msgstr "Impossibile leggere il file dei parametri \"{0}\", motivo: {1}" + +#: Server/Strings.cs:20 msgid "Outputs log information to the file given" msgstr "Il registro mostra informazioni del file dato" -#: Server/Strings.cs:16 +#: Server/Strings.cs:21 msgid "Determines the amount of information written in the log file" msgstr "Determina la quantità di informazioni scritte nel file di registro" -#: Server/Strings.cs:17 +#: Server/Strings.cs:22 msgid "" "Activates portable mode where the database is placed below the program " "executable" @@ -64,12 +112,12 @@ msgstr "" "Attiva la modalità portable in cui il database è posizionato sotto " "l'eseguibile del programma" -#: Server/Strings.cs:18 +#: Server/Strings.cs:23 #, csharp-format msgid "A serious error occurred in Duplicati: {0}" msgstr "Si è verificato un errore grave in Duplicati: {0}" -#: Server/Strings.cs:19 +#: Server/Strings.cs:24 #, csharp-format msgid "" "Unable to start up, perhaps another process is already running?\n" @@ -78,18 +126,18 @@ msgstr "" "Impossibile avviare il backup, magari un altro processo è già in esecuzione?\n" "Messaggio di errore: {0}" -#: Server/Strings.cs:21 +#: Server/Strings.cs:26 msgid "Disables database encryption" msgstr "Disattiva crittografia database" -#: Server/Strings.cs:22 +#: Server/Strings.cs:27 #, csharp-format msgid "Unsupported version of SQLite detected ({0}), must be {1} or higher" msgstr "" "Rilevata una versione non supportata di SQLite ({0}), deve essere {1} o " "superiore" -#: Server/Strings.cs:23 +#: Server/Strings.cs:28 msgid "" "The path to the folder where the static files for the webserver is present. " "The folder must be located beneath the installation folder" @@ -97,7 +145,7 @@ msgstr "" "Il percorso della cartella in cui risiedono i file statici per il webserver." " La cartella deve trovarsi sotto la cartella di installazione" -#: Server/Strings.cs:24 +#: Server/Strings.cs:29 msgid "" "The port the webserver listens on. Multiple values may be supplied with a " "comma in between." @@ -105,7 +153,7 @@ msgstr "" "La porta su cui il webserver è in ascolto. Valori multipli possono essere " "forniti con una virgola in mezzo." -#: Server/Strings.cs:25 +#: Server/Strings.cs:30 msgid "" "The certificate and key file in PKCS #12 format the webserver use for SSL. " "Only RSA/DSA keys are supported." @@ -113,11 +161,11 @@ msgstr "" "Il certificato e il file chiave in PKCS #12 formato utilizzato del webserver" " per SSL. Sono supportate solo le chiavi RSA/DSA." -#: Server/Strings.cs:26 +#: Server/Strings.cs:31 msgid "The password for decryption of certificate PKCS #12 file." msgstr "Password per decriptare il file del certificato PKCS #12." -#: Server/Strings.cs:27 +#: Server/Strings.cs:32 msgid "" "The interface the webserver listens on. The special values \"*\" and \"any\"" " means any interface. The special value \"loopback\" means the loopback " @@ -127,7 +175,7 @@ msgstr "" "\"any\" significano qualsiasi interfaccia. Il valore speciale \"loopback\" " "significa la scheda loopback." -#: Server/Strings.cs:28 +#: Server/Strings.cs:33 msgid "" "The password required to access the webserver. This option is saved so you " "do not need to set it on each run. Setting an empty value disables the " @@ -137,11 +185,11 @@ msgstr "" "in modo che non sia necessario impostarla su ogni volta. L'impostazione di " "un valore vuoto disattiva la password." -#: Server/Strings.cs:29 +#: Server/Strings.cs:34 msgid "Enables the ping-pong responder" msgstr "Abilita il risponditore ping-pong" -#: Server/Strings.cs:30 +#: Server/Strings.cs:35 msgid "" "When running as a server, the service daemon must verify that the process is" " responding. If this option is enabled, the server reads stdin and writes a " @@ -151,21 +199,21 @@ msgstr "" "il processo stia rispondendo. Se questa opzione è abilitata, il server legge" " stdin e scrive una risposta a ogni riga di lettura" -#: Server/Strings.cs:31 Library/Main/Strings.cs:218 +#: Server/Strings.cs:36 Library/Main/Strings.cs:220 msgid "Clean up old log data" msgstr "Pulisci i vecchi dati del registro" -#: Server/Strings.cs:32 Library/Main/Strings.cs:219 +#: Server/Strings.cs:37 Library/Main/Strings.cs:221 msgid "Set the time after which log data will be purged from the database." msgstr "" "Imposta l'ora dopo la quale i dati del registro saranno eliminati dal " "database." -#: Server/Strings.cs:33 +#: Server/Strings.cs:38 msgid "Sets the folder where settings are stored" msgstr "Imposta la cartella in cui sono salvate le impostazioni" -#: Server/Strings.cs:34 +#: Server/Strings.cs:39 #, csharp-format msgid "" "Duplicati needs to store a small database with all settings. Use this option" @@ -177,11 +225,11 @@ msgstr "" "archiviate le impostazioni. Questa opzione può essere impostata anche con la" " variabile d'ambiente {0}." -#: Server/Strings.cs:35 +#: Server/Strings.cs:40 msgid "Sets the database encryption key" msgstr "Imposta la chiave di crittografia del database" -#: Server/Strings.cs:36 +#: Server/Strings.cs:41 #, csharp-format msgid "" "This option sets the encryption key used to scramble the local settings " @@ -193,7 +241,7 @@ msgstr "" "con la variabile d'ambiente {0}. Usa l'opzione --{1} per disabilitare la " "codifica del database." -#: Server/Strings.cs:39 +#: Server/Strings.cs:44 #, csharp-format msgid "" "Unable to find a valid date, given the start date {0}, the repetition " @@ -202,12 +250,12 @@ msgstr "" "Impossibile trovare una data valida, stabilita la data d'inizio {0}, " "l'intervallo di ripetizione {1} e i giorni consentiti {2}" -#: Server/Strings.cs:44 +#: Server/Strings.cs:49 #, csharp-format msgid "Server has started and is listening on {0}, port {1}" msgstr "Server avviato e in ascolto su {0}, porta {1}" -#: Server/Strings.cs:45 +#: Server/Strings.cs:50 #, csharp-format msgid "" "Unable to create SSL certificate using provided parameters. Exception " @@ -216,7 +264,7 @@ msgstr "" "Impossibile creare il certificato SSL usando i parametri forniti. Dettaglio " "eccezione: {0}" -#: Server/Strings.cs:46 +#: Server/Strings.cs:51 #, csharp-format msgid "Unable to open a socket for listening, tried ports: {0}" msgstr "Impossibile aprire un socket per l'ascolto, porte provate: {0}" @@ -980,6 +1028,18 @@ msgstr "" msgid "Google Drive" msgstr "Google Drive" +#: Library/Backend/GoogleServices/Strings.cs:48 +msgid "Hide team drives" +msgstr "Nascondi unità di squadra" + +#: Library/Backend/GoogleServices/Strings.cs:49 +msgid "" +"This option disables the team drives, showing only files and folders " +"accesible with the account itself" +msgstr "" +"Questa opzione disabilita le unità di squadra, mostrando solo i file e le " +"cartelle accessibile con l'account stesso" + #: Library/Backend/CloudFiles/Strings.cs:4 #, csharp-format msgid "" @@ -1535,6 +1595,65 @@ msgstr "" "cui sarà cancellato dopo un po di tempo. Usa questo comando per forzare la " "rimozione immediata dei file da cancellare." +#: Library/Backend/Rclone/Strings.cs:6 +msgid "Rclone" +msgstr "Rclone" + +#: Library/Backend/Rclone/Strings.cs:7 +msgid "This backend can read and write data to Rclone." +msgstr "Questo backend può leggere e scrivere dati in Rclone." + +#: Library/Backend/Rclone/Strings.cs:8 +msgid "Local repository" +msgstr "Repository locale" + +#: Library/Backend/Rclone/Strings.cs:9 +msgid "" +"Local repository for Rclone. Make sure it is configured as a local drive, as" +" it needs access to the files generated by Duplicati." +msgstr "" +"Repository locale per Rclone. Assicurati che sia configurato come unità " +"locale, in quanto ha bisogno di accedere ai file generati da Duplicati." + +#: Library/Backend/Rclone/Strings.cs:10 +msgid "Remote repository" +msgstr "Repository remoto" + +#: Library/Backend/Rclone/Strings.cs:11 +msgid "" +"Remote repository for Rclone. This can be any of the backends provided by " +"Rclone. More info available on https://rclone.org/." +msgstr "" +"Repository remoto per Rclone. Questo può essere uno dei backend forniti da " +"Rclone. Maggiori informazioni disponibili su https://rclone.org/." + +#: Library/Backend/Rclone/Strings.cs:12 +msgid "Remote path" +msgstr "Percorso remoto" + +#: Library/Backend/Rclone/Strings.cs:13 +msgid "Path on the Remote repository. " +msgstr "Percorso nel repository remoto." + +#: Library/Backend/Rclone/Strings.cs:14 +msgid "Rclone options." +msgstr "Opzioni Rclone." + +#: Library/Backend/Rclone/Strings.cs:15 +msgid "Options will be transferred to rclone." +msgstr "Le opzioni saranno trasferite su Rclone." + +#: Library/Backend/Rclone/Strings.cs:16 +msgid "Rclone executable" +msgstr "Eseguibile Rclone" + +#: Library/Backend/Rclone/Strings.cs:17 +msgid "" +"Full path to the rclone executable. Only needed if it's not in your path." +msgstr "" +"Percorso completo per l'eseguibile Rclone. Necessario solo se non è nel tuo " +"percorso." + #: Library/Backend/File/Strings.cs:4 #, csharp-format msgid "" @@ -2370,31 +2489,6 @@ msgstr "" "Errore: {1}\n" "Database NON aggiornato. " -#: Library/Main/Database/ExtensionMethods.cs:48 -#, csharp-format -msgid "ExecuteNonQuery: {0}" -msgstr "Esegui Non Query: {0}" - -#: Library/Main/Database/ExtensionMethods.cs:64 -#, csharp-format -msgid "ExecuteScalar: {0}" -msgstr "Esegui Scalare: {0}" - -#: Library/Main/Database/ExtensionMethods.cs:90 -#, csharp-format -msgid "ExecuteScalarInt64: {0}" -msgstr "Esegui Scalare Int64: {0}" - -#: Library/Main/Database/ExtensionMethods.cs:110 -#, csharp-format -msgid "ExecuteReader: {0}" -msgstr "Esegui Lettura: {0}" - -#: Library/Main/Database/ExtensionMethods.cs:200 -#, csharp-format -msgid "{0} records" -msgstr "{0} registrazioni" - #: Library/Main/Strings.cs:8 #, csharp-format msgid "Hash mismatch on file \"{0}\", recorded hash: {1}, actual hash {2}" @@ -3195,6 +3289,24 @@ msgid "A reported maximum storage" msgstr "Una segnalazione massimo archivio" #: Library/Main/Strings.cs:122 +msgid "" +"Sets a threshold for when to warn about the backend quota being nearly " +"exceeded. It is given as a percentage, and a warning is generated if the " +"amount of available quota is less that this percentage of the total backup " +"size. If the backend does not report the quota information, this value will " +"be ignored" +msgstr "" +"Imposta una soglia di avvertimento per quando si starà quasi per superare la" +" quota del backend. È dato come percentuale e un messaggio di avviso è " +"generato se la dimensione della quota disponibile è inferiore a questa " +"percentuale del totale della dimensione dei backup. Se il backend non " +"riporta le informazioni sulla quota, questo valore sarà ignorato" + +#: Library/Main/Strings.cs:123 +msgid "Threshold for warning about low quota" +msgstr "Soglia di avviso su quota bassa" + +#: Library/Main/Strings.cs:124 #, csharp-format msgid "" "Exclude files that match the given filter sets. Which default filter sets " @@ -3207,15 +3319,15 @@ msgstr "" "\"{1}\", \"{2}\" e \"{3}\". Se questo parametro è impostato senza alcun " "valore, sarà utilizzato il set per il sistema operativo corrente." -#: Library/Main/Strings.cs:123 +#: Library/Main/Strings.cs:125 msgid "Default filter sets" msgstr "Set di filtri predefiniti" -#: Library/Main/Strings.cs:124 +#: Library/Main/Strings.cs:126 msgid "Symlink handling" msgstr "Gestione collegamento simbolico" -#: Library/Main/Strings.cs:125 +#: Library/Main/Strings.cs:127 #, csharp-format msgid "" "Use this option to handle symlinks differently. The \"{0}\" option will " @@ -3233,11 +3345,11 @@ msgstr "" "Le versioni precedenti di Duplicati usavano l'impostazione \"{2}\", che " "causava l'inclusione dei file collegati e il ripristino come normali file." -#: Library/Main/Strings.cs:126 +#: Library/Main/Strings.cs:128 msgid "Hardlink handling" msgstr "Gestione hardlink" -#: Library/Main/Strings.cs:127 +#: Library/Main/Strings.cs:129 #, csharp-format msgid "" "Use this option to handle hardlinks (only works on Linux/OSX). The \"{0}\" " @@ -3252,11 +3364,11 @@ msgstr "" "informazioni hardlink e tratterà ogni hardlink come un percorso univoco. " "L'opzione \"{2}\" ignorerà tutti i hardlink con più di un collegamento." -#: Library/Main/Strings.cs:128 +#: Library/Main/Strings.cs:130 msgid "Exclude files by attribute" msgstr "Escludi file per attributo" -#: Library/Main/Strings.cs:129 +#: Library/Main/Strings.cs:131 #, csharp-format msgid "" "Use this option to exclude files with certain attributes. Use a comma " @@ -3267,7 +3379,7 @@ msgstr "" "elenco separato da virgole di nomi di attributi per specificare più di uno. " "I valori possibili sono: {0}" -#: Library/Main/Strings.cs:130 +#: Library/Main/Strings.cs:132 msgid "" "Activate this option to map VSS snapshots to a drive (similar to SUBST, " "using Win32 DefineDosDevice). This will create temporary drives that are " @@ -3279,11 +3391,11 @@ msgstr "" "temporanee utilizzate per accedere al contenuto di una istantanea. Questa " "soluzione può velocizzare l'accesso ai file su Windows XP." -#: Library/Main/Strings.cs:131 +#: Library/Main/Strings.cs:133 msgid "Map snapshots to a drive (Windows only)" msgstr "Mappa istantanee su un'unità (solo Windows)" -#: Library/Main/Strings.cs:132 +#: Library/Main/Strings.cs:134 msgid "" "A display name that is attached to this backup. Can be used to identify the " "backup when sending mail or running scripts." @@ -3291,11 +3403,11 @@ msgstr "" "Il nome visualizzato è associato a questo backup. Può essere utilizzato per " "identificare il backup durante l'invio di posta o esecuzione di script." -#: Library/Main/Strings.cs:133 +#: Library/Main/Strings.cs:135 msgid "Name of the backup" msgstr "Nome del backup" -#: Library/Main/Strings.cs:134 +#: Library/Main/Strings.cs:136 #, csharp-format msgid "" "This property can be used to point to a text file where each line contains a" @@ -3314,12 +3426,12 @@ msgstr "" "per indicare la fine dell'estensione. È fornito un file predefinito, che " "funge anche da esempio. Il file predefinito è inserito in {0}." -#: Library/Main/Strings.cs:135 +#: Library/Main/Strings.cs:137 msgid "Manage non-compressible file extensions" msgstr "Gestisci le estensioni di file non comprimibili" -#: Library/Main/Strings.cs:136 Library/Main/Strings.cs:146 -#: Library/Main/Strings.cs:155 +#: Library/Main/Strings.cs:138 Library/Main/Strings.cs:148 +#: Library/Main/Strings.cs:157 msgid "" "A fragment of memory is used to reduce database lookups. You should not " "change this value unless you get warnings in the log." @@ -3328,11 +3440,11 @@ msgstr "" "Non è necessario modificare questo valore a meno che non si ottengano avvisi" " nel registro." -#: Library/Main/Strings.cs:137 +#: Library/Main/Strings.cs:139 msgid "Memory used by the block hash" msgstr "Memoria utilizzata dal hash del blocco" -#: Library/Main/Strings.cs:138 +#: Library/Main/Strings.cs:140 msgid "" "The block size determines how files are fragmented. Choosing a large value " "will cause a larger overhead on file changes, choosing a small value will " @@ -3346,11 +3458,11 @@ msgstr "" "di file. Nota che il valore non può essere modificato dopo la creazione di " "file remoti." -#: Library/Main/Strings.cs:139 +#: Library/Main/Strings.cs:141 msgid "Block size used in hashing" msgstr "Dimensione del blocco usato nell'hash" -#: Library/Main/Strings.cs:140 +#: Library/Main/Strings.cs:142 msgid "" "This option can be used to limit the scan to only files that are known to " "have changed. This is usually only activated in combination with a " @@ -3361,20 +3473,20 @@ msgstr "" "solo in combinazione con un osservatore di filesystem che tiene traccia " "delle modifiche dei file." -#: Library/Main/Strings.cs:141 +#: Library/Main/Strings.cs:143 msgid "List of files to examine for changes" msgstr "Elenco di file da esaminare per le modifiche" -#: Library/Main/Strings.cs:142 +#: Library/Main/Strings.cs:144 msgid "" "Path to the file containing the local cache of the remote file database" msgstr "Percorso del file contiene la cache locale del file database remoto" -#: Library/Main/Strings.cs:143 +#: Library/Main/Strings.cs:145 msgid "Path to the local state database" msgstr "Percorso dello stato locale del database" -#: Library/Main/Strings.cs:144 +#: Library/Main/Strings.cs:146 #, csharp-format msgid "" "This option can be used to supply a list of deleted files. This option will " @@ -3384,15 +3496,15 @@ msgstr "" "cancellati. Questa opzione sarà ignorata a meno che non sia impostata anche " "l'opzione --{0}." -#: Library/Main/Strings.cs:145 +#: Library/Main/Strings.cs:147 msgid "List of deleted files" msgstr "Elenco dei file cancellati" -#: Library/Main/Strings.cs:147 +#: Library/Main/Strings.cs:149 msgid "Memory used by the file hash" msgstr "Memoria utilizzata dal file hash" -#: Library/Main/Strings.cs:148 +#: Library/Main/Strings.cs:150 msgid "" "This option can be used to reduce the memory footprint by not keeping paths " "and modification timestamps in memory" @@ -3400,23 +3512,23 @@ msgstr "" "Questa opzione può essere utilizzata per ridurre lo spazio di memoria " "occupata non mantenendo i percorsi e la modifica dei timestamp in memoria" -#: Library/Main/Strings.cs:149 +#: Library/Main/Strings.cs:151 msgid "Reduce memory footprint by disabling in-memory lookups" msgstr "" "Riduci lo spazio di memoria occupata disabilitando le ricerche in memoria" -#: Library/Main/Strings.cs:150 +#: Library/Main/Strings.cs:152 msgid "" "This option can be used to increase speed in exchange for extra memory use." msgstr "" "Questa opzione può essere utilizzata per aumentare la velocità in cambio " "dell'utilizzo di più memoria." -#: Library/Main/Strings.cs:151 +#: Library/Main/Strings.cs:153 msgid "Store an in-memory block cache" msgstr "Archiviare un blocco cache in memoria" -#: Library/Main/Strings.cs:152 +#: Library/Main/Strings.cs:154 msgid "" "Stores metadata, such as file timestamps and attributes. This increases the " "required storage space as well as the processing time." @@ -3424,21 +3536,21 @@ msgstr "" "Archivia i metadati, ad esempio timestamp e attributi del file. Questo " "aumenta lo spazio di archiviazione richiesto e il tempo di elaborazione." -#: Library/Main/Strings.cs:153 +#: Library/Main/Strings.cs:155 msgid "Enables storing file metadata" msgstr "Consente di archiviare i metadati dei file" -#: Library/Main/Strings.cs:154 +#: Library/Main/Strings.cs:156 msgid "This option is no longer used as metadata is now stored by default" msgstr "" "Questa opzione non è più utilizzata come metadati è ora archiviata per " "impostazione predefinita" -#: Library/Main/Strings.cs:156 +#: Library/Main/Strings.cs:158 msgid "Memory used by the metadata hash" msgstr "Memoria utilizzata dall'hash metadati" -#: Library/Main/Strings.cs:157 +#: Library/Main/Strings.cs:159 msgid "" "If this flag is set, the local database is not compared to the remote " "filelist on startup. The intended usage for this option is to work correctly" @@ -3449,11 +3561,11 @@ msgstr "" "funzionare correttamente nei casi in cui il file elenco è corrotto o non " "disponibile." -#: Library/Main/Strings.cs:158 +#: Library/Main/Strings.cs:160 msgid "Do not query backend at startup" msgstr "Non eseguire query sul backend all'avvio" -#: Library/Main/Strings.cs:159 +#: Library/Main/Strings.cs:161 msgid "" "The index files are used to limit the need for downloading dblock files when" " there is no local database present. The more information is recorded in the" @@ -3467,11 +3579,11 @@ msgstr "" "senza il database. Il compromesso è che i file indice più grandi occupano " "più spazio remoto e che non possono mai essere utilizzati." -#: Library/Main/Strings.cs:160 +#: Library/Main/Strings.cs:162 msgid "Determines usage of index files" msgstr "Determina l'utilizzo dei file indice" -#: Library/Main/Strings.cs:161 +#: Library/Main/Strings.cs:163 msgid "" "As files are changed, some data stored at the remote destination may not be " "required. This option controls how much wasted space the destination can " @@ -3484,11 +3596,11 @@ msgstr "" "recuperato. Questo valore è una percentuale utilizzata per ogni volume e per" " l'archiviazione totale." -#: Library/Main/Strings.cs:162 +#: Library/Main/Strings.cs:164 msgid "The maximum wasted space in percent" msgstr "Lo spazio massimo sprecato in percentuale" -#: Library/Main/Strings.cs:163 +#: Library/Main/Strings.cs:165 msgid "" "This option can be used to experiment with different settings and observe " "the outcome without changing actual files." @@ -3496,11 +3608,11 @@ msgstr "" "Questa opzione può essere utilizzata per sperimentare impostazioni diverse e" " osservare il risultato senza modificare gli effettivi file." -#: Library/Main/Strings.cs:164 +#: Library/Main/Strings.cs:166 msgid "Does not perform any modifications" msgstr "Non esegue alcuna modifica" -#: Library/Main/Strings.cs:165 +#: Library/Main/Strings.cs:167 msgid "" "This is a very advanced option! This option can be used to select a block " "hash algorithm with smaller or larger hash size, for performance or storage " @@ -3510,11 +3622,11 @@ msgstr "" " selezionare un algoritmo hash sul blocco con dimensioni hash più piccole o " "più grandi, per motivi di prestazioni o spazio di archiviazione." -#: Library/Main/Strings.cs:166 +#: Library/Main/Strings.cs:168 msgid "The hash algorithm used on blocks" msgstr "L'algoritmo hash usato sui blocchi" -#: Library/Main/Strings.cs:167 +#: Library/Main/Strings.cs:169 msgid "" "This is a very advanced option! This option can be used to select a file " "hash algorithm with smaller or larger hash size, for performance or storage " @@ -3524,11 +3636,11 @@ msgstr "" " selezionare un algoritmo hash sul file con dimensioni hash più piccole o " "più grandi, per motivi di prestazioni o spazio di archiviazione." -#: Library/Main/Strings.cs:168 +#: Library/Main/Strings.cs:170 msgid "The hash algorithm used on files" msgstr "L'algoritmo hash utilizzato sui file" -#: Library/Main/Strings.cs:169 +#: Library/Main/Strings.cs:171 msgid "" "If a large number of small files are detected during a backup, or wasted " "space is found after deleting backups, the remote data will be compacted. " @@ -3541,11 +3653,11 @@ msgstr "" "compressione automatica e compatta solo quando si esegue il comando " "comprimi." -#: Library/Main/Strings.cs:170 +#: Library/Main/Strings.cs:172 msgid "Disable automatic compacting" msgstr "Disattiva compressione automatica" -#: Library/Main/Strings.cs:171 +#: Library/Main/Strings.cs:173 msgid "" "When examining the size of a volume in consideration for compacting, a small" " tolerance value is used, by default 20 percent of the volume size. This " @@ -3558,11 +3670,11 @@ msgstr "" "possono avere alcuni byte di spazio sprecato, non siano scaricati e " "riscritti." -#: Library/Main/Strings.cs:172 +#: Library/Main/Strings.cs:174 msgid "Volume size threshold" msgstr "Soglia dimensione volume" -#: Library/Main/Strings.cs:173 +#: Library/Main/Strings.cs:175 msgid "" "To avoid filling the remote storage with small files, this value can force " "grouping small files. The small volumes will always be combined when they " @@ -3573,11 +3685,11 @@ msgstr "" " I piccoli volumi saranno sempre uniti quando possono riempire un intero " "volume." -#: Library/Main/Strings.cs:174 +#: Library/Main/Strings.cs:176 msgid "Maximum number of small volumes" msgstr "Numero massimo dei piccoli volumi" -#: Library/Main/Strings.cs:175 +#: Library/Main/Strings.cs:177 msgid "" "Enable this option to look into other files on this machine to find existing" " blocks. This is a fairly slow operation but can limit the size of " @@ -3587,15 +3699,15 @@ msgstr "" "trovare blocchi esistenti. Questa è un'operazione abbastanza lenta, ma può " "limitare la dimensione dei file scaricati." -#: Library/Main/Strings.cs:176 +#: Library/Main/Strings.cs:178 msgid "Use local file data when restoring" msgstr "Utilizza i dati dei file locali durante il ripristino" -#: Library/Main/Strings.cs:177 +#: Library/Main/Strings.cs:179 msgid "Disables the local database" msgstr "Disattiva il database locale" -#: Library/Main/Strings.cs:178 +#: Library/Main/Strings.cs:180 msgid "" "When listing contents or when restoring files, the local database can be " "skipped. This is usually slower, but can be used to verify the actual " @@ -3605,11 +3717,11 @@ msgstr "" "ignorare il database locale. Questo è di solito più lento, ma può essere " "utilizzato per verificare il contenuto effettivo dell'archivio remoto" -#: Library/Main/Strings.cs:179 +#: Library/Main/Strings.cs:181 msgid "Keep a number of versions" msgstr "Mantieni un numero di versioni" -#: Library/Main/Strings.cs:180 +#: Library/Main/Strings.cs:182 msgid "" "Use this option to set number of versions to keep, supply -1 to keep all " "versions" @@ -3617,49 +3729,50 @@ msgstr "" "Usa questa opzione per impostare il numero di versioni da mantenere, metti " "-1 per mantenere tutte le versioni" -#: Library/Main/Strings.cs:181 +#: Library/Main/Strings.cs:183 msgid "Keep all versions within a timespan" msgstr "Mantieni tutte le versioni all'interno di un periodo" -#: Library/Main/Strings.cs:182 +#: Library/Main/Strings.cs:184 msgid "Use this option to set the timespan in which backups are kept." msgstr "" "Usa questa opzione per impostare il periodo in cui sono conservati i backup." -#: Library/Main/Strings.cs:183 +#: Library/Main/Strings.cs:185 msgid "Reduce number of versions by deleting old intermediate backups" msgstr "Riduci il numero di versioni eliminando i vecchi backup intermedi" -#: Library/Main/Strings.cs:184 +#: Library/Main/Strings.cs:186 msgid "" "Use this option to reduce the number of versions that are kept with " "increasing version age by deleting most of the old backups. The expected " -"format is a comma seperated list of collon sperated time frame and interval " +"format is a comma separated list of colon separated time frame and interval " "pairs. For example the value \"7D:0s,3M:1D,10Y:2M\" means \"For 7 day keep " -"all backups, for 3 months keep one backup per day and for 10 years one " -"backup every 2nd month" +"all backups, for 3 months keep one backup every day, for 10 years one backup" +" every 2nd month and delete every backup older than this.\"" msgstr "" -"Usa questa opzione per ridurre il numero di versioni mantenute con l'aumento" -" dell'età della versione eliminando la maggior parte dei vecchi backup. Il " -"formato previsto è un elenco separato da virgole di coppie di tempo separate" -" da due punti. Ad esempio il valore \"7D:0s,3M:1D,10Y:2M\" significa 'per 7 " -"giorni mantieni tutti i backup, per 3 mesi manteni un backup al giorno e per" -" 10 anni un backup ogni 2 mesi" +"Usa questa opzione per ridurre il numero di versioni che sono mantenute con " +"il passare del tempo, eliminando la maggior parte dei vecchi backup. Il " +"formato previsto è un elenco separato da virgola di coppie di intervalli di " +"tempo separati da due punti. Ad esempio il valore \"7D:0s,3M:1D,10Y:2M\" " +"significa \"Per 7 giorni conserva tutti i backup, per 3 mesi conserva un " +"backup ogni giorno, per 10 anni un backup ogni 2 mesi ed eliminare tutti i " +"backup più vecchi di questo.\"" -#: Library/Main/Strings.cs:185 +#: Library/Main/Strings.cs:187 msgid "Ignore missing source elements" msgstr "Ignora elementi sorgente mancanti" -#: Library/Main/Strings.cs:186 +#: Library/Main/Strings.cs:188 msgid "Use this option to continue even if some source entries are missing." msgstr "" "Usa questa opzione per continuare, anche se alcune voci sorgenti mancano." -#: Library/Main/Strings.cs:187 +#: Library/Main/Strings.cs:189 msgid "Overwrite files when restoring" msgstr "Sovrascrivi i file durante il ripristino" -#: Library/Main/Strings.cs:188 +#: Library/Main/Strings.cs:190 msgid "" "Use this option to overwrite target files when restoring, if this option is " "not set the files will be restored with a timestamp and a number appended." @@ -3668,11 +3781,11 @@ msgstr "" "ripristino, se questa opzione non è impostata, i file saranno ripristinati " "con un timestamp e un numero aggiunto." -#: Library/Main/Strings.cs:189 +#: Library/Main/Strings.cs:191 msgid "Output more progress information" msgstr "Fornisci ulteriori informazioni sull'avanzamento" -#: Library/Main/Strings.cs:190 +#: Library/Main/Strings.cs:192 msgid "" "Use this option to increase the amount of output generated when running an " "option. Generally this option will produce a line for each file processed." @@ -3681,11 +3794,11 @@ msgstr "" "durante l'esecuzione di un'opzione. Generalmente questa opzione produrrà una" " linea per ogni file elaborato." -#: Library/Main/Strings.cs:191 +#: Library/Main/Strings.cs:193 msgid "Output full results" msgstr "Fornisci risultati completi" -#: Library/Main/Strings.cs:192 +#: Library/Main/Strings.cs:194 msgid "" "Use this option to increase the amount of output generated as the result of " "the operation, including all filenames." @@ -3693,11 +3806,11 @@ msgstr "" "Usa questa opzione per aumentare la quantità di dati generati in uscita come" " risultato dell'operazione, includendo tutti i nomi dei file." -#: Library/Main/Strings.cs:193 +#: Library/Main/Strings.cs:195 msgid "Determine if verification files are uploaded" msgstr "Determina se i file di verifica sono caricati" -#: Library/Main/Strings.cs:194 +#: Library/Main/Strings.cs:196 msgid "" "Use this option to upload a verification file after changing the remote " "storage. The file is not encrypted and contains the size and SHA256 hashes " @@ -3709,11 +3822,11 @@ msgstr "" "gli hash SHA256 di tutti i file remoti e può essere usato per verificare " "l'integrità dei file." -#: Library/Main/Strings.cs:195 +#: Library/Main/Strings.cs:197 msgid "The number of samples to test after a backup" msgstr "Il numero di campioni da testare dopo un backup" -#: Library/Main/Strings.cs:196 +#: Library/Main/Strings.cs:198 #, csharp-format msgid "" "After a backup is completed, some files are selected for verification on the" @@ -3725,11 +3838,11 @@ msgstr "" " questo valore è impostato a 0 o l'opzione --{0} è impostata, i file remoti " "non sono verificati" -#: Library/Main/Strings.cs:197 +#: Library/Main/Strings.cs:199 msgid "Activates in-depth verification of files" msgstr "Attiva verifica approfondita dei file" -#: Library/Main/Strings.cs:198 +#: Library/Main/Strings.cs:200 #, csharp-format msgid "" "After a backup is completed, some files are selected for verification on the" @@ -3746,22 +3859,22 @@ msgstr "" "impostata, non sono verificati file remoti. Questa opzione è impostata " "automaticamente quando la verifica è eseguita direttamente." -#: Library/Main/Strings.cs:199 +#: Library/Main/Strings.cs:201 msgid "Size of the file read buffer" msgstr "Dimensione del buffer di lettura del file" -#: Library/Main/Strings.cs:200 +#: Library/Main/Strings.cs:202 msgid "" "Use this size to control how many bytes a read from a file before processing" msgstr "" "Usa questa dimensione per controllare il numero di byte letti da un file " "prima dell'elaborazione" -#: Library/Main/Strings.cs:201 +#: Library/Main/Strings.cs:203 msgid "Allow the passphrase to change" msgstr "Consenti la modifica della passphrase" -#: Library/Main/Strings.cs:202 +#: Library/Main/Strings.cs:204 msgid "" "Use this option to allow the passphrase to change, note that this option is " "not permitted for a backup or repair operation" @@ -3769,11 +3882,11 @@ msgstr "" "Usa questa opzione per consentire la modifica della passphrase, nota che " "questa opzione non è consentita per un'operazione di backup o di riparazione" -#: Library/Main/Strings.cs:203 +#: Library/Main/Strings.cs:205 msgid "List only filesets" msgstr "Elenca solo gruppi di file" -#: Library/Main/Strings.cs:204 +#: Library/Main/Strings.cs:206 msgid "" "Use this option to only list filesets and avoid traversing file names and " "other metadata which slows down the process" @@ -3781,11 +3894,11 @@ msgstr "" "Usa questa opzione per elencare solo un gruppo di file ed evitare di " "attraversare i nomi dei file e altri metadati che rallentano il processo" -#: Library/Main/Strings.cs:206 +#: Library/Main/Strings.cs:208 msgid "Don't store metadata" msgstr "Non archiviare i metadati" -#: Library/Main/Strings.cs:207 +#: Library/Main/Strings.cs:209 msgid "" "Use this option to disable the storage of metadata, such as file timestamps." " Disabling metadata storage will speed up the backup and restore operations," @@ -3796,11 +3909,11 @@ msgstr "" "accelererà le operazioni di backup e ripristino, ma non influisce molto " "sulla dimensione del file." -#: Library/Main/Strings.cs:208 +#: Library/Main/Strings.cs:210 msgid "Restore file permissions" msgstr "Ripristina le autorizzazioni sui file" -#: Library/Main/Strings.cs:209 +#: Library/Main/Strings.cs:211 msgid "" "By default permissions are not restored as they might prevent you from " "accessing your files. Use this option to restore the permissions as well." @@ -3809,11 +3922,11 @@ msgstr "" "quanto potrebbero impedire l'accesso ai file. Usa questa opzione per " "ripristinare anche le autorizzazioni." -#: Library/Main/Strings.cs:210 +#: Library/Main/Strings.cs:212 msgid "Skip restored file check" msgstr "Salta il controllo del file ripristinati" -#: Library/Main/Strings.cs:211 +#: Library/Main/Strings.cs:213 msgid "" "After restoring files, the file hash of all restored files are checked to " "verify that the restore was successful. Use this option to disable the check" @@ -3824,20 +3937,20 @@ msgstr "" "correttamente. Usa questa opzione per disabilitare il controllo ed evitare " "di aspettare la verifica." -#: Library/Main/Strings.cs:212 +#: Library/Main/Strings.cs:214 msgid "Activate caches" msgstr "Attiva cache" -#: Library/Main/Strings.cs:213 +#: Library/Main/Strings.cs:215 msgid "Activate in-memory caches, which are now off by default" msgstr "" "Attiva cache in memoria, ora è disattivata per impostazione predefinita" -#: Library/Main/Strings.cs:214 +#: Library/Main/Strings.cs:216 msgid "Do not use local data" msgstr "Non usare dati locali" -#: Library/Main/Strings.cs:215 +#: Library/Main/Strings.cs:217 msgid "" "Duplicati will attempt to use data from source files to minimize the amount " "of downloaded data. Use this option to skip this optimization and only use " @@ -3847,11 +3960,11 @@ msgstr "" "al minimo la quantità di dati scaricati. Utilizza questa opzione per " "ignorare questa ottimizzazione e usare solo i dati remoti." -#: Library/Main/Strings.cs:216 +#: Library/Main/Strings.cs:218 msgid "Check block hashes" msgstr "Controllo hash blocco" -#: Library/Main/Strings.cs:217 +#: Library/Main/Strings.cs:219 msgid "" "Use this option to increase verification by checking the hash of blocks read" " from a volume before patching restored files with the data." @@ -3860,11 +3973,11 @@ msgstr "" "blocchi letti da un volume prima di sistemare i file ripristinati con i " "dati." -#: Library/Main/Strings.cs:220 +#: Library/Main/Strings.cs:222 msgid "Repair database with paths" msgstr "Ripara database con percorsi" -#: Library/Main/Strings.cs:221 +#: Library/Main/Strings.cs:223 msgid "" "Use this option to build a searchable local database which only contains " "path information. This option is usable for quickly building a database to " @@ -3877,11 +3990,11 @@ msgstr "" "ricostruire tutte le informazioni. Il database risultante può essere " "cercato, ma non può essere utilizzato per ripristinare i dati." -#: Library/Main/Strings.cs:222 +#: Library/Main/Strings.cs:224 msgid "Force the locale setting" msgstr "Forza le impostazioni locali" -#: Library/Main/Strings.cs:223 +#: Library/Main/Strings.cs:225 msgid "" "By default, your system locale and culture settings will be used. In some " "cases you may prefer to run with another locale, for example to get messages" @@ -3894,11 +4007,11 @@ msgstr "" "opzione può essere usata per settare le impostazioni locali. Fornire una " "stringa vuota per scegliere la \"lingua non variabile\"." -#: Library/Main/Strings.cs:224 +#: Library/Main/Strings.cs:226 msgid "Handle file communication with backend using threaded pipes" msgstr "Gestire la comunicazione file con backend usando threaded pipe" -#: Library/Main/Strings.cs:225 +#: Library/Main/Strings.cs:227 msgid "" "Use this option to disable multithreaded handling of up- and downloads, that" " can significantly speed up backend operations depending on the hardware " @@ -3909,11 +4022,11 @@ msgstr "" "di backend a seconda dell'hardware che stai usando e della velocità di " "trasferimento del backend." -#: Library/Main/Strings.cs:226 +#: Library/Main/Strings.cs:228 msgid "Perform backup of Hyper-V machines (Windows only)" msgstr "Esegui il backup di macchine Hyper-V (solo Windows)" -#: Library/Main/Strings.cs:227 +#: Library/Main/Strings.cs:229 msgid "" "Use this option to specify the IDs of machines to include in the backup. " "Specify multiple machine IDs with a semicolon separator. (You can use this " @@ -3924,7 +4037,7 @@ msgstr "" "(Puoi usare questo comando Powershell per ottenere ID 'Get-VM | ft VMName, " "ID')" -#: Library/Main/Strings.cs:228 +#: Library/Main/Strings.cs:230 msgid "" "If Duplicati detects that the previous backup did not complete, it will " "generate a filelist that is a merge of the last completed backup and the " @@ -3934,11 +4047,11 @@ msgstr "" "genererà un file elenco che è l'unione dell'ultimo backup completato e del " "contenuto caricato nella sessione di backup incompleta." -#: Library/Main/Strings.cs:229 +#: Library/Main/Strings.cs:231 msgid "Disables synthetic filelist" msgstr "Disabilita elenco file sintetico" -#: Library/Main/Strings.cs:230 +#: Library/Main/Strings.cs:232 msgid "" "This flag instructs Duplicati to not look at metadata or filesize when " "deciding to scan a file for changes. Use this option if you have a large " @@ -3950,15 +4063,15 @@ msgstr "" "modifiche. Usa questa opzione se disponi di un numero elevato di file e noti" " che la scansione richiede molto tempo con i file non modificati." -#: Library/Main/Strings.cs:231 +#: Library/Main/Strings.cs:233 msgid "Checks only file lastmodified" msgstr "Controlla solo il file modificato l'ultima volta" -#: Library/Main/Strings.cs:232 +#: Library/Main/Strings.cs:234 msgid "Disables path compresion on restore" msgstr "Disattiva compressione percorso durante il ripristino" -#: Library/Main/Strings.cs:233 +#: Library/Main/Strings.cs:235 msgid "" "When restore a subset of a backup into a new folder, the shortest possible " "path is used to avoid generating deep paths with empty folders. Use this " @@ -3971,11 +4084,11 @@ msgstr "" "compressione, in modo che l'intera struttura di cartelle originali sia " "mantenuta, incluse le cartelle vuote di livello superiore." -#: Library/Main/Strings.cs:234 +#: Library/Main/Strings.cs:236 msgid "Allow removing all filesets" msgstr "Consenti rimozione di tutti i gruppi di file" -#: Library/Main/Strings.cs:235 +#: Library/Main/Strings.cs:237 msgid "" "By default, the last fileset cannot be removed. This is a safeguard to make " "sure that all remote data is not deleted by a configuration mistake. Use " @@ -3987,13 +4100,13 @@ msgstr "" "disabilitare tale protezione, in modo che tutti i gruppo di file possano " "essere cancellati." -#: Library/Main/Strings.cs:236 +#: Library/Main/Strings.cs:238 msgid "Allow automatic rebuilding of local database to save space." msgstr "" "Consenti la ricostruzione automatica del database locale per risparmiare " "spazio." -#: Library/Main/Strings.cs:237 +#: Library/Main/Strings.cs:239 msgid "" "Some operations that manipulate the local database leave unused entries " "behind. These entries are not deleted from a hard drive until a VACUUM " @@ -4010,7 +4123,23 @@ msgstr "" "L'impostazione a true consentirà a Duplicati di eseguire operazioni VACUUM a" " sua discrezione." -#: Library/Main/Strings.cs:242 +#: Library/Main/Strings.cs:240 +msgid "Disable the read-ahead scanner" +msgstr "Disabilita lo scanner di lettura in anticipo" + +#: Library/Main/Strings.cs:241 +msgid "" +"When this flag is enabled, the scanner that computes the size of source " +"files is disabled, and instead the reported size is read from the database. " +"Using this flag can speed up the backup by reducing disk access, but will " +"give a less accurate progress indicator." +msgstr "" +"Quando questo flag è abilitato, lo scanner che calcola la dimensione dei " +"file di origine è disabilitato, la dimensione riportata è letta dal " +"database. L'uso di questo flag può accelerare il backup riducendo l'accesso " +"al disco, ma fornirà un indicatore di progresso meno preciso." + +#: Library/Main/Strings.cs:246 #, csharp-format msgid "" "The cryptolibrary does not support re-usable transforms for the hash " @@ -4019,16 +4148,16 @@ msgstr "" "La libreria di crittografia non supporta le trasformazioni riutilizzabili " "per l'algoritmo hash {0}" -#: Library/Main/Strings.cs:243 +#: Library/Main/Strings.cs:247 #, csharp-format msgid "The cryptolibrary does not support the hash algorithm {0}" msgstr "La libreria di crittografia non supporta l'algoritmo hash {0}" -#: Library/Main/Strings.cs:244 +#: Library/Main/Strings.cs:248 msgid "The passphrase cannot be changed for an existing backup" msgstr "La passphrase non può essere modificata per un backup esistente" -#: Library/Main/Strings.cs:245 +#: Library/Main/Strings.cs:249 #, csharp-format msgid "Failed to create a snapshot: {0}" msgstr "Creare dell'istantanea fallita: {0}" @@ -4868,24 +4997,6 @@ msgstr "" msgid "Supported generic modules:" msgstr "Moduli generici supportati:" -#: CommandLine/Strings.cs:18 -#, csharp-format -msgid "Unable to read the parameters file \"{0}\", reason: {1}" -msgstr "Impossibile leggere il file dei parametri \"{0}\", motivo: {1}" - -#: CommandLine/Strings.cs:19 -#, csharp-format -msgid "" -"Filters cannot be specified on the commandline if filters are also present " -"in the parameter file. Use the special --{0}, --{1}, or --{2} options to " -"specify filters inside the parameter file. Each filter must be prefixed with" -" either a + or a -, and multiple filters must be joined with {3}" -msgstr "" -"I filtri non possono essere specificati dalla riga di comando se sono " -"presenti anche nel file parametri. Usa le opzioni speciali --{0}, --{1}, o " -"--{2} per specificare i filtri all'interno del file parametri. Ogni filtro " -"deve avere un prefisso + o un -, e più filtri devono essere uniti con {3}" - #: CommandLine/Strings.cs:20 #, csharp-format msgid "" @@ -4895,36 +5006,6 @@ msgstr "" "L'opzione --{0} è stata impostata, ma essa è riservata per uso interno e " "non può essere usata da riga di comando" -#: CommandLine/Strings.cs:21 -#, csharp-format -msgid "" -"This option can be used to store some or all of the options given to the " -"commandline client. The file must be a plain text file, UTF-8 encoding is " -"preferred. Each line in the file should be of the format --option=value. The" -" special options --{0} and --{1} can be used to override the localpath and " -"the remote destination uri, respectively. The options in this file take " -"precedence over the options provided on the commandline. You cannot specify " -"filters in both the file and on the commandline. Instead, you can use the " -"special --{2}, --{3}, or --{4} options to specify filters inside the " -"parameter file. Each filter must be prefixed with either a + or a -, and " -"multiple filters must be joined with {5} " -msgstr "" -"Questa opzione può essere utilizzata per memorizzare alcune o tutte le " -"opzioni fornite al client Riga di comando. Il file deve essere un file di " -"testo normale, la codifica UTF-8 è preferibile. Ogni riga nel file deve " -"essere del formato -option=value. Le opzioni speciali -{0} e --{1} possono " -"essere utilizzate per sovrascrivere rispettivamente il LocalPath e l'URI di " -"destinazione remota. Le opzioni in questo file hanno la precedenza sulle " -"opzioni fornite dalla riga di comando. Non è possibile specificare filtri " -"sia nel file sia nella riga di comando. È invece possibile utilizzare le " -"opzioni speciali --{2}, --{3}, o --{4} per specificare i filtri all'interno " -"del file dei parametri. Ogni filtro deve essere preceduto con un + o un -, e" -" più filtri devono essere uniti con {5}" - -#: CommandLine/Strings.cs:22 -msgid "Path to a file with parameters" -msgstr "Percorso di un file con parametri" - #: CommandLine/Strings.cs:23 #, csharp-format msgid "An error occured: {0}" diff --git a/Localizations/duplicati/localization-nl_NL.mo b/Localizations/duplicati/localization-nl_NL.mo index ff340517f..88810a229 100644 Binary files a/Localizations/duplicati/localization-nl_NL.mo and b/Localizations/duplicati/localization-nl_NL.mo differ diff --git a/Localizations/duplicati/localization-nl_NL.po b/Localizations/duplicati/localization-nl_NL.po index e86d52af7..54474c3f9 100644 --- a/Localizations/duplicati/localization-nl_NL.po +++ b/Localizations/duplicati/localization-nl_NL.po @@ -10,7 +10,7 @@ msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2018-02-12 07:39+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: Kees Zaaijer , 2016\n" +"Last-Translator: Kees Zaaijer, 2016\n" "Language-Team: Dutch (Netherlands) (https://www.transifex.com/duplicati/teams/67655/nl_NL/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -1037,13 +1037,15 @@ msgstr "Google Drive" #: Library/Backend/GoogleServices/Strings.cs:48 msgid "Hide team drives" -msgstr "" +msgstr "Verberg team drives" #: Library/Backend/GoogleServices/Strings.cs:49 msgid "" "This option disables the team drives, showing only files and folders " "accesible with the account itself" msgstr "" +"Deze optie schakelt team drives uit, waardoor alleen bestanden en mappen " +"getoond worden die voor de account zelf toegankelijk zijn." #: Library/Backend/CloudFiles/Strings.cs:4 #, csharp-format @@ -1613,56 +1615,63 @@ msgstr "" #: Library/Backend/Rclone/Strings.cs:6 msgid "Rclone" -msgstr "" +msgstr "Rclone" #: Library/Backend/Rclone/Strings.cs:7 msgid "This backend can read and write data to Rclone." -msgstr "" +msgstr "Deze backend kan gegevens lezen en schrijven naar Rclone." #: Library/Backend/Rclone/Strings.cs:8 msgid "Local repository" -msgstr "" +msgstr "Lokale opslagplaats" #: Library/Backend/Rclone/Strings.cs:9 msgid "" "Local repository for Rclone. Make sure it is configured as a local drive, as" " it needs access to the files generated by Duplicati." msgstr "" +"Lokale opslagplaats voor Rclone. Zorg ervoor dat deze is ingesteld als een " +"lokaal station, omdat het toegang moet hebben tot de bestanden die door " +"Duplicati zijn aangemaakt." #: Library/Backend/Rclone/Strings.cs:10 msgid "Remote repository" -msgstr "" +msgstr "Remote opslagplaats" #: Library/Backend/Rclone/Strings.cs:11 msgid "" "Remote repository for Rclone. This can be any of the backends provided by " "Rclone. More info available on https://rclone.org/." msgstr "" +"Remote opslagplaats voor Rclone. Dit kan iedere backend zijn die door Rclone" +" wordt geleverd. Meer info beschikbaar op https://rclone.org/." #: Library/Backend/Rclone/Strings.cs:12 msgid "Remote path" -msgstr "" +msgstr "Remote pad" #: Library/Backend/Rclone/Strings.cs:13 msgid "Path on the Remote repository. " -msgstr "" +msgstr "Pad op de Remote opslagplaats." #: Library/Backend/Rclone/Strings.cs:14 msgid "Rclone options." -msgstr "" +msgstr "Rclone opties." #: Library/Backend/Rclone/Strings.cs:15 msgid "Options will be transferred to rclone." -msgstr "" +msgstr "Opties worden overgebracht naar Rclone." #: Library/Backend/Rclone/Strings.cs:16 msgid "Rclone executable" -msgstr "" +msgstr "Rclone uitvoerbaar bestand" #: Library/Backend/Rclone/Strings.cs:17 msgid "" "Full path to the rclone executable. Only needed if it's not in your path." msgstr "" +"Volledig pad naar het Rclone uitvoerbaar bestand. Alleen nodig als het zich " +"niet in het zoekpad bevindt." #: Library/Backend/File/Strings.cs:4 #, csharp-format @@ -3310,10 +3319,15 @@ msgid "" "size. If the backend does not report the quota information, this value will " "be ignored" msgstr "" +"Stelt de drempelwaarde in wanneer gewaarschuwd moet worden als de backend " +"quota bijna overschreven wordt. Het wordt opgegeven als een percentage, en " +"een waarschuwing wordt gegenereerd als de hoeveelheid beschikbare quota " +"minder is dan dit percentage van de totale back-upgrootte. Als de backend " +"deze quota-informatie niet ondersteunt, zal deze waarde worden genegeerd." #: Library/Main/Strings.cs:123 msgid "Threshold for warning about low quota" -msgstr "" +msgstr "Drempelwaarde voor waarschuwing voor lage quota" #: Library/Main/Strings.cs:124 #, csharp-format @@ -3769,6 +3783,14 @@ msgid "" "all backups, for 3 months keep one backup every day, for 10 years one backup" " every 2nd month and delete every backup older than this.\"" msgstr "" +"Gebruik deze optie om het aantal versies te verminderen dat behouden wordt " +"bij toenemende versie-ouderdom door de meeste oude back-ups te verwijderen. " +"De verwachte indeling is een door komma's gescheiden lijst met door dubbele " +"punt gescheiden paren van tijdvensters en intervallen. Bijvoorbeeld de " +"waarde \"7D:0s,3M:1D,10Y:2M\" betekent \"Bewaar alle back-ups van de laatste" +" 7 dagen, bewaar van iedere dag één backup-up voor 3 maanden, bewaar van " +"iedere twee maanden één backup voor 10 jaar en verwijder alle back-ups die " +"nog ouder zijn." #: Library/Main/Strings.cs:187 msgid "Ignore missing source elements" @@ -4138,7 +4160,7 @@ msgstr "" #: Library/Main/Strings.cs:240 msgid "Disable the read-ahead scanner" -msgstr "" +msgstr "Schakel de vooruit lees-scanner uit" #: Library/Main/Strings.cs:241 msgid "" @@ -4147,6 +4169,11 @@ msgid "" "Using this flag can speed up the backup by reducing disk access, but will " "give a less accurate progress indicator." msgstr "" +"Als deze vlag is ingeschakeld, wordt de scanner die de omvang van " +"bronbestanden berekent uitgeschakeld. In plaats hiervan wordt de " +"gerapporteerde grootte gelezen uit de database. Het gebruik van deze vlag " +"kan het back-up proces versnellen door het verminderen van schijftoegang, " +"maar zak een minder accurate voortgangsindicator tot gevolg hebben." #: Library/Main/Strings.cs:246 #, csharp-format diff --git a/Localizations/duplicati/localization-pt.mo b/Localizations/duplicati/localization-pt.mo index 357783c80..a283ebd03 100644 Binary files a/Localizations/duplicati/localization-pt.mo and b/Localizations/duplicati/localization-pt.mo differ diff --git a/Localizations/duplicati/localization-pt.po b/Localizations/duplicati/localization-pt.po index 62100fdcd..564835347 100644 --- a/Localizations/duplicati/localization-pt.po +++ b/Localizations/duplicati/localization-pt.po @@ -65,7 +65,7 @@ msgstr "" #: Server/Strings.cs:16 CommandLine/Strings.cs:22 msgid "Path to a file with parameters" -msgstr "Caminho do ficheiro (com parâmetros)" +msgstr "Caminho para o ficheiro, com parâmetros" #: Server/Strings.cs:17 CommandLine/Strings.cs:19 #, csharp-format @@ -296,7 +296,7 @@ msgstr "" #: Library/Encryption/Strings.cs:22 #, csharp-format msgid "Failed to execute GPG at \"\"{0}\" {1}\": {2}" -msgstr "" +msgstr "Falha ao executar GPG em \"\"{0}\" {1}\": {2}" #: Library/Encryption/Strings.cs:23 msgid "" @@ -306,7 +306,7 @@ msgstr "" #: Library/Encryption/Strings.cs:24 msgid "The path to GnuPG" -msgstr "" +msgstr "O caminho para GnuPG" #: Library/Encryption/Strings.cs:25 #, csharp-format diff --git a/Localizations/duplicati/localization-zh_TW.mo b/Localizations/duplicati/localization-zh_TW.mo index 029adb501..0d30f23b6 100644 Binary files a/Localizations/duplicati/localization-zh_TW.mo and b/Localizations/duplicati/localization-zh_TW.mo differ diff --git a/Localizations/duplicati/localization-zh_TW.po b/Localizations/duplicati/localization-zh_TW.po index 79ec9dd6a..c938c6376 100644 --- a/Localizations/duplicati/localization-zh_TW.po +++ b/Localizations/duplicati/localization-zh_TW.po @@ -161,7 +161,7 @@ msgstr "" #: Server/Strings.cs:36 Library/Main/Strings.cs:220 msgid "Clean up old log data" -msgstr "" +msgstr "清理舊的記錄資料" #: Server/Strings.cs:37 Library/Main/Strings.cs:221 msgid "Set the time after which log data will be purged from the database." @@ -445,7 +445,7 @@ msgstr "" #: Library/Interface/Strings.cs:30 msgid "You must enter a username" -msgstr "" +msgstr "您需要輸入帳號" #: Library/Interface/Strings.cs:31 msgid "" @@ -467,7 +467,7 @@ msgstr "" #: Library/Interface/Strings.cs:38 msgid "Folder created!" -msgstr "" +msgstr "資料夾已建立" #: Library/Interface/Strings.cs:39 msgid "The requested folder does not exist" @@ -480,7 +480,7 @@ msgstr "" #: Library/Interface/Strings.cs:41 msgid "Cancelled" -msgstr "" +msgstr "已取消" #: Library/Interface/CustomExceptions.cs:77 #: Library/Interface/CustomExceptions.cs:85 @@ -1339,7 +1339,7 @@ msgstr "" #: Library/Backend/Rclone/Strings.cs:8 msgid "Local repository" -msgstr "" +msgstr "本機 repository" #: Library/Backend/Rclone/Strings.cs:9 msgid "" @@ -1349,7 +1349,7 @@ msgstr "" #: Library/Backend/Rclone/Strings.cs:10 msgid "Remote repository" -msgstr "" +msgstr "遠端 repository" #: Library/Backend/Rclone/Strings.cs:11 msgid "" @@ -1359,7 +1359,7 @@ msgstr "" #: Library/Backend/Rclone/Strings.cs:12 msgid "Remote path" -msgstr "" +msgstr "遠端 path" #: Library/Backend/Rclone/Strings.cs:13 msgid "Path on the Remote repository. " @@ -1428,7 +1428,7 @@ msgstr "" #: Library/Backend/File/Strings.cs:13 msgid "Local folder or drive" -msgstr "" +msgstr "本機資料夾或磁碟" #: Library/Backend/File/Strings.cs:14 #, csharp-format @@ -3455,7 +3455,7 @@ msgstr "" #: Library/Modules/Builtin/Strings.cs:29 msgid "Configure http requests" -msgstr "" +msgstr "http 相關選項" #: Library/Modules/Builtin/Strings.cs:30 msgid "Alternate OAuth URL" @@ -3538,7 +3538,7 @@ msgstr "" #: Library/Modules/Builtin/Strings.cs:52 msgid "Run script" -msgstr "" +msgstr "執行 script" #: Library/Modules/Builtin/Strings.cs:53 msgid "" @@ -3608,7 +3608,7 @@ msgstr "" #: Library/Modules/Builtin/Strings.cs:68 msgid "Send mail" -msgstr "" +msgstr "寄送郵件" #: Library/Modules/Builtin/Strings.cs:69 #, csharp-format @@ -3813,7 +3813,7 @@ msgstr "" #: Library/Modules/Builtin/Strings.cs:134 msgid "XMPP report module" -msgstr "" +msgstr "XMPP 通知功能" #: Library/Modules/Builtin/Strings.cs:135 msgid "" @@ -3831,7 +3831,7 @@ msgstr "" #: Library/Modules/Builtin/Strings.cs:141 msgid "HTTP report module" -msgstr "" +msgstr "HTTP 通知功能" #: Library/Modules/Builtin/Strings.cs:142 msgid "" diff --git a/Localizations/webroot/localization_webroot-cs.po b/Localizations/webroot/localization_webroot-cs.po index 4936eb3a1..5f85683fe 100644 --- a/Localizations/webroot/localization_webroot-cs.po +++ b/Localizations/webroot/localization_webroot-cs.po @@ -22,12 +22,12 @@ msgstr "…načítání…" msgid "API Key" msgstr "Klíč k aplikačnímu programovému rozhraní (API)" -#: scripts/services/EditUriBuiltins.js:691 templates/backends/s3.html:54 +#: scripts/services/EditUriBuiltins.js:725 templates/backends/s3.html:54 #: templates/backends/s3.html:55 msgid "AWS Access ID" msgstr "Přístupový identifikátor ke službe AWS" -#: scripts/services/EditUriBuiltins.js:692 templates/backends/s3.html:58 +#: scripts/services/EditUriBuiltins.js:726 templates/backends/s3.html:58 #: templates/backends/s3.html:59 msgid "AWS Access Key" msgstr "Přístupový klíč ke službě AWS" @@ -36,7 +36,7 @@ msgstr "Přístupový klíč ke službě AWS" msgid "AWS IAM Policy" msgstr "Zásady IAM služby AWS" -#: index.html:226 index.html:242 +#: index.html:217 index.html:233 msgid "About" msgstr "O aplikaci" @@ -44,7 +44,7 @@ msgstr "O aplikaci" msgid "About {{appname}}" msgstr "O aplikaci {{appname}}" -#: scripts/services/EditUriBuiltins.js:656 templates/backends/azure.html:11 +#: scripts/services/EditUriBuiltins.js:690 templates/backends/azure.html:11 msgid "Access Key" msgstr "Přístupový klíč" @@ -56,7 +56,7 @@ msgstr "Přístup odepřen" msgid "Access to user interface" msgstr "Přístup k uživatelskému rozhraní" -#: scripts/services/EditUriBuiltins.js:655 templates/backends/azure.html:7 +#: scripts/services/EditUriBuiltins.js:689 templates/backends/azure.html:7 msgid "Account name" msgstr "Název účtu" @@ -81,7 +81,7 @@ msgstr "Přidat popis umístění přímo" msgid "Add advanced option" msgstr "Přidat pokročilou volbu" -#: index.html:211 +#: index.html:205 msgid "Add backup" msgstr "Přidat zálohu" @@ -93,12 +93,12 @@ msgstr "Přidat filtr" msgid "Add path" msgstr "Přidat popis umístění" -#: scripts/services/EditUriBuiltins.js:702 -#: scripts/services/EditUriBuiltins.js:719 +#: scripts/services/EditUriBuiltins.js:736 +#: scripts/services/EditUriBuiltins.js:753 msgid "Adjust bucket name?" msgstr "Přizpůsobit název „nádoby“ (bucket)?" -#: scripts/services/EditUriBuiltins.js:630 +#: scripts/services/EditUriBuiltins.js:664 msgid "Adjust path name?" msgstr "Přizpůsobit popis umístění?" @@ -106,7 +106,7 @@ msgstr "Přizpůsobit popis umístění?" msgid "Advanced Options" msgstr "Pokročilé volby" -#: templates/addoredit.html:348 templates/edituri.html:28 +#: templates/addoredit.html:374 templates/edituri.html:28 msgid "Advanced options" msgstr "Pokročilé volby" @@ -114,7 +114,7 @@ msgstr "Pokročilé volby" msgid "Advanced:" msgstr "Pokročilé:" -#: scripts/controllers/EditBackupController.js:22 +#: scripts/controllers/EditBackupController.js:24 msgid "All" msgstr "Vše" @@ -157,7 +157,7 @@ msgstr "" "V novém umístění byl nalezen už existující soubor\n" "Opravdu chcete nasměrovat databázi do existujícího souboru?" -#: scripts/controllers/EditBackupController.js:472 +#: scripts/controllers/EditBackupController.js:496 msgid "" "An existing local database for the storage has been found.\n" "Re-using the database will allow the command-line and server instances to work on the same remote storage.\n" @@ -177,7 +177,7 @@ msgstr "Anonymní hlášení o použití" msgid "As Command-line" msgstr "Jako příkazový řádek" -#: scripts/services/EditUriBuiltins.js:614 templates/backends/gcs.html:8 +#: scripts/services/EditUriBuiltins.js:648 templates/backends/gcs.html:8 #: templates/backends/gcs.html:9 templates/backends/oauth.html:8 #: templates/backends/oauth.html:9 msgid "AuthID" @@ -191,7 +191,7 @@ msgstr "Ověřovací heslo" msgid "Authentication username" msgstr "Ověřovací uživatelské jméno" -#: scripts/controllers/EditBackupController.js:381 +#: scripts/controllers/EditBackupController.js:405 msgid "Autogenerated passphrase" msgstr "Automaticky vytvořená heslová fráze" @@ -207,11 +207,11 @@ msgstr "Identifikátor účtu u služby B2" msgid "B2 Application Key" msgstr "Aplikační klíč ke službě B2" -#: scripts/services/EditUriBuiltins.js:738 templates/backends/b2.html:13 +#: scripts/services/EditUriBuiltins.js:772 templates/backends/b2.html:13 msgid "B2 Cloud Storage Account ID" msgstr "Identifikátor účtu u cloudového úložiště B2" -#: scripts/services/EditUriBuiltins.js:739 templates/backends/b2.html:17 +#: scripts/services/EditUriBuiltins.js:773 templates/backends/b2.html:17 msgid "B2 Cloud Storage Application Key" msgstr "Aplikační klíč ke cloudovému úložišti B2" @@ -219,7 +219,7 @@ msgstr "Aplikační klíč ke cloudovému úložišti B2" msgid "Back" msgstr "Zpět" -#: templates/about.html:66 +#: templates/about.html:67 msgid "Backend modules:" msgstr "Moduly podpůrných vrstev (backend):" @@ -232,6 +232,10 @@ msgstr "Cíl zálohy" msgid "Backup location" msgstr "Umístění zálohy" +#: templates/addoredit.html:317 +msgid "Backup retention" +msgstr "Doba uchovávání záloh" + #: templates/home.html:60 msgid "Backup:" msgstr "Záloha:" @@ -252,9 +256,9 @@ msgstr "Procházet" msgid "Browser default" msgstr "Výchozí nastavení webového prohlížeče" -#: scripts/services/EditUriBuiltins.js:666 -#: scripts/services/EditUriBuiltins.js:690 -#: scripts/services/EditUriBuiltins.js:737 +#: scripts/services/EditUriBuiltins.js:700 +#: scripts/services/EditUriBuiltins.js:724 +#: scripts/services/EditUriBuiltins.js:771 msgid "Bucket Name" msgstr "Název „nádoby“ (bucket)" @@ -294,13 +298,13 @@ msgstr "Kanárek" #: scripts/controllers/AppController.js:44 #: scripts/controllers/AppController.js:59 -#: scripts/controllers/EditBackupController.js:366 -#: scripts/controllers/EditBackupController.js:381 -#: scripts/controllers/EditBackupController.js:415 -#: scripts/controllers/EditBackupController.js:424 -#: scripts/controllers/EditBackupController.js:451 -#: scripts/controllers/EditBackupController.js:472 -#: scripts/controllers/EditBackupController.js:82 +#: scripts/controllers/EditBackupController.js:390 +#: scripts/controllers/EditBackupController.js:405 +#: scripts/controllers/EditBackupController.js:439 +#: scripts/controllers/EditBackupController.js:448 +#: scripts/controllers/EditBackupController.js:475 +#: scripts/controllers/EditBackupController.js:496 +#: scripts/controllers/EditBackupController.js:84 #: scripts/controllers/LocalDatabaseController.js:72 #: scripts/controllers/LocalDatabaseController.js:88 #: scripts/controllers/RestoreDirectController.js:24 @@ -308,9 +312,9 @@ msgstr "Kanárek" #: scripts/controllers/StateController.js:112 #: scripts/services/CaptchaService.js:22 scripts/services/DialogService.js:50 #: scripts/services/EditUriBuiltins.js:47 -#: scripts/services/EditUriBuiltins.js:630 -#: scripts/services/EditUriBuiltins.js:702 -#: scripts/services/EditUriBuiltins.js:719 templates/delete.html:54 +#: scripts/services/EditUriBuiltins.js:664 +#: scripts/services/EditUriBuiltins.js:736 +#: scripts/services/EditUriBuiltins.js:753 templates/delete.html:54 #: templates/export.html:26 templates/settings.html:146 #: templates/waitarea.html:19 msgid "Cancel" @@ -332,7 +336,7 @@ msgstr "Seznam změn v {{appname}} {{version}}" msgid "Check failed:" msgstr "Zjištění se nezdařilo:" -#: templates/about.html:35 +#: templates/about.html:36 msgid "Check for updates now" msgstr "Zjistit dostupnost případných aktualizací nyní" @@ -340,7 +344,7 @@ msgstr "Zjistit dostupnost případných aktualizací nyní" msgid "Checking ..." msgstr "Zjišťování…" -#: templates/about.html:36 +#: templates/about.html:37 msgid "Checking for updates ..." msgstr "Zjišťování dostupnosti případných aktualizací…" @@ -352,7 +356,7 @@ msgstr "Pro začátek vyberte typ úložiště" msgid "Click the AuthID link to create an AuthID" msgstr "AuthID vytvoříte kliknutím na odkaz AuthID" -#: index.html:156 index.html:199 +#: index.html:150 index.html:193 msgid "Click to set throttle options" msgstr "Kliknutím nastavte předvolby přiškrcování" @@ -376,7 +380,7 @@ msgstr "Dokončování zálohy…" msgid "Completing previous backup ..." msgstr "Dokončování předchozí zálohy…" -#: templates/about.html:67 +#: templates/about.html:68 msgid "Compression modules:" msgstr "Komprimační moduly:" @@ -410,11 +414,11 @@ msgstr "Vyžadováno potvrzení" msgid "Connect" msgstr "Připojit" -#: index.html:319 +#: index.html:305 msgid "Connect now" msgstr "Připojit nyní" -#: index.html:315 +#: index.html:301 msgid "Connecting to server ..." msgstr "Připojování k serveru…" @@ -422,11 +426,11 @@ msgstr "Připojování k serveru…" msgid "Connecting to task ...." msgstr "Připojování k úloze…" -#: index.html:320 +#: index.html:306 msgid "Connecting..." msgstr "Připojování…" -#: index.html:311 +#: index.html:297 msgid "Connection lost" msgstr "Spojení ztraceno" @@ -435,7 +439,7 @@ msgstr "Spojení ztraceno" msgid "Connection worked!" msgstr "Spojení funguje!" -#: scripts/services/EditUriBuiltins.js:657 templates/backends/azure.html:2 +#: scripts/services/EditUriBuiltins.js:691 templates/backends/azure.html:2 msgid "Container name" msgstr "Název kontejneru" @@ -447,7 +451,7 @@ msgstr "Region umístění kontejneru" msgid "Continue" msgstr "Pokračovat" -#: scripts/controllers/EditBackupController.js:451 +#: scripts/controllers/EditBackupController.js:475 msgid "Continue without encryption" msgstr "Pokračovat bez šifrování" @@ -455,6 +459,10 @@ msgstr "Pokračovat bez šifrování" msgid "Copied!" msgstr "Zkopírováno!" +#: templates/copy_clipboard_buttons.html:3 +msgid "Copy" +msgstr "Kopírovat" + #: templates/addoredit.html:99 templates/restoredirect.html:42 msgid "Copy Destination URL to Clipboard" msgstr "Zkopírovat URL adresu cíle do schránky" @@ -519,6 +527,10 @@ msgstr "Vlastní S3 koncový bod" msgid "Custom authentication url" msgstr "Vlastní ověřovací URL adresa" +#: templates/addoredit.html:323 +msgid "Custom backup retention" +msgstr "Uživatelem určená doba uchovávání záloh" + #: templates/backends/gcs.html:18 msgid "Custom location ({{server}})" msgstr "Vlastní umístění ({{server}})" @@ -543,7 +555,7 @@ msgstr "Vlastní třída úložiště ({{class}})" msgid "Database ..." msgstr "Databáze…" -#: scripts/services/AppUtils.js:90 templates/addoredit.html:328 +#: scripts/services/AppUtils.js:90 templates/addoredit.html:349 msgid "Days" msgstr "Dnů" @@ -575,6 +587,10 @@ msgstr "Smazat…" msgid "Delete backup" msgstr "Smazat zálohu" +#: templates/addoredit.html:320 +msgid "Delete backups that are older than" +msgstr "Smazat zálohy starší než" + #: templates/delete.html:13 msgid "Delete local database" msgstr "Smazat místní databázi" @@ -641,18 +657,10 @@ msgstr "Opravdu chcete smazat zálohu: „{{name}}“?" msgid "Do you really want to delete the local database for: {{name}}" msgstr "Opravdu chcete smazat místní databázi pro: {{name}}" -#: index.html:141 index.html:269 +#: index.html:142 index.html:241 msgid "Donate" msgstr "Darovat" -#: index.html:147 index.html:275 -msgid "Donate with PayPal" -msgstr "Darovat prostřednictvím PayPal" - -#: index.html:144 index.html:272 -msgid "Donate with crypto currency" -msgstr "Darovat v kryptoměně" - #: templates/settings.html:58 templates/settings.html:60 msgid "Donation messages" msgstr "Darovací zprávy" @@ -689,11 +697,11 @@ msgstr "Stahování aktualizace…" msgid "Duplicate option {{opt}}" msgstr "Volba duplikace {{opt}}" -#: index.html:263 +#: index.html:261 msgid "Duplicati Website" msgstr "Webové stránky projektu Duplicati" -#: index.html:251 +#: index.html:249 msgid "Duplicati forum" msgstr "Diskuzní fórum o Duplicati" @@ -722,12 +730,12 @@ msgstr "" msgid "Edit ..." msgstr "Upravit…" -#: templates/addoredit.html:170 templates/addoredit.html:359 +#: templates/addoredit.html:170 templates/addoredit.html:385 #: templates/edituri.html:39 templates/settings.html:135 msgid "Edit as list" msgstr "Upravit jako seznam" -#: templates/addoredit.html:173 templates/addoredit.html:362 +#: templates/addoredit.html:173 templates/addoredit.html:388 #: templates/edituri.html:42 templates/settings.html:141 msgid "Edit as text" msgstr "Upravit jako text" @@ -741,19 +749,33 @@ msgstr "Zašifrovat soubor" msgid "Encryption" msgstr "Šifrování" -#: scripts/controllers/EditBackupController.js:424 +#: scripts/controllers/EditBackupController.js:448 msgid "Encryption changed" msgstr "Šifrování změněno" -#: templates/about.html:68 +#: templates/about.html:69 msgid "Encryption modules:" msgstr "Šifrovací moduly:" -#: scripts/controllers/EditBackupController.js:82 +#: scripts/controllers/EditBackupController.js:84 #: scripts/controllers/RestoreDirectController.js:24 msgid "Enter URL" msgstr "Zadejte URL adresu" +#: templates/addoredit.html:337 +msgid "" +"Enter a retention strategy manually. Placeholders are D/W/Y for " +"days/weeks/years. The syntax is: 7D:1D,4W:1W,36M:1M. This example keeps one " +"backup for each of the next 7 days, one for each of the next 4 weeks, and " +"one for each of the next 36 months. This can also be written as " +"1W:1D,1M:1W,3Y:1M." +msgstr "" +"Zadejte strategii uchovávání záloh ručně. Výplň je D/W/Y pro dny/týdny/roky." +" Forma zápisu je: 7D:1D,4W:1W,36M:1M. V tomto příkladu je ponechána jedna " +"záloha z každého dne po dobu příštích 7 dnů, jedna z každého týdne po dobu " +"příštích 4 týdnů a jedna z každého měsíce po dobu příštích 36 měsíců. Je " +"možné zapsat také jako 1W:1D,1M:1W,3Y:1M." + #: templates/backends/azure.html:12 msgid "Enter access key" msgstr "Zadejte přístupový klíč" @@ -885,6 +907,10 @@ msgstr "Exportovat nastavení" msgid "Exporting ..." msgstr "Exportování…" +#: templates/externallink.html:1 +msgid "External link" +msgstr "Vnější odkaz" + #: scripts/services/SystemInfo.js:52 msgid "FTP (Alternative)" msgstr "FTP (alternativní)" @@ -925,7 +951,7 @@ msgstr "Nepodařilo se stáhnout informaci o popisu umístění: {{message}}" msgid "Failed to import:" msgstr "Nepodařilo se importovat:" -#: scripts/controllers/EditBackupController.js:737 +#: scripts/controllers/EditBackupController.js:768 msgid "Failed to read backup defaults:" msgstr "Nepodařilo se načíst výchozí parametry zálohy:" @@ -1015,7 +1041,7 @@ msgstr "Vytvořit IAM zásady přístupu" msgid "Getting file versions ..." msgstr "Získávání verzí souboru…" -#: scripts/controllers/EditBackupController.js:26 +#: scripts/controllers/EditBackupController.js:28 msgid "Hidden files" msgstr "Skryté soubory" @@ -1027,7 +1053,7 @@ msgstr "Skrýt" msgid "Hide hidden folders" msgstr "Skrýt skryté složky" -#: index.html:208 scripts/services/AppUtils.js:61 +#: index.html:202 scripts/services/AppUtils.js:61 msgid "Home" msgstr "Domovská složka" @@ -1062,6 +1088,14 @@ msgstr "Identifikátor:" msgid "If a date was missed, the job will run as soon as possible." msgstr "Pokud chybělo datum, úloha bude spuštěna co možná nejdříve." +#: templates/addoredit.html:357 +msgid "" +"If at least one newer backup is found, all backups older than this date are " +"deleted." +msgstr "" +"Pokud je nalezena alespoň jedna novější záloha, všechny zálohy starší než " +"tento datum budou smazány." + #: templates/localdatabase.html:13 msgid "" "If the backup and the remote storage is out of sync, Duplicati will require " @@ -1121,7 +1155,7 @@ msgstr "" "Pokud je stroj používán vícero uživateli (tj. je na něm více než jeden uživatelský účet), je třeba nastavit heslo, které ostatním uživatelům brání v přístupu k datům ve vašem účtu.\n" "Nastavit heslo nyní?" -#: templates/import.html:26 +#: templates/import.html:31 msgid "Import" msgstr "Import" @@ -1145,11 +1179,15 @@ msgstr "Import se nezdařil" msgid "Import from a file" msgstr "Importovat ze souboru" -#: templates/import.html:30 +#: templates/import.html:19 +msgid "Import metadata" +msgstr "Importovat metadata" + +#: templates/import.html:35 msgid "Importing ..." msgstr "Importování…" -#: scripts/controllers/EditBackupController.js:150 +#: scripts/controllers/EditBackupController.js:152 msgid "Include a file?" msgstr "Zahrnout soubor?" @@ -1181,16 +1219,17 @@ msgstr "Nainstalovat" msgid "Install failed:" msgstr "Instalace se nezdařila:" -#: scripts/services/EditUriBuiltins.js:771 +#: scripts/services/EditUriBuiltins.js:805 msgid "Invalid characters in path" msgstr "Neplatné znaky v popisu umístění" -#: scripts/controllers/EditBackupController.js:323 -#: scripts/controllers/EditBackupController.js:330 +#: scripts/controllers/EditBackupController.js:337 +#: scripts/controllers/EditBackupController.js:344 +#: scripts/controllers/EditBackupController.js:351 msgid "Invalid retention time" msgstr "Neplatná doba ponechání" -#: scripts/services/EditUriBuiltins.js:590 +#: scripts/services/EditUriBuiltins.js:624 msgid "" "It is possible to connect to some FTP without a password.\n" "Are you sure your FTP server supports password-less logins?" @@ -1206,9 +1245,13 @@ msgstr "KB" msgid "KByte/s" msgstr "KB/s" -#: templates/addoredit.html:317 -msgid "Keep this number of backups" -msgstr "Ponechat tento počet záloh" +#: templates/addoredit.html:321 +msgid "Keep a specific number of backups" +msgstr "Ponechat konkrétní počet záloh" + +#: templates/addoredit.html:319 +msgid "Keep all backups" +msgstr "Ponechat všechny zálohy" #: templates/settings.html:40 msgid "Language in user interface" @@ -1230,7 +1273,7 @@ msgstr "Poslední" msgid "Libraries" msgstr "Knihovny" -#: scripts/controllers/EditBackupController.js:21 +#: scripts/controllers/EditBackupController.js:23 msgid "Linux" msgstr "GNU/Linux" @@ -1258,7 +1301,7 @@ msgstr "Načíst cíl z exportované úlohy nebo poskytovatele úložiště" msgid "Load older data" msgstr "Načíst starší data" -#: templates/about.html:44 templates/about.html:49 templates/about.html:55 +#: templates/about.html:45 templates/about.html:50 templates/about.html:56 #: templates/captcha.html:14 templates/log.html:15 templates/log.html:22 #: templates/log.html:45 templates/log.html:53 templates/log.html:60 #: templates/log.html:67 templates/updatechangelog.html:7 @@ -1269,6 +1312,10 @@ msgstr "Načítání…" msgid "Loading remote storage usage ..." msgstr "Načítání údajů o využití vzdáleného úložiště…" +#: scripts/services/EditUriBuiltins.js:818 +msgid "Local Repository" +msgstr "Místní repozitář" + #: templates/localdatabase.html:2 msgid "Local database for" msgstr "Místní databáze pro" @@ -1277,7 +1324,11 @@ msgstr "Místní databáze pro" msgid "Local database path:" msgstr "Popis umístění místní databáze:" -#: scripts/services/SystemInfo.js:77 +#: templates/backends/rclone.html:2 +msgid "Local repository" +msgstr "Místní repozitář" + +#: scripts/services/SystemInfo.js:78 msgid "Local storage" msgstr "Místní úložiště" @@ -1297,7 +1348,7 @@ msgstr "Zaznamenávat (log) údaje pro {{Backup.Backup.Name}}" msgid "Log data from the server" msgstr "Zaznamenávat data ze serveru" -#: index.html:229 +#: index.html:220 msgid "Log out" msgstr "Odhlásit se" @@ -1325,8 +1376,8 @@ msgstr "Nejvyšší rychlost stahování" msgid "Max upload speed" msgstr "Nejvyšší rychlost odesílání" -#: index.html:152 templates/addoredit.html:123 templates/addoredit.html:165 -#: templates/addoredit.html:354 templates/addoredit.html:91 +#: index.html:146 templates/addoredit.html:123 templates/addoredit.html:165 +#: templates/addoredit.html:380 templates/addoredit.html:91 #: templates/edituri.html:34 templates/restoredirect.html:34 msgid "Menu" msgstr "Nabídka" @@ -1343,7 +1394,7 @@ msgstr "Databáze Microsoft SQL" msgid "Minimum redundancy" msgstr "Minimální redundance" -#: scripts/services/EditUriBuiltins.js:775 +#: scripts/services/EditUriBuiltins.js:809 msgid "Minimum redundancy is 1.0" msgstr "Minimální redundance je 1.0" @@ -1352,15 +1403,15 @@ msgstr "Minimální redundance je 1.0" msgid "Minutes" msgstr "Minut" -#: scripts/controllers/EditBackupController.js:290 +#: scripts/controllers/EditBackupController.js:292 msgid "Missing name" msgstr "Chybějící název" -#: scripts/controllers/EditBackupController.js:298 +#: scripts/controllers/EditBackupController.js:300 msgid "Missing passphrase" msgstr "Chybějící heslová fráze" -#: scripts/controllers/EditBackupController.js:311 +#: scripts/controllers/EditBackupController.js:313 msgid "Missing sources" msgstr "Chybějící zdroje" @@ -1368,7 +1419,7 @@ msgstr "Chybějící zdroje" msgid "Mon" msgstr "Po" -#: scripts/services/AppUtils.js:92 templates/addoredit.html:330 +#: scripts/services/AppUtils.js:92 templates/addoredit.html:351 msgid "Months" msgstr "Měsíců" @@ -1427,11 +1478,11 @@ msgstr "Další" msgid "Next scheduled run:" msgstr "Příští naplánované spuštění:" -#: index.html:183 +#: index.html:177 msgid "Next scheduled task:" msgstr "Příští naplánovaná úloha:" -#: index.html:180 +#: index.html:174 msgid "Next task:" msgstr "Příští úloha:" @@ -1440,9 +1491,9 @@ msgid "Next time" msgstr "Příště" #: scripts/controllers/DeleteController.js:77 -#: scripts/controllers/EditBackupController.js:140 -#: scripts/controllers/EditBackupController.js:150 -#: scripts/controllers/EditBackupController.js:472 +#: scripts/controllers/EditBackupController.js:142 +#: scripts/controllers/EditBackupController.js:152 +#: scripts/controllers/EditBackupController.js:496 #: scripts/controllers/HomeController.js:7 #: scripts/controllers/LocalDatabaseController.js:28 #: scripts/controllers/LocalDatabaseController.js:72 @@ -1452,9 +1503,9 @@ msgstr "Příště" #: scripts/directives/backupEditUri.js:87 #: scripts/services/EditUriBackendConfig.js:66 #: scripts/services/EditUriBuiltins.js:47 -#: scripts/services/EditUriBuiltins.js:630 -#: scripts/services/EditUriBuiltins.js:702 -#: scripts/services/EditUriBuiltins.js:719 +#: scripts/services/EditUriBuiltins.js:664 +#: scripts/services/EditUriBuiltins.js:736 +#: scripts/services/EditUriBuiltins.js:753 msgid "No" msgstr "Ne" @@ -1472,7 +1523,7 @@ msgstr "" msgid "No editor found for the "{{backend}}" storage type" msgstr "Nebyl nalezen žádný editor pro typ úložiště „{{backend}}“" -#: scripts/controllers/EditBackupController.js:451 templates/addoredit.html:45 +#: scripts/controllers/EditBackupController.js:475 templates/addoredit.html:45 msgid "No encryption" msgstr "Nešifrovat" @@ -1488,7 +1539,7 @@ msgstr "Žádné položky pro obnovení – vyberte alespoň jednu" msgid "No passphrase entered" msgstr "Není zadaná žádná heslová fráze" -#: index.html:185 +#: index.html:179 msgid "No scheduled tasks" msgstr "Žádné naplánované úlohy" @@ -1496,7 +1547,7 @@ msgstr "Žádné naplánované úlohy" msgid "No, my machine has only a single account" msgstr "Ne, na mém stroji je pouze jediný uživatelský účet" -#: scripts/controllers/EditBackupController.js:304 +#: scripts/controllers/EditBackupController.js:306 msgid "Non-matching passphrase" msgstr "Zadání heslové fráze se neshodují" @@ -1504,10 +1555,14 @@ msgstr "Zadání heslové fráze se neshodují" msgid "None / disabled" msgstr "Žádné / vypnuté" +#: templates/addoredit.html:326 +msgid "Nothing will be deleted. The backup size will grow with each change." +msgstr "Nic nebude smazáno. Velikost zálohy naroste při každé změně." + #: scripts/controllers/AppController.js:44 #: scripts/controllers/AppController.js:59 -#: scripts/controllers/EditBackupController.js:82 -#: scripts/controllers/EditBackupController.js:90 +#: scripts/controllers/EditBackupController.js:84 +#: scripts/controllers/EditBackupController.js:92 #: scripts/controllers/RestoreDirectController.js:24 #: scripts/controllers/RestoreDirectController.js:33 #: scripts/services/CaptchaService.js:22 scripts/services/DialogService.js:28 @@ -1517,10 +1572,17 @@ msgstr "Žádné / vypnuté" msgid "OK" msgstr "OK" -#: scripts/controllers/EditBackupController.js:20 +#: scripts/controllers/EditBackupController.js:22 msgid "OSX" msgstr "Apple macOS" +#: templates/addoredit.html:344 +msgid "" +"Once there are more backups than the specified number, the oldest backups " +"are deleted." +msgstr "" +"Jakmile je zde více záloh než zadané číslo, nejstarší zálohy budou smazané." + #: templates/backends/openstack.html:7 msgid "OpenStack AuthURI" msgstr "AuthURI pro OpenStack" @@ -1563,10 +1625,21 @@ msgstr "" msgid "Original location" msgstr "Původní umístění" -#: scripts/services/SystemInfo.js:80 +#: scripts/services/SystemInfo.js:81 msgid "Others" msgstr "Ostatní" +#: templates/addoredit.html:330 +msgid "" +"Over time backups will be deleted automatically. There will remain one " +"backup for each of the last 7 days, each of the last 4 weeks, each of the " +"last 12 months. There will always be at least one remaining backup." +msgstr "" +"Po čase jsou zálohy automaticky odmazávány. Bude udržována jedna záloha z " +"každého dne za minulých 7 dnů, jedna z každého týdne za minulé 4 týdny a " +"jedna z každého měsíce za minulých 12 měsíců. A vždy zde bude přinejmenším " +"jedna ponechaná záloha." + #: templates/restore.html:114 msgid "Overwrite" msgstr "Přepsat" @@ -1580,16 +1653,16 @@ msgstr "Heslová fráze" msgid "Passphrase (if encrypted)" msgstr "Heslová fráze (v případě, že je použito šifrování)" -#: scripts/controllers/EditBackupController.js:415 +#: scripts/controllers/EditBackupController.js:439 msgid "Passphrase changed" msgstr "Heslová fráze změněna" -#: scripts/controllers/EditBackupController.js:304 +#: scripts/controllers/EditBackupController.js:306 msgid "Passphrases are not matching" msgstr "Zadání heslové fráze se neshodují" -#: scripts/services/EditUriBuiltins.js:749 -#: scripts/services/EditUriBuiltins.js:759 templates/backends/file.html:33 +#: scripts/services/EditUriBuiltins.js:783 +#: scripts/services/EditUriBuiltins.js:793 templates/backends/file.html:33 #: templates/backends/generic.html:22 templates/backends/jottacloud.html:11 #: templates/backends/jottacloud.html:12 templates/backends/mega.html:11 #: templates/backends/mega.html:12 templates/backends/openstack.html:22 @@ -1597,7 +1670,7 @@ msgstr "Zadání heslové fráze se neshodují" msgid "Password" msgstr "Heslo" -#: scripts/controllers/EditBackupController.js:36 +#: scripts/controllers/EditBackupController.js:38 msgid "Passwords do not match" msgstr "Zadání hesla se neshodují" @@ -1605,7 +1678,7 @@ msgstr "Zadání hesla se neshodují" msgid "Patching files with local blocks ..." msgstr "Opravování souborů pomocí místních bloků…" -#: scripts/controllers/EditBackupController.js:140 +#: scripts/controllers/EditBackupController.js:142 msgid "Path not found" msgstr "Umístění nenalezeno" @@ -1646,7 +1719,7 @@ msgid "Port" msgstr "Port" #: templates/addoredit.html:110 templates/addoredit.html:251 -#: templates/addoredit.html:301 templates/addoredit.html:381 +#: templates/addoredit.html:301 templates/addoredit.html:407 #: templates/restoredirect.html:81 msgid "Previous" msgstr "Předchozí" @@ -1657,7 +1730,7 @@ msgstr "" "Pokud „nádoba“ (bucket) existuje, je identifikátor projektu (ProjectID) " "nepovinný" -#: scripts/services/SystemInfo.js:79 +#: scripts/services/SystemInfo.js:80 msgid "Proprietary" msgstr "Proprietární" @@ -1681,7 +1754,7 @@ msgstr "Znovuvytváření databáze…" msgid "Registering temporary backup ..." msgstr "Registrace dočasné zálohy…" -#: scripts/controllers/EditBackupController.js:125 +#: scripts/controllers/EditBackupController.js:127 msgid "Relative paths not allowed" msgstr "Vztažené (relativní) popisy umístění není možné použít" @@ -1693,6 +1766,22 @@ msgstr "Načíst znovu" msgid "Remote" msgstr "Vzdálené" +#: scripts/services/EditUriBuiltins.js:819 +msgid "Remote Path" +msgstr "Vzdálené umístění" + +#: scripts/services/EditUriBuiltins.js:817 +msgid "Remote Repository" +msgstr "Vzdálený repozitář" + +#: templates/backends/rclone.html:10 +msgid "Remote path" +msgstr "Vzdálené umístění" + +#: templates/backends/rclone.html:6 +msgid "Remote repository" +msgstr "Vzdálený repozitář" + #: templates/addoredit.html:193 msgid "Remove" msgstr "Odebrat" @@ -1721,7 +1810,7 @@ msgstr "Hlášení:" msgid "Reset" msgstr "Resetovat" -#: index.html:214 templates/restore.html:131 +#: index.html:208 templates/restore.html:131 msgid "Restore" msgstr "Obnovit" @@ -1763,7 +1852,7 @@ msgstr "Obnovit práva pro čtení/zápis" msgid "Restoring files ..." msgstr "Obnovování souborů…" -#: index.html:217 +#: index.html:211 msgid "Resume" msgstr "Pokračovat" @@ -1787,7 +1876,7 @@ msgstr "Spuštěné…" msgid "Running commandline entry" msgstr "Spuštěná položka příkazového řádku" -#: index.html:172 +#: index.html:166 msgid "Running task:" msgstr "Spuštěná úloha:" @@ -1803,7 +1892,7 @@ msgstr "Stejné jako základní nainstalovaná verze: {{channelname}}" msgid "Sat" msgstr "So" -#: templates/addoredit.html:380 templates/localdatabase.html:32 +#: templates/addoredit.html:406 templates/localdatabase.html:32 msgid "Save" msgstr "Uložit" @@ -1815,7 +1904,7 @@ msgstr "Uložit a opravit" msgid "Save different versions with timestamp in file name" msgstr "Uložit různé verze odlišené časovou značkou v názvu souboru" -#: templates/import.html:19 +#: templates/import.html:24 msgid "Save immediately" msgstr "Okamžitě uložit" @@ -1853,7 +1942,7 @@ msgstr "" msgid "Select files" msgstr "Vybrat soubory" -#: scripts/services/EditUriBuiltins.js:767 templates/backends/s3.html:8 +#: scripts/services/EditUriBuiltins.js:801 templates/backends/s3.html:8 #: templates/backends/sia.html:2 msgid "Server" msgstr "Server" @@ -1883,11 +1972,11 @@ msgstr "Heslo serveru" msgid "Server paused" msgstr "Server pozastaven" -#: templates/about.html:71 +#: templates/about.html:72 msgid "Server state properties" msgstr "Vlastnosti stavu serveru" -#: index.html:220 templates/settings.html:2 +#: index.html:214 templates/settings.html:2 msgid "Settings" msgstr "Nastavení" @@ -1905,7 +1994,7 @@ msgstr "Zobrazit pokročilý editor" msgid "Show hidden folders" msgstr "Zobrazit skryté složky" -#: index.html:223 +#: templates/about.html:8 msgid "Show log" msgstr "Zobrazit záznam událostí (log)" @@ -1921,6 +2010,10 @@ msgstr "Zobrazit stromový pohled" msgid "Sia server password" msgstr "Heslo Sia serveru" +#: templates/addoredit.html:322 +msgid "Smart backup retention" +msgstr "Chytrá doba uchovávání záloh" + #: templates/backends/openstack.html:33 msgid "" "Some OpenStack providers allow an API key instead of a password and tenant " @@ -1949,7 +2042,7 @@ msgstr "Zdroj:" msgid "Specific builds for developers only." msgstr "Konkrétní sestavení pouze pro vývojáře." -#: scripts/services/SystemInfo.js:78 +#: scripts/services/SystemInfo.js:79 msgid "Standard protocols" msgstr "Standardní protokoly" @@ -1983,11 +2076,11 @@ msgstr "Zastavit probíhající zálohu" msgid "Stop running task" msgstr "Zastavit probíhající úlohu" -#: index.html:168 +#: index.html:162 msgid "Stopping after upload:" msgstr "Zastavování po nahrávání:" -#: index.html:173 +#: index.html:167 msgid "Stopping task:" msgstr "Zastavování úlohy:" @@ -2007,7 +2100,7 @@ msgstr "Třída úložiště pro vytváření „nádoby“ (bucket)" msgid "Stored" msgstr "Uloženo" -#: scripts/controllers/EditBackupController.js:40 +#: scripts/controllers/EditBackupController.js:42 msgid "Strong" msgstr "Silné" @@ -2028,7 +2121,7 @@ msgstr "Symbolický odkaz" msgid "System default ({{levelname}})" msgstr "Systémové výchozí ({{levelname}})" -#: scripts/controllers/EditBackupController.js:27 +#: scripts/controllers/EditBackupController.js:29 msgid "System files" msgstr "Systémové soubory" @@ -2036,7 +2129,7 @@ msgstr "Systémové soubory" msgid "System info" msgstr "Informace o systému" -#: templates/about.html:63 +#: templates/about.html:64 msgid "System properties" msgstr "Vlastnosti systému" @@ -2056,7 +2149,7 @@ msgstr "Popis umístění cíle, tj. /zaloha" msgid "Task is running" msgstr "Úloha je spuštěná" -#: scripts/controllers/EditBackupController.js:28 +#: scripts/controllers/EditBackupController.js:30 msgid "Temporary files" msgstr "Dočasné soubory" @@ -2084,18 +2177,18 @@ msgstr "Zkouška přístupových práv…" msgid "Testing permissions..." msgstr "Zkouška přístupových práv…" -#: scripts/services/EditUriBuiltins.js:719 +#: scripts/services/EditUriBuiltins.js:753 msgid "The bucket name should be all lower-case, convert automatically?" msgstr "Název nádoby by měl být malými písmeny, převést automaticky?" -#: scripts/services/EditUriBuiltins.js:702 +#: scripts/services/EditUriBuiltins.js:736 msgid "" "The bucket name should start with your username, prepend automatically?" msgstr "" "Název „nádoby“ (bucket) by měl začínat vaším uživatelským jménem – předřadit" " automaticky?" -#: index.html:312 +#: index.html:298 msgid "The connection to the server is lost, attempting again in {{time}} ..." msgstr "Spojení se serverem ztraceno, opětovný pokus za {{time}}…" @@ -2125,11 +2218,11 @@ msgstr "" "\n" "Chcete NAHRADIT STÁVAJÍCÍ klíč stroje \"{{prev}}\" NAHLÁŠENÝM klíčem stroje: {{key}}?" -#: scripts/controllers/EditBackupController.js:140 +#: scripts/controllers/EditBackupController.js:142 msgid "The path does not appear to exist, do you want to add it anyway?" msgstr "Popisované umístění zdá se neexistuje, přejete si ho přidat i tak?" -#: scripts/controllers/EditBackupController.js:150 +#: scripts/controllers/EditBackupController.js:152 msgid "" "The path does not end with a '{{dirsep}}' character, which means that you include a file, not a folder.\n" "\n" @@ -2139,7 +2232,7 @@ msgstr "" "\n" "Chcete zahrnout daný soubor?" -#: scripts/controllers/EditBackupController.js:125 +#: scripts/controllers/EditBackupController.js:127 msgid "" "The path must be an absolute path, i.e. it must start with a forward slash " "'/'" @@ -2147,7 +2240,7 @@ msgstr "" "Je třeba, aby se jednalo o úplný popis umístění, tj. aby začínal dopředným " "lomítkem „/“" -#: scripts/services/EditUriBuiltins.js:630 +#: scripts/services/EditUriBuiltins.js:664 msgid "" "The path should start with \"{{prefix1}}\" or \"{{prefix2}}\", otherwise you will not be able to see the files in the HubiC web interface.\n" "\n" @@ -2291,12 +2384,12 @@ msgstr "Nahrávání ověřovacího souboru…" #: templates/settings.html:114 msgid "" "Usage reports help us improve the user experience and evaluate impact of new" -" features. We use them to generate public usage statistics" +" features. We use them to generate public usage" +" statistics" msgstr "" -"Hlášení využití nám pomáhají zlepšovat pro uživatele dojem z používání " -"aplikace a vyhodnocovat úspěšnost nových funkcí. Používáme je pro vytváření " -"veřejných statistik o používání" +"Hlášení o využití pomáhá vývojářům zlepšovat dojem z používání a " +"vyhodnocovat dopad nových funkcí. Slouží k vytváření anonymizovaných " +"veřejných statistik využívání" #: templates/settings.html:102 msgid "Usage statistics" @@ -2310,15 +2403,15 @@ msgstr "Statistiky využití, varování, chyby a pády" msgid "Use SSL" msgstr "Použít SSL" -#: scripts/controllers/EditBackupController.js:472 +#: scripts/controllers/EditBackupController.js:496 msgid "Use existing database?" msgstr "Použít existující databázi?" -#: scripts/controllers/EditBackupController.js:366 +#: scripts/controllers/EditBackupController.js:390 msgid "Use weak passphrase" msgstr "Použít slabou heslovou frázi" -#: scripts/controllers/EditBackupController.js:37 +#: scripts/controllers/EditBackupController.js:39 msgid "Useless" msgstr "Nepoužitelné" @@ -2334,10 +2427,10 @@ msgstr "Uživatel má příliš mnoho oprávnění" msgid "User interface settings" msgstr "Nastavení uživatelského rozhraní" -#: scripts/services/EditUriBuiltins.js:585 -#: scripts/services/EditUriBuiltins.js:665 -#: scripts/services/EditUriBuiltins.js:748 -#: scripts/services/EditUriBuiltins.js:758 templates/backends/file.html:29 +#: scripts/services/EditUriBuiltins.js:619 +#: scripts/services/EditUriBuiltins.js:699 +#: scripts/services/EditUriBuiltins.js:782 +#: scripts/services/EditUriBuiltins.js:792 templates/backends/file.html:29 #: templates/backends/generic.html:18 templates/backends/jottacloud.html:7 #: templates/backends/jottacloud.html:8 templates/backends/mega.html:7 #: templates/backends/mega.html:8 templates/backends/openstack.html:18 @@ -2373,15 +2466,15 @@ msgstr "Ověřování vzdálených dat…" msgid "Verifying restored files ..." msgstr "Ověřování obnovených souborů…" -#: scripts/controllers/EditBackupController.js:41 +#: scripts/controllers/EditBackupController.js:43 msgid "Very strong" msgstr "Velmi silné" -#: scripts/controllers/EditBackupController.js:38 +#: scripts/controllers/EditBackupController.js:40 msgid "Very weak" msgstr "Velmi slabé" -#: index.html:248 +#: index.html:246 msgid "Visit us on" msgstr "Navštivte nás na" @@ -2426,11 +2519,11 @@ msgid "We recommend that you encrypt all backups stored outside your system" msgstr "" "Doporučujeme šifrovat všechny zálohy, které jsou ukládány mimo váš stroj" -#: scripts/controllers/EditBackupController.js:39 +#: scripts/controllers/EditBackupController.js:41 msgid "Weak" msgstr "Slabé" -#: scripts/controllers/EditBackupController.js:366 +#: scripts/controllers/EditBackupController.js:390 msgid "Weak passphrase" msgstr "Slabá heslová fráze" @@ -2438,7 +2531,7 @@ msgstr "Slabá heslová fráze" msgid "Wed" msgstr "St" -#: scripts/services/AppUtils.js:91 templates/addoredit.html:329 +#: scripts/services/AppUtils.js:91 templates/addoredit.html:350 msgid "Weeks" msgstr "Týdny" @@ -2450,19 +2543,19 @@ msgstr "Odkud chcete obnovit?" msgid "Where do you want to restore the files to?" msgstr "Kam chcete soubory obnovit?" -#: scripts/controllers/EditBackupController.js:19 +#: scripts/controllers/EditBackupController.js:21 msgid "Windows" msgstr "MS Windows" -#: scripts/services/AppUtils.js:93 templates/addoredit.html:331 +#: scripts/services/AppUtils.js:93 templates/addoredit.html:352 msgid "Years" msgstr "Let" #: scripts/controllers/AppController.js:172 #: scripts/controllers/DeleteController.js:77 -#: scripts/controllers/EditBackupController.js:140 -#: scripts/controllers/EditBackupController.js:150 -#: scripts/controllers/EditBackupController.js:472 +#: scripts/controllers/EditBackupController.js:142 +#: scripts/controllers/EditBackupController.js:152 +#: scripts/controllers/EditBackupController.js:496 #: scripts/controllers/HomeController.js:7 #: scripts/controllers/LocalDatabaseController.js:28 #: scripts/controllers/LocalDatabaseController.js:72 @@ -2472,21 +2565,21 @@ msgstr "Let" #: scripts/directives/backupEditUri.js:87 #: scripts/services/EditUriBackendConfig.js:66 #: scripts/services/EditUriBuiltins.js:47 -#: scripts/services/EditUriBuiltins.js:630 -#: scripts/services/EditUriBuiltins.js:702 -#: scripts/services/EditUriBuiltins.js:719 +#: scripts/services/EditUriBuiltins.js:664 +#: scripts/services/EditUriBuiltins.js:736 +#: scripts/services/EditUriBuiltins.js:753 msgid "Yes" msgstr "Ano" -#: scripts/controllers/EditBackupController.js:381 +#: scripts/controllers/EditBackupController.js:405 msgid "Yes, I have stored the passphrase safely" msgstr "Ano, heslovou frázi mám bezpečně uloženou" -#: scripts/controllers/EditBackupController.js:424 +#: scripts/controllers/EditBackupController.js:448 msgid "Yes, I'm brave!" msgstr "Ano, mám odvahu!" -#: scripts/controllers/EditBackupController.js:415 +#: scripts/controllers/EditBackupController.js:439 msgid "Yes, please break my backup!" msgstr "Ano, chci rozbít své zálohy!" @@ -2510,7 +2603,7 @@ msgstr "" "Měníte umístění databáze pryč z existující databáze.\n" "Opravdu je to to, co chcete?" -#: templates/about.html:26 +#: templates/about.html:27 msgid "You are currently running {{appname}} {{version}}" msgstr "Nyní provozujete {{appname}} {{version}}" @@ -2530,7 +2623,7 @@ msgstr "" "Úlohu můžete ukončit buď teď hned, nebo procesu umožnit zpracovat stávající " "soubor a pak zastavit." -#: scripts/controllers/EditBackupController.js:424 +#: scripts/controllers/EditBackupController.js:448 msgid "" "You have changed the encryption mode. This may break stuff. You are " "encouraged to create a new backup instead" @@ -2538,7 +2631,7 @@ msgstr "" "Změnili jste režim šifrování. To může něco rozbít. Doporučujeme namísto toho" " vytvořit novou zálohu" -#: scripts/controllers/EditBackupController.js:415 +#: scripts/controllers/EditBackupController.js:439 msgid "" "You have changed the passphrase, which is not supported. You are encouraged " "to create a new backup instead." @@ -2546,7 +2639,7 @@ msgstr "" "Změnili jste heslovou frázi, což není podporováno. Doporučujeme namísto toho" " vytvořit novou zálohu." -#: scripts/controllers/EditBackupController.js:451 +#: scripts/controllers/EditBackupController.js:475 msgid "" "You have chosen not to encrypt the backup. Encryption is recommended for all" " data stored on a remote server." @@ -2558,7 +2651,7 @@ msgstr "" msgid "You have chosen to restore to a new location, but not entered one" msgstr "Zvolili jste obnovu do nového umístění, ale nezadali jste ho" -#: scripts/controllers/EditBackupController.js:381 +#: scripts/controllers/EditBackupController.js:405 msgid "" "You have generated a strong passphrase. Make sure you have made a safe copy " "of the passphrase, as the data cannot be recovered if you lose the " @@ -2567,35 +2660,39 @@ msgstr "" "Vytvořili jste odolnou heslovou frázi. Tu si dobře uschovejte, protože v " "případě její ztráty data nebude možné obnovit." -#: scripts/controllers/EditBackupController.js:311 +#: scripts/controllers/EditBackupController.js:313 msgid "You must choose at least one source folder" msgstr "Je třeba zvolit alespoň jednu zdrojovou složku" -#: scripts/controllers/EditBackupController.js:290 +#: scripts/controllers/EditBackupController.js:292 msgid "You must enter a name for the backup" msgstr "Je třeba zadat název zálohy" -#: scripts/controllers/EditBackupController.js:298 +#: scripts/controllers/EditBackupController.js:300 msgid "You must enter a passphrase or disable encryption" msgstr "Buď je třeba zadat heslovou frázi nebo šifrování vypnout" -#: scripts/controllers/EditBackupController.js:330 +#: scripts/controllers/EditBackupController.js:344 msgid "You must enter a positive number of backups to keep" msgstr "Je třeba zadat kladný počet záloh které uchovávat" -#: scripts/services/EditUriBuiltins.js:677 +#: scripts/services/EditUriBuiltins.js:711 msgid "You must enter a tenant name if you do not provide an API Key" msgstr "Pokud nezadáte klíč k API, je třeba zadat jméno nájemníka (tenant)" -#: scripts/controllers/EditBackupController.js:323 +#: scripts/controllers/EditBackupController.js:337 msgid "You must enter a valid duration for the time to keep backups" msgstr "Je třeba zadat platnou dobu po kterou ponechávat zálohy" -#: scripts/services/EditUriBuiltins.js:674 +#: scripts/controllers/EditBackupController.js:351 +msgid "You must enter a valid rentention policy string" +msgstr "Je třeba zadat platný řetězec zásady doby uchovávání záloh" + +#: scripts/services/EditUriBuiltins.js:708 msgid "You must enter either a password or an API Key" msgstr "Je třeba zadat buď klíč k API nebo heslo" -#: scripts/services/EditUriBuiltins.js:681 +#: scripts/services/EditUriBuiltins.js:715 msgid "You must enter either a password or an API Key, not both" msgstr "Je třeba zadat buď heslo, nebo klíč k API – ne obojí naráz" @@ -2616,11 +2713,11 @@ msgstr "Je třeba vyplnit uživatelské jméno" msgid "You must fill in {{field}}" msgstr "Je třeba vyplnit kolonku {{field}}" -#: scripts/services/EditUriBuiltins.js:669 +#: scripts/services/EditUriBuiltins.js:703 msgid "You must select or fill in the AuthURI" msgstr "Je třeba vybrat nebo vyplnit AuthURI" -#: scripts/services/EditUriBuiltins.js:695 +#: scripts/services/EditUriBuiltins.js:729 msgid "You must select or fill in the server" msgstr "Je třeba vybrat nebo vyplnit server" @@ -2632,14 +2729,10 @@ msgstr "Je třeba zadat popis umístění" msgid "Your files and folders have been restored successfully." msgstr "Soubory a složky byly úspěšně obnoveny." -#: scripts/controllers/EditBackupController.js:366 +#: scripts/controllers/EditBackupController.js:390 msgid "Your passphrase is easy to guess. Consider changing passphrase." msgstr "Vaše heslová fráze je snadno uhodnutelná. Zvažte volbu jiné." -#: templates/addoredit.html:321 -msgid "a specific number" -msgstr "konkrétní číslo" - #: templates/backends/gcs.html:3 templates/backends/openstack.html:3 msgid "bucket/folder/subfolder" msgstr "nadoba/slozka/podslozka" @@ -2652,7 +2745,7 @@ msgstr "B" msgid "byte/s" msgstr "B/s" -#: templates/addoredit.html:276 templates/addoredit.html:332 +#: templates/addoredit.html:276 templates/addoredit.html:353 #: templates/advancedoptionseditor.html:28 #: templates/advancedoptionseditor.html:35 msgid "custom" @@ -2663,15 +2756,7 @@ msgstr "vlastní" msgid "resume now" msgstr "pokračovat nyní" -#: templates/addoredit.html:319 -msgid "unlimited" -msgstr "neomezené" - -#: templates/addoredit.html:320 -msgid "until they are older than" -msgstr "dokud nejsou starší než" - -#: templates/about.html:11 +#: templates/about.html:12 msgid "" "{{appname}} was primarily developed by {{dev1}} " "and {{dev2}}. {{appname}} can be downloaded from " diff --git a/Localizations/webroot/localization_webroot-da.po b/Localizations/webroot/localization_webroot-da.po index 1342903da..147a84a1e 100644 --- a/Localizations/webroot/localization_webroot-da.po +++ b/Localizations/webroot/localization_webroot-da.po @@ -3,10 +3,11 @@ # Mikki Sørensen , 2016 # Brian Kirkegaard, 2016 # Rune Henriksen , 2017 +# Michael Fogh Kristensen , 2018 msgid "" msgstr "" "Project-Id-Version: \n" -"Last-Translator: Rune Henriksen , 2017\n" +"Last-Translator: Michael Fogh Kristensen , 2018\n" "Language-Team: Danish (https://www.transifex.com/duplicati/teams/67655/da/)\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -467,7 +468,7 @@ msgstr "Kopieret!" #: templates/copy_clipboard_buttons.html:3 msgid "Copy" -msgstr "" +msgstr "Kopier" #: templates/addoredit.html:99 templates/restoredirect.html:42 msgid "Copy Destination URL to Clipboard" @@ -595,7 +596,7 @@ msgstr "Slet backup" #: templates/addoredit.html:320 msgid "Delete backups that are older than" -msgstr "" +msgstr "Slet sikkerhedskopier, der er ældre end" #: templates/delete.html:13 msgid "Delete local database" @@ -911,7 +912,7 @@ msgstr "Eksporterer ..." #: templates/externallink.html:1 msgid "External link" -msgstr "" +msgstr "Eksternt link" #: scripts/services/SystemInfo.js:52 msgid "FTP (Alternative)" @@ -1097,6 +1098,8 @@ msgid "" "If at least one newer backup is found, all backups older than this date are " "deleted." msgstr "" +"Hvis der findes mindst en nyere sikkerhedskopi, slettes alle backups, der er" +" ældre end denne dato." #: templates/localdatabase.html:13 msgid "" @@ -1183,7 +1186,7 @@ msgstr "Importer fra en fil" #: templates/import.html:19 msgid "Import metadata" -msgstr "" +msgstr "Importer metadata" #: templates/import.html:35 msgid "Importing ..." @@ -1249,11 +1252,11 @@ msgstr "KByte/s" #: templates/addoredit.html:321 msgid "Keep a specific number of backups" -msgstr "" +msgstr "Gem et bestemt antal backups" #: templates/addoredit.html:319 msgid "Keep all backups" -msgstr "" +msgstr "Gem alle backups" #: templates/settings.html:40 msgid "Language in user interface" @@ -1560,7 +1563,7 @@ msgstr "Ingen / deaktiveret" #: templates/addoredit.html:326 msgid "Nothing will be deleted. The backup size will grow with each change." -msgstr "" +msgstr "Intet vil blive slettet. Backup størrelsen vokser med hver ændring." #: scripts/controllers/AppController.js:44 #: scripts/controllers/AppController.js:59 @@ -1584,6 +1587,8 @@ msgid "" "Once there are more backups than the specified number, the oldest backups " "are deleted." msgstr "" +"Når der er flere backups end det angivne antal, slettes de ældste " +"sikkerhedskopier." #: templates/backends/openstack.html:7 msgid "OpenStack AuthURI" @@ -1637,6 +1642,9 @@ msgid "" "backup for each of the last 7 days, each of the last 4 weeks, each of the " "last 12 months. There will always be at least one remaining backup." msgstr "" +"Over tid vil backups blive slettet automatisk. Der vil forblive en backup " +"for hver af de sidste 7 dage, hver af de sidste 4 uger, hver af de sidste 12" +" måneder. Der vil altid være mindst en tilbageværende backup." #: templates/restore.html:114 msgid "Overwrite" @@ -2200,6 +2208,8 @@ msgid "" "The folder {{folder}} does not exist.\n" "Create it now?" msgstr "" +"Mappen {{folder}} eksisterer ikke.\n" +"Opret den nu?" #: scripts/directives/backupEditUri.js:212 msgid "" @@ -2501,6 +2511,8 @@ msgid "" "We accept donations via different services, such as OpenCollective, PayPal, " "BountySource and various crypto currencies." msgstr "" +"Vi accepterer donationer via forskellige tjenester, såsom OpenCollective, " +"PayPal, BountySource og forskellige krypto-valutaer." #: templates/addoredit.html:50 msgid "We recommend that you encrypt all backups stored outside your system" diff --git a/Localizations/webroot/localization_webroot-it.po b/Localizations/webroot/localization_webroot-it.po index 8ef24833d..02dff2d05 100644 --- a/Localizations/webroot/localization_webroot-it.po +++ b/Localizations/webroot/localization_webroot-it.po @@ -27,12 +27,12 @@ msgstr "... caricamento in corso ..." msgid "API Key" msgstr "Chiave API" -#: scripts/services/EditUriBuiltins.js:691 templates/backends/s3.html:54 +#: scripts/services/EditUriBuiltins.js:725 templates/backends/s3.html:54 #: templates/backends/s3.html:55 msgid "AWS Access ID" msgstr "ID di accesso AWS" -#: scripts/services/EditUriBuiltins.js:692 templates/backends/s3.html:58 +#: scripts/services/EditUriBuiltins.js:726 templates/backends/s3.html:58 #: templates/backends/s3.html:59 msgid "AWS Access Key" msgstr "Chiave di accesso AWS" @@ -41,7 +41,7 @@ msgstr "Chiave di accesso AWS" msgid "AWS IAM Policy" msgstr "Norme AWS IAM" -#: index.html:226 index.html:242 +#: index.html:217 index.html:233 msgid "About" msgstr "Informazioni" @@ -49,7 +49,7 @@ msgstr "Informazioni" msgid "About {{appname}}" msgstr "Informazioni {{appname}}" -#: scripts/services/EditUriBuiltins.js:656 templates/backends/azure.html:11 +#: scripts/services/EditUriBuiltins.js:690 templates/backends/azure.html:11 msgid "Access Key" msgstr "Chiave di accesso" @@ -61,7 +61,7 @@ msgstr "Accesso negato" msgid "Access to user interface" msgstr "Accesso all'interfaccia utente" -#: scripts/services/EditUriBuiltins.js:655 templates/backends/azure.html:7 +#: scripts/services/EditUriBuiltins.js:689 templates/backends/azure.html:7 msgid "Account name" msgstr "Nome account" @@ -86,7 +86,7 @@ msgstr "Aggiungi direttamente un percorso" msgid "Add advanced option" msgstr "Aggiungi opzione" -#: index.html:211 +#: index.html:205 msgid "Add backup" msgstr "Aggiungi backup" @@ -98,12 +98,12 @@ msgstr "Aggiungi filtro" msgid "Add path" msgstr "Aggiungi percorso" -#: scripts/services/EditUriBuiltins.js:702 -#: scripts/services/EditUriBuiltins.js:719 +#: scripts/services/EditUriBuiltins.js:736 +#: scripts/services/EditUriBuiltins.js:753 msgid "Adjust bucket name?" msgstr "Sistemare il nome bucket?" -#: scripts/services/EditUriBuiltins.js:630 +#: scripts/services/EditUriBuiltins.js:664 msgid "Adjust path name?" msgstr "Sistemare il nome del percorso?" @@ -111,7 +111,7 @@ msgstr "Sistemare il nome del percorso?" msgid "Advanced Options" msgstr "Opzioni Avanzate" -#: templates/addoredit.html:348 templates/edituri.html:28 +#: templates/addoredit.html:374 templates/edituri.html:28 msgid "Advanced options" msgstr "Opzioni avanzate" @@ -119,7 +119,7 @@ msgstr "Opzioni avanzate" msgid "Advanced:" msgstr "Avanzate:" -#: scripts/controllers/EditBackupController.js:22 +#: scripts/controllers/EditBackupController.js:24 msgid "All" msgstr "Tutti" @@ -165,7 +165,7 @@ msgstr "" "Un file esistente è stato trovato nella nuova posizione.\n" "Sei sicuro di volere che il database punti ad un file esistente?" -#: scripts/controllers/EditBackupController.js:472 +#: scripts/controllers/EditBackupController.js:496 msgid "" "An existing local database for the storage has been found.\n" "Re-using the database will allow the command-line and server instances to work on the same remote storage.\n" @@ -185,7 +185,7 @@ msgstr "Rapporti d'uso anonimi" msgid "As Command-line" msgstr "Come riga di comando" -#: scripts/services/EditUriBuiltins.js:614 templates/backends/gcs.html:8 +#: scripts/services/EditUriBuiltins.js:648 templates/backends/gcs.html:8 #: templates/backends/gcs.html:9 templates/backends/oauth.html:8 #: templates/backends/oauth.html:9 msgid "AuthID" @@ -199,7 +199,7 @@ msgstr "Password di autenticazione" msgid "Authentication username" msgstr "Nome utente di autenticazione" -#: scripts/controllers/EditBackupController.js:381 +#: scripts/controllers/EditBackupController.js:405 msgid "Autogenerated passphrase" msgstr "Genera automaticamente passphrase" @@ -215,11 +215,11 @@ msgstr "ID Account B2" msgid "B2 Application Key" msgstr "Chiave Applicazione B2" -#: scripts/services/EditUriBuiltins.js:738 templates/backends/b2.html:13 +#: scripts/services/EditUriBuiltins.js:772 templates/backends/b2.html:13 msgid "B2 Cloud Storage Account ID" msgstr "ID Account Cloud B2 Storage" -#: scripts/services/EditUriBuiltins.js:739 templates/backends/b2.html:17 +#: scripts/services/EditUriBuiltins.js:773 templates/backends/b2.html:17 msgid "B2 Cloud Storage Application Key" msgstr "Chiave applicazione Archiviazione Cloud B2" @@ -227,7 +227,7 @@ msgstr "Chiave applicazione Archiviazione Cloud B2" msgid "Back" msgstr "Indietro" -#: templates/about.html:66 +#: templates/about.html:67 msgid "Backend modules:" msgstr "Moduli backend:" @@ -240,6 +240,10 @@ msgstr "Destinazione backup" msgid "Backup location" msgstr "Posizione Backup" +#: templates/addoredit.html:317 +msgid "Backup retention" +msgstr "Conservazione backup" + #: templates/home.html:60 msgid "Backup:" msgstr "Dimensione backup:" @@ -260,9 +264,9 @@ msgstr "Browse" msgid "Browser default" msgstr "Browser predefinito" -#: scripts/services/EditUriBuiltins.js:666 -#: scripts/services/EditUriBuiltins.js:690 -#: scripts/services/EditUriBuiltins.js:737 +#: scripts/services/EditUriBuiltins.js:700 +#: scripts/services/EditUriBuiltins.js:724 +#: scripts/services/EditUriBuiltins.js:771 msgid "Bucket Name" msgstr "Nome Bucket" @@ -302,13 +306,13 @@ msgstr "Canary" #: scripts/controllers/AppController.js:44 #: scripts/controllers/AppController.js:59 -#: scripts/controllers/EditBackupController.js:366 -#: scripts/controllers/EditBackupController.js:381 -#: scripts/controllers/EditBackupController.js:415 -#: scripts/controllers/EditBackupController.js:424 -#: scripts/controllers/EditBackupController.js:451 -#: scripts/controllers/EditBackupController.js:472 -#: scripts/controllers/EditBackupController.js:82 +#: scripts/controllers/EditBackupController.js:390 +#: scripts/controllers/EditBackupController.js:405 +#: scripts/controllers/EditBackupController.js:439 +#: scripts/controllers/EditBackupController.js:448 +#: scripts/controllers/EditBackupController.js:475 +#: scripts/controllers/EditBackupController.js:496 +#: scripts/controllers/EditBackupController.js:84 #: scripts/controllers/LocalDatabaseController.js:72 #: scripts/controllers/LocalDatabaseController.js:88 #: scripts/controllers/RestoreDirectController.js:24 @@ -316,9 +320,9 @@ msgstr "Canary" #: scripts/controllers/StateController.js:112 #: scripts/services/CaptchaService.js:22 scripts/services/DialogService.js:50 #: scripts/services/EditUriBuiltins.js:47 -#: scripts/services/EditUriBuiltins.js:630 -#: scripts/services/EditUriBuiltins.js:702 -#: scripts/services/EditUriBuiltins.js:719 templates/delete.html:54 +#: scripts/services/EditUriBuiltins.js:664 +#: scripts/services/EditUriBuiltins.js:736 +#: scripts/services/EditUriBuiltins.js:753 templates/delete.html:54 #: templates/export.html:26 templates/settings.html:146 #: templates/waitarea.html:19 msgid "Cancel" @@ -340,7 +344,7 @@ msgstr "Changelog di {{appname}} {{version}}" msgid "Check failed:" msgstr "Controllo fallito:" -#: templates/about.html:35 +#: templates/about.html:36 msgid "Check for updates now" msgstr "Controlla aggiornamenti ora" @@ -348,7 +352,7 @@ msgstr "Controlla aggiornamenti ora" msgid "Checking ..." msgstr "Controllo..." -#: templates/about.html:36 +#: templates/about.html:37 msgid "Checking for updates ..." msgstr "Controllo aggiornamenti..." @@ -360,7 +364,7 @@ msgstr "Scegliere un tipo di archiviazione per iniziare" msgid "Click the AuthID link to create an AuthID" msgstr "Clicca sul link AuthID per creare un nuovo AuthID" -#: index.html:156 index.html:199 +#: index.html:150 index.html:193 msgid "Click to set throttle options" msgstr "Clicca per impostare le opzioni di limitazione" @@ -384,7 +388,7 @@ msgstr "Completamento backup..." msgid "Completing previous backup ..." msgstr "Completamento backup precedente..." -#: templates/about.html:67 +#: templates/about.html:68 msgid "Compression modules:" msgstr "Moduli di compressione:" @@ -418,11 +422,11 @@ msgstr "Conferma richiesta" msgid "Connect" msgstr "Connetti" -#: index.html:319 +#: index.html:305 msgid "Connect now" msgstr "Connetti ora" -#: index.html:315 +#: index.html:301 msgid "Connecting to server ..." msgstr "Connessione al server..." @@ -430,11 +434,11 @@ msgstr "Connessione al server..." msgid "Connecting to task ...." msgstr "Connessione all'attività..." -#: index.html:320 +#: index.html:306 msgid "Connecting..." msgstr "Connessione..." -#: index.html:311 +#: index.html:297 msgid "Connection lost" msgstr "Connessione persa" @@ -443,7 +447,7 @@ msgstr "Connessione persa" msgid "Connection worked!" msgstr "Connessione funzionante!" -#: scripts/services/EditUriBuiltins.js:657 templates/backends/azure.html:2 +#: scripts/services/EditUriBuiltins.js:691 templates/backends/azure.html:2 msgid "Container name" msgstr "Nome contenitore" @@ -455,7 +459,7 @@ msgstr "Area contenitore" msgid "Continue" msgstr "Continua" -#: scripts/controllers/EditBackupController.js:451 +#: scripts/controllers/EditBackupController.js:475 msgid "Continue without encryption" msgstr "Continua senza crittografia" @@ -463,6 +467,10 @@ msgstr "Continua senza crittografia" msgid "Copied!" msgstr "Copiato!" +#: templates/copy_clipboard_buttons.html:3 +msgid "Copy" +msgstr "Copia" + #: templates/addoredit.html:99 templates/restoredirect.html:42 msgid "Copy Destination URL to Clipboard" msgstr "Copia URL Destinazione negli Appunti" @@ -527,6 +535,10 @@ msgstr "End point S3 personalizzato" msgid "Custom authentication url" msgstr "URL di autenticazione personalizzato" +#: templates/addoredit.html:323 +msgid "Custom backup retention" +msgstr "Conservazione backup personalizzato" + #: templates/backends/gcs.html:18 msgid "Custom location ({{server}})" msgstr "Posizione personalizzata ({{server}})" @@ -551,7 +563,7 @@ msgstr "Classe di archiviazione personalizzata ({{class}})" msgid "Database ..." msgstr "Database..." -#: scripts/services/AppUtils.js:90 templates/addoredit.html:328 +#: scripts/services/AppUtils.js:90 templates/addoredit.html:349 msgid "Days" msgstr "Giorni" @@ -583,6 +595,10 @@ msgstr "Cancella..." msgid "Delete backup" msgstr "Cancella backup" +#: templates/addoredit.html:320 +msgid "Delete backups that are older than" +msgstr "Elimina i backup più vecchi di" + #: templates/delete.html:13 msgid "Delete local database" msgstr "Cancella database locale" @@ -649,18 +665,10 @@ msgstr "Vuoi veramente cancellare il backup: \"{{name}}\" ?" msgid "Do you really want to delete the local database for: {{name}}" msgstr "Vuoi veramente cancellare il database locale per: {{name}} ?" -#: index.html:141 index.html:269 +#: index.html:142 index.html:241 msgid "Donate" msgstr "Donazione" -#: index.html:147 index.html:275 -msgid "Donate with PayPal" -msgstr "Donazione con PayPal" - -#: index.html:144 index.html:272 -msgid "Donate with crypto currency" -msgstr "Dona con valuta criptata" - #: templates/settings.html:58 templates/settings.html:60 msgid "Donation messages" msgstr "Messaggi donazione" @@ -697,11 +705,11 @@ msgstr "Sto scaricando l'aggiornamento..." msgid "Duplicate option {{opt}}" msgstr "Opzione duplicata {{opt}}" -#: index.html:263 +#: index.html:261 msgid "Duplicati Website" msgstr "Sito web di Duplicati" -#: index.html:251 +#: index.html:249 msgid "Duplicati forum" msgstr "Forum Duplicati" @@ -729,12 +737,12 @@ msgstr "" msgid "Edit ..." msgstr "Modifica..." -#: templates/addoredit.html:170 templates/addoredit.html:359 +#: templates/addoredit.html:170 templates/addoredit.html:385 #: templates/edituri.html:39 templates/settings.html:135 msgid "Edit as list" msgstr "Modifica come elenco" -#: templates/addoredit.html:173 templates/addoredit.html:362 +#: templates/addoredit.html:173 templates/addoredit.html:388 #: templates/edituri.html:42 templates/settings.html:141 msgid "Edit as text" msgstr "Modifica come testo" @@ -748,19 +756,33 @@ msgstr "Cripta file" msgid "Encryption" msgstr "Crittografia" -#: scripts/controllers/EditBackupController.js:424 +#: scripts/controllers/EditBackupController.js:448 msgid "Encryption changed" msgstr "Crittografia cambiata" -#: templates/about.html:68 +#: templates/about.html:69 msgid "Encryption modules:" msgstr "Moduli crittografia:" -#: scripts/controllers/EditBackupController.js:82 +#: scripts/controllers/EditBackupController.js:84 #: scripts/controllers/RestoreDirectController.js:24 msgid "Enter URL" msgstr "Inserisci URL" +#: templates/addoredit.html:337 +msgid "" +"Enter a retention strategy manually. Placeholders are D/W/Y for " +"days/weeks/years. The syntax is: 7D:1D,4W:1W,36M:1M. This example keeps one " +"backup for each of the next 7 days, one for each of the next 4 weeks, and " +"one for each of the next 36 months. This can also be written as " +"1W:1D,1M:1W,3Y:1M." +msgstr "" +"Immettere manualmente una strategia di conservazione. I segnaposto sono " +"D/W/Y per giorni/settimane/anni. La sintassi è: 7D:1D,4W:1W,36M:1M. Questo " +"esempio mantiene un backup per ciascuno dei prossimi 7 giorni, uno per " +"ciascuno delle prossime 4 settimane e uno per ciascuno dei prossimi 36 mesi." +" Questo può anche essere scritta come 1W:1D,1M:1W,3Y:1M." + #: templates/backends/azure.html:12 msgid "Enter access key" msgstr "Inserisci chiave di accesso" @@ -892,6 +914,10 @@ msgstr "Esporta configurazione" msgid "Exporting ..." msgstr "Esportazione..." +#: templates/externallink.html:1 +msgid "External link" +msgstr "Link esterno" + #: scripts/services/SystemInfo.js:52 msgid "FTP (Alternative)" msgstr "FTP (Alternativo)" @@ -932,7 +958,7 @@ msgstr "Recupero informazioni sul percorso fallito: {{message}}" msgid "Failed to import:" msgstr "Importazione fallita:" -#: scripts/controllers/EditBackupController.js:737 +#: scripts/controllers/EditBackupController.js:768 msgid "Failed to read backup defaults:" msgstr "Lettura impostazioni predefinite backup fallita:" @@ -1022,7 +1048,7 @@ msgstr "Genera criteri di accesso IAM" msgid "Getting file versions ..." msgstr "Ottenimento versione file..." -#: scripts/controllers/EditBackupController.js:26 +#: scripts/controllers/EditBackupController.js:28 msgid "Hidden files" msgstr "File nascosti" @@ -1034,7 +1060,7 @@ msgstr "Nascondi" msgid "Hide hidden folders" msgstr "Nascondi cartelle nascoste" -#: index.html:208 scripts/services/AppUtils.js:61 +#: index.html:202 scripts/services/AppUtils.js:61 msgid "Home" msgstr "Home" @@ -1071,6 +1097,14 @@ msgstr "" "Se una pianificazione non è eseguita, il backup sarà effettuato il prima " "possibile." +#: templates/addoredit.html:357 +msgid "" +"If at least one newer backup is found, all backups older than this date are " +"deleted." +msgstr "" +"Se si trova almeno un backup più recente, tutti i backup precedenti a questa" +" data sono eliminati." + #: templates/localdatabase.html:13 msgid "" "If the backup and the remote storage is out of sync, Duplicati will require " @@ -1128,7 +1162,7 @@ msgstr "" "Se la tua macchina è in un ambiente multi-utente (cioè la macchina ha più di un account), è necessario impostare una password per impedire ad altri utenti di accedere ai dati del tuo account. \n" "Vuoi impostare una password ora?" -#: templates/import.html:26 +#: templates/import.html:31 msgid "Import" msgstr "Importa" @@ -1154,11 +1188,15 @@ msgstr "Importazione fallita" msgid "Import from a file" msgstr "Importa da un file" -#: templates/import.html:30 +#: templates/import.html:19 +msgid "Import metadata" +msgstr "Importa metadati" + +#: templates/import.html:35 msgid "Importing ..." msgstr "Importazione..." -#: scripts/controllers/EditBackupController.js:150 +#: scripts/controllers/EditBackupController.js:152 msgid "Include a file?" msgstr "Includi un file?" @@ -1190,16 +1228,17 @@ msgstr "Installa" msgid "Install failed:" msgstr "Installazione fallita:" -#: scripts/services/EditUriBuiltins.js:771 +#: scripts/services/EditUriBuiltins.js:805 msgid "Invalid characters in path" msgstr "Caratteri non validi nel percorso" -#: scripts/controllers/EditBackupController.js:323 -#: scripts/controllers/EditBackupController.js:330 +#: scripts/controllers/EditBackupController.js:337 +#: scripts/controllers/EditBackupController.js:344 +#: scripts/controllers/EditBackupController.js:351 msgid "Invalid retention time" msgstr "Tempo ritenzione non valido" -#: scripts/services/EditUriBuiltins.js:590 +#: scripts/services/EditUriBuiltins.js:624 msgid "" "It is possible to connect to some FTP without a password.\n" "Are you sure your FTP server supports password-less logins?" @@ -1215,9 +1254,13 @@ msgstr "KByte" msgid "KByte/s" msgstr "KByte/s" -#: templates/addoredit.html:317 -msgid "Keep this number of backups" -msgstr "Backup da mantenere" +#: templates/addoredit.html:321 +msgid "Keep a specific number of backups" +msgstr "Mantieni un numero specifico di backup" + +#: templates/addoredit.html:319 +msgid "Keep all backups" +msgstr "Mantieni tutti i backup" #: templates/settings.html:40 msgid "Language in user interface" @@ -1239,7 +1282,7 @@ msgstr "Più recente" msgid "Libraries" msgstr "Librerie" -#: scripts/controllers/EditBackupController.js:21 +#: scripts/controllers/EditBackupController.js:23 msgid "Linux" msgstr "Linux" @@ -1271,7 +1314,7 @@ msgstr "" msgid "Load older data" msgstr "Carica dati precedenti" -#: templates/about.html:44 templates/about.html:49 templates/about.html:55 +#: templates/about.html:45 templates/about.html:50 templates/about.html:56 #: templates/captcha.html:14 templates/log.html:15 templates/log.html:22 #: templates/log.html:45 templates/log.html:53 templates/log.html:60 #: templates/log.html:67 templates/updatechangelog.html:7 @@ -1282,6 +1325,10 @@ msgstr "Caricamento..." msgid "Loading remote storage usage ..." msgstr "Caricamento dell'archivio remoto utilizzato ..." +#: scripts/services/EditUriBuiltins.js:818 +msgid "Local Repository" +msgstr "Repository locale" + #: templates/localdatabase.html:2 msgid "Local database for" msgstr "Database locale per " @@ -1290,7 +1337,11 @@ msgstr "Database locale per " msgid "Local database path:" msgstr "Percorso database locale:" -#: scripts/services/SystemInfo.js:77 +#: templates/backends/rclone.html:2 +msgid "Local repository" +msgstr "Repository locale" + +#: scripts/services/SystemInfo.js:78 msgid "Local storage" msgstr "Archivio locale" @@ -1310,7 +1361,7 @@ msgstr "Dati di log per {{Backup.Backup.Name}}" msgid "Log data from the server" msgstr "Dati di log dal server" -#: index.html:229 +#: index.html:220 msgid "Log out" msgstr "Log out" @@ -1338,8 +1389,8 @@ msgstr "Velocità massima per scaricare" msgid "Max upload speed" msgstr "Velocità massima per caricare" -#: index.html:152 templates/addoredit.html:123 templates/addoredit.html:165 -#: templates/addoredit.html:354 templates/addoredit.html:91 +#: index.html:146 templates/addoredit.html:123 templates/addoredit.html:165 +#: templates/addoredit.html:380 templates/addoredit.html:91 #: templates/edituri.html:34 templates/restoredirect.html:34 msgid "Menu" msgstr "Menu" @@ -1356,7 +1407,7 @@ msgstr "Microsoft SQL Database" msgid "Minimum redundancy" msgstr "Ridondanza minima" -#: scripts/services/EditUriBuiltins.js:775 +#: scripts/services/EditUriBuiltins.js:809 msgid "Minimum redundancy is 1.0" msgstr "Ridondanza minima è 1.0" @@ -1365,15 +1416,15 @@ msgstr "Ridondanza minima è 1.0" msgid "Minutes" msgstr "Minuti" -#: scripts/controllers/EditBackupController.js:290 +#: scripts/controllers/EditBackupController.js:292 msgid "Missing name" msgstr "Nome mancante" -#: scripts/controllers/EditBackupController.js:298 +#: scripts/controllers/EditBackupController.js:300 msgid "Missing passphrase" msgstr "Passphrase mancante" -#: scripts/controllers/EditBackupController.js:311 +#: scripts/controllers/EditBackupController.js:313 msgid "Missing sources" msgstr "Sorgente mancante" @@ -1381,7 +1432,7 @@ msgstr "Sorgente mancante" msgid "Mon" msgstr "Lun" -#: scripts/services/AppUtils.js:92 templates/addoredit.html:330 +#: scripts/services/AppUtils.js:92 templates/addoredit.html:351 msgid "Months" msgstr "Mesi" @@ -1440,11 +1491,11 @@ msgstr "Avanti" msgid "Next scheduled run:" msgstr "Prossima esecuzione: " -#: index.html:183 +#: index.html:177 msgid "Next scheduled task:" msgstr "Prossima attività pianificata:" -#: index.html:180 +#: index.html:174 msgid "Next task:" msgstr "Prossima attività:" @@ -1453,9 +1504,9 @@ msgid "Next time" msgstr "Prossima volta" #: scripts/controllers/DeleteController.js:77 -#: scripts/controllers/EditBackupController.js:140 -#: scripts/controllers/EditBackupController.js:150 -#: scripts/controllers/EditBackupController.js:472 +#: scripts/controllers/EditBackupController.js:142 +#: scripts/controllers/EditBackupController.js:152 +#: scripts/controllers/EditBackupController.js:496 #: scripts/controllers/HomeController.js:7 #: scripts/controllers/LocalDatabaseController.js:28 #: scripts/controllers/LocalDatabaseController.js:72 @@ -1465,9 +1516,9 @@ msgstr "Prossima volta" #: scripts/directives/backupEditUri.js:87 #: scripts/services/EditUriBackendConfig.js:66 #: scripts/services/EditUriBuiltins.js:47 -#: scripts/services/EditUriBuiltins.js:630 -#: scripts/services/EditUriBuiltins.js:702 -#: scripts/services/EditUriBuiltins.js:719 +#: scripts/services/EditUriBuiltins.js:664 +#: scripts/services/EditUriBuiltins.js:736 +#: scripts/services/EditUriBuiltins.js:753 msgid "No" msgstr "No" @@ -1485,7 +1536,7 @@ msgstr "" msgid "No editor found for the "{{backend}}" storage type" msgstr "Nessun editor trovato per il "{{backend}}" tipo archivio" -#: scripts/controllers/EditBackupController.js:451 templates/addoredit.html:45 +#: scripts/controllers/EditBackupController.js:475 templates/addoredit.html:45 msgid "No encryption" msgstr "Nessuna crittografia" @@ -1501,7 +1552,7 @@ msgstr "Nessun elemento da ripristinare, seleziona uno o più elementi" msgid "No passphrase entered" msgstr "Nessuna passphrase inserita" -#: index.html:185 +#: index.html:179 msgid "No scheduled tasks" msgstr "Nessuna attività pianificata" @@ -1509,7 +1560,7 @@ msgstr "Nessuna attività pianificata" msgid "No, my machine has only a single account" msgstr "No, la mia macchina ha solo un singolo account" -#: scripts/controllers/EditBackupController.js:304 +#: scripts/controllers/EditBackupController.js:306 msgid "Non-matching passphrase" msgstr "Passphrase non corrispondente" @@ -1517,10 +1568,16 @@ msgstr "Passphrase non corrispondente" msgid "None / disabled" msgstr "Nessuno / disattivato" +#: templates/addoredit.html:326 +msgid "Nothing will be deleted. The backup size will grow with each change." +msgstr "" +"Niente sarà eliminato. La dimensione del backup crescerà con ogni " +"cambiamento." + #: scripts/controllers/AppController.js:44 #: scripts/controllers/AppController.js:59 -#: scripts/controllers/EditBackupController.js:82 -#: scripts/controllers/EditBackupController.js:90 +#: scripts/controllers/EditBackupController.js:84 +#: scripts/controllers/EditBackupController.js:92 #: scripts/controllers/RestoreDirectController.js:24 #: scripts/controllers/RestoreDirectController.js:33 #: scripts/services/CaptchaService.js:22 scripts/services/DialogService.js:28 @@ -1530,10 +1587,18 @@ msgstr "Nessuno / disattivato" msgid "OK" msgstr "OK" -#: scripts/controllers/EditBackupController.js:20 +#: scripts/controllers/EditBackupController.js:22 msgid "OSX" msgstr "OSX" +#: templates/addoredit.html:344 +msgid "" +"Once there are more backups than the specified number, the oldest backups " +"are deleted." +msgstr "" +"Una volta che ci sono più backup del numero specificato, i backup più vecchi" +" sono cancellati." + #: templates/backends/openstack.html:7 msgid "OpenStack AuthURI" msgstr "OpenStack AuthURI" @@ -1576,10 +1641,20 @@ msgstr "" msgid "Original location" msgstr "Percorso originale" -#: scripts/services/SystemInfo.js:80 +#: scripts/services/SystemInfo.js:81 msgid "Others" msgstr "Altri" +#: templates/addoredit.html:330 +msgid "" +"Over time backups will be deleted automatically. There will remain one " +"backup for each of the last 7 days, each of the last 4 weeks, each of the " +"last 12 months. There will always be at least one remaining backup." +msgstr "" +"Nel corso del tempo i backup saranno eliminati automaticamente. Rimarrà un " +"backup per ciascuno degli ultimi 7 giorni, ognuna delle ultime 4 settimane, " +"ciascuno degli ultimi 12 mesi. Ci sarà sempre almeno un backup rimanente." + #: templates/restore.html:114 msgid "Overwrite" msgstr "Sovrascrivi" @@ -1593,16 +1668,16 @@ msgstr "Passphrase" msgid "Passphrase (if encrypted)" msgstr "Passphrase (se criptato)" -#: scripts/controllers/EditBackupController.js:415 +#: scripts/controllers/EditBackupController.js:439 msgid "Passphrase changed" msgstr "Passphrase modificata" -#: scripts/controllers/EditBackupController.js:304 +#: scripts/controllers/EditBackupController.js:306 msgid "Passphrases are not matching" msgstr "Passphrase non corrispondenti" -#: scripts/services/EditUriBuiltins.js:749 -#: scripts/services/EditUriBuiltins.js:759 templates/backends/file.html:33 +#: scripts/services/EditUriBuiltins.js:783 +#: scripts/services/EditUriBuiltins.js:793 templates/backends/file.html:33 #: templates/backends/generic.html:22 templates/backends/jottacloud.html:11 #: templates/backends/jottacloud.html:12 templates/backends/mega.html:11 #: templates/backends/mega.html:12 templates/backends/openstack.html:22 @@ -1610,7 +1685,7 @@ msgstr "Passphrase non corrispondenti" msgid "Password" msgstr "Password" -#: scripts/controllers/EditBackupController.js:36 +#: scripts/controllers/EditBackupController.js:38 msgid "Passwords do not match" msgstr "Password non corrispondenti" @@ -1618,7 +1693,7 @@ msgstr "Password non corrispondenti" msgid "Patching files with local blocks ..." msgstr "Sistemazione file con blocchi locali..." -#: scripts/controllers/EditBackupController.js:140 +#: scripts/controllers/EditBackupController.js:142 msgid "Path not found" msgstr "Percorso non trovato" @@ -1659,7 +1734,7 @@ msgid "Port" msgstr "Porta" #: templates/addoredit.html:110 templates/addoredit.html:251 -#: templates/addoredit.html:301 templates/addoredit.html:381 +#: templates/addoredit.html:301 templates/addoredit.html:407 #: templates/restoredirect.html:81 msgid "Previous" msgstr "Precedente" @@ -1668,7 +1743,7 @@ msgstr "Precedente" msgid "ProjectID is optional if the bucket exist" msgstr "ID Progetto è opzionale se esiste un bucket" -#: scripts/services/SystemInfo.js:79 +#: scripts/services/SystemInfo.js:80 msgid "Proprietary" msgstr "Proprietario" @@ -1692,7 +1767,7 @@ msgstr "Ricreazione database..." msgid "Registering temporary backup ..." msgstr "Registrazione backup temporaneo..." -#: scripts/controllers/EditBackupController.js:125 +#: scripts/controllers/EditBackupController.js:127 msgid "Relative paths not allowed" msgstr "Percorsi relativi non consentiti" @@ -1704,6 +1779,22 @@ msgstr "Ricarica" msgid "Remote" msgstr "Remoto" +#: scripts/services/EditUriBuiltins.js:819 +msgid "Remote Path" +msgstr "Percorso remoto" + +#: scripts/services/EditUriBuiltins.js:817 +msgid "Remote Repository" +msgstr "Repository remoto" + +#: templates/backends/rclone.html:10 +msgid "Remote path" +msgstr "Percorso remoto" + +#: templates/backends/rclone.html:6 +msgid "Remote repository" +msgstr "Repository remoto" + #: templates/addoredit.html:193 msgid "Remove" msgstr "Rimuovi" @@ -1732,7 +1823,7 @@ msgstr "Segnalazione:" msgid "Reset" msgstr "Reset" -#: index.html:214 templates/restore.html:131 +#: index.html:208 templates/restore.html:131 msgid "Restore" msgstr "Ripristina" @@ -1774,7 +1865,7 @@ msgstr "Ripristina autorizzazioni lettura/scrittura" msgid "Restoring files ..." msgstr "Ripristino file..." -#: index.html:217 +#: index.html:211 msgid "Resume" msgstr "Riprendi" @@ -1798,7 +1889,7 @@ msgstr "Esecuzione..." msgid "Running commandline entry" msgstr "Riga di comando in esecuzione" -#: index.html:172 +#: index.html:166 msgid "Running task:" msgstr "Attività in esecuzione:" @@ -1814,7 +1905,7 @@ msgstr "Come la versione di base installata: {{channelname}}" msgid "Sat" msgstr "Sab" -#: templates/addoredit.html:380 templates/localdatabase.html:32 +#: templates/addoredit.html:406 templates/localdatabase.html:32 msgid "Save" msgstr "Salva" @@ -1826,7 +1917,7 @@ msgstr "Salva e ripara" msgid "Save different versions with timestamp in file name" msgstr "Salva versioni diverse con timestamp nel nome del file" -#: templates/import.html:19 +#: templates/import.html:24 msgid "Save immediately" msgstr "Salva immediatamente" @@ -1863,7 +1954,7 @@ msgstr "Selezionare un livello di log e visiona i messaggi che avvengono:" msgid "Select files" msgstr "Seleziona file" -#: scripts/services/EditUriBuiltins.js:767 templates/backends/s3.html:8 +#: scripts/services/EditUriBuiltins.js:801 templates/backends/s3.html:8 #: templates/backends/sia.html:2 msgid "Server" msgstr "Server" @@ -1893,11 +1984,11 @@ msgstr "Password del server" msgid "Server paused" msgstr "Server in pausa" -#: templates/about.html:71 +#: templates/about.html:72 msgid "Server state properties" msgstr "Proprietà stato del server" -#: index.html:220 templates/settings.html:2 +#: index.html:214 templates/settings.html:2 msgid "Settings" msgstr "Impostazioni" @@ -1915,7 +2006,7 @@ msgstr "Mostra editor avanzato" msgid "Show hidden folders" msgstr "Mostra cartelle nascoste" -#: index.html:223 +#: templates/about.html:8 msgid "Show log" msgstr "Mostra log" @@ -1931,6 +2022,10 @@ msgstr "Visualizza ad albero" msgid "Sia server password" msgstr "Password del server Sia" +#: templates/addoredit.html:322 +msgid "Smart backup retention" +msgstr "Conservazione intelligente backup" + #: templates/backends/openstack.html:33 msgid "" "Some OpenStack providers allow an API key instead of a password and tenant " @@ -1959,7 +2054,7 @@ msgstr "Dimensione sorgente:" msgid "Specific builds for developers only." msgstr "Build specifiche per soli sviluppatori." -#: scripts/services/SystemInfo.js:78 +#: scripts/services/SystemInfo.js:79 msgid "Standard protocols" msgstr "Protocolli standard" @@ -1993,11 +2088,11 @@ msgstr "Ferma esecuzione backup" msgid "Stop running task" msgstr "Ferma esecuzione attività" -#: index.html:168 +#: index.html:162 msgid "Stopping after upload:" msgstr "Ferma dopo caricamento:" -#: index.html:173 +#: index.html:167 msgid "Stopping task:" msgstr "Ferma attività:" @@ -2017,7 +2112,7 @@ msgstr "Classe di archiviazione per la creazione di un bucket" msgid "Stored" msgstr "Archiviati" -#: scripts/controllers/EditBackupController.js:40 +#: scripts/controllers/EditBackupController.js:42 msgid "Strong" msgstr "Forte" @@ -2038,7 +2133,7 @@ msgstr "Link simbolico" msgid "System default ({{levelname}})" msgstr "Sistema predefinito ({{levelname}})" -#: scripts/controllers/EditBackupController.js:27 +#: scripts/controllers/EditBackupController.js:29 msgid "System files" msgstr "File di sistema" @@ -2046,7 +2141,7 @@ msgstr "File di sistema" msgid "System info" msgstr "Informazioni di sistema" -#: templates/about.html:63 +#: templates/about.html:64 msgid "System properties" msgstr "Proprietà di sistema" @@ -2066,7 +2161,7 @@ msgstr "Percorso di destinazione, cioè /backup" msgid "Task is running" msgstr "Attività in esecuzione" -#: scripts/controllers/EditBackupController.js:28 +#: scripts/controllers/EditBackupController.js:30 msgid "Temporary files" msgstr "File temporanei" @@ -2094,20 +2189,20 @@ msgstr "Prova autorizzazioni..." msgid "Testing permissions..." msgstr "Prova autorizzazioni..." -#: scripts/services/EditUriBuiltins.js:719 +#: scripts/services/EditUriBuiltins.js:753 msgid "The bucket name should be all lower-case, convert automatically?" msgstr "" "Il nome del bucket dovrebbe essere tutto minuscolo, convertirlo " "automaticamente?" -#: scripts/services/EditUriBuiltins.js:702 +#: scripts/services/EditUriBuiltins.js:736 msgid "" "The bucket name should start with your username, prepend automatically?" msgstr "" "Il nome del bucket dovrebbe iniziare con il tuo nome utente, anteporlo " "automaticamente?" -#: index.html:312 +#: index.html:298 msgid "The connection to the server is lost, attempting again in {{time}} ..." msgstr "Connessione al server persa, nuovo tentativo tra {{time}}..." @@ -2137,11 +2232,11 @@ msgstr "" "\n" "Vuoi SOSTITUIRE la chiave host CORRENTE \"{{prev}}\" con la chiave host SEGNALATA: {{key}}?" -#: scripts/controllers/EditBackupController.js:140 +#: scripts/controllers/EditBackupController.js:142 msgid "The path does not appear to exist, do you want to add it anyway?" msgstr "Il percorso sembra non esistere, vuoi aggiungerlo comunque?" -#: scripts/controllers/EditBackupController.js:150 +#: scripts/controllers/EditBackupController.js:152 msgid "" "The path does not end with a '{{dirsep}}' character, which means that you include a file, not a folder.\n" "\n" @@ -2151,7 +2246,7 @@ msgstr "" "\n" "Vuoi includere il file specificato?" -#: scripts/controllers/EditBackupController.js:125 +#: scripts/controllers/EditBackupController.js:127 msgid "" "The path must be an absolute path, i.e. it must start with a forward slash " "'/'" @@ -2159,7 +2254,7 @@ msgstr "" "Il percorso deve essere un percorso assoluto, cioè deve iniziare con una " "barra '/'" -#: scripts/services/EditUriBuiltins.js:630 +#: scripts/services/EditUriBuiltins.js:664 msgid "" "The path should start with \"{{prefix1}}\" or \"{{prefix2}}\", otherwise you will not be able to see the files in the HubiC web interface.\n" "\n" @@ -2310,12 +2405,12 @@ msgstr "Caricamento file di verifica..." #: templates/settings.html:114 msgid "" "Usage reports help us improve the user experience and evaluate impact of new" -" features. We use them to generate public usage statistics" +" features. We use them to generate public usage" +" statistics" msgstr "" -"I rapporti sull'utilizzo ci aiutano a migliorare l'esperienza dell'utente e " -"a valutare l'impatto delle nuove funzionalità. Li usiamo per generare statistiche di utilizzo pubblico" +"I report di utilizzo ci aiutano a migliorare l'esperienza utente e valutare " +"l'impatto di nuove funzionalità. Li usiamo per generare statistiche di utilizzo pubblico" #: templates/settings.html:102 msgid "Usage statistics" @@ -2329,15 +2424,15 @@ msgstr "Statistiche di utilizzo, avvisi, errori e arresti anomali" msgid "Use SSL" msgstr "Usa SSL" -#: scripts/controllers/EditBackupController.js:472 +#: scripts/controllers/EditBackupController.js:496 msgid "Use existing database?" msgstr "Usare database esistente?" -#: scripts/controllers/EditBackupController.js:366 +#: scripts/controllers/EditBackupController.js:390 msgid "Use weak passphrase" msgstr "Usa passphrase debole" -#: scripts/controllers/EditBackupController.js:37 +#: scripts/controllers/EditBackupController.js:39 msgid "Useless" msgstr "Inutile" @@ -2353,10 +2448,10 @@ msgstr "L'utente ha troppe autorizzazioni" msgid "User interface settings" msgstr "Impostazioni interfaccia utente" -#: scripts/services/EditUriBuiltins.js:585 -#: scripts/services/EditUriBuiltins.js:665 -#: scripts/services/EditUriBuiltins.js:748 -#: scripts/services/EditUriBuiltins.js:758 templates/backends/file.html:29 +#: scripts/services/EditUriBuiltins.js:619 +#: scripts/services/EditUriBuiltins.js:699 +#: scripts/services/EditUriBuiltins.js:782 +#: scripts/services/EditUriBuiltins.js:792 templates/backends/file.html:29 #: templates/backends/generic.html:18 templates/backends/jottacloud.html:7 #: templates/backends/jottacloud.html:8 templates/backends/mega.html:7 #: templates/backends/mega.html:8 templates/backends/openstack.html:18 @@ -2392,15 +2487,15 @@ msgstr "Verifica dati remoti..." msgid "Verifying restored files ..." msgstr "Verifica file ripristinati..." -#: scripts/controllers/EditBackupController.js:41 +#: scripts/controllers/EditBackupController.js:43 msgid "Very strong" msgstr "Molto forte" -#: scripts/controllers/EditBackupController.js:38 +#: scripts/controllers/EditBackupController.js:40 msgid "Very weak" msgstr "Molto debole" -#: index.html:248 +#: index.html:246 msgid "Visit us on" msgstr "Seguici su" @@ -2446,11 +2541,11 @@ msgstr "" "Ti consigliamo di criptare tutti i backup archiviati al di fuori del tuo " "sistema" -#: scripts/controllers/EditBackupController.js:39 +#: scripts/controllers/EditBackupController.js:41 msgid "Weak" msgstr "Debole" -#: scripts/controllers/EditBackupController.js:366 +#: scripts/controllers/EditBackupController.js:390 msgid "Weak passphrase" msgstr "Passphrase debole" @@ -2458,7 +2553,7 @@ msgstr "Passphrase debole" msgid "Wed" msgstr "Mer" -#: scripts/services/AppUtils.js:91 templates/addoredit.html:329 +#: scripts/services/AppUtils.js:91 templates/addoredit.html:350 msgid "Weeks" msgstr "Settimane" @@ -2470,19 +2565,19 @@ msgstr "Da dove vuoi ripristinare?" msgid "Where do you want to restore the files to?" msgstr "Dove vuoi ripristinare i files?" -#: scripts/controllers/EditBackupController.js:19 +#: scripts/controllers/EditBackupController.js:21 msgid "Windows" msgstr "Windows" -#: scripts/services/AppUtils.js:93 templates/addoredit.html:331 +#: scripts/services/AppUtils.js:93 templates/addoredit.html:352 msgid "Years" msgstr "Anni" #: scripts/controllers/AppController.js:172 #: scripts/controllers/DeleteController.js:77 -#: scripts/controllers/EditBackupController.js:140 -#: scripts/controllers/EditBackupController.js:150 -#: scripts/controllers/EditBackupController.js:472 +#: scripts/controllers/EditBackupController.js:142 +#: scripts/controllers/EditBackupController.js:152 +#: scripts/controllers/EditBackupController.js:496 #: scripts/controllers/HomeController.js:7 #: scripts/controllers/LocalDatabaseController.js:28 #: scripts/controllers/LocalDatabaseController.js:72 @@ -2492,21 +2587,21 @@ msgstr "Anni" #: scripts/directives/backupEditUri.js:87 #: scripts/services/EditUriBackendConfig.js:66 #: scripts/services/EditUriBuiltins.js:47 -#: scripts/services/EditUriBuiltins.js:630 -#: scripts/services/EditUriBuiltins.js:702 -#: scripts/services/EditUriBuiltins.js:719 +#: scripts/services/EditUriBuiltins.js:664 +#: scripts/services/EditUriBuiltins.js:736 +#: scripts/services/EditUriBuiltins.js:753 msgid "Yes" msgstr "Si" -#: scripts/controllers/EditBackupController.js:381 +#: scripts/controllers/EditBackupController.js:405 msgid "Yes, I have stored the passphrase safely" msgstr "Si, ho archiviato la passphrase in modo sicuro" -#: scripts/controllers/EditBackupController.js:424 +#: scripts/controllers/EditBackupController.js:448 msgid "Yes, I'm brave!" msgstr "Sì, sono coraggioso!" -#: scripts/controllers/EditBackupController.js:415 +#: scripts/controllers/EditBackupController.js:439 msgid "Yes, please break my backup!" msgstr "Sì, per favore rompi il mio backup!" @@ -2530,7 +2625,7 @@ msgstr "" "Stai cambiando il percorso di un database esistente.\n" "Sei sicuro che questo è ciò che vuoi?" -#: templates/about.html:26 +#: templates/about.html:27 msgid "You are currently running {{appname}} {{version}}" msgstr "Attualmente stai eseguendo {{appname}} {{version}}" @@ -2550,7 +2645,7 @@ msgstr "" "Puoi arrestare immediatamente l'attività o consentire al processo di " "continuare il file in corso e fermarlo." -#: scripts/controllers/EditBackupController.js:424 +#: scripts/controllers/EditBackupController.js:448 msgid "" "You have changed the encryption mode. This may break stuff. You are " "encouraged to create a new backup instead" @@ -2558,7 +2653,7 @@ msgstr "" "Hai modificato l'algoritmo di crittografia. Questa azione potrebbe " "corrompere i dati. Ti consigliamo di creare un nuovo backup." -#: scripts/controllers/EditBackupController.js:415 +#: scripts/controllers/EditBackupController.js:439 msgid "" "You have changed the passphrase, which is not supported. You are encouraged " "to create a new backup instead." @@ -2566,7 +2661,7 @@ msgstr "" "Hai modificato la passphrase ma questo non è supportato. Ti consigliamo di " "creare un nuovo backup." -#: scripts/controllers/EditBackupController.js:451 +#: scripts/controllers/EditBackupController.js:475 msgid "" "You have chosen not to encrypt the backup. Encryption is recommended for all" " data stored on a remote server." @@ -2580,7 +2675,7 @@ msgstr "" "Si è scelto di ripristinare in una nuova posizione, ma non ne è stata " "inserita una" -#: scripts/controllers/EditBackupController.js:381 +#: scripts/controllers/EditBackupController.js:405 msgid "" "You have generated a strong passphrase. Make sure you have made a safe copy " "of the passphrase, as the data cannot be recovered if you lose the " @@ -2590,35 +2685,39 @@ msgstr "" " della passphrase, poiché i dati non possono essere recuperati se perdi la " "passphrase." -#: scripts/controllers/EditBackupController.js:311 +#: scripts/controllers/EditBackupController.js:313 msgid "You must choose at least one source folder" msgstr "Devi scegliere almeno una cartella sorgente" -#: scripts/controllers/EditBackupController.js:290 +#: scripts/controllers/EditBackupController.js:292 msgid "You must enter a name for the backup" msgstr "Devi inserire un nome un nome per il backup" -#: scripts/controllers/EditBackupController.js:298 +#: scripts/controllers/EditBackupController.js:300 msgid "You must enter a passphrase or disable encryption" msgstr "Devi inserire una passphrase o disattivare la crittografia" -#: scripts/controllers/EditBackupController.js:330 +#: scripts/controllers/EditBackupController.js:344 msgid "You must enter a positive number of backups to keep" msgstr "Devi inserire un numero positivo di backup da mantenere" -#: scripts/services/EditUriBuiltins.js:677 +#: scripts/services/EditUriBuiltins.js:711 msgid "You must enter a tenant name if you do not provide an API Key" msgstr "Devi inserire il nome di un inquilino se non fornisci una Chiave API" -#: scripts/controllers/EditBackupController.js:323 +#: scripts/controllers/EditBackupController.js:337 msgid "You must enter a valid duration for the time to keep backups" msgstr "Devi inserire un periodo di tempo valido in cui mantenere i backup" -#: scripts/services/EditUriBuiltins.js:674 +#: scripts/controllers/EditBackupController.js:351 +msgid "You must enter a valid rentention policy string" +msgstr "Devi immettere una stringa di criteri di conservazione valida" + +#: scripts/services/EditUriBuiltins.js:708 msgid "You must enter either a password or an API Key" msgstr "Devi inserire una password o una Chiave API" -#: scripts/services/EditUriBuiltins.js:681 +#: scripts/services/EditUriBuiltins.js:715 msgid "You must enter either a password or an API Key, not both" msgstr "Devi inserire una password o una Chiave API, non entrambe" @@ -2639,11 +2738,11 @@ msgstr "Devi compilare in nome utente" msgid "You must fill in {{field}}" msgstr "Devi compilare in {{field}}" -#: scripts/services/EditUriBuiltins.js:669 +#: scripts/services/EditUriBuiltins.js:703 msgid "You must select or fill in the AuthURI" msgstr "Devi selezionare o compilare in AuthURI" -#: scripts/services/EditUriBuiltins.js:695 +#: scripts/services/EditUriBuiltins.js:729 msgid "You must select or fill in the server" msgstr "Devi selezionare o compilare in server" @@ -2655,15 +2754,11 @@ msgstr "Devi specificare un percorso" msgid "Your files and folders have been restored successfully." msgstr "I tuoi file e cartelle sono stati ripristinati correttamente." -#: scripts/controllers/EditBackupController.js:366 +#: scripts/controllers/EditBackupController.js:390 msgid "Your passphrase is easy to guess. Consider changing passphrase." msgstr "" "La tua passphrase è facile da indovinare. Considera l'idea di cambiarla." -#: templates/addoredit.html:321 -msgid "a specific number" -msgstr "un numero specifico" - #: templates/backends/gcs.html:3 templates/backends/openstack.html:3 msgid "bucket/folder/subfolder" msgstr "bucket/cartella/sottocartella" @@ -2676,7 +2771,7 @@ msgstr "byte" msgid "byte/s" msgstr "byte/s" -#: templates/addoredit.html:276 templates/addoredit.html:332 +#: templates/addoredit.html:276 templates/addoredit.html:353 #: templates/advancedoptionseditor.html:28 #: templates/advancedoptionseditor.html:35 msgid "custom" @@ -2687,15 +2782,7 @@ msgstr "Personalizzato" msgid "resume now" msgstr "riprendi ora" -#: templates/addoredit.html:319 -msgid "unlimited" -msgstr "illimitato" - -#: templates/addoredit.html:320 -msgid "until they are older than" -msgstr "finché non sono più vecchi di" - -#: templates/about.html:11 +#: templates/about.html:12 msgid "" "{{appname}} was primarily developed by {{dev1}} " "and {{dev2}}. {{appname}} can be downloaded from " diff --git a/Localizations/webroot/localization_webroot-nl_NL.po b/Localizations/webroot/localization_webroot-nl_NL.po index 5371b6458..f781aaeb7 100644 --- a/Localizations/webroot/localization_webroot-nl_NL.po +++ b/Localizations/webroot/localization_webroot-nl_NL.po @@ -1,9 +1,9 @@ # Translators: -# Kees Zaaijer , 2016 +# Kees Zaaijer, 2016 msgid "" msgstr "" "Project-Id-Version: \n" -"Last-Translator: Kees Zaaijer , 2016\n" +"Last-Translator: Kees Zaaijer, 2016\n" "Language-Team: Dutch (Netherlands) (https://www.transifex.com/duplicati/teams/67655/nl_NL/)\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -22,12 +22,12 @@ msgstr "...laden..." msgid "API Key" msgstr "API sleutel" -#: scripts/services/EditUriBuiltins.js:691 templates/backends/s3.html:54 +#: scripts/services/EditUriBuiltins.js:725 templates/backends/s3.html:54 #: templates/backends/s3.html:55 msgid "AWS Access ID" msgstr "AWS Toegangs ID" -#: scripts/services/EditUriBuiltins.js:692 templates/backends/s3.html:58 +#: scripts/services/EditUriBuiltins.js:726 templates/backends/s3.html:58 #: templates/backends/s3.html:59 msgid "AWS Access Key" msgstr "AWS Toegangssleutel" @@ -36,7 +36,7 @@ msgstr "AWS Toegangssleutel" msgid "AWS IAM Policy" msgstr "AWS IAM Beleid" -#: index.html:226 index.html:242 +#: index.html:217 index.html:233 msgid "About" msgstr "Over" @@ -44,7 +44,7 @@ msgstr "Over" msgid "About {{appname}}" msgstr "Over {{appname}}" -#: scripts/services/EditUriBuiltins.js:656 templates/backends/azure.html:11 +#: scripts/services/EditUriBuiltins.js:690 templates/backends/azure.html:11 msgid "Access Key" msgstr "Toegangssleutel" @@ -56,7 +56,7 @@ msgstr "Toegang geweigerd" msgid "Access to user interface" msgstr "Toegang tot gebruikersinterface" -#: scripts/services/EditUriBuiltins.js:655 templates/backends/azure.html:7 +#: scripts/services/EditUriBuiltins.js:689 templates/backends/azure.html:7 msgid "Account name" msgstr "Accountnaam" @@ -81,7 +81,7 @@ msgstr "Voeg een pad rechtstreeks toe" msgid "Add advanced option" msgstr "Voeg geavanceerde optie toe" -#: index.html:211 +#: index.html:205 msgid "Add backup" msgstr "Back-up toevoegen" @@ -93,12 +93,12 @@ msgstr "Voeg filter toe" msgid "Add path" msgstr "Voeg pad toe" -#: scripts/services/EditUriBuiltins.js:702 -#: scripts/services/EditUriBuiltins.js:719 +#: scripts/services/EditUriBuiltins.js:736 +#: scripts/services/EditUriBuiltins.js:753 msgid "Adjust bucket name?" msgstr "Bucket naam aanpassen?" -#: scripts/services/EditUriBuiltins.js:630 +#: scripts/services/EditUriBuiltins.js:664 msgid "Adjust path name?" msgstr "Padnaam aanpassen?" @@ -106,7 +106,7 @@ msgstr "Padnaam aanpassen?" msgid "Advanced Options" msgstr "Geavanceerde Opties" -#: templates/addoredit.html:348 templates/edituri.html:28 +#: templates/addoredit.html:374 templates/edituri.html:28 msgid "Advanced options" msgstr "Geavanceerde opties" @@ -114,7 +114,7 @@ msgstr "Geavanceerde opties" msgid "Advanced:" msgstr "Geavanceerd:" -#: scripts/controllers/EditBackupController.js:22 +#: scripts/controllers/EditBackupController.js:24 msgid "All" msgstr "Alle" @@ -161,7 +161,7 @@ msgstr "" "Een bestaand bestand was gevonden op de nieuwe locatie. Weet u zeker dat de " "database moet verwijzen naar een bestaand bestand?" -#: scripts/controllers/EditBackupController.js:472 +#: scripts/controllers/EditBackupController.js:496 msgid "" "An existing local database for the storage has been found.\n" "Re-using the database will allow the command-line and server instances to work on the same remote storage.\n" @@ -181,7 +181,7 @@ msgstr "Anonieme gebruiksrapporten" msgid "As Command-line" msgstr "Als Opdrachtregel" -#: scripts/services/EditUriBuiltins.js:614 templates/backends/gcs.html:8 +#: scripts/services/EditUriBuiltins.js:648 templates/backends/gcs.html:8 #: templates/backends/gcs.html:9 templates/backends/oauth.html:8 #: templates/backends/oauth.html:9 msgid "AuthID" @@ -195,7 +195,7 @@ msgstr "Authenticatie wachtwoord" msgid "Authentication username" msgstr "Authenticatie gebruikersnaam" -#: scripts/controllers/EditBackupController.js:381 +#: scripts/controllers/EditBackupController.js:405 msgid "Autogenerated passphrase" msgstr "Automatisch gegenereerde wachtwoordzin" @@ -211,11 +211,11 @@ msgstr "B2 Account ID" msgid "B2 Application Key" msgstr "B2 Applicatiesleutel" -#: scripts/services/EditUriBuiltins.js:738 templates/backends/b2.html:13 +#: scripts/services/EditUriBuiltins.js:772 templates/backends/b2.html:13 msgid "B2 Cloud Storage Account ID" msgstr "B2 Cloud Storage Account ID" -#: scripts/services/EditUriBuiltins.js:739 templates/backends/b2.html:17 +#: scripts/services/EditUriBuiltins.js:773 templates/backends/b2.html:17 msgid "B2 Cloud Storage Application Key" msgstr "B2 Cloud Storage Applicatiesleutel" @@ -223,7 +223,7 @@ msgstr "B2 Cloud Storage Applicatiesleutel" msgid "Back" msgstr "Vorige" -#: templates/about.html:66 +#: templates/about.html:67 msgid "Backend modules:" msgstr "Backend modules:" @@ -236,6 +236,10 @@ msgstr "Back-updoel" msgid "Backup location" msgstr "Back-up locatie" +#: templates/addoredit.html:317 +msgid "Backup retention" +msgstr "Back-up retentie" + #: templates/home.html:60 msgid "Backup:" msgstr "Back-up:" @@ -256,9 +260,9 @@ msgstr "Bladeren" msgid "Browser default" msgstr "Browser standaard" -#: scripts/services/EditUriBuiltins.js:666 -#: scripts/services/EditUriBuiltins.js:690 -#: scripts/services/EditUriBuiltins.js:737 +#: scripts/services/EditUriBuiltins.js:700 +#: scripts/services/EditUriBuiltins.js:724 +#: scripts/services/EditUriBuiltins.js:771 msgid "Bucket Name" msgstr "Bucket Naam" @@ -298,13 +302,13 @@ msgstr "Canary" #: scripts/controllers/AppController.js:44 #: scripts/controllers/AppController.js:59 -#: scripts/controllers/EditBackupController.js:366 -#: scripts/controllers/EditBackupController.js:381 -#: scripts/controllers/EditBackupController.js:415 -#: scripts/controllers/EditBackupController.js:424 -#: scripts/controllers/EditBackupController.js:451 -#: scripts/controllers/EditBackupController.js:472 -#: scripts/controllers/EditBackupController.js:82 +#: scripts/controllers/EditBackupController.js:390 +#: scripts/controllers/EditBackupController.js:405 +#: scripts/controllers/EditBackupController.js:439 +#: scripts/controllers/EditBackupController.js:448 +#: scripts/controllers/EditBackupController.js:475 +#: scripts/controllers/EditBackupController.js:496 +#: scripts/controllers/EditBackupController.js:84 #: scripts/controllers/LocalDatabaseController.js:72 #: scripts/controllers/LocalDatabaseController.js:88 #: scripts/controllers/RestoreDirectController.js:24 @@ -312,9 +316,9 @@ msgstr "Canary" #: scripts/controllers/StateController.js:112 #: scripts/services/CaptchaService.js:22 scripts/services/DialogService.js:50 #: scripts/services/EditUriBuiltins.js:47 -#: scripts/services/EditUriBuiltins.js:630 -#: scripts/services/EditUriBuiltins.js:702 -#: scripts/services/EditUriBuiltins.js:719 templates/delete.html:54 +#: scripts/services/EditUriBuiltins.js:664 +#: scripts/services/EditUriBuiltins.js:736 +#: scripts/services/EditUriBuiltins.js:753 templates/delete.html:54 #: templates/export.html:26 templates/settings.html:146 #: templates/waitarea.html:19 msgid "Cancel" @@ -336,7 +340,7 @@ msgstr "Aanpassingen-log voor {{appname}} {{version}}" msgid "Check failed:" msgstr "Controle mislukt:" -#: templates/about.html:35 +#: templates/about.html:36 msgid "Check for updates now" msgstr "Controleer nu op updates" @@ -344,7 +348,7 @@ msgstr "Controleer nu op updates" msgid "Checking ..." msgstr "Controleren ..." -#: templates/about.html:36 +#: templates/about.html:37 msgid "Checking for updates ..." msgstr "Controleren op updates ..." @@ -356,7 +360,7 @@ msgstr "Kies een opslagtype om aan de slag te gaan" msgid "Click the AuthID link to create an AuthID" msgstr "Klik op de AuthID link om een AuthID aan te maken" -#: index.html:156 index.html:199 +#: index.html:150 index.html:193 msgid "Click to set throttle options" msgstr "Klik om bandbreedte-opties in te stellen" @@ -380,7 +384,7 @@ msgstr "Back-up wordt voltooid ..." msgid "Completing previous backup ..." msgstr "Vorige back-up wordt voltooid ..." -#: templates/about.html:67 +#: templates/about.html:68 msgid "Compression modules:" msgstr "Compressiemodules:" @@ -414,11 +418,11 @@ msgstr "Bevestiging vereist" msgid "Connect" msgstr "Verbind" -#: index.html:319 +#: index.html:305 msgid "Connect now" msgstr "Verbind nu" -#: index.html:315 +#: index.html:301 msgid "Connecting to server ..." msgstr "Verbinden met server ..." @@ -426,11 +430,11 @@ msgstr "Verbinden met server ..." msgid "Connecting to task ...." msgstr "Verbinding maken met taak ..." -#: index.html:320 +#: index.html:306 msgid "Connecting..." msgstr "Verbinden..." -#: index.html:311 +#: index.html:297 msgid "Connection lost" msgstr "Verbinding verbroken" @@ -439,7 +443,7 @@ msgstr "Verbinding verbroken" msgid "Connection worked!" msgstr "Verbinding werkt!" -#: scripts/services/EditUriBuiltins.js:657 templates/backends/azure.html:2 +#: scripts/services/EditUriBuiltins.js:691 templates/backends/azure.html:2 msgid "Container name" msgstr "Containernaam" @@ -451,7 +455,7 @@ msgstr "Container-regio" msgid "Continue" msgstr "Volgende" -#: scripts/controllers/EditBackupController.js:451 +#: scripts/controllers/EditBackupController.js:475 msgid "Continue without encryption" msgstr "Ga verder zonder versleuteling" @@ -459,6 +463,10 @@ msgstr "Ga verder zonder versleuteling" msgid "Copied!" msgstr "Gekopieerd!" +#: templates/copy_clipboard_buttons.html:3 +msgid "Copy" +msgstr "Kopie" + #: templates/addoredit.html:99 templates/restoredirect.html:42 msgid "Copy Destination URL to Clipboard" msgstr "Kopieer doel URL naar Klembord" @@ -523,6 +531,10 @@ msgstr "Aangepaste S3 endpoint" msgid "Custom authentication url" msgstr "Aangepaste authenticatie url" +#: templates/addoredit.html:323 +msgid "Custom backup retention" +msgstr "Aangepaste back-up retentie" + #: templates/backends/gcs.html:18 msgid "Custom location ({{server}})" msgstr "Aangepaste locatie ({{server}})" @@ -547,7 +559,7 @@ msgstr "Aangepaste opslagklasse ({{class}})" msgid "Database ..." msgstr "Database ..." -#: scripts/services/AppUtils.js:90 templates/addoredit.html:328 +#: scripts/services/AppUtils.js:90 templates/addoredit.html:349 msgid "Days" msgstr "Dagen" @@ -579,6 +591,10 @@ msgstr "Verwijderen ..." msgid "Delete backup" msgstr "Verwijder back-up" +#: templates/addoredit.html:320 +msgid "Delete backups that are older than" +msgstr "Verwijder back-ups die ouder zijn dan" + #: templates/delete.html:13 msgid "Delete local database" msgstr "Verwijder lokale database" @@ -646,18 +662,10 @@ msgstr "Wilt u de back-up \"{{name}}\" echt verwijderen?" msgid "Do you really want to delete the local database for: {{name}}" msgstr "Wilt u de lokale database voor: {{name}} echt verwijderen?" -#: index.html:141 index.html:269 +#: index.html:142 index.html:241 msgid "Donate" msgstr "Doneren" -#: index.html:147 index.html:275 -msgid "Donate with PayPal" -msgstr "Doneer met PayPal" - -#: index.html:144 index.html:272 -msgid "Donate with crypto currency" -msgstr "Doneer met crypto-valuta" - #: templates/settings.html:58 templates/settings.html:60 msgid "Donation messages" msgstr "Doneer-berichten" @@ -694,11 +702,11 @@ msgstr "Update downloaden ..." msgid "Duplicate option {{opt}}" msgstr "Dupliceer optie {{opt}}" -#: index.html:263 +#: index.html:261 msgid "Duplicati Website" msgstr "Duplicati Website" -#: index.html:251 +#: index.html:249 msgid "Duplicati forum" msgstr "Duplicati forum" @@ -726,12 +734,12 @@ msgstr "" msgid "Edit ..." msgstr "Bewerken ..." -#: templates/addoredit.html:170 templates/addoredit.html:359 +#: templates/addoredit.html:170 templates/addoredit.html:385 #: templates/edituri.html:39 templates/settings.html:135 msgid "Edit as list" msgstr "Bewerk als lijst" -#: templates/addoredit.html:173 templates/addoredit.html:362 +#: templates/addoredit.html:173 templates/addoredit.html:388 #: templates/edituri.html:42 templates/settings.html:141 msgid "Edit as text" msgstr "Bewerk als tekst" @@ -745,19 +753,33 @@ msgstr "Versleutel bestand" msgid "Encryption" msgstr "Versleuteling" -#: scripts/controllers/EditBackupController.js:424 +#: scripts/controllers/EditBackupController.js:448 msgid "Encryption changed" msgstr "Versleuteling aangepast" -#: templates/about.html:68 +#: templates/about.html:69 msgid "Encryption modules:" msgstr "Versleutelingsmodules:" -#: scripts/controllers/EditBackupController.js:82 +#: scripts/controllers/EditBackupController.js:84 #: scripts/controllers/RestoreDirectController.js:24 msgid "Enter URL" msgstr "Geef URL in" +#: templates/addoredit.html:337 +msgid "" +"Enter a retention strategy manually. Placeholders are D/W/Y for " +"days/weeks/years. The syntax is: 7D:1D,4W:1W,36M:1M. This example keeps one " +"backup for each of the next 7 days, one for each of the next 4 weeks, and " +"one for each of the next 36 months. This can also be written as " +"1W:1D,1M:1W,3Y:1M." +msgstr "" +"Geef handmatig een retentie-strategie op. Aanduidingen zijn D/W/Y voor " +"dagen/weken/jaren. De syntaxis is: 7D:1D,4W:1W,36M:1M. Dit voorbeeld behoudt" +" één back-up voor elk van de volgende 7 dagen, één voor elk van de volgende " +"4 weken, en één voor elk van de volgende 36 maanden. Dit kan ook geschreven " +"worden als 1W:1D,1M:1W,3Y:1M." + #: templates/backends/azure.html:12 msgid "Enter access key" msgstr "Geef toegangscode in" @@ -890,6 +912,10 @@ msgstr "Exporteer configuratie" msgid "Exporting ..." msgstr "Exporteren ..." +#: templates/externallink.html:1 +msgid "External link" +msgstr "Externe link" + #: scripts/services/SystemInfo.js:52 msgid "FTP (Alternative)" msgstr "FTP (Alternatief)" @@ -930,7 +956,7 @@ msgstr "Ophalen pad-informatie mislukt: {{message}}" msgid "Failed to import:" msgstr "Importeren mislukt:" -#: scripts/controllers/EditBackupController.js:737 +#: scripts/controllers/EditBackupController.js:768 msgid "Failed to read backup defaults:" msgstr "Standaard instellingen voor back-up inlezen mislukt:" @@ -1020,7 +1046,7 @@ msgstr "Genereer IAM toegangsbeleid" msgid "Getting file versions ..." msgstr "Bestandsversies ophalen ..." -#: scripts/controllers/EditBackupController.js:26 +#: scripts/controllers/EditBackupController.js:28 msgid "Hidden files" msgstr "Verborgen bestanden" @@ -1032,7 +1058,7 @@ msgstr "Verberg" msgid "Hide hidden folders" msgstr "Verberg verborgen bestanden" -#: index.html:208 scripts/services/AppUtils.js:61 +#: index.html:202 scripts/services/AppUtils.js:61 msgid "Home" msgstr "Start" @@ -1069,6 +1095,14 @@ msgstr "" "Als een geplande taak werd overgeslagen, zal de taak zo snel mogelijk na het" " geplande tijdstip starten." +#: templates/addoredit.html:357 +msgid "" +"If at least one newer backup is found, all backups older than this date are " +"deleted." +msgstr "" +"Als tenminste één nieuwere back-up is gevonden, zullen alle back-ups die " +"ouder zijn dan deze datum worden verwijderd." + #: templates/localdatabase.html:13 msgid "" "If the backup and the remote storage is out of sync, Duplicati will require " @@ -1126,7 +1160,7 @@ msgstr "" "Als uw machine zich in een multi-user omgeving bevindt (bijvoorbeeld als op de machine met meer dan één account kan worden aangemeld), moet een wachtwoord worden ingesteld om te voorkomen dat andere gebruikers togang kunnen krijgen tot gegevens behorend bij uw account.\n" "Wilt u nu een wachtwoord instellen?" -#: templates/import.html:26 +#: templates/import.html:31 msgid "Import" msgstr "Importeer" @@ -1151,11 +1185,15 @@ msgstr "Importeren mislukt" msgid "Import from a file" msgstr "Importeer vanuit een bestand" -#: templates/import.html:30 +#: templates/import.html:19 +msgid "Import metadata" +msgstr "Importeer metadata" + +#: templates/import.html:35 msgid "Importing ..." msgstr "Importeren ..." -#: scripts/controllers/EditBackupController.js:150 +#: scripts/controllers/EditBackupController.js:152 msgid "Include a file?" msgstr "Een bestand opnemen?" @@ -1187,16 +1225,17 @@ msgstr "Installeren" msgid "Install failed:" msgstr "Installeren mislukt" -#: scripts/services/EditUriBuiltins.js:771 +#: scripts/services/EditUriBuiltins.js:805 msgid "Invalid characters in path" msgstr "Ongeldige tekens in pad" -#: scripts/controllers/EditBackupController.js:323 -#: scripts/controllers/EditBackupController.js:330 +#: scripts/controllers/EditBackupController.js:337 +#: scripts/controllers/EditBackupController.js:344 +#: scripts/controllers/EditBackupController.js:351 msgid "Invalid retention time" msgstr "Ongeldige retentietijd" -#: scripts/services/EditUriBuiltins.js:590 +#: scripts/services/EditUriBuiltins.js:624 msgid "" "It is possible to connect to some FTP without a password.\n" "Are you sure your FTP server supports password-less logins?" @@ -1212,9 +1251,13 @@ msgstr "KByte" msgid "KByte/s" msgstr "KByte/s" -#: templates/addoredit.html:317 -msgid "Keep this number of backups" -msgstr "Bewaar dit aantal back-ups" +#: templates/addoredit.html:321 +msgid "Keep a specific number of backups" +msgstr "Behoud een specifiek aantal back-ups" + +#: templates/addoredit.html:319 +msgid "Keep all backups" +msgstr "Behoud alle back-ups" #: templates/settings.html:40 msgid "Language in user interface" @@ -1236,7 +1279,7 @@ msgstr "Laatste" msgid "Libraries" msgstr "Bibliotheken" -#: scripts/controllers/EditBackupController.js:21 +#: scripts/controllers/EditBackupController.js:23 msgid "Linux" msgstr "Linux" @@ -1265,7 +1308,7 @@ msgstr "Laad doel vanuit een geëxporteerde taak of een opslagprovider" msgid "Load older data" msgstr "Laad oudere gegevens" -#: templates/about.html:44 templates/about.html:49 templates/about.html:55 +#: templates/about.html:45 templates/about.html:50 templates/about.html:56 #: templates/captcha.html:14 templates/log.html:15 templates/log.html:22 #: templates/log.html:45 templates/log.html:53 templates/log.html:60 #: templates/log.html:67 templates/updatechangelog.html:7 @@ -1276,6 +1319,10 @@ msgstr "Laden ..." msgid "Loading remote storage usage ..." msgstr "Laden van remote opslaggebruik ..." +#: scripts/services/EditUriBuiltins.js:818 +msgid "Local Repository" +msgstr "Lokale Opslagplaats" + #: templates/localdatabase.html:2 msgid "Local database for" msgstr "Lokale database voor" @@ -1284,7 +1331,11 @@ msgstr "Lokale database voor" msgid "Local database path:" msgstr "Lokaal database-pad:" -#: scripts/services/SystemInfo.js:77 +#: templates/backends/rclone.html:2 +msgid "Local repository" +msgstr "Lokale opslagplaats" + +#: scripts/services/SystemInfo.js:78 msgid "Local storage" msgstr "Lokale opslag" @@ -1304,7 +1355,7 @@ msgstr "Log gegevens voor {{Backup.Backup.Name}}" msgid "Log data from the server" msgstr "Log gegevens van de server" -#: index.html:229 +#: index.html:220 msgid "Log out" msgstr "Uitloggen" @@ -1332,8 +1383,8 @@ msgstr "Max downloadsnelheid" msgid "Max upload speed" msgstr "Max Uploadsnelheid" -#: index.html:152 templates/addoredit.html:123 templates/addoredit.html:165 -#: templates/addoredit.html:354 templates/addoredit.html:91 +#: index.html:146 templates/addoredit.html:123 templates/addoredit.html:165 +#: templates/addoredit.html:380 templates/addoredit.html:91 #: templates/edituri.html:34 templates/restoredirect.html:34 msgid "Menu" msgstr "Menu" @@ -1350,7 +1401,7 @@ msgstr "Microsoft SQL Databases" msgid "Minimum redundancy" msgstr "Minimale redundantie" -#: scripts/services/EditUriBuiltins.js:775 +#: scripts/services/EditUriBuiltins.js:809 msgid "Minimum redundancy is 1.0" msgstr "Minimale redundantie is 1.0" @@ -1359,15 +1410,15 @@ msgstr "Minimale redundantie is 1.0" msgid "Minutes" msgstr "Minuten" -#: scripts/controllers/EditBackupController.js:290 +#: scripts/controllers/EditBackupController.js:292 msgid "Missing name" msgstr "Ontbrekende naam" -#: scripts/controllers/EditBackupController.js:298 +#: scripts/controllers/EditBackupController.js:300 msgid "Missing passphrase" msgstr "Ontbrekende wachtwoordzin" -#: scripts/controllers/EditBackupController.js:311 +#: scripts/controllers/EditBackupController.js:313 msgid "Missing sources" msgstr "Ontbrekende bronnen" @@ -1375,7 +1426,7 @@ msgstr "Ontbrekende bronnen" msgid "Mon" msgstr "Maandag" -#: scripts/services/AppUtils.js:92 templates/addoredit.html:330 +#: scripts/services/AppUtils.js:92 templates/addoredit.html:351 msgid "Months" msgstr "Maanden" @@ -1434,11 +1485,11 @@ msgstr "Volgende" msgid "Next scheduled run:" msgstr "Volgende geplande uitvoering:" -#: index.html:183 +#: index.html:177 msgid "Next scheduled task:" msgstr "Volgende geplande taak:" -#: index.html:180 +#: index.html:174 msgid "Next task:" msgstr "Volgende taak:" @@ -1447,9 +1498,9 @@ msgid "Next time" msgstr "Volgende keer" #: scripts/controllers/DeleteController.js:77 -#: scripts/controllers/EditBackupController.js:140 -#: scripts/controllers/EditBackupController.js:150 -#: scripts/controllers/EditBackupController.js:472 +#: scripts/controllers/EditBackupController.js:142 +#: scripts/controllers/EditBackupController.js:152 +#: scripts/controllers/EditBackupController.js:496 #: scripts/controllers/HomeController.js:7 #: scripts/controllers/LocalDatabaseController.js:28 #: scripts/controllers/LocalDatabaseController.js:72 @@ -1459,9 +1510,9 @@ msgstr "Volgende keer" #: scripts/directives/backupEditUri.js:87 #: scripts/services/EditUriBackendConfig.js:66 #: scripts/services/EditUriBuiltins.js:47 -#: scripts/services/EditUriBuiltins.js:630 -#: scripts/services/EditUriBuiltins.js:702 -#: scripts/services/EditUriBuiltins.js:719 +#: scripts/services/EditUriBuiltins.js:664 +#: scripts/services/EditUriBuiltins.js:736 +#: scripts/services/EditUriBuiltins.js:753 msgid "No" msgstr "Nee" @@ -1481,7 +1532,7 @@ msgstr "" "Geen bewerkingsprogramma gevonden voor het "{{backend}}" " "opslagtype" -#: scripts/controllers/EditBackupController.js:451 templates/addoredit.html:45 +#: scripts/controllers/EditBackupController.js:475 templates/addoredit.html:45 msgid "No encryption" msgstr "Geen versleuteling" @@ -1497,7 +1548,7 @@ msgstr "Geen items om te herstellen, selecteer één of meer items" msgid "No passphrase entered" msgstr "Geen wachtwoordzin ingegeven" -#: index.html:185 +#: index.html:179 msgid "No scheduled tasks" msgstr "Geen geplande taken" @@ -1505,7 +1556,7 @@ msgstr "Geen geplande taken" msgid "No, my machine has only a single account" msgstr "Nee, mijn machine heeft slechts een enkele account" -#: scripts/controllers/EditBackupController.js:304 +#: scripts/controllers/EditBackupController.js:306 msgid "Non-matching passphrase" msgstr "Niet-bijbehorende wachtwoordzin" @@ -1513,10 +1564,16 @@ msgstr "Niet-bijbehorende wachtwoordzin" msgid "None / disabled" msgstr "Geen / uitgeschakeld" +#: templates/addoredit.html:326 +msgid "Nothing will be deleted. The backup size will grow with each change." +msgstr "" +"Er zal niets verwijderd worden. De back-upgrootte zal toenemen met iedere " +"verandering." + #: scripts/controllers/AppController.js:44 #: scripts/controllers/AppController.js:59 -#: scripts/controllers/EditBackupController.js:82 -#: scripts/controllers/EditBackupController.js:90 +#: scripts/controllers/EditBackupController.js:84 +#: scripts/controllers/EditBackupController.js:92 #: scripts/controllers/RestoreDirectController.js:24 #: scripts/controllers/RestoreDirectController.js:33 #: scripts/services/CaptchaService.js:22 scripts/services/DialogService.js:28 @@ -1526,10 +1583,18 @@ msgstr "Geen / uitgeschakeld" msgid "OK" msgstr "OK" -#: scripts/controllers/EditBackupController.js:20 +#: scripts/controllers/EditBackupController.js:22 msgid "OSX" msgstr "OSX" +#: templates/addoredit.html:344 +msgid "" +"Once there are more backups than the specified number, the oldest backups " +"are deleted." +msgstr "" +"Zodra er meer back-ups zijn dan het opgegeven aantal, zullen de oudste back-" +"ups worden verwijderd." + #: templates/backends/openstack.html:7 msgid "OpenStack AuthURI" msgstr "OpenStack AuthURI" @@ -1572,10 +1637,21 @@ msgstr "" msgid "Original location" msgstr "Originele locatie" -#: scripts/services/SystemInfo.js:80 +#: scripts/services/SystemInfo.js:81 msgid "Others" msgstr "Anderen" +#: templates/addoredit.html:330 +msgid "" +"Over time backups will be deleted automatically. There will remain one " +"backup for each of the last 7 days, each of the last 4 weeks, each of the " +"last 12 months. There will always be at least one remaining backup." +msgstr "" +"Na verloop van tijd zullen back-ups automatisch verwijderd worden. Er zal " +"één back-up overblijven voor elk van de laatste 7 dagen, voor elk van de " +"laatste 4 weken, en voor elk van de laatste 12 maanden. Er zal altijd " +"tenminste één back-up overblijven." + #: templates/restore.html:114 msgid "Overwrite" msgstr "Overschrijven" @@ -1589,16 +1665,16 @@ msgstr "Wachtwoordzin" msgid "Passphrase (if encrypted)" msgstr "Wachtwoordzin (indien versleuteld)" -#: scripts/controllers/EditBackupController.js:415 +#: scripts/controllers/EditBackupController.js:439 msgid "Passphrase changed" msgstr "Wachtwoordzin veranderd" -#: scripts/controllers/EditBackupController.js:304 +#: scripts/controllers/EditBackupController.js:306 msgid "Passphrases are not matching" msgstr "Wachtwoordzinnen komen niet overeen" -#: scripts/services/EditUriBuiltins.js:749 -#: scripts/services/EditUriBuiltins.js:759 templates/backends/file.html:33 +#: scripts/services/EditUriBuiltins.js:783 +#: scripts/services/EditUriBuiltins.js:793 templates/backends/file.html:33 #: templates/backends/generic.html:22 templates/backends/jottacloud.html:11 #: templates/backends/jottacloud.html:12 templates/backends/mega.html:11 #: templates/backends/mega.html:12 templates/backends/openstack.html:22 @@ -1606,7 +1682,7 @@ msgstr "Wachtwoordzinnen komen niet overeen" msgid "Password" msgstr "Wachtwoord" -#: scripts/controllers/EditBackupController.js:36 +#: scripts/controllers/EditBackupController.js:38 msgid "Passwords do not match" msgstr "Wachtwoorden komen niet overeen" @@ -1614,7 +1690,7 @@ msgstr "Wachtwoorden komen niet overeen" msgid "Patching files with local blocks ..." msgstr "Bestanden bijwerken met lokale blokken ..." -#: scripts/controllers/EditBackupController.js:140 +#: scripts/controllers/EditBackupController.js:142 msgid "Path not found" msgstr "Pad niet gevonden" @@ -1655,7 +1731,7 @@ msgid "Port" msgstr "Poort" #: templates/addoredit.html:110 templates/addoredit.html:251 -#: templates/addoredit.html:301 templates/addoredit.html:381 +#: templates/addoredit.html:301 templates/addoredit.html:407 #: templates/restoredirect.html:81 msgid "Previous" msgstr "Vorige" @@ -1664,7 +1740,7 @@ msgstr "Vorige" msgid "ProjectID is optional if the bucket exist" msgstr "ProjectID is optioneel als de bucket bestaat" -#: scripts/services/SystemInfo.js:79 +#: scripts/services/SystemInfo.js:80 msgid "Proprietary" msgstr "Fabrikantgebonden" @@ -1688,7 +1764,7 @@ msgstr "Opnieuw opbouwen van de database ..." msgid "Registering temporary backup ..." msgstr "Registreren tijdelijke back-up ..." -#: scripts/controllers/EditBackupController.js:125 +#: scripts/controllers/EditBackupController.js:127 msgid "Relative paths not allowed" msgstr "Relatieve paden zijn niet toegestaan" @@ -1700,6 +1776,22 @@ msgstr "Andere code" msgid "Remote" msgstr "Remote" +#: scripts/services/EditUriBuiltins.js:819 +msgid "Remote Path" +msgstr "Remote Pad" + +#: scripts/services/EditUriBuiltins.js:817 +msgid "Remote Repository" +msgstr "Remote Opslagplaats" + +#: templates/backends/rclone.html:10 +msgid "Remote path" +msgstr "Remote pad" + +#: templates/backends/rclone.html:6 +msgid "Remote repository" +msgstr "Remote opslagplaats" + #: templates/addoredit.html:193 msgid "Remove" msgstr "Verwijderen" @@ -1728,7 +1820,7 @@ msgstr "Rapportage:" msgid "Reset" msgstr "Reset" -#: index.html:214 templates/restore.html:131 +#: index.html:208 templates/restore.html:131 msgid "Restore" msgstr "Herstellen" @@ -1770,7 +1862,7 @@ msgstr "Herstel lees/schrijfpermissies" msgid "Restoring files ..." msgstr "Bestanden worden hersteld ..." -#: index.html:217 +#: index.html:211 msgid "Resume" msgstr "Hervat" @@ -1794,7 +1886,7 @@ msgstr "Uitvoeren ..." msgid "Running commandline entry" msgstr "Opdrachtregelinvoer in uitvoering" -#: index.html:172 +#: index.html:166 msgid "Running task:" msgstr "Taak in uitvoering:" @@ -1810,7 +1902,7 @@ msgstr "Zelfde als de basis installatie versie: {{channelname}}" msgid "Sat" msgstr "Zaterdag" -#: templates/addoredit.html:380 templates/localdatabase.html:32 +#: templates/addoredit.html:406 templates/localdatabase.html:32 msgid "Save" msgstr "Opslaan" @@ -1822,7 +1914,7 @@ msgstr "Opslaan en repareren" msgid "Save different versions with timestamp in file name" msgstr "Sla verschillende versies op met tijdstempel in de bestandsnaam" -#: templates/import.html:19 +#: templates/import.html:24 msgid "Save immediately" msgstr "Onmiddellijk opslaan" @@ -1859,7 +1951,7 @@ msgstr "Selecteer een logniveau en bekijk meldingen zodra ze zich voordoen:" msgid "Select files" msgstr "Selecteer bestanden" -#: scripts/services/EditUriBuiltins.js:767 templates/backends/s3.html:8 +#: scripts/services/EditUriBuiltins.js:801 templates/backends/s3.html:8 #: templates/backends/sia.html:2 msgid "Server" msgstr "Server" @@ -1889,11 +1981,11 @@ msgstr "Server wachtwoord" msgid "Server paused" msgstr "Server gepauzeerd" -#: templates/about.html:71 +#: templates/about.html:72 msgid "Server state properties" msgstr "Server status eigenschappen" -#: index.html:220 templates/settings.html:2 +#: index.html:214 templates/settings.html:2 msgid "Settings" msgstr "Instellingen" @@ -1911,7 +2003,7 @@ msgstr "Toon geavanceerde editor" msgid "Show hidden folders" msgstr "Toon verborgen mappen" -#: index.html:223 +#: templates/about.html:8 msgid "Show log" msgstr "Log weergeven" @@ -1927,6 +2019,10 @@ msgstr "Toon boomstructuur" msgid "Sia server password" msgstr "Sia server wachtwoord" +#: templates/addoredit.html:322 +msgid "Smart backup retention" +msgstr "Slimme back-up retentie" + #: templates/backends/openstack.html:33 msgid "" "Some OpenStack providers allow an API key instead of a password and tenant " @@ -1955,7 +2051,7 @@ msgstr "Bron:" msgid "Specific builds for developers only." msgstr "Specifieke builds alleen voor ontwikkelaars." -#: scripts/services/SystemInfo.js:78 +#: scripts/services/SystemInfo.js:79 msgid "Standard protocols" msgstr "Standaard protocollen" @@ -1989,11 +2085,11 @@ msgstr "Stop de back-up in uitvoering" msgid "Stop running task" msgstr "Stop de taak in uitvoering" -#: index.html:168 +#: index.html:162 msgid "Stopping after upload:" msgstr "Stop na de upload:" -#: index.html:173 +#: index.html:167 msgid "Stopping task:" msgstr "Taak wordt gestopt:" @@ -2013,7 +2109,7 @@ msgstr "Opslagklasse voor het aanmaken van een bucket" msgid "Stored" msgstr "Opgeslagen" -#: scripts/controllers/EditBackupController.js:40 +#: scripts/controllers/EditBackupController.js:42 msgid "Strong" msgstr "Sterk" @@ -2034,7 +2130,7 @@ msgstr "Symbolische link" msgid "System default ({{levelname}})" msgstr "Systeem standaard ({{levelname}})" -#: scripts/controllers/EditBackupController.js:27 +#: scripts/controllers/EditBackupController.js:29 msgid "System files" msgstr "Systeembestanden" @@ -2042,7 +2138,7 @@ msgstr "Systeembestanden" msgid "System info" msgstr "Systeeminformatie" -#: templates/about.html:63 +#: templates/about.html:64 msgid "System properties" msgstr "Systeemeigenschappen" @@ -2062,7 +2158,7 @@ msgstr "Doelpad, bijvoorbeeld /backup" msgid "Task is running" msgstr "Taak is in uitvoering" -#: scripts/controllers/EditBackupController.js:28 +#: scripts/controllers/EditBackupController.js:30 msgid "Temporary files" msgstr "Tijdelijke bestanden" @@ -2090,19 +2186,19 @@ msgstr "Testen van de permissies ..." msgid "Testing permissions..." msgstr "Testen van de permissies ..." -#: scripts/services/EditUriBuiltins.js:719 +#: scripts/services/EditUriBuiltins.js:753 msgid "The bucket name should be all lower-case, convert automatically?" msgstr "" "De bucket-naam hoort in kleine letters te zijn, automatisch converteren?" -#: scripts/services/EditUriBuiltins.js:702 +#: scripts/services/EditUriBuiltins.js:736 msgid "" "The bucket name should start with your username, prepend automatically?" msgstr "" "De bucket naam hoort te beginnen met uw gebruikersnaam, automatisch " "voorvoegen?" -#: index.html:312 +#: index.html:298 msgid "The connection to the server is lost, attempting again in {{time}} ..." msgstr "" "De verbinding met de server is verbroken, opnieuw proberen over {{time}} ..." @@ -2133,11 +2229,11 @@ msgstr "" "\n" "Wilt u de HUIDIGE host sleutel \"{prev}\" VERVANGEN door de GERAPPORTEERDE host sleutel: {{key}}?" -#: scripts/controllers/EditBackupController.js:140 +#: scripts/controllers/EditBackupController.js:142 msgid "The path does not appear to exist, do you want to add it anyway?" msgstr "Het pad lijkt niet te bestaan, wilt u het desondanks toevoegen?" -#: scripts/controllers/EditBackupController.js:150 +#: scripts/controllers/EditBackupController.js:152 msgid "" "The path does not end with a '{{dirsep}}' character, which means that you include a file, not a folder.\n" "\n" @@ -2147,7 +2243,7 @@ msgstr "" "\n" "Wilt u het aangegeven bestand opnemen?" -#: scripts/controllers/EditBackupController.js:125 +#: scripts/controllers/EditBackupController.js:127 msgid "" "The path must be an absolute path, i.e. it must start with a forward slash " "'/'" @@ -2155,7 +2251,7 @@ msgstr "" "Het pad moet een absoluut pad zijn, bijvoorbeeld het moet beginnen met een " "forward slash '/'" -#: scripts/services/EditUriBuiltins.js:630 +#: scripts/services/EditUriBuiltins.js:664 msgid "" "The path should start with \"{{prefix1}}\" or \"{{prefix2}}\", otherwise you will not be able to see the files in the HubiC web interface.\n" "\n" @@ -2306,13 +2402,13 @@ msgstr "Uploaden controlebestand ..." #: templates/settings.html:114 msgid "" "Usage reports help us improve the user experience and evaluate impact of new" -" features. We use them to generate public usage statistics" +" features. We use them to generate public usage" +" statistics" msgstr "" "Gebruiksrapporten helpen ons de gebruikerservaring te verbeteren en de " -"impact van nieuwe mogelijkheden te evalueren. We gebruiken ze om openbare gebruikstatistieken te " -"genereren." +"impact van nieuwe mogelijkheden te evalueren. We gebruiken ze omopenbare gebruikstatistieken te " +"genereren. " #: templates/settings.html:102 msgid "Usage statistics" @@ -2326,15 +2422,15 @@ msgstr "Gebruikstatistieken, waarschuwingen, fouten en crashes" msgid "Use SSL" msgstr "Gebruik SSL" -#: scripts/controllers/EditBackupController.js:472 +#: scripts/controllers/EditBackupController.js:496 msgid "Use existing database?" msgstr "Gebruik bestaande database?" -#: scripts/controllers/EditBackupController.js:366 +#: scripts/controllers/EditBackupController.js:390 msgid "Use weak passphrase" msgstr "Gebruik zwakke wachtwoordzin" -#: scripts/controllers/EditBackupController.js:37 +#: scripts/controllers/EditBackupController.js:39 msgid "Useless" msgstr "Waardeloos" @@ -2350,10 +2446,10 @@ msgstr "Gebruiker heeft teveel permissies" msgid "User interface settings" msgstr "Gebruikersinterface instellingen" -#: scripts/services/EditUriBuiltins.js:585 -#: scripts/services/EditUriBuiltins.js:665 -#: scripts/services/EditUriBuiltins.js:748 -#: scripts/services/EditUriBuiltins.js:758 templates/backends/file.html:29 +#: scripts/services/EditUriBuiltins.js:619 +#: scripts/services/EditUriBuiltins.js:699 +#: scripts/services/EditUriBuiltins.js:782 +#: scripts/services/EditUriBuiltins.js:792 templates/backends/file.html:29 #: templates/backends/generic.html:18 templates/backends/jottacloud.html:7 #: templates/backends/jottacloud.html:8 templates/backends/mega.html:7 #: templates/backends/mega.html:8 templates/backends/openstack.html:18 @@ -2389,15 +2485,15 @@ msgstr "Controleren van remote gegevens ..." msgid "Verifying restored files ..." msgstr "Controleren van herstelde bestanden ..." -#: scripts/controllers/EditBackupController.js:41 +#: scripts/controllers/EditBackupController.js:43 msgid "Very strong" msgstr "Erg sterk" -#: scripts/controllers/EditBackupController.js:38 +#: scripts/controllers/EditBackupController.js:40 msgid "Very weak" msgstr "Erg zwak" -#: index.html:248 +#: index.html:246 msgid "Visit us on" msgstr "Bezoek ons op" @@ -2445,11 +2541,11 @@ msgstr "" "We raden aan dat u alle back-ups die buiten uw systeem worden opgeslagen " "versleutelt" -#: scripts/controllers/EditBackupController.js:39 +#: scripts/controllers/EditBackupController.js:41 msgid "Weak" msgstr "Zwak" -#: scripts/controllers/EditBackupController.js:366 +#: scripts/controllers/EditBackupController.js:390 msgid "Weak passphrase" msgstr "Zwakke wachtwoordzin" @@ -2457,7 +2553,7 @@ msgstr "Zwakke wachtwoordzin" msgid "Wed" msgstr "Woensdag" -#: scripts/services/AppUtils.js:91 templates/addoredit.html:329 +#: scripts/services/AppUtils.js:91 templates/addoredit.html:350 msgid "Weeks" msgstr "Weken" @@ -2469,19 +2565,19 @@ msgstr "Waar vandaan wilt u herstellen?" msgid "Where do you want to restore the files to?" msgstr "Waarheen wilt u de bestanden herstellen?" -#: scripts/controllers/EditBackupController.js:19 +#: scripts/controllers/EditBackupController.js:21 msgid "Windows" msgstr "Windows" -#: scripts/services/AppUtils.js:93 templates/addoredit.html:331 +#: scripts/services/AppUtils.js:93 templates/addoredit.html:352 msgid "Years" msgstr "Jaren" #: scripts/controllers/AppController.js:172 #: scripts/controllers/DeleteController.js:77 -#: scripts/controllers/EditBackupController.js:140 -#: scripts/controllers/EditBackupController.js:150 -#: scripts/controllers/EditBackupController.js:472 +#: scripts/controllers/EditBackupController.js:142 +#: scripts/controllers/EditBackupController.js:152 +#: scripts/controllers/EditBackupController.js:496 #: scripts/controllers/HomeController.js:7 #: scripts/controllers/LocalDatabaseController.js:28 #: scripts/controllers/LocalDatabaseController.js:72 @@ -2491,21 +2587,21 @@ msgstr "Jaren" #: scripts/directives/backupEditUri.js:87 #: scripts/services/EditUriBackendConfig.js:66 #: scripts/services/EditUriBuiltins.js:47 -#: scripts/services/EditUriBuiltins.js:630 -#: scripts/services/EditUriBuiltins.js:702 -#: scripts/services/EditUriBuiltins.js:719 +#: scripts/services/EditUriBuiltins.js:664 +#: scripts/services/EditUriBuiltins.js:736 +#: scripts/services/EditUriBuiltins.js:753 msgid "Yes" msgstr "Ja" -#: scripts/controllers/EditBackupController.js:381 +#: scripts/controllers/EditBackupController.js:405 msgid "Yes, I have stored the passphrase safely" msgstr "Ja, ik heb de wachtwoordzin op een veilige plaats opgeborgen" -#: scripts/controllers/EditBackupController.js:424 +#: scripts/controllers/EditBackupController.js:448 msgid "Yes, I'm brave!" msgstr "Ja, ik ben dapper!" -#: scripts/controllers/EditBackupController.js:415 +#: scripts/controllers/EditBackupController.js:439 msgid "Yes, please break my backup!" msgstr "Ja, help mijn back-up om zeep!" @@ -2529,7 +2625,7 @@ msgstr "" "U verandert het database pad weg van een bestaande database.\n" "Weet u zeker dat dit is wat u wilt?" -#: templates/about.html:26 +#: templates/about.html:27 msgid "You are currently running {{appname}} {{version}}" msgstr "U werkt momenteel met {{appname}} {{version}}" @@ -2549,7 +2645,7 @@ msgstr "" "De taak kan onmiddellijk worden gestopt, of het proces toestaan om door te " "gaan met het huidige bestand en dan stoppen." -#: scripts/controllers/EditBackupController.js:424 +#: scripts/controllers/EditBackupController.js:448 msgid "" "You have changed the encryption mode. This may break stuff. You are " "encouraged to create a new backup instead" @@ -2557,7 +2653,7 @@ msgstr "" "U hebt de versleutelingsmodus veranderd. Dit kan dingen kapotmaken. U wordt " "daarom aangemoedigd een nieuwe back-up aan te maken" -#: scripts/controllers/EditBackupController.js:415 +#: scripts/controllers/EditBackupController.js:439 msgid "" "You have changed the passphrase, which is not supported. You are encouraged " "to create a new backup instead." @@ -2565,7 +2661,7 @@ msgstr "" "U hebt de wachtwoordzin aangepast, wat niet wordt ondersteund. U wordt " "daarom aangemoedigd een nieuwe back-up aan te maken." -#: scripts/controllers/EditBackupController.js:451 +#: scripts/controllers/EditBackupController.js:475 msgid "" "You have chosen not to encrypt the backup. Encryption is recommended for all" " data stored on a remote server." @@ -2579,7 +2675,7 @@ msgstr "" "U koos voor terugzetten naar een nieuwe locatie, maar hebt geen locatie " "opgegeven" -#: scripts/controllers/EditBackupController.js:381 +#: scripts/controllers/EditBackupController.js:405 msgid "" "You have generated a strong passphrase. Make sure you have made a safe copy " "of the passphrase, as the data cannot be recovered if you lose the " @@ -2589,38 +2685,42 @@ msgstr "" "veilige kopie heeft van de wachtwoordzin, omdat de gegevens niet hersteld " "kunnen worden als u de wachtwoordzin verliest." -#: scripts/controllers/EditBackupController.js:311 +#: scripts/controllers/EditBackupController.js:313 msgid "You must choose at least one source folder" msgstr "U moet tenminste één bronmap kiezen" -#: scripts/controllers/EditBackupController.js:290 +#: scripts/controllers/EditBackupController.js:292 msgid "You must enter a name for the backup" msgstr "U moet een naam ingeven voor de back-up" -#: scripts/controllers/EditBackupController.js:298 +#: scripts/controllers/EditBackupController.js:300 msgid "You must enter a passphrase or disable encryption" msgstr "U moet een wachtwoordzin ingeven of versleuteling uitschakelen" -#: scripts/controllers/EditBackupController.js:330 +#: scripts/controllers/EditBackupController.js:344 msgid "You must enter a positive number of backups to keep" msgstr "" "U moet een positief getal opgeven voor de hoeveelheid te bewaren back-ups" -#: scripts/services/EditUriBuiltins.js:677 +#: scripts/services/EditUriBuiltins.js:711 msgid "You must enter a tenant name if you do not provide an API Key" msgstr "U moet een tenant naam ingeven als u de API sleutel niet verstrekt" -#: scripts/controllers/EditBackupController.js:323 +#: scripts/controllers/EditBackupController.js:337 msgid "You must enter a valid duration for the time to keep backups" msgstr "" "U moet een geldige tijdsduur ingeven voor de tijd dat back-ups bewaard " "moeten worden" -#: scripts/services/EditUriBuiltins.js:674 +#: scripts/controllers/EditBackupController.js:351 +msgid "You must enter a valid rentention policy string" +msgstr "Er moet een geldige tekenreeks voor retentiebeleid worden opgegeven" + +#: scripts/services/EditUriBuiltins.js:708 msgid "You must enter either a password or an API Key" msgstr "U moet òf een wachtwoord, òf een API sleutel ingeven" -#: scripts/services/EditUriBuiltins.js:681 +#: scripts/services/EditUriBuiltins.js:715 msgid "You must enter either a password or an API Key, not both" msgstr "U moet òf een wachtwoord, òf een API sleutel ingeven, niet beide" @@ -2641,11 +2741,11 @@ msgstr "U moet de gebruikersnaam invullen" msgid "You must fill in {{field}}" msgstr "U moet {{field}} invullen" -#: scripts/services/EditUriBuiltins.js:669 +#: scripts/services/EditUriBuiltins.js:703 msgid "You must select or fill in the AuthURI" msgstr "U moet de AuthURI selecteren of invullen" -#: scripts/services/EditUriBuiltins.js:695 +#: scripts/services/EditUriBuiltins.js:729 msgid "You must select or fill in the server" msgstr "U moet de server selecteren of invullen" @@ -2657,16 +2757,12 @@ msgstr "U moet een pad opgeven" msgid "Your files and folders have been restored successfully." msgstr "Uw bestanden en mappen zijn succesvol hersteld" -#: scripts/controllers/EditBackupController.js:366 +#: scripts/controllers/EditBackupController.js:390 msgid "Your passphrase is easy to guess. Consider changing passphrase." msgstr "" "Uw wachtwoordzin is eenvoudig te raden. Overweeg de wachtwoordzin te " "veranderen." -#: templates/addoredit.html:321 -msgid "a specific number" -msgstr "een bepaald aantal" - #: templates/backends/gcs.html:3 templates/backends/openstack.html:3 msgid "bucket/folder/subfolder" msgstr "bucket/map/submap" @@ -2679,7 +2775,7 @@ msgstr "byte" msgid "byte/s" msgstr "byte/s" -#: templates/addoredit.html:276 templates/addoredit.html:332 +#: templates/addoredit.html:276 templates/addoredit.html:353 #: templates/advancedoptionseditor.html:28 #: templates/advancedoptionseditor.html:35 msgid "custom" @@ -2690,15 +2786,7 @@ msgstr "aangepast" msgid "resume now" msgstr "nu hervatten" -#: templates/addoredit.html:319 -msgid "unlimited" -msgstr "onbeperkt" - -#: templates/addoredit.html:320 -msgid "until they are older than" -msgstr "totdat ze ouder zijn dan" - -#: templates/about.html:11 +#: templates/about.html:12 msgid "" "{{appname}} was primarily developed by {{dev1}} " "and {{dev2}}. {{appname}} can be downloaded from " diff --git a/Localizations/webroot/localization_webroot-zh_TW.po b/Localizations/webroot/localization_webroot-zh_TW.po index 31fa38470..23c9b1c67 100644 --- a/Localizations/webroot/localization_webroot-zh_TW.po +++ b/Localizations/webroot/localization_webroot-zh_TW.po @@ -12,7 +12,7 @@ msgstr "" #: templates/advancedoptionseditor.html:48 msgid "- pick an option -" -msgstr "選擇一個選項" +msgstr "選擇一個項目" #: templates/delete.html:7 templates/localdatabase.html:4 msgid "...loading..." @@ -83,7 +83,7 @@ msgstr "加入進階選項" #: index.html:205 msgid "Add backup" -msgstr "加入備份" +msgstr "備份" #: templates/addoredit.html:197 msgid "Add filter" @@ -116,7 +116,7 @@ msgstr "進階:" #: scripts/controllers/EditBackupController.js:24 msgid "All" -msgstr "" +msgstr "全部" #: scripts/directives/sourceFolderPicker.js:423 msgid "All Hyper-V Machines" @@ -176,7 +176,7 @@ msgstr "匿名使用報告" #: templates/export.html:8 msgid "As Command-line" -msgstr "如同 Command-Line" +msgstr "顯示為 Command-Line" #: scripts/services/EditUriBuiltins.js:648 templates/backends/gcs.html:8 #: templates/backends/gcs.html:9 templates/backends/oauth.html:8 @@ -235,7 +235,7 @@ msgstr "備份位置" #: templates/addoredit.html:317 msgid "Backup retention" -msgstr "" +msgstr "保留備份數目" #: templates/home.html:60 msgid "Backup:" @@ -462,7 +462,7 @@ msgstr "已複製" #: templates/copy_clipboard_buttons.html:3 msgid "Copy" -msgstr "" +msgstr "複製" #: templates/addoredit.html:99 templates/restoredirect.html:42 msgid "Copy Destination URL to Clipboard" @@ -530,7 +530,7 @@ msgstr "自訂授權 URL" #: templates/addoredit.html:323 msgid "Custom backup retention" -msgstr "" +msgstr "自訂備份保留規則" #: templates/backends/gcs.html:18 msgid "Custom location ({{server}})" @@ -570,7 +570,7 @@ msgstr "預設 ({{channelname}})" #: templates/addoredit.html:201 msgid "Default Filters" -msgstr "" +msgstr "預設篩選條件" #: templates/settings.html:131 msgid "Default options" @@ -590,7 +590,7 @@ msgstr "刪除備份" #: templates/addoredit.html:320 msgid "Delete backups that are older than" -msgstr "" +msgstr "刪除指定條件以前的備份" #: templates/delete.html:13 msgid "Delete local database" @@ -771,6 +771,9 @@ msgid "" "one for each of the next 36 months. This can also be written as " "1W:1D,1M:1W,3Y:1M." msgstr "" +"手動輸入保留原則。可用關鍵字為 D/W/Y 分別代表 日/週/ " +"年。語法為:7D:1D,4W:1W,36M:1M。上述例子表示,每7日保留1份,每4週保留1份,每36個月保留1份。您也可以寫成 " +"1W:1D,1M:1W,3Y:1M。" #: templates/backends/azure.html:12 msgid "Enter access key" @@ -905,7 +908,7 @@ msgstr "正在匯出 ..." #: templates/externallink.html:1 msgid "External link" -msgstr "" +msgstr "外部連結" #: scripts/services/SystemInfo.js:52 msgid "FTP (Alternative)" @@ -1088,7 +1091,7 @@ msgstr "如果已錯過時間,將儘可能快速進行這個工作。" msgid "" "If at least one newer backup is found, all backups older than this date are " "deleted." -msgstr "" +msgstr "如果有更新的備份存在,則刪除比這個日期早的所有備份。" #: templates/localdatabase.html:13 msgid "" @@ -1168,7 +1171,7 @@ msgstr "從檔案匯入" #: templates/import.html:19 msgid "Import metadata" -msgstr "" +msgstr "匯入 metadata" #: templates/import.html:35 msgid "Importing ..." @@ -1192,7 +1195,7 @@ msgstr "回應不正確,請重試一次" #: templates/settings.html:92 msgid "Individual builds for developers only." -msgstr "Individual builds for developers only." +msgstr "開發者專用個人版本,一般使用者請勿使用。" #: scripts/services/DialogService.js:27 msgid "Information" @@ -1234,11 +1237,11 @@ msgstr "KByte/s" #: templates/addoredit.html:321 msgid "Keep a specific number of backups" -msgstr "" +msgstr "保留指定份數的備份" #: templates/addoredit.html:319 msgid "Keep all backups" -msgstr "" +msgstr "保留所有備份" #: templates/settings.html:40 msgid "Language in user interface" @@ -1258,11 +1261,11 @@ msgstr "最新" #: templates/about.html:6 msgid "Libraries" -msgstr "Libraries" +msgstr "函式庫" #: scripts/controllers/EditBackupController.js:23 msgid "Linux" -msgstr "" +msgstr "Linux" #: scripts/controllers/RestoreDirectController.js:64 msgid "Listing backup dates ..." @@ -1301,7 +1304,7 @@ msgstr "正在載入遠端儲存區使用資訊 ..." #: scripts/services/EditUriBuiltins.js:818 msgid "Local Repository" -msgstr "" +msgstr "本機 Repository" #: templates/localdatabase.html:2 msgid "Local database for" @@ -1313,7 +1316,7 @@ msgstr "本機資料庫路徑:" #: templates/backends/rclone.html:2 msgid "Local repository" -msgstr "" +msgstr "本機 repository" #: scripts/services/SystemInfo.js:78 msgid "Local storage" @@ -1463,7 +1466,7 @@ msgstr "下一頁" #: templates/home.html:51 msgid "Next scheduled run:" -msgstr "下一次排程執行時間:" +msgstr "下一次排程執行:" #: index.html:177 msgid "Next scheduled task:" @@ -1544,7 +1547,7 @@ msgstr "無 / 取消" #: templates/addoredit.html:326 msgid "Nothing will be deleted. The backup size will grow with each change." -msgstr "" +msgstr "什麼都不刪除。備份大小將隨著每次異動而持續增長。" #: scripts/controllers/AppController.js:44 #: scripts/controllers/AppController.js:59 @@ -1561,13 +1564,13 @@ msgstr "確定" #: scripts/controllers/EditBackupController.js:22 msgid "OSX" -msgstr "" +msgstr "OSX" #: templates/addoredit.html:344 msgid "" "Once there are more backups than the specified number, the oldest backups " "are deleted." -msgstr "" +msgstr "當備份數量超過指定數目,最舊的備份將被刪除。" #: templates/backends/openstack.html:7 msgid "OpenStack AuthURI" @@ -1618,7 +1621,7 @@ msgid "" "Over time backups will be deleted automatically. There will remain one " "backup for each of the last 7 days, each of the last 4 weeks, each of the " "last 12 months. There will always be at least one remaining backup." -msgstr "" +msgstr "智慧保留模式,兼具長時間保存與短時間份數考量。保留每7天、每4週、每12個月均有一份備份。" #: templates/restore.html:114 msgid "Overwrite" @@ -1710,7 +1713,7 @@ msgstr "ProjectID is optional if the bucket exist" #: scripts/services/SystemInfo.js:80 msgid "Proprietary" -msgstr "所有權" +msgstr "雲端服務" #: scripts/services/ServerStatus.js:63 msgid "Purging files ..." @@ -1746,19 +1749,19 @@ msgstr "入遠端" #: scripts/services/EditUriBuiltins.js:819 msgid "Remote Path" -msgstr "" +msgstr "遠端 Path" #: scripts/services/EditUriBuiltins.js:817 msgid "Remote Repository" -msgstr "" +msgstr "遠端 Repository" #: templates/backends/rclone.html:10 msgid "Remote path" -msgstr "" +msgstr "遠端 path" #: templates/backends/rclone.html:6 msgid "Remote repository" -msgstr "" +msgstr "遠端 repository" #: templates/addoredit.html:193 msgid "Remove" @@ -1989,7 +1992,7 @@ msgstr "Sia 伺服器密碼" #: templates/addoredit.html:322 msgid "Smart backup retention" -msgstr "" +msgstr "智慧管理備份數" #: templates/backends/openstack.html:33 msgid "" @@ -2015,7 +2018,7 @@ msgstr "來源:" #: templates/settings.html:87 msgid "Specific builds for developers only." -msgstr "Specific builds for developers only." +msgstr "開發者實驗正在開發中的新功能用,非開發者請勿使用。" #: scripts/services/SystemInfo.js:79 msgid "Standard protocols" @@ -2177,7 +2180,7 @@ msgstr "預設白色主題 (by Alex)" msgid "" "The folder {{folder}} does not exist.\n" "Create it now?" -msgstr "" +msgstr "資料夾 {{folder}} 不存在,是否立即建立?" #: scripts/directives/backupEditUri.js:212 msgid "" @@ -2309,7 +2312,7 @@ msgstr "信任伺服器憑證?" #: templates/settings.html:82 msgid "" "Try out the new features we are working on. Don't use with important data." -msgstr "試試我們正在進行的新功能。不要使用在重要的資料上。" +msgstr "試試我們正在進行的新功能。請避免使用在重要的資料上。" #: scripts/services/AppUtils.js:104 msgid "Tue" @@ -2329,7 +2332,7 @@ msgstr "手動繼續" #: templates/settings.html:65 msgid "Update channel" -msgstr "更新分支" +msgstr "更新頻道" #: scripts/controllers/LocalDatabaseController.js:66 msgid "Update failed:" @@ -2337,7 +2340,7 @@ msgstr "更新失敗:" #: scripts/controllers/LocalDatabaseController.js:88 msgid "Updating with existing database" -msgstr "正在更新已存在資料庫 ..." +msgstr "正在更新既有資料庫 ..." #: templates/addoredit.html:311 msgid "Upload volume size" @@ -2353,6 +2356,8 @@ msgid "" " features. We use them to generate public usage" " statistics" msgstr "" +"使用情況報告有助於我們改進使用者體驗並評估新功能的影響。 We use them to generate public usage statistics" #: templates/settings.html:102 msgid "Usage statistics" @@ -2473,7 +2478,7 @@ msgstr "警告、錯誤與當機" msgid "" "We accept donations via different services, such as OpenCollective, PayPal, " "BountySource and various crypto currencies." -msgstr "" +msgstr "我們接受多種服務的贊助,例如 OpenCollective、PayPal、BountySource 以及多種加密貨幣。" #: templates/addoredit.html:50 msgid "We recommend that you encrypt all backups stored outside your system" @@ -2505,7 +2510,7 @@ msgstr "您要還原檔案到哪裡?" #: scripts/controllers/EditBackupController.js:21 msgid "Windows" -msgstr "" +msgstr "Windows" #: scripts/services/AppUtils.js:93 templates/addoredit.html:352 msgid "Years" @@ -2610,7 +2615,7 @@ msgid "" "You have generated a strong passphrase. Make sure you have made a safe copy " "of the passphrase, as the data cannot be recovered if you lose the " "passphrase." -msgstr "" +msgstr "您已經產生足夠強度的密碼。請確保您已經另外備份好這組密碼,若您遺失這組密碼,您的資料將無法還原。" #: scripts/controllers/EditBackupController.js:313 msgid "You must choose at least one source folder" @@ -2638,7 +2643,7 @@ msgstr "您必須輸入有效的起迄時間來保留備份" #: scripts/controllers/EditBackupController.js:351 msgid "You must enter a valid rentention policy string" -msgstr "" +msgstr "您必需輸入符合可用字串的備份保留原則" #: scripts/services/EditUriBuiltins.js:708 msgid "You must enter either a password or an API Key" diff --git a/README.md b/README.md index 6cd8b1c36..5a996d7bf 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,8 @@ Support Duplicati is supported by an [active community and you can reach them via our forum](https://forum.duplicati.com). +We have a great [Duplicati manual](https://docs.duplicati.com) that you can also [contribute to](https://github.com/kees-z/DuplicatiDocs). + Features ======== diff --git a/Tools/Commandline/ReEncrypt/ReEncrypt.py b/Tools/Commandline/ReEncrypt/ReEncrypt.py new file mode 100644 index 000000000..96fbc575a --- /dev/null +++ b/Tools/Commandline/ReEncrypt/ReEncrypt.py @@ -0,0 +1,203 @@ +#!/usr/bin/env python3 +## Copyright (C) 2018, The Duplicati Team +## http://www.duplicati.com, info@duplicati.com +## +## This library is free software; you can redistribute it and/or modify +## it under the terms of the GNU Lesser General Public License as +## published by the Free Software Foundation; either version 2.1 of the +## License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +import os +import sys, getopt +import io +import json +import zipfile +import base64 +import hashlib +import pyAesCrypt +from collections import OrderedDict +from tempfile import mkstemp, mkdtemp, TemporaryFile, TemporaryDirectory, NamedTemporaryFile +import gnupg +import shutil +from joblib import Parallel, delayed +import multiprocessing + +def mainReEncrypt(options): + # locate dlist + dlists = [name for name in os.listdir(options['orig']['path']) if name.endswith(".dlist.%s" %(options['orig']['extension']))] + + # loop over all dlists; they only need to be enencrypted, and encrypted. They have no relation to the dindex and dblock files. + with NamedTemporaryFile() as temp_file: + for dlist_enc in dlists: + dlist_enc_fullpath = os.path.join(options['orig']['path'],dlist_enc) + dlist_reenc_fullpath = os.path.join(options['new']['path'],change_ext(dlist_enc,options['orig']['extension'],options['new']['extension'])) + decrypt(options['orig'],dlist_enc_fullpath,options['orig']['passwd'],temp_file.name) + encrypt(options['new'],temp_file.name,options['new']['passwd'], dlist_reenc_fullpath) + + # locate dlist + dindex = [name for name in os.listdir(options['orig']['path']) if name.endswith(".dindex.%s" %(options['orig']['extension']))] + + num_cores = multiprocessing.cpu_count() + Parallel(n_jobs=num_cores*2)(delayed(handleIndex)(options, dindex_enc) for dindex_enc in dindex) + +def handleIndex(options, dindex_enc): + with NamedTemporaryFile() as temp_dindex, NamedTemporaryFile() as temp_dindex_reenc, TemporaryDirectory() as temp_path_zip: + dindex_enc_fullpath = os.path.join(options['orig']['path'],dindex_enc) + dindex_reenc_fullpath = os.path.join(options['new']['path'],change_ext(dindex_enc,options['orig']['extension'],options['new']['extension'])) + + decrypt(options['orig'],dindex_enc_fullpath,options['orig']['passwd'],temp_dindex.name) + + unzip(temp_dindex,temp_path_zip) + + vol_path = os.path.join(temp_path_zip,'vol') + + for dblock in os.listdir(vol_path): + data = [] + with open(os.path.join(vol_path, dblock)) as data_file: + data = json.load(data_file, object_pairs_hook=OrderedDict) + + expected_hash = data['volumehash'].encode('utf8') + expected_volumesize = data['volumesize'] + + if (options['verify_hash']): + actual_hash = computeHash(os.path.join(options['orig']['path'],dblock)) + actual_volumesize=os.stat(os.path.join(options['orig']['path'],dblock)).st_size + print('dblock: %s expected_hash: %s calc_hash: %s exact: %s' % (dblock,expected_hash.decode('utf8'),actual_hash.decode('utf8'),expected_hash==actual_hash)) + + with NamedTemporaryFile() as temp_dblock: + dblock_enc_fullpath = os.path.join(options['orig']['path'],dblock) + dblock_reenc_fullpath = os.path.join(options['new']['path'],change_ext(dblock,options['orig']['extension'],options['new']['extension'])) + decrypt(options['orig'],dblock_enc_fullpath,options['orig']['passwd'],temp_dblock.name) + encrypt(options['new'],temp_dblock.name,options['new']['passwd'], dblock_reenc_fullpath) + new_hash = computeHash(dblock_reenc_fullpath) + + data['volumehash'] = new_hash.decode('utf8') + data['volumesize'] = os.stat(os.path.join(options['new']['path'],change_ext(dblock,options['orig']['extension'],options['new']['extension']))).st_size + print('dblock: %s old_hash: %s new_hash: %s' % (dblock,expected_hash.decode('utf8'),data['volumehash'])) + + with open(os.path.join(vol_path,dblock),'w') as data_file: + json.dump(data, data_file) + + os.rename(os.path.join(vol_path, dblock), os.path.join(vol_path, change_ext(dblock,options['orig']['extension'],options['new']['extension']))) + + make_zipfile(temp_dindex_reenc.name,temp_path_zip) + encrypt(options['new'],temp_dindex_reenc.name, options['new']['passwd'],dindex_reenc_fullpath) + +def change_ext(filename, ext_old, ext_new): + return filename.replace(ext_old, ext_new) + +def decrypt(options, encrypted, passw, decrypted): + print('decrypting: %s to %s' % (encrypted, decrypted)) + if options['encryption']=='aes': + bufferSize = 64 * 1024 + pyAesCrypt.decryptFile(encrypted, decrypted, passw, bufferSize) + if options['encryption']=='gpg': + gpg = gnupg.GPG() + with open(encrypted, 'rb') as f: + status = gpg.decrypt_file(f, output=decrypted,passphrase=passw) + if options['encryption']=='none': + shutil.copy(encrypted,decrypted) + + +def encrypt(options,decrypted, passw, encrypted): + print('encrypting: %s %s' % (decrypted, encrypted)) + if options['encryption']=='aes': + bufferSize = 64 * 1024 + pyAesCrypt.encryptFile(decrypted, encrypted, passw, bufferSize) + if options['encryption']=='gpg': + gpg = gnupg.GPG() + with open(decrypted, 'rb') as f: + status = gpg.encrypt_file(f, recipients=options['recipients'], output=encrypted, armor=False) + if options['encryption']=='none': + shutil.copy(decrypted,encrypted) + +def emptydir(top): + if(top == '/' or top == "\\"): return + else: + for root, dirs, files in os.walk(top, topdown=False): + for name in files: + os.remove(os.path.join(root, name)) + for name in dirs: + os.rmdir(os.path.join(root, name)) + +def unzip(archive, path): + emptydir(path) + with zipfile.ZipFile(archive.name) as zf: + zf.extractall(path) + +def make_zipfile(output_filename, source_dir): + print('zipping: %s to %s' % (source_dir, output_filename)) + emptydir(output_filename) + relroot=source_dir + with zipfile.ZipFile(output_filename, "w", zipfile.ZIP_DEFLATED) as zip: + for root, dirs, files in os.walk(source_dir): + # add directory (needed for empty dirs) + zip.write(root, os.path.relpath(root, relroot)) + for file in files: + filename = os.path.join(root, file) + if os.path.isfile(filename): # regular files only + arcname = os.path.join(os.path.relpath(root, relroot), file) + zip.write(filename, arcname) + + +def rezip(temp_path_z, path): + zf = zipfile.ZipFile(path, "w") + for dirname, subdirs, files in os.walk(temp_path_z): + zf.write(dirname) + for filename in files: + zf.write(os.path.join(dirname, filename)) + zf.close() + +def zipdir(path,ziph): + for root, dirs, files in os.walk(path): + for file in files: + ziph.write(os.path.join(root, file)) + +def computeHash(path): + print('hashing: %s ' % (path)) + buffersize=64 * 1024 + hasher = hashlib.sha256() + with open(path, 'rb') as f: + while True: + buffer = f.read(buffersize) + if not buffer: + break + hasher.update(buffer) + return base64.b64encode(hasher.digest()) + +def main(argv): + configfile = '' + try: + opts, args = getopt.getopt(argv,"hc:") + except getopt.GetoptError: + print('ReEncrypt.py -c ') + sys.exit(2) + for opt, arg in opts: + if opt == '-h': + print('ReEncrypt.py -c ') + sys.exit(2) + elif opt == '-c': + configfile = arg + else: + print( "unhandled option") + if (configfile == ''): + print('ReEncrypt.py -c ') + sys.exit(2) + + with open(configfile) as infile: + options = json.load(infile) + mainReEncrypt(options) + print('Complete.') + +if __name__ == "__main__": + main(sys.argv[1:]) + diff --git a/Tools/Commandline/ReEncrypt/Readme b/Tools/Commandline/ReEncrypt/Readme new file mode 100644 index 000000000..d05bb736c --- /dev/null +++ b/Tools/Commandline/ReEncrypt/Readme @@ -0,0 +1,17 @@ + +A Python script to change the encryption from Duplicati. You can go from aes to gpg or vice versa. It is also possible to remove encryption. + +Usage: +0) Take a backup of your data. + +1) Confirm that your Duplicati data is on disk in .zip or .zip.aes or .zip.gpg format.. + +2) Install Python 3 if it is not already installed. pyAesCrypt, gnupg and joblib packages need to be installed in python as well. + +3) Prepare a config file (see example config.txt). + +3) Run ReEncrypt.py -c config.txt. + +4) Update your backup settings to the changed encryption settings. + +5) Take a backup of your database and do a delete & recreate. Don't forget to delete, a simple "repair" may delete the whole backup! diff --git a/Tools/Commandline/ReEncrypt/config.txt b/Tools/Commandline/ReEncrypt/config.txt new file mode 100644 index 000000000..b0b2d4679 --- /dev/null +++ b/Tools/Commandline/ReEncrypt/config.txt @@ -0,0 +1,16 @@ +{ + "orig": { + "extension": "zip.aes", + "path": "/path/to/backup/orig", + "passwd": "123456", + "encryption": "aes" + }, + "new": { + "recipients": ["user@host.com"], + "extension": "zip.gpg", + "path": "/path/to/backup/new", + "passwd": "654321", + "encryption": "gpg" + }, + "verify_hash": true +} \ No newline at end of file diff --git a/Updates/build_version.txt b/Updates/build_version.txt index d6b24041c..0cfbf0888 100644 --- a/Updates/build_version.txt +++ b/Updates/build_version.txt @@ -1 +1 @@ -19 +2 diff --git a/build-debug-update.sh b/build-debug-update.sh index 289c58138..6660cd38b 100755 --- a/build-debug-update.sh +++ b/build-debug-update.sh @@ -1,10 +1,10 @@ -RELEASE_TIMESTAMP=`date +%Y-%m-%d` +RELEASE_TIMESTAMP=$(date +%Y-%m-%d) -RELEASE_INC_VERSION=`cat Updates/build_version.txt` +RELEASE_INC_VERSION=$(cat Updates/build_version.txt) RELEASE_INC_VERSION=$((RELEASE_INC_VERSION+1)) RELEASE_NAME=2.0_CLI_experimental_${RELEASE_TIMESTAMP} -RELEASE_CHANGEINFO=`cat Updates/debug_changeinfo.txt` +RELEASE_CHANGEINFO=$(cat Updates/debug_changeinfo.txt) RELEASE_VERSION="2.0.0.${RELEASE_INC_VERSION}" UPDATE_ZIP_URLS=http://updates.duplicati.com/debug/duplicati.zip\;http://alt.updates.duplicati.com/debug/duplicati.zip diff --git a/build-installers.sh b/build-installers.sh index 92f0d177f..b15d102cf 100755 --- a/build-installers.sh +++ b/build-installers.sh @@ -26,10 +26,10 @@ MONO=/Library/Frameworks/Mono.framework/Commands/mono GPG=/usr/local/bin/gpg2 -ZIPFILE=`basename "$1"` -VERSION=`echo "${ZIPFILE}" | cut -d "-" -f 2 | cut -d "_" -f 1` -BUILDTYPE=`echo "${ZIPFILE}" | cut -d "-" -f 2 | cut -d "_" -f 2` -BUILDTAG_RAW=`echo "${ZIPFILE}" | cut -d "." -f 1-4 | cut -d "-" -f 2-4` +ZIPFILE=$(basename "$1") +VERSION=$(echo "${ZIPFILE}" | cut -d "-" -f 2 | cut -d "_" -f 1) +BUILDTYPE=$(echo "${ZIPFILE}" | cut -d "-" -f 2 | cut -d "_" -f 2) +BUILDTAG_RAW=$(echo "${ZIPFILE}" | cut -d "." -f 1-4 | cut -d "-" -f 2-4) BUILDTAG="${BUILDTAG_RAW//-}" RPMNAME="duplicati-${VERSION}-${BUILDTAG}.noarch.rpm" @@ -69,13 +69,13 @@ if [ -f "${GPG_KEYFILE}" ]; then echo fi - GPGDATA=`"${MONO}" "BuildTools/AutoUpdateBuilder/bin/Debug/SharpAESCrypt.exe" d "${KEYFILE_PASSWORD}" "${GPG_KEYFILE}"` + GPGDATA=$("${MONO}" "BuildTools/AutoUpdateBuilder/bin/Debug/SharpAESCrypt.exe" d "${KEYFILE_PASSWORD}" "${GPG_KEYFILE}") if [ ! $? -eq 0 ]; then echo "Decrypting GPG keyfile failed" exit 1 fi - GPGID=`echo "${GPGDATA}" | head -n 1` - GPGKEY=`echo "${GPGDATA}" | head -n 2 | tail -n 1` + GPGID=$(echo "${GPGDATA}" | head -n 1) + GPGKEY=$(echo "${GPGDATA}" | head -n 2 | tail -n 1) else echo "No GPG keyfile found, skipping gpg signatures" fi @@ -188,14 +188,14 @@ if [ -f "${AUTHENTICODE_PFXFILE}" ] && [ -f "${AUTHENTICODE_PASSWORD}" ]; then authenticode_sign() { NEST="" for hashalg in sha1 sha256; do - SIGN_MSG=`osslsigncode sign -pkcs12 "${AUTHENTICODE_PFXFILE}" -pass "${PFX_PASS}" -n "Duplicati" -i "http://www.duplicati.com" -h "${hashalg}" ${NEST} -t "http://timestamp.verisign.com/scripts/timstamp.dll" -in "$1" -out tmpfile` + SIGN_MSG=$(osslsigncode sign -pkcs12 "${AUTHENTICODE_PFXFILE}" -pass "${PFX_PASS}" -n "Duplicati" -i "http://www.duplicati.com" -h "${hashalg}" ${NEST} -t "http://timestamp.verisign.com/scripts/timstamp.dll" -in "$1" -out tmpfile) if [ "${SIGN_MSG}" != "Succeeded" ]; then echo "${SIGN_MSG}"; fi mv tmpfile "$1" NEST="-nest" done } - PFX_PASS=`"${MONO}" "BuildTools/AutoUpdateBuilder/bin/Debug/SharpAESCrypt.exe" d "${KEYFILE_PASSWORD}" "${AUTHENTICODE_PASSWORD}"` + PFX_PASS=$("${MONO}" "BuildTools/AutoUpdateBuilder/bin/Debug/SharpAESCrypt.exe" d "${KEYFILE_PASSWORD}" "${AUTHENTICODE_PASSWORD}") DECRYPT_STATUS=$? if [ "${DECRYPT_STATUS}" -ne 0 ]; then @@ -232,9 +232,9 @@ process_installer() { aws --profile=duplicati-upload s3 cp "${UPDATE_TARGET}/$1" "s3://updates.duplicati.com/${BUILDTYPE}/$1" fi - local MD5=`md5 ${UPDATE_TARGET}/$1 | awk -F ' ' '{print $NF}'` - local SHA1=`shasum -a 1 ${UPDATE_TARGET}/$1 | awk -F ' ' '{print $1}'` - local SHA256=`shasum -a 256 ${UPDATE_TARGET}/$1 | awk -F ' ' '{print $1}'` + local MD5=$(md5 ${UPDATE_TARGET}/$1 | awk -F ' ' '{print $NF}') + local SHA1=$(shasum -a 1 ${UPDATE_TARGET}/$1 | awk -F ' ' '{print $1}') + local SHA256=$(shasum -a 256 ${UPDATE_TARGET}/$1 | awk -F ' ' '{print $1}') cat >> "./tmp/latest-installers.json" < "Duplicati/Library/AutoUpdater/AutoUpdateBuildChannel.t echo "${UPDATE_MANIFEST_URLS}" > "Duplicati/Library/AutoUpdater/AutoUpdateURL.txt" cp "Updates/release_key.txt" "Duplicati/Library/AutoUpdater/AutoUpdateSignKey.txt" -RELEASE_CHANGEINFO=`cat ${RELEASE_CHANGELOG_FILE}` +RELEASE_CHANGEINFO=$(cat ${RELEASE_CHANGELOG_FILE}) if [ "x${RELEASE_CHANGEINFO}" == "x" ]; then echo "No information in changeinfo file" exit 0 @@ -199,14 +200,14 @@ if [ -f "${AUTHENTICODE_PFXFILE}" ] && [ -f "${AUTHENTICODE_PASSWORD}" ]; then authenticode_sign() { NEST="" for hashalg in sha1 sha256; do - SIGN_MSG=`osslsigncode sign -pkcs12 "${AUTHENTICODE_PFXFILE}" -pass "${PFX_PASS}" -n "Duplicati" -i "http://www.duplicati.com" -h "${hashalg}" ${NEST} -t "http://timestamp.verisign.com/scripts/timstamp.dll" -in "$1" -out tmpfile` + SIGN_MSG=$(osslsigncode sign -pkcs12 "${AUTHENTICODE_PFXFILE}" -pass "${PFX_PASS}" -n "Duplicati" -i "http://www.duplicati.com" -h "${hashalg}" ${NEST} -t "http://timestamp.verisign.com/scripts/timstamp.dll" -in "$1" -out tmpfile) if [ "${SIGN_MSG}" != "Succeeded" ]; then echo "${SIGN_MSG}"; fi mv tmpfile "$1" NEST="-nest" done } - PFX_PASS=`"${MONO}" "BuildTools/AutoUpdateBuilder/bin/Debug/SharpAESCrypt.exe" d "${KEYFILE_PASSWORD}" "${AUTHENTICODE_PASSWORD}"` + PFX_PASS=$("${MONO}" "BuildTools/AutoUpdateBuilder/bin/Debug/SharpAESCrypt.exe" d "${KEYFILE_PASSWORD}" "${AUTHENTICODE_PASSWORD}") DECRYPT_STATUS=$? if [ "${DECRYPT_STATUS}" -ne 0 ]; then @@ -263,9 +264,9 @@ aws --profile=duplicati-upload s3 cp "${UPDATE_TARGET}/${RELEASE_FILE_NAME}.mani aws --profile=duplicati-upload s3 cp "s3://updates.duplicati.com/${RELEASE_TYPE}/${RELEASE_FILE_NAME}.manifest" "s3://updates.duplicati.com/${RELEASE_TYPE}/latest.manifest" -ZIP_MD5=`md5 ${UPDATE_TARGET}/${RELEASE_FILE_NAME}.zip | awk -F ' ' '{print $NF}'` -ZIP_SHA1=`shasum -a 1 ${UPDATE_TARGET}/${RELEASE_FILE_NAME}.zip | awk -F ' ' '{print $1}'` -ZIP_SHA256=`shasum -a 256 ${UPDATE_TARGET}/${RELEASE_FILE_NAME}.zip | awk -F ' ' '{print $1}'` +ZIP_MD5=$(md5 ${UPDATE_TARGET}/${RELEASE_FILE_NAME}.zip | awk -F ' ' '{print $NF}') +ZIP_SHA1=$(shasum -a 1 ${UPDATE_TARGET}/${RELEASE_FILE_NAME}.zip | awk -F ' ' '{print $1}') +ZIP_SHA256=$(shasum -a 256 ${UPDATE_TARGET}/${RELEASE_FILE_NAME}.zip | awk -F ' ' '{print $1}') cat > "latest.json" <