Commit 6489179a authored by Michael Terry's avatar Michael Terry

Hide cloud backends by default.

GNOME Online Accounts is now the preferred cloud provider. This lets us
standardize on gvfs and they are generally more user-friendly than signing
up for a S3 account or the like.

Cloud providers are still available for use and will show up in the UI if
the user was using one before or if they manually set it in gsettings.

We also show all cloud providers in the drop down when restoring (since who
knows where the user had their data at that point).
parent 46bd0fa5
......@@ -9,7 +9,7 @@
<description>
<p>Déjà Dup is a simple backup tool. It hides the complexity of backing up the Right Way (encrypted, off-site, and regular) and uses duplicity as the backend.</p>
<ul>
<li>Support for local, remote, or cloud backup locations, such as Amazon S3 and Rackspace Cloud Files</li>
<li>Support for local, remote, or cloud backup locations such as Nextcloud</li>
<li>Securely encrypts and compresses your data</li>
<li>Incrementally backs up, letting you restore from any particular backup</li>
<li>Schedules regular backups</li>
......
......@@ -42,8 +42,7 @@ Description: Back up your files
backend.
.
Features:
* Support for local, remote, or cloud backup locations, such as Amazon S3 and
Rackspace Cloud Files
* Support for local, remote, or cloud backup locations such as Nextcloud
* Securely encrypts and compresses your data
* Incrementally backs up, letting you restore from any particular backup
* Schedules regular backups
......
......@@ -87,7 +87,7 @@ public class AssistantRestore : AssistantOperation
"column-spacing", 12,
"border-width", 12);
var location = new DejaDup.ConfigLocation(label_sizes);
var location = new DejaDup.ConfigLocation(true, label_sizes);
label = new Gtk.Label.with_mnemonic(_("_Backup location"));
label.set("xalign", 1.0f,
"mnemonic-widget", location);
......
......@@ -313,7 +313,7 @@ public class Preferences : Gtk.Grid
row = 0;
label_sizes = new Gtk.SizeGroup(Gtk.SizeGroupMode.HORIZONTAL);
var location = new DejaDup.ConfigLocation(label_sizes);
var location = new DejaDup.ConfigLocation(false, label_sizes);
label = new Gtk.Label(_("_Storage location"));
label.mnemonic_widget = location;
label.use_underline = true;
......
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2017-08-13 21:03-0400\n"
"POT-Creation-Date: 2017-08-14 17:05-0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
......
......@@ -48,6 +48,7 @@ public class ConfigLocation : ConfigWidget
public Gtk.EventBox extras {get; private set;}
public Gtk.SizeGroup label_sizes {get; construct;}
public bool show_deprecated {get; construct;}
public Gtk.Requisition hidden_size()
{
......@@ -58,12 +59,11 @@ public class ConfigLocation : ConfigWidget
return pagereq;
}
public ConfigLocation(Gtk.SizeGroup? sg = null)
public ConfigLocation(bool show_deprecated, Gtk.SizeGroup? sg = null)
{
Object(label_sizes: sg);
Object(show_deprecated: show_deprecated, label_sizes: sg);
}
bool have_clouds;
int num_volumes = 0;
int extras_max_width = 0;
......@@ -106,20 +106,13 @@ public class ConfigLocation : ConfigWidget
remake_goa();
BackendGOA.get_client_sync().account_added.connect(remake_goa);
BackendGOA.get_client_sync().account_removed.connect(remake_goa);
add_separator(Group.GOA_SEP);
// Insert cloud providers
insert_u1();
insert_s3();
insert_gcs();
insert_rackspace();
insert_openstack();
insert_clouds();
add_entry(new ThemedIcon("network-server"),
_("Network Server"), Group.REMOTE,
new ConfigLocationCustom(label_sizes));
add_separator(Group.REMOTE_SEP);
// And a local folder option
......@@ -284,71 +277,34 @@ public class ConfigLocation : ConfigWidget
"", type);
}
delegate void CloudCallback();
void insert_s3() {
insert_cloud_if_available("s3", BackendS3.get_checker(),
new ThemedIcon("deja-dup-cloud"),
_("Amazon S3"),
new ConfigLocationS3(label_sizes),
insert_s3);
}
void insert_gcs() {
insert_cloud_if_available("gcs", BackendGCS.get_checker(),
new ThemedIcon("deja-dup-cloud"),
_("Google Cloud Storage"),
new ConfigLocationGCS(label_sizes),
insert_gcs);
}
void insert_u1() {
// No longer functional.
// Only shown if user already had it configured, for migration purposes.
insert_cloud_if_available("u1", null,
new ThemedIcon.from_names({"ubuntuone",
"ubuntuone-installer",
"deja-dup-cloud"}),
_("Ubuntu One"),
new ConfigLocationU1(label_sizes),
insert_u1);
}
void insert_rackspace() {
insert_cloud_if_available("rackspace", BackendRackspace.get_checker(),
new ThemedIcon("deja-dup-cloud"),
_("Rackspace Cloud Files"),
new ConfigLocationRackspace(label_sizes),
insert_rackspace);
}
void insert_openstack() {
insert_cloud_if_available("openstack", BackendOpenstack.get_checker(),
new ThemedIcon("deja-dup-cloud"),
_("OpenStack Swift"),
new ConfigLocationOpenstack(label_sizes),
insert_openstack);
}
void insert_cloud_if_available(string id, Checker? checker,
Icon icon, string name,
Gtk.Widget? w,
CloudCallback cb)
void insert_clouds()
{
// Note that we are using | not || here, because if show_deprecated is set,
// we want to insert multiple backends.
if (insert_cloud("s3", _("Amazon S3"), show_deprecated,
new ConfigLocationS3(label_sizes)) |
insert_cloud("gcs", _("Google Cloud Storage"), show_deprecated,
new ConfigLocationGCS(label_sizes)) |
insert_cloud("u1", _("Ubuntu One"), false, /* u1 is more than deprecated */
new ConfigLocationU1(label_sizes)) |
insert_cloud("rackspace", _("Rackspace Cloud Files"), show_deprecated,
new ConfigLocationRackspace(label_sizes)) |
insert_cloud("openstack", _("OpenStack Swift"), show_deprecated,
new ConfigLocationOpenstack(label_sizes)))
add_separator(Group.CLOUD_SEP);
}
bool insert_cloud(string id, string name, bool force_show, Gtk.Widget w)
{
// All cloud backends are deprecated in favor of GOA. So we only show
// them if they are already configured as the backend (either from older
// users or they manually set the gsettings value).
var backend = Backend.get_default_type();
if (backend == id || (checker != null && checker.complete && checker.available)) {
add_entry(icon, name, Group.CLOUD, w, id);
if (!have_clouds) {
add_separator(Group.CLOUD_SEP);
have_clouds = true;
}
}
else if (checker != null && !checker.complete) {
// Call ourselves when we've got enough information. Also make sure to
// set from config again, in case in a previous set_from_config, we
// weren't available in the combo yet.
checker.notify["complete"].connect(() => {cb(); set_from_config.begin();});
}
if (force_show || backend == id) {
add_entry(new ThemedIcon("deja-dup-cloud"), name, Group.CLOUD, w, id);
return true;
} else
return false;
}
bool is_allowed_volume(Volume vol)
......
/* -*- Mode: Vala; indent-tabs-mode: nil; tab-width: 2 -*- */
/*
This file is part of Déjà Dup.
For copyright information, see AUTHORS.
Déjà Dup is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Déjà Dup 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Déjà Dup. If not, see <http://www.gnu.org/licenses/>.
*/
using GLib;
namespace DejaDup {
class AsyncCommand : Object
{
public signal void done(bool success);
public string[] argv {get; construct;}
public AsyncCommand(string[] argv)
{
Object(argv: argv);
}
Pid pid = 0;
uint watch = 0;
MainLoop loop;
construct {
loop = new MainLoop(null, false);
}
~AsyncCommand() {
if (watch > 0)
Source.remove(watch);
if (pid > 0)
handle_done(pid, 1); // fake error if we're still waiting
}
public void run()
{
try {
if (!Process.spawn_async(null, argv, null,
SpawnFlags.STDOUT_TO_DEV_NULL |
SpawnFlags.STDERR_TO_DEV_NULL |
SpawnFlags.DO_NOT_REAP_CHILD |
SpawnFlags.SEARCH_PATH,
null, out pid)) {
done(false);
return;
}
}
catch (Error e) {
warning("%s\n", e.message);
done(false);
return;
}
watch = ChildWatch.add(pid, handle_done);
}
void handle_done(Pid pid, int sig)
{
done(sig == 0);
Process.close_pid(pid);
this.pid = 0;
}
}
} // end namespace
......@@ -30,10 +30,6 @@ const string GCS_SERVER = "www.googleapis.com";
public class BackendGCS : Backend
{
public static Checker get_checker() {
return PythonChecker.get_checker("boto");
}
public override Backend clone() {
return new BackendGCS();
}
......
......@@ -29,10 +29,6 @@ public const string OPENSTACK_AUTHURL_KEY = "authurl";
public class BackendOpenstack : Backend
{
public static Checker get_checker() {
return PythonChecker.get_checker("swiftclient");
}
public override Backend clone() {
return new BackendOpenstack();
}
......
......@@ -29,10 +29,6 @@ const string RACKSPACE_SERVER = "auth.api.rackspacecloud.com";
public class BackendRackspace : Backend
{
public static Checker get_checker() {
return PythonChecker.get_checker("cloudfiles");
}
public override Backend clone() {
return new BackendRackspace();
}
......
......@@ -30,10 +30,6 @@ const string S3_SERVER = "s3.amazonaws.com";
public class BackendS3 : Backend
{
public static Checker get_checker() {
return PythonChecker.get_checker("boto");
}
public override Backend clone() {
return new BackendS3();
}
......
/* -*- Mode: Vala; indent-tabs-mode: nil; tab-width: 2 -*- */
/*
This file is part of Déjà Dup.
For copyright information, see AUTHORS.
Déjà Dup is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Déjà Dup 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Déjà Dup. If not, see <http://www.gnu.org/licenses/>.
*/
using GLib;
namespace DejaDup {
/* This class is for asynchronously watching the availablility of a
backend. */
public class Checker : Object
{
// Guaranteed to only switch from false to true, never back again
public bool available {get; protected set; default = false;}
public bool complete {get; protected set; default = false;}
public Checker()
{
Object();
}
public Checker.with_available(bool available)
{
Object(available: available, complete: true);
}
}
} // end namespace
/* -*- Mode: Vala; indent-tabs-mode: nil; tab-width: 2 -*- */
/*
This file is part of Déjà Dup.
For copyright information, see AUTHORS.
Déjà Dup is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Déjà Dup 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Déjà Dup. If not, see <http://www.gnu.org/licenses/>.
*/
using GLib;
namespace DejaDup {
class PythonChecker : Checker
{
static HashTable<string, PythonChecker> modules;
// returned objects guaranteed to never die
public static PythonChecker get_checker(string module)
{
PythonChecker checker = null;
if (modules == null)
modules = new HashTable<string, PythonChecker>(str_hash, str_equal);
else
checker = modules.lookup(module);
if (checker == null) {
checker = new PythonChecker(module);
modules.insert(module, checker);
}
return checker;
}
public string module {get; construct;}
protected PythonChecker(string module)
{
Object(module: module);
}
AsyncCommand cmd;
construct {
string import = "import %s".printf(module);
string[] argv = {"python", "-c", import};
cmd = new AsyncCommand(argv);
cmd.done.connect((s) => {
available = s;
complete = true;
});
cmd.run();
}
}
} // end namespace
......@@ -17,8 +17,7 @@
# along with Déjà Dup. If not, see <http://www.gnu.org/licenses/>.
libdeja = shared_library('deja',
['AsyncCommand.vala',
'Backend.vala',
['Backend.vala',
'BackendAuto.vala',
'BackendDrive.vala',
'BackendFile.vala',
......@@ -30,7 +29,6 @@ libdeja = shared_library('deja',
'BackendRemote.vala',
'BackendS3.vala',
'BackendU1.vala',
'Checker.vala',
'CommonUtils.vala',
'DirHandling.vala',
'FilteredSettings.vala',
......@@ -41,7 +39,6 @@ libdeja = shared_library('deja',
'OperationRestore.vala',
'OperationStatus.vala',
'OperationVerify.vala',
'PythonChecker.vala',
'RecursiveDelete.vala',
'RecursiveMove.vala',
'RecursiveOp.vala',
......
......@@ -44,7 +44,6 @@ deja-dup/widgets/ConfigLocationVolume.vala
deja-dup/widgets/ConfigPeriod.vala
deja-dup/widgets/ConfigWidget.vala
deja-dup/widgets/WidgetUtils.vala
libdeja/AsyncCommand.vala
libdeja/BackendAuto.vala
libdeja/BackendDrive.vala
libdeja/BackendFile.vala
......@@ -55,7 +54,6 @@ libdeja/BackendRemote.vala
libdeja/BackendS3.vala
libdeja/BackendU1.vala
libdeja/Backend.vala
libdeja/Checker.vala
libdeja/CommonUtils.vala
libdeja/FilteredSettings.vala
libdeja/Network.vala
......@@ -65,7 +63,6 @@ libdeja/OperationRestore.vala
libdeja/OperationStatus.vala
libdeja/OperationVerify.vala
libdeja/Operation.vala
libdeja/PythonChecker.vala
libdeja/RecursiveDelete.vala
libdeja/RecursiveMove.vala
libdeja/RecursiveOp.vala
......
......@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: deja-dup\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-08-13 21:03-0400\n"
"POT-Creation-Date: 2017-08-14 17:05-0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
......@@ -40,9 +40,7 @@ msgid ""
msgstr ""
#: data/org.gnome.DejaDup.appdata.xml.in:12
msgid ""
"Support for local, remote, or cloud backup locations, such as Amazon S3 and "
"Rackspace Cloud Files"
msgid "Support for local, remote, or cloud backup locations such as Nextcloud"
msgstr ""
#: data/org.gnome.DejaDup.appdata.xml.in:13
......@@ -573,11 +571,11 @@ msgctxt "back up is verb"
msgid "_Back Up"
msgstr ""
#: deja-dup/AssistantBackup.vala:49
#: deja-dup/AssistantBackup.vala:51
msgid "Creating the first backup. This may take a while."
msgstr ""
#: deja-dup/AssistantBackup.vala:50
#: deja-dup/AssistantBackup.vala:52
msgid ""
"Creating a fresh backup to protect against backup corruption. This will "
"take longer than normal."
......@@ -585,24 +583,24 @@ msgstr ""
#. Translators: This is the phrase 'Backing up' in the larger phrase
#. "Backing up '%s'". %s is a filename.
#: deja-dup/AssistantBackup.vala:80
#: deja-dup/AssistantBackup.vala:82
msgid "Backing up:"
msgstr ""
#: deja-dup/AssistantBackup.vala:89
#: deja-dup/AssistantBackup.vala:91
msgid "Backup Failed"
msgstr ""
#: deja-dup/AssistantBackup.vala:92
#: deja-dup/AssistantBackup.vala:94
msgid "Backup Finished"
msgstr ""
#. Also leave ourselves up if we just finished a restore test.
#: deja-dup/AssistantBackup.vala:96
#: deja-dup/AssistantBackup.vala:98
msgid "Your files were successfully backed up and tested."
msgstr ""
#: deja-dup/AssistantBackup.vala:103
#: deja-dup/AssistantBackup.vala:105
msgid "Backing Up…"
msgstr ""
......@@ -610,57 +608,57 @@ msgstr ""
msgid "Scanning:"
msgstr ""
#: deja-dup/AssistantOperation.vala:239
#: deja-dup/AssistantOperation.vala:240
msgid "_Details"
msgstr ""
#: deja-dup/AssistantOperation.vala:287
#: deja-dup/AssistantOperation.vala:288
msgid "_Allow restoring without a password"
msgstr ""
#: deja-dup/AssistantOperation.vala:293
#: deja-dup/AssistantOperation.vala:294
msgid "_Password-protect your backup"
msgstr ""
#: deja-dup/AssistantOperation.vala:305
#: deja-dup/AssistantOperation.vala:306
msgid ""
"You will need your password to restore your files. You might want to write "
"it down."
msgstr ""
#: deja-dup/AssistantOperation.vala:320 deja-dup/AssistantOperation.vala:389
#: deja-dup/AssistantOperation.vala:321 deja-dup/AssistantOperation.vala:390
msgid "E_ncryption password"
msgstr ""
#: deja-dup/AssistantOperation.vala:337
#: deja-dup/AssistantOperation.vala:338
msgid "Confir_m password"
msgstr ""
#: deja-dup/AssistantOperation.vala:350 deja-dup/AssistantOperation.vala:398
#: deja-dup/AssistantOperation.vala:351 deja-dup/AssistantOperation.vala:399
msgid "_Show password"
msgstr ""
#: deja-dup/AssistantOperation.vala:357
#: deja-dup/AssistantOperation.vala:358
#: deja-dup/MountOperationAssistant.vala:40
msgid "_Remember password"
msgstr ""
#: deja-dup/AssistantOperation.vala:376
#: deja-dup/AssistantOperation.vala:377
msgid ""
"In order to check that you will be able to retrieve your files in the case "
"of an emergency, please enter your encryption password again to perform a "
"brief restore test."
msgstr ""
#: deja-dup/AssistantOperation.vala:403
#: deja-dup/AssistantOperation.vala:404
msgid "Test every two _months"
msgstr ""
#: deja-dup/AssistantOperation.vala:477
#: deja-dup/AssistantOperation.vala:478
msgid "Summary"
msgstr ""
#: deja-dup/AssistantOperation.vala:499
#: deja-dup/AssistantOperation.vala:500
msgid "Restore Test"
msgstr ""
......@@ -670,21 +668,21 @@ msgstr ""
#. But first, try to restart without a cache, since that seems to quite
#. frequently fix odd metadata errors with duplicity. If we hit an error
#. a second time, we'll show the unknown error message.
#: deja-dup/AssistantOperation.vala:574
#: libdeja/tools/duplicity/DuplicityJob.vala:706
#: libdeja/tools/duplicity/DuplicityJob.vala:1085
#: deja-dup/AssistantOperation.vala:575
#: libdeja/tools/duplicity/DuplicityJob.vala:710
#: libdeja/tools/duplicity/DuplicityJob.vala:1098
msgid "Failed with an unknown error."
msgstr ""
#: deja-dup/AssistantOperation.vala:771
#: deja-dup/AssistantOperation.vala:772
msgid "Require Password?"
msgstr ""
#: deja-dup/AssistantOperation.vala:773
#: deja-dup/AssistantOperation.vala:774
msgid "Encryption Password Needed"
msgstr ""
#: deja-dup/AssistantOperation.vala:845
#: deja-dup/AssistantOperation.vala:846
msgid "Backup encryption password"
msgstr ""
......@@ -844,33 +842,33 @@ msgstr ""
msgid "_OK"
msgstr ""
#: deja-dup/Assistant.vala:296
#: deja-dup/Assistant.vala:298
msgid "_Forward"
msgstr ""
#: deja-dup/Assistant.vala:314
#: deja-dup/Assistant.vala:316
msgid "Co_ntinue"
msgstr ""
#: deja-dup/Assistant.vala:320
#: deja-dup/Assistant.vala:322
msgctxt "verb"
msgid "_Test"
msgstr ""
#: deja-dup/Assistant.vala:349 deja-dup/widgets/ConfigList.vala:255
#: deja-dup/Assistant.vala:352 deja-dup/widgets/ConfigList.vala:255
#: deja-dup/widgets/ConfigLocationFile.vala:52
msgid "_Cancel"
msgstr ""
#: deja-dup/Assistant.vala:351
#: deja-dup/Assistant.vala:354
msgid "_Close"
msgstr ""
#: deja-dup/Assistant.vala:355
#: deja-dup/Assistant.vala:358
msgid "_Back"
msgstr ""
#: deja-dup/Assistant.vala:357
#: deja-dup/Assistant.vala:360
msgid "_Resume Later"
msgstr ""
......@@ -973,8 +971,8 @@ msgid "_Install…"
msgstr ""
#: deja-dup/Preferences.vala:258
#: deja-dup/widgets/ConfigLabelDescription.vala:59
#: deja-dup/widgets/ConfigLabelDescription.vala:83
#: deja-dup/widgets/ConfigLabelDescription.vala:63
#: deja-dup/widgets/ConfigLabelDescription.vala:87
msgid "Install…"
msgstr ""
......@@ -1055,8 +1053,8 @@ msgstr ""
msgid "%.1f%% complete"
msgstr ""
#: deja-dup/monitor/monitor.vala:82 libdeja/BackendRackspace.vala:49
#: libdeja/BackendS3.vala:59
#: deja-dup/monitor/monitor.vala:82 libdeja/BackendRackspace.vala:45
#: libdeja/BackendS3.vala:55
msgid "Backup will begin when a network connection becomes available."
msgstr ""
......@@ -1124,7 +1122,7 @@ msgstr ""
msgid "No backup scheduled."
msgstr ""
#: deja-dup/widgets/ConfigLabelDescription.vala:60
#: deja-dup/widgets/ConfigLabelDescription.vala:64
#, c-format
msgid ""
"You can restore existing backups after you first install some necessary "
......@@ -1133,57 +1131,49 @@ msgstr ""
#. This here encodes a lot of outside GUI information in this widget,
#. but it's a very special case thing.
#: deja-dup/widgets/ConfigLabelDescription.vala:69
#: deja-dup/widgets/ConfigLabelDescription.vala:73
msgid "Restore…"
msgstr ""
#: deja-dup/widgets/ConfigLabelDescription.vala:71
#: deja-dup/widgets/ConfigLabelDescription.vala:75
#, c-format
msgid "You may use the %s button to browse for existing backups."
msgstr ""
#: deja-dup/widgets/ConfigLabelDescription.vala:73
msgid "Files"
msgstr ""
#: deja-dup/widgets/ConfigLabelDescription.vala:75
msgid "Caja"
msgstr ""
#: deja-dup/widgets/ConfigLabelDescription.vala:76
#: deja-dup/widgets/ConfigLabelDescription.vala:80
#, c-format
msgid ""
"You can restore the entire backup with the %s button or use %s to either "
"revert individual files or restore missing ones."
msgstr ""
#: deja-dup/widgets/ConfigLabelDescription.vala:84
#: deja-dup/widgets/ConfigLabelDescription.vala:88
#, c-format
msgid ""
"You can create a backup after you first install some necessary software by "
"clicking the %s button."
msgstr ""
#: deja-dup/widgets/ConfigLabelDescription.vala:90
#: deja-dup/widgets/ConfigLabelDescription.vala:94
msgid "Back Up Now…"
msgstr ""
#: deja-dup/widgets/ConfigLabelDescription.vala:91
#: deja-dup/widgets/ConfigLabelDescription.vala:95
#, c-format
msgid ""
"You should <a href=''>enable</a> automatic backups or use the %s button to "
"start one now."
msgstr ""
#: deja-dup/widgets/ConfigLabelDescription.vala:97
#: deja-dup/widgets/ConfigLabelDescription.vala:101
msgid "A backup automatically starts every day."