- Backup now
+
+ ${this.hass.localize("ui.panel.config.backup.dialogs.new.title")}
+
@@ -76,17 +80,29 @@ class DialogNewBackup extends LitElement implements HassDialog {
.disabled=${!this._params.config.create_backup.password}
>
- Automatic backup
+
+ ${this.hass.localize(
+ "ui.panel.config.backup.dialogs.new.automatic.description"
+ )}
+
- Create a backup with the data and locations you have configured.
+ ${this.hass.localize(
+ "ui.panel.config.backup.dialogs.new.automatic.description"
+ )}
- Manual backup
+
+ ${this.hass.localize(
+ "ui.panel.config.backup.dialogs.new.manual.title"
+ )}
+
- Select data and locations for a manual backup.
+ ${this.hass.localize(
+ "ui.panel.config.backup.dialogs.new.manual.description"
+ )}
diff --git a/src/panels/config/backup/dialogs/dialog-restore-backup.ts b/src/panels/config/backup/dialogs/dialog-restore-backup.ts
index 588767b1dc..2620cf5ec5 100644
--- a/src/panels/config/backup/dialogs/dialog-restore-backup.ts
+++ b/src/panels/config/backup/dialogs/dialog-restore-backup.ts
@@ -122,7 +122,9 @@ class DialogRestoreBackup extends LitElement implements HassDialog {
return nothing;
}
- const dialogTitle = "Restore backup";
+ const dialogTitle = this.hass.localize(
+ "ui.panel.config.backup.dialogs.restore.title"
+ );
return html`
@@ -146,7 +148,11 @@ class DialogRestoreBackup extends LitElement implements HassDialog {
${this._error
- ? html`
Close`
+ ? html`
+
+ ${this.hass.localize("ui.common.close")}
+
+ `
: this._step === "confirm" || this._step === "encryption"
? this._renderConfirmActions()
: nothing}
@@ -156,40 +162,71 @@ class DialogRestoreBackup extends LitElement implements HassDialog {
}
private _renderConfirm() {
- return html`
- Your backup will be restored and all current data will be overwritten.
- Depending on the size of the backup, this can take a while.
-
`;
+ return html`
+
+ ${this.hass.localize(
+ "ui.panel.config.backup.dialogs.restore.confirm.description"
+ )}
+
+ `;
+ }
+
+ private _renderEncryptionIntro() {
+ if (this._usedUserInput) {
+ return html`
+ ${this.hass.localize(
+ "ui.panel.config.backup.dialogs.restore.encryption.incorrect_key"
+ )}
+ `;
+ }
+ if (this._backupEncryptionKey) {
+ return html`
+ ${this.hass.localize(
+ "ui.panel.config.backup.dialogs.restore.encryption.different_key"
+ )}
+ ${this._params!.selectedData.homeassistant_included
+ ? html`
+
+ ${this.hass.localize(
+ "ui.panel.config.backup.dialogs.restore.encryption.warning"
+ )}
+
+ `
+ : nothing}
+ `;
+ }
+ return html`
+ ${this.hass.localize(
+ "ui.panel.config.backup.dialogs.restore.encryption.description"
+ )}
+ `;
}
private _renderEncryption() {
- return html`${this._usedUserInput
- ? "The provided encryption key was incorrect, please try again."
- : this._backupEncryptionKey
- ? html`The Backup is encrypted with a different encryption key than
- that is saved on this system. Please enter the encryption key for
- this backup.
- ${this._params!.selectedData.homeassistant_included
- ? html`
After restoring the backup, your new backups will be
- encrypted with the encryption key that was present during
- the time of this backup.`
- : nothing}`
- : "The backup is encrypted. Provide the encryption key to decrypt the backup."}
+ return html`
+ ${this._renderEncryptionIntro()}
`;
+ >
+ `;
}
private _renderConfirmActions() {
- return html`
Cancel
-
Restore`;
+ return html`
+
+ ${this.hass.localize("ui.common.cancel")}
+
+
+ ${this.hass.localize(
+ "ui.panel.config.backup.dialogs.restore.actions.restore"
+ )}
+
+ `;
}
private _renderProgress() {
@@ -198,7 +235,9 @@ class DialogRestoreBackup extends LitElement implements HassDialog {
${this.hass.connected
? this._restoreState()
- : "Restarting Home Assistant"}
+ : this.hass.localize(
+ "ui.panel.config.backup.dialogs.restore.progress.restarting"
+ )}
`;
}
@@ -245,7 +284,9 @@ class DialogRestoreBackup extends LitElement implements HassDialog {
this.closeDialog();
}
if (event.state === "failed") {
- this._error = "Backup restore failed";
+ this._error = this.hass.localize(
+ "ui.panel.config.backup.dialogs.restore.restore_failed"
+ );
}
if (event.state === "in_progress") {
this._stage = event.stage;
@@ -263,29 +304,14 @@ class DialogRestoreBackup extends LitElement implements HassDialog {
}
private _restoreState() {
- switch (this._stage) {
- case "addon_repositories":
- return "Restoring add-on repositories";
- case "addons":
- return "Restoring add-ons";
- case "await_addon_restarts":
- return "Waiting for add-ons to restart";
- case "await_home_assistant_restart":
- return "Waiting for Home Assistant to restart";
- case "check_home_assistant":
- return "Checking Home Assistant configuration";
- case "docker_config":
- return "Restoring Docker configuration";
- case "download_from_agent":
- return "Downloading backup";
- case "folders":
- return "Restoring folders";
- case "home_assistant":
- return "Restoring Home Assistant";
- case "remove_delta_addons":
- return "Removing add-ons that are no longer in the backup";
+ if (!this._stage) {
+ return this.hass.localize(
+ "ui.panel.config.backup.dialogs.restore.progress.restoring"
+ );
}
- return "Restoring backup";
+ return this.hass.localize(
+ `ui.panel.config.backup.overview.progress.description.restore_backup.${this._stage}`
+ );
}
private async _doRestoreBackup(password?: string) {
diff --git a/src/panels/config/backup/dialogs/dialog-set-backup-encryption-key.ts b/src/panels/config/backup/dialogs/dialog-set-backup-encryption-key.ts
index 956b969dc1..03ed6c0b87 100644
--- a/src/panels/config/backup/dialogs/dialog-set-backup-encryption-key.ts
+++ b/src/panels/config/backup/dialogs/dialog-set-backup-encryption-key.ts
@@ -1,11 +1,13 @@
-import { mdiClose, mdiDownload, mdiKey } from "@mdi/js";
+import { mdiClose, mdiContentCopy, mdiDownload } from "@mdi/js";
import type { CSSResultGroup } from "lit";
import { LitElement, css, html, nothing } from "lit";
import { customElement, property, query, state } from "lit/decorators";
import { fireEvent } from "../../../../common/dom/fire_event";
+import { copyToClipboard } from "../../../../common/util/copy-clipboard";
import "../../../../components/ha-button";
import "../../../../components/ha-dialog-header";
import "../../../../components/ha-icon-button";
+import "../../../../components/ha-icon-button-prev";
import "../../../../components/ha-md-dialog";
import type { HaMdDialog } from "../../../../components/ha-md-dialog";
import "../../../../components/ha-md-list";
@@ -18,9 +20,12 @@ import {
import type { HassDialog } from "../../../../dialogs/make-dialog-manager";
import { haStyle, haStyleDialog } from "../../../../resources/styles";
import type { HomeAssistant } from "../../../../types";
+import { showToast } from "../../../../util/toast";
import type { SetBackupEncryptionKeyDialogParams } from "./show-dialog-set-backup-encryption-key";
-const STEPS = ["new", "save"] as const;
+const STEPS = ["key", "done"] as const;
+
+type Step = (typeof STEPS)[number];
@customElement("ha-dialog-set-backup-encryption-key")
class DialogSetBackupEncryptionKey extends LitElement implements HassDialog {
@@ -28,7 +33,7 @@ class DialogSetBackupEncryptionKey extends LitElement implements HassDialog {
@state() private _opened = false;
- @state() private _step?: "new" | "save";
+ @state() private _step?: Step;
@state() private _params?: SetBackupEncryptionKeyDialogParams;
@@ -36,13 +41,11 @@ class DialogSetBackupEncryptionKey extends LitElement implements HassDialog {
@state() private _newEncryptionKey?: string;
- private _suggestedEncryptionKey?: string;
-
public showDialog(params: SetBackupEncryptionKeyDialogParams): void {
this._params = params;
this._step = STEPS[0];
this._opened = true;
- this._suggestedEncryptionKey = generateEncryptionKey();
+ this._newEncryptionKey = generateEncryptionKey();
}
public closeDialog(): void {
@@ -56,7 +59,6 @@ class DialogSetBackupEncryptionKey extends LitElement implements HassDialog {
this._step = undefined;
this._params = undefined;
this._newEncryptionKey = undefined;
- this._suggestedEncryptionKey = undefined;
}
private _done() {
@@ -78,7 +80,11 @@ class DialogSetBackupEncryptionKey extends LitElement implements HassDialog {
}
const dialogTitle =
- this._step === "new" ? "Encryption key" : "Save new encryption key";
+ this._step === "key"
+ ? this.hass.localize(
+ `ui.panel.config.backup.dialogs.set_encryption_key.key.title`
+ )
+ : "";
return html`
@@ -93,18 +99,24 @@ class DialogSetBackupEncryptionKey extends LitElement implements HassDialog {
${this._renderStepContent()}
- ${this._step === "new"
+ ${this._step === "key"
? html`
- Next
+ ${this.hass.localize(
+ "ui.panel.config.backup.dialogs.set_encryption_key.actions.set"
+ )}
`
- : this._step === "save"
- ? html`Done`
- : nothing}
+ : html`
+
+ ${this.hass.localize(
+ "ui.panel.config.backup.dialogs.set_encryption_key.actions.done"
+ )}
+
+ `}
`;
@@ -112,69 +124,76 @@ class DialogSetBackupEncryptionKey extends LitElement implements HassDialog {
private _renderStepContent() {
switch (this._step) {
- case "new":
+ case "key":
return html`
- All your backups are encrypted to keep your data private and secure.
- You need this encryption key to restore any backup.
+ ${this.hass.localize(
+ "ui.panel.config.backup.dialogs.set_encryption_key.new.description"
+ )}
-
+
+
${this._newEncryptionKey}
+
+
-
- Use suggested encryption key
-
- ${this._suggestedEncryptionKey}
+
+ ${this.hass.localize(
+ "ui.panel.config.backup.encryption_key.download_emergency_kit"
+ )}
-
- Enter
+
+ ${this.hass.localize(
+ "ui.panel.config.backup.encryption_key.download_emergency_kit_description"
+ )}
+
+
+
+ ${this.hass.localize(
+ "ui.panel.config.backup.encryption_key.download_emergency_kit_action"
+ )}
`;
- case "save":
+ case "done":
return html`
-
- It’s important that you don’t lose this encryption key. We recommend
- to save this key somewhere secure. As you can only restore your data
- with the backup encryption key.
-
-
-
- Download emergency kit
-
- We recommend to save this encryption key somewhere secure.
-
-
-
- Download
-
-
-
+
+

+
+ ${this.hass.localize(
+ "ui.panel.config.backup.dialogs.set_encryption_key.done.title"
+ )}
+
+
`;
}
return nothing;
}
- private _downloadNew() {
+ private async _copyKeyToClipboard() {
+ await copyToClipboard(
+ this._newEncryptionKey,
+ this.renderRoot.querySelector("div")!
+ );
+ showToast(this, {
+ message: this.hass.localize("ui.common.copied_clipboard"),
+ });
+ }
+
+ private _download() {
if (!this._newEncryptionKey) {
return;
}
downloadEmergencyKit(this.hass, this._newEncryptionKey);
}
- private _encryptionKeyChanged(ev) {
- this._newEncryptionKey = ev.target.value;
- }
-
- private _useSuggestedEncryptionKey() {
- this._newEncryptionKey = this._suggestedEncryptionKey;
- }
-
private async _submit() {
if (!this._newEncryptionKey) {
return;
@@ -190,7 +209,7 @@ class DialogSetBackupEncryptionKey extends LitElement implements HassDialog {
css`
ha-md-dialog {
width: 90vw;
- max-width: 500px;
+ max-width: 560px;
--dialog-content-padding: 8px 24px;
}
ha-md-list {
@@ -198,6 +217,30 @@ class DialogSetBackupEncryptionKey extends LitElement implements HassDialog {
--md-list-item-leading-space: 0;
--md-list-item-trailing-space: 0;
}
+ .encryption-key {
+ border: 1px solid var(--divider-color);
+ background-color: var(--primary-background-color);
+ border-radius: 8px;
+ padding: 16px;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ gap: 24px;
+ }
+ .encryption-key p {
+ margin: 0;
+ flex: 1;
+ font-family: "Roboto Mono", "Consolas", "Menlo", monospace;
+ font-size: 20px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: 28px;
+ text-align: center;
+ }
+ .encryption-key ha-icon-button {
+ flex: none;
+ margin: -16px;
+ }
@media all and (max-width: 450px), all and (max-height: 500px) {
ha-md-dialog {
max-width: none;
@@ -209,6 +252,9 @@ class DialogSetBackupEncryptionKey extends LitElement implements HassDialog {
p {
margin-top: 0;
}
+ .done {
+ text-align: center;
+ }
`,
];
}
diff --git a/src/panels/config/backup/dialogs/dialog-show-backup-encryption-key.ts b/src/panels/config/backup/dialogs/dialog-show-backup-encryption-key.ts
index 5861ad35a7..283d4fc082 100644
--- a/src/panels/config/backup/dialogs/dialog-show-backup-encryption-key.ts
+++ b/src/panels/config/backup/dialogs/dialog-show-backup-encryption-key.ts
@@ -55,12 +55,17 @@ class DialogShowBackupEncryptionKey extends LitElement implements HassDialog {
.path=${mdiClose}
@click=${this._closeDialog}
>
- Encryption key
+
+ ${this.hass.localize(
+ "ui.panel.config.backup.dialogs.show_encryption_key.title"
+ )}
+
- Make sure you save the encryption key in a secure place so always
- have access to your backups.
+ ${this.hass.localize(
+ "ui.panel.config.backup.dialogs.show_encryption_key.description"
+ )}
${this._params?.currentKey}
@@ -71,19 +76,29 @@ class DialogShowBackupEncryptionKey extends LitElement implements HassDialog {
- Download emergency kit
+
+ ${this.hass.localize(
+ "ui.panel.config.backup.encryption_key.download_emergency_kit"
+ )}
+
- We recommend saving this encryption key file somewhere secure.
+ ${this.hass.localize(
+ "ui.panel.config.backup.encryption_key.download_emergency_kit_description"
+ )}
- Download
+ ${this.hass.localize(
+ "ui.panel.config.backup.encryption_key.download_emergency_kit_action"
+ )}
- Close
+
+ ${this.hass.localize("ui.dialogs.generic.close")}
+
`;
@@ -124,9 +139,6 @@ class DialogShowBackupEncryptionKey extends LitElement implements HassDialog {
--md-list-item-leading-space: 0;
--md-list-item-trailing-space: 0;
}
- ha-button.danger {
- --mdc-theme-primary: var(--error-color);
- }
.encryption-key {
border: 1px solid var(--divider-color);
background-color: var(--primary-background-color);
diff --git a/src/panels/config/backup/dialogs/dialog-upload-backup.ts b/src/panels/config/backup/dialogs/dialog-upload-backup.ts
index e1258a0f51..09e5e5b5d6 100644
--- a/src/panels/config/backup/dialogs/dialog-upload-backup.ts
+++ b/src/panels/config/backup/dialogs/dialog-upload-backup.ts
@@ -86,7 +86,9 @@ export class DialogUploadBackup
@click=${this.closeDialog}
>
- Upload backup
+
+ ${this.hass.localize("ui.panel.config.backup.dialogs.upload.title")}
+
${this._error
@@ -97,15 +99,21 @@ export class DialogUploadBackup
.uploading=${this._uploading}
.icon=${mdiFolderUpload}
accept=${SUPPORTED_FORMAT}
- label="Select backup file"
- supports="Supports .tar files"
+ .label=${this.hass.localize(
+ "ui.panel.config.backup.dialogs.upload.input_label"
+ )}
+ .supports=${this.hass.localize(
+ "ui.panel.config.backup.dialogs.upload.supports_tar"
+ )}
@file-picked=${this._filePicked}
>
Cancel
- Upload backup
+ ${this.hass.localize(
+ "ui.panel.config.backup.dialogs.upload.action"
+ )}
@@ -126,9 +134,13 @@ export class DialogUploadBackup
const { file } = this._formData!;
if (!file || file.type !== SUPPORTED_FORMAT) {
showAlertDialog(this, {
- title: "Unsupported file format",
- text: "Please choose a Home Assistant backup file (.tar)",
- confirmText: "ok",
+ title: this.hass.localize(
+ "ui.panel.config.backup.dialogs.upload.unsupported.title"
+ ),
+ text: this.hass.localize(
+ "ui.panel.config.backup.dialogs.upload.unsupported.text"
+ ),
+ confirmText: this.hass.localize("ui.common.ok"),
});
return;
}
diff --git a/src/panels/config/backup/ha-config-backup-backups.ts b/src/panels/config/backup/ha-config-backup-backups.ts
index 18d65557f0..18682cd054 100644
--- a/src/panels/config/backup/ha-config-backup-backups.ts
+++ b/src/panels/config/backup/ha-config-backup-backups.ts
@@ -17,7 +17,6 @@ import { fireEvent, type HASSDomEvent } from "../../../common/dom/fire_event";
import { computeDomain } from "../../../common/entity/compute_domain";
import { shouldHandleRequestSelectedEvent } from "../../../common/mwc/handle-request-selected-event";
import { navigate } from "../../../common/navigate";
-import { capitalizeFirstLetter } from "../../../common/string/capitalize-first-letter";
import type { LocalizeFunc } from "../../../common/translations/localize";
import type {
DataTableColumnContainer,
@@ -70,9 +69,9 @@ interface BackupRow extends DataTableRowData, BackupContent {
formatted_type: string;
}
-type BackupType = "automatic" | "manual" | "imported";
+type BackupType = "automatic" | "manual";
-const TYPE_ORDER: Array = ["automatic", "manual", "imported"];
+const TYPE_ORDER: Array = ["automatic", "manual"];
@customElement("ha-config-backup-backups")
class HaConfigBackupBackups extends SubscribeMixin(LitElement) {
@@ -158,13 +157,13 @@ class HaConfigBackupBackups extends SubscribeMixin(LitElement) {
relativeTime(new Date(backup.date), this.hass.locale),
},
formatted_type: {
- title: "Type",
+ title: localize("ui.panel.config.backup.backup_type"),
filterable: true,
sortable: true,
groupable: true,
},
locations: {
- title: "Locations",
+ title: localize("ui.panel.config.backup.locations"),
showNarrow: true,
minWidth: "60px",
template: (backup) => html`
@@ -246,10 +245,13 @@ class HaConfigBackupBackups extends SubscribeMixin(LitElement) {
})
);
- private _groupOrder = memoizeOne((activeGrouping: string | undefined) =>
- activeGrouping === "formatted_type"
- ? TYPE_ORDER.map((type) => this._formatBackupType(type))
- : undefined
+ private _groupOrder = memoizeOne(
+ (activeGrouping: string | undefined, localize: LocalizeFunc) =>
+ activeGrouping === "formatted_type"
+ ? TYPE_ORDER.map((type) =>
+ localize(`ui.panel.config.backup.type.${type}`)
+ )
+ : undefined
);
private _handleGroupingChanged(ev: CustomEvent) {
@@ -266,15 +268,11 @@ class HaConfigBackupBackups extends SubscribeMixin(LitElement) {
this._selected = ev.detail.value;
}
- private _formatBackupType(type: BackupType): string {
- // Todo translate
- return capitalizeFirstLetter(type);
- }
-
private _data = memoizeOne(
(
backups: BackupContent[],
- filters: DataTableFiltersValues
+ filters: DataTableFiltersValues,
+ localize: LocalizeFunc
): BackupRow[] => {
const typeFilter = filters["ha-filter-states"] as string[] | undefined;
let filteredBackups = backups;
@@ -286,12 +284,13 @@ class HaConfigBackupBackups extends SubscribeMixin(LitElement) {
(!backup.with_automatic_settings && typeFilter.includes("manual"))
);
}
- return filteredBackups.map((backup) => ({
- ...backup,
- formatted_type: this._formatBackupType(
- backup.with_automatic_settings ? "automatic" : "manual"
- ),
- }));
+ return filteredBackups.map((backup) => {
+ const type = backup.with_automatic_settings ? "automatic" : "manual";
+ return {
+ ...backup,
+ formatted_type: localize(`ui.panel.config.backup.type.${type}`),
+ };
+ });
}
);
@@ -304,7 +303,7 @@ class HaConfigBackupBackups extends SubscribeMixin(LitElement) {
has-fab
.tabs=${[
{
- name: "My backups",
+ name: this.hass.localize("ui.panel.config.backup.backups.header"),
path: `/config/backup/list`,
},
]}
@@ -326,14 +325,17 @@ class HaConfigBackupBackups extends SubscribeMixin(LitElement) {
.selected=${this._selected.length}
.initialGroupColumn=${this._activeGrouping}
.initialCollapsedGroups=${this._activeCollapsed}
- .groupOrder=${this._groupOrder(this._activeGrouping)}
+ .groupOrder=${this._groupOrder(
+ this._activeGrouping,
+ this.hass.localize
+ )}
@grouping-changed=${this._handleGroupingChanged}
@collapsed-changed=${this._handleCollapseChanged}
@selection-changed=${this._handleSelectionChanged}
.route=${this.route}
@row-click=${this._showBackupDetails}
.columns=${this._columns(this.hass.localize)}
- .data=${this._data(this.backups, this._filters)}
+ .data=${this._data(this.backups, this._filters, this.hass.localize)}
.noDataText=${this.hass.localize("ui.panel.config.backup.no_backups")}
.searchLabel=${this.hass.localize(
"ui.panel.config.backup.picker.search"
@@ -351,7 +353,9 @@ class HaConfigBackupBackups extends SubscribeMixin(LitElement) {
@request-selected=${this._uploadBackup}
>
- Upload backup
+ ${this.hass.localize(
+ "ui.panel.config.backup.backups.menu.upload_backup"
+ )}
@@ -360,26 +364,32 @@ class HaConfigBackupBackups extends SubscribeMixin(LitElement) {
${!this.narrow
? html`
- Delete selected
+ ${this.hass.localize(
+ "ui.panel.config.backup.backups.delete_selected"
+ )}
`
: html`
- Delete selected
+ ${this.hass.localize(
+ "ui.panel.config.backup.backups.delete_selected"
+ )}
`}
@@ -404,16 +416,12 @@ class HaConfigBackupBackups extends SubscribeMixin(LitElement) {
`;
}
- private _states = memoizeOne((_localize: LocalizeFunc) => [
- {
- value: "automatic",
- label: "Automatic",
- },
- {
- value: "manual",
- label: "Manual",
- },
- ]);
+ private _states = memoizeOne((localize: LocalizeFunc) =>
+ TYPE_ORDER.map((type) => ({
+ value: type,
+ label: localize(`ui.panel.config.backup.type.${type}`),
+ }))
+ );
private _filterChanged(ev) {
const type = ev.target.localName;
@@ -489,8 +497,8 @@ class HaConfigBackupBackups extends SubscribeMixin(LitElement) {
private async _deleteBackup(backup: BackupContent): Promise {
const confirm = await showConfirmationDialog(this, {
- title: "Delete backup",
- text: "This backup will be permanently deleted.",
+ title: this.hass.localize("ui.panel.config.backup.dialogs.delete.title"),
+ text: this.hass.localize("ui.panel.config.backup.dialogs.delete.text"),
confirmText: this.hass.localize("ui.common.delete"),
destructive: true,
});
@@ -499,17 +507,31 @@ class HaConfigBackupBackups extends SubscribeMixin(LitElement) {
return;
}
- await deleteBackup(this.hass, backup.backup_id);
- if (this._selected.includes(backup.backup_id)) {
- this._selected = this._selected.filter((id) => id !== backup.backup_id);
+ try {
+ await deleteBackup(this.hass, backup.backup_id);
+ if (this._selected.includes(backup.backup_id)) {
+ this._selected = this._selected.filter((id) => id !== backup.backup_id);
+ }
+ } catch (err: any) {
+ showAlertDialog(this, {
+ title: this.hass.localize(
+ "ui.panel.config.backup.dialogs.delete.failed"
+ ),
+ text: extractApiErrorMessage(err),
+ });
+ return;
}
fireEvent(this, "ha-refresh-backup-info");
}
private async _deleteSelected() {
const confirm = await showConfirmationDialog(this, {
- title: "Delete selected backups",
- text: "These backups will be permanently deleted.",
+ title: this.hass.localize(
+ "ui.panel.config.backup.dialogs.delete_selected.title"
+ ),
+ text: this.hass.localize(
+ "ui.panel.config.backup.dialogs.delete_selected.text"
+ ),
confirmText: this.hass.localize("ui.common.delete"),
destructive: true,
});
@@ -524,7 +546,9 @@ class HaConfigBackupBackups extends SubscribeMixin(LitElement) {
);
} catch (err: any) {
showAlertDialog(this, {
- title: "Failed to delete backups",
+ title: this.hass.localize(
+ "ui.panel.config.backup.dialogs.delete_selected.failed"
+ ),
text: extractApiErrorMessage(err),
});
return;
diff --git a/src/panels/config/backup/ha-config-backup-details.ts b/src/panels/config/backup/ha-config-backup-details.ts
index 8c42bfe69f..5c8f2ea510 100644
--- a/src/panels/config/backup/ha-config-backup-details.ts
+++ b/src/panels/config/backup/ha-config-backup-details.ts
@@ -41,6 +41,7 @@ import { fileDownload } from "../../../util/file_download";
import { showConfirmationDialog } from "../../lovelace/custom-card-helpers";
import "./components/ha-backup-data-picker";
import { showRestoreBackupDialog } from "./dialogs/show-dialog-restore-backup";
+import { fireEvent } from "../../../common/dom/fire_event";
type Agent = {
id: string;
@@ -96,7 +97,8 @@ class HaConfigBackupDetails extends LitElement {
back-path="/config/backup/backups"
.hass=${this.hass}
.narrow=${this.narrow}
- .header=${this._backup?.name || "Backup"}
+ .header=${this._backup?.name ||
+ this.hass.localize("ui.panel.config.backup.details.header")}
>
${this._error}`}
${this._backup === null
? html`
-
- Backup matching ${this.backupId} not found
+
+ ${this.hass.localize(
+ "ui.panel.config.backup.details.not_found_description",
+ { backupId: this.backupId }
+ )}
`
: !this._backup
? html``
: html`
-
+
${bytesToString(this._backup.size)}
- Size
+
+ ${this.hass.localize(
+ "ui.panel.config.backup.details.summary.size"
+ )}
+
${formatDateTime(
@@ -141,21 +159,37 @@ class HaConfigBackupDetails extends LitElement {
this.hass.locale,
this.hass.config
)}
- Created
+
+ ${this.hass.localize(
+ "ui.panel.config.backup.details.summary.created"
+ )}
+
${this._backup.protected
- ? "Encrypted AES-128"
- : "Not encrypted"}
+ ? this.hass.localize(
+ "ui.panel.config.backup.details.summary.protected_encrypted_aes_128"
+ )
+ : this.hass.localize(
+ "ui.panel.config.backup.details.summary.protected_not_encrypted"
+ )}
+
+
+ ${this.hass.localize(
+ "ui.panel.config.backup.details.summary.protected"
+ )}
- Protected
-
+
- Restore
+ ${this.hass.localize(
+ "ui.panel.config.backup.details.restore.action"
+ )}
-
+
${this._agents.map((agent) => {
@@ -187,11 +227,9 @@ class HaConfigBackupDetails extends LitElement {
const name = computeBackupAgentName(
this.hass.localize,
agentId,
- this._backup!.agent_ids!
+ this._backup!.agent_ids
);
- const isLocal = isLocalAgent(agentId);
-
return html`
${isLocalAgent(agentId)
@@ -232,10 +270,12 @@ class HaConfigBackupDetails extends LitElement {
${success
- ? isLocal
- ? "Backup created"
- : "Backup uploaded"
- : "Backup failed"}
+ ? this.hass.localize(
+ "ui.panel.config.backup.details.locations.backup_stored"
+ )
+ : this.hass.localize(
+ "ui.panel.config.backup.details.locations.backup_failed"
+ )}
${success
@@ -257,7 +297,9 @@ class HaConfigBackupDetails extends LitElement {
slot="graphic"
.path=${mdiDownload}
>
- Download from this location
+ ${this.hass.localize(
+ "ui.panel.config.backup.details.locations.download"
+ )}
`
: nothing}
@@ -309,7 +351,9 @@ class HaConfigBackupDetails extends LitElement {
response.backup.failed_agent_ids || []
);
} catch (err: any) {
- this._error = err?.message || "Could not fetch backup details";
+ this._error =
+ err?.message ||
+ this.hass.localize("ui.panel.config.backup.details.error");
}
}
@@ -342,8 +386,8 @@ class HaConfigBackupDetails extends LitElement {
private async _deleteBackup(): Promise {
const confirm = await showConfirmationDialog(this, {
- title: "Delete backup",
- text: "This backup will be permanently deleted.",
+ title: this.hass.localize("ui.panel.config.backup.dialogs.delete.title"),
+ text: this.hass.localize("ui.panel.config.backup.dialogs.delete.text"),
confirmText: this.hass.localize("ui.common.delete"),
destructive: true,
});
@@ -353,6 +397,7 @@ class HaConfigBackupDetails extends LitElement {
}
await deleteBackup(this.hass, this._backup!.backup_id);
+ fireEvent(this, "ha-refresh-backup-info");
navigate("/config/backup");
}
diff --git a/src/panels/config/backup/ha-config-backup-overview.ts b/src/panels/config/backup/ha-config-backup-overview.ts
index 26e86a2105..e121d62b30 100644
--- a/src/panels/config/backup/ha-config-backup-overview.ts
+++ b/src/panels/config/backup/ha-config-backup-overview.ts
@@ -130,7 +130,7 @@ class HaConfigBackupOverview extends LitElement {
back-path="/config/system"
.hass=${this.hass}
.narrow=${this.narrow}
- .header=${"Backup"}
+ .header=${this.hass.localize("ui.panel.config.backup.overview.header")}
>
- Upload backup
+ ${this.hass.localize(
+ "ui.panel.config.backup.overview.menu.upload_backup"
+ )}
@@ -190,7 +192,9 @@ class HaConfigBackupOverview extends LitElement {
diff --git a/src/panels/config/backup/ha-config-backup-settings.ts b/src/panels/config/backup/ha-config-backup-settings.ts
index f581f5cd92..4bed661988 100644
--- a/src/panels/config/backup/ha-config-backup-settings.ts
+++ b/src/panels/config/backup/ha-config-backup-settings.ts
@@ -99,7 +99,7 @@ class HaConfigBackupSettings extends LitElement {
back-path="/config/backup"
.hass=${this.hass}
.narrow=${this.narrow}
- .header=${"Backup settings"}
+ .header=${this.hass.localize("ui.panel.config.backup.settings.header")}
>
${isComponentLoaded(this.hass, "hassio")
? html`
@@ -117,7 +117,9 @@ class HaConfigBackupSettings extends LitElement {
slot="graphic"
.path=${mdiHarddisk}
>
- Change default action location
+ ${this.hass.localize(
+ "ui.panel.config.backup.settings.menu.change_default_location"
+ )}
`
@@ -125,11 +127,16 @@ class HaConfigBackupSettings extends LitElement {
-
+
- Let Home Assistant take care of your backups by creating a
- scheduled backup that also removes older backups.
+ ${this.hass.localize(
+ "ui.panel.config.backup.settings.schedule.description"
+ )}
-
+
-
+
- Your backup will be stored on these locations when this default
- backup is created. You can use all locations for custom backups.
+ ${this.hass.localize(
+ "ui.panel.config.backup.settings.locations.description"
+ )}
${!this._config.create_backup.agent_ids.length
- ? html`
You have to select at least one location to create a
- backup.`
+ .title=${this.hass.localize(
+ "ui.panel.config.backup.settings.locations.no_location"
+ )}
+ >
+ ${this.hass.localize(
+ "ui.panel.config.backup.settings.locations.no_location_description"
+ )}
+
+
+ `
: nothing}
-
+
- Keep this encryption key in a safe place, as you will need it to
- access your backup, allowing it to be restored. Download them as
- an emergency kit file and store it somewhere safe. Encryption
- keeps your backups private and secure.
+ ${this.hass.localize(
+ "ui.panel.config.backup.settings.encryption_key.description"
+ )}