diff --git a/hassio/src/addon-store/hassio-addon-repository.ts b/hassio/src/addon-store/hassio-addon-repository.ts index 67c4c50849..746ee5cd8d 100644 --- a/hassio/src/addon-store/hassio-addon-repository.ts +++ b/hassio/src/addon-store/hassio-addon-repository.ts @@ -15,6 +15,7 @@ import { HassioAddonInfo, HassioAddonRepository, } from "../../../src/data/hassio/addon"; +import { Supervisor } from "../../../src/data/supervisor/supervisor"; import { HomeAssistant } from "../../../src/types"; import "../components/hassio-card-content"; import { filterAndSort } from "../components/hassio-filter-addons"; @@ -23,6 +24,8 @@ import { hassioStyle } from "../resources/hassio-style"; class HassioAddonRepositoryEl extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; + @property({ attribute: false }) public supervisor!: Supervisor; + @property({ attribute: false }) public repo!: HassioAddonRepository; @property({ attribute: false }) public addons!: HassioAddonInfo[]; @@ -54,7 +57,11 @@ class HassioAddonRepositoryEl extends LitElement { return html`

- No results found in "${repo.name}." + ${this.supervisor.localize( + "store.no_results_found", + "repository", + repo.name + )}

`; @@ -83,11 +90,13 @@ class HassioAddonRepositoryEl extends LitElement { : mdiPuzzle} .iconTitle=${addon.installed ? addon.update_available - ? "New version available" - : "Add-on is installed" + ? this.supervisor.localize( + "common.new_version_available" + ) + : this.supervisor.localize("addon.installed") : addon.available - ? "Add-on is not installed" - : "Add-on is not available on your system"} + ? this.supervisor.localize("addon.not_installed") + : this.supervisor.localize("addon.not_available")} .iconClass=${addon.installed ? addon.update_available ? "update" diff --git a/hassio/src/addon-store/hassio-addon-store.ts b/hassio/src/addon-store/hassio-addon-store.ts index 2ccac48290..80e06f36fd 100644 --- a/hassio/src/addon-store/hassio-addon-store.ts +++ b/hassio/src/addon-store/hassio-addon-store.ts @@ -96,15 +96,15 @@ class HassioAddonStore extends LitElement { - Repositories + ${this.supervisor.localize("store.repositories")} - Reload + ${this.supervisor.localize("common.reload")} ${this.hass.userData?.showAdvanced && atLeastVersion(this.hass.config.version, 0, 117) ? html` - Registries + ${this.supervisor.localize("store.registries")} ` : ""} @@ -125,11 +125,9 @@ class HassioAddonStore extends LitElement { ${!this.hass.userData?.showAdvanced ? html`
- Missing add-ons? Enable advanced mode on - your profile page + ${this.supervisor.localize("store.missing_addons")} - .
` : ""} @@ -161,6 +159,7 @@ class HassioAddonStore extends LitElement { .repo=${repo} .addons=${filteredAddons} .filter=${filter!} + .supervisor=${this.supervisor} > ` : html``; @@ -190,13 +189,13 @@ class HassioAddonStore extends LitElement { private async _manageRepositories() { showRepositoriesDialog(this, { - repos: this.supervisor.addon.repositories, + supervisor: this.supervisor, loadData: () => this._loadData(), }); } private async _manageRegistries() { - showRegistriesDialog(this); + showRegistriesDialog(this, { supervisor: this.supervisor }); } private async _loadData() { diff --git a/hassio/src/addon-view/config/hassio-addon-audio.ts b/hassio/src/addon-view/config/hassio-addon-audio.ts index e3349b0144..de682a9520 100644 --- a/hassio/src/addon-view/config/hassio-addon-audio.ts +++ b/hassio/src/addon-view/config/hassio-addon-audio.ts @@ -25,6 +25,7 @@ import { fetchHassioHardwareAudio, HassioHardwareAudioDevice, } from "../../../../src/data/hassio/hardware"; +import { Supervisor } from "../../../../src/data/supervisor/supervisor"; import { haStyle } from "../../../../src/resources/styles"; import { HomeAssistant } from "../../../../src/types"; import { suggestAddonRestart } from "../../dialogs/suggestAddonRestart"; @@ -34,6 +35,8 @@ import { hassioStyle } from "../../resources/hassio-style"; class HassioAddonAudio extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; + @property({ attribute: false }) public supervisor!: Supervisor; + @property({ attribute: false }) public addon!: HassioAddonDetails; @internalProperty() private _error?: string; @@ -48,12 +51,16 @@ class HassioAddonAudio extends LitElement { protected render(): TemplateResult { return html` - +
${this._error ? html`
${this._error}
` : ""} { return html` - ${item.name} + + ${item.name} + `; })}
- Save + ${this.supervisor.localize("common.save")}
@@ -152,7 +161,7 @@ class HassioAddonAudio extends LitElement { const noDevice: HassioHardwareAudioDevice = { device: "default", - name: "Default", + name: this.supervisor.localize("addon.configuration.audio.default"), }; try { @@ -189,7 +198,7 @@ class HassioAddonAudio extends LitElement { try { await setHassioAddonOption(this.hass, this.addon.slug, data); if (this.addon?.state === "started") { - await suggestAddonRestart(this, this.hass, this.addon); + await suggestAddonRestart(this, this.hass, this.supervisor, this.addon); } } catch { this._error = "Failed to set addon audio device"; diff --git a/hassio/src/addon-view/config/hassio-addon-config-tab.ts b/hassio/src/addon-view/config/hassio-addon-config-tab.ts index d59b150e18..b9a5907075 100644 --- a/hassio/src/addon-view/config/hassio-addon-config-tab.ts +++ b/hassio/src/addon-view/config/hassio-addon-config-tab.ts @@ -9,6 +9,7 @@ import { } from "lit-element"; import "../../../../src/components/ha-circular-progress"; import { HassioAddonDetails } from "../../../../src/data/hassio/addon"; +import { Supervisor } from "../../../../src/data/supervisor/supervisor"; import { haStyle } from "../../../../src/resources/styles"; import { HomeAssistant } from "../../../../src/types"; import { hassioStyle } from "../../resources/hassio-style"; @@ -20,6 +21,8 @@ import "./hassio-addon-network"; class HassioAddonConfigDashboard extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; + @property({ attribute: false }) public supervisor!: Supervisor; + @property({ attribute: false }) public addon?: HassioAddonDetails; protected render(): TemplateResult { @@ -39,6 +42,7 @@ class HassioAddonConfigDashboard extends LitElement { ` : ""} @@ -47,6 +51,7 @@ class HassioAddonConfigDashboard extends LitElement { ` : ""} @@ -55,11 +60,12 @@ class HassioAddonConfigDashboard extends LitElement { ` : ""} ` - : "This add-on does not expose configuration for you to mess with.... 👋"} + : this.supervisor.localize("addon.configuration.no_configuration")}
`; } diff --git a/hassio/src/addon-view/config/hassio-addon-config.ts b/hassio/src/addon-view/config/hassio-addon-config.ts index c81f417e26..2a5c2bfcfe 100644 --- a/hassio/src/addon-view/config/hassio-addon-config.ts +++ b/hassio/src/addon-view/config/hassio-addon-config.ts @@ -32,6 +32,7 @@ import { setHassioAddonOption, } from "../../../../src/data/hassio/addon"; import { extractApiErrorMessage } from "../../../../src/data/hassio/common"; +import { Supervisor } from "../../../../src/data/supervisor/supervisor"; import { showConfirmationDialog } from "../../../../src/dialogs/generic/show-dialog-box"; import { haStyle } from "../../../../src/resources/styles"; import type { HomeAssistant } from "../../../../src/types"; @@ -46,6 +47,8 @@ class HassioAddonConfig extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; + @property({ attribute: false }) public supervisor!: Supervisor; + @property({ type: Boolean }) private _configHasChanged = false; @property({ type: Boolean }) private _valid = true; @@ -90,17 +93,25 @@ class HassioAddonConfig extends LitElement {

${this.addon.name}

-

Configuration

+

+ ${this.supervisor.localize("addon.configuration.options.header")} +

- ${this._yamlMode ? "Edit in UI" : "Edit in YAML"} + ${this._yamlMode + ? this.supervisor.localize( + "addon.configuration.options.edit_in_ui" + ) + : this.supervisor.localize( + "addon.configuration.options.edit_in_yaml" + )} - Reset to defaults + ${this.supervisor.localize("common.reset_defaults")}
@@ -127,12 +138,20 @@ class HassioAddonConfig extends LitElement { (this._canShowSchema && this.addon.schema) || this._valid ? "" - : html`
Invalid YAML
`} + : html` +
+ ${this.supervisor.localize( + "addon.configuration.options.invalid_yaml" + )} +
+ `}
${hasHiddenOptions ? html` - Save + Save ${this.supervisor.localize("common.save")}
@@ -211,10 +230,10 @@ class HassioAddonConfig extends LitElement { button.progress = true; const confirmed = await showConfirmationDialog(this, { - title: this.addon.name, - text: "Are you sure you want to reset all your options?", - confirmText: "reset options", - dismissText: "no", + title: this.supervisor.localize("confirm.reset_options.title"), + text: this.supervisor.localize("confirm.reset_options.text"), + confirmText: this.supervisor.localize("common.reset_options"), + dismissText: this.supervisor.localize("common.cancel"), }); if (!confirmed) { @@ -236,9 +255,11 @@ class HassioAddonConfig extends LitElement { }; fireEvent(this, "hass-api-called", eventdata); } catch (err) { - this._error = `Failed to reset addon configuration, ${extractApiErrorMessage( - err - )}`; + this._error = this.supervisor.localize( + "addon.common.update_available", + "error", + extractApiErrorMessage(err) + ); } button.progress = false; } @@ -262,12 +283,14 @@ class HassioAddonConfig extends LitElement { }; fireEvent(this, "hass-api-called", eventdata); if (this.addon?.state === "started") { - await suggestAddonRestart(this, this.hass, this.addon); + await suggestAddonRestart(this, this.hass, this.supervisor, this.addon); } } catch (err) { - this._error = `Failed to save addon configuration, ${extractApiErrorMessage( - err - )}`; + this._error = this.supervisor.localize( + "addon.configuration.options.failed_to_save", + "error", + extractApiErrorMessage(err) + ); } button.progress = false; } diff --git a/hassio/src/addon-view/config/hassio-addon-network.ts b/hassio/src/addon-view/config/hassio-addon-network.ts index 99f871be99..57eeacd187 100644 --- a/hassio/src/addon-view/config/hassio-addon-network.ts +++ b/hassio/src/addon-view/config/hassio-addon-network.ts @@ -19,6 +19,7 @@ import { setHassioAddonOption, } from "../../../../src/data/hassio/addon"; import { extractApiErrorMessage } from "../../../../src/data/hassio/common"; +import { Supervisor } from "../../../../src/data/supervisor/supervisor"; import { haStyle } from "../../../../src/resources/styles"; import { HomeAssistant } from "../../../../src/types"; import { suggestAddonRestart } from "../../dialogs/suggestAddonRestart"; @@ -38,6 +39,8 @@ interface NetworkItemInput extends PaperInputElement { class HassioAddonNetwork extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; + @property({ attribute: false }) public supervisor!: Supervisor; + @property({ attribute: false }) public addon!: HassioAddonDetails; @internalProperty() private _error?: string; @@ -55,16 +58,30 @@ class HassioAddonNetwork extends LitElement { } return html` - +
${this._error ? html`
${this._error}
` : ""} - - - + + + ${this._config!.map((item) => { return html` @@ -73,13 +90,15 @@ class HassioAddonNetwork extends LitElement { - + `; })} @@ -88,10 +107,10 @@ class HassioAddonNetwork extends LitElement {
- Reset to defaults + ${this.supervisor.localize("common.reset_defaults")} - Save + ${this.supervisor.localize("common.save")}
@@ -105,6 +124,15 @@ class HassioAddonNetwork extends LitElement { } } + private _computeDescription = (item: NetworkItem): string => { + return ( + this.addon.translations[this.hass.language]?.network?.[item.container] + ?.description || + this.addon.translations.en?.network?.[item.container]?.description || + item.description + ); + }; + private _setNetworkConfig(): void { const network = this.addon.network || {}; const description = this.addon.network_description || {}; @@ -147,12 +175,14 @@ class HassioAddonNetwork extends LitElement { }; fireEvent(this, "hass-api-called", eventdata); if (this.addon?.state === "started") { - await suggestAddonRestart(this, this.hass, this.addon); + await suggestAddonRestart(this, this.hass, this.supervisor, this.addon); } } catch (err) { - this._error = `Failed to set addon network configuration, ${extractApiErrorMessage( - err - )}`; + this._error = this.supervisor.localize( + "addon.failed_to_reset", + "error", + extractApiErrorMessage(err) + ); } button.progress = false; @@ -181,12 +211,14 @@ class HassioAddonNetwork extends LitElement { }; fireEvent(this, "hass-api-called", eventdata); if (this.addon?.state === "started") { - await suggestAddonRestart(this, this.hass, this.addon); + await suggestAddonRestart(this, this.hass, this.supervisor, this.addon); } } catch (err) { - this._error = `Failed to set addon network configuration, ${extractApiErrorMessage( - err - )}`; + this._error = this.supervisor.localize( + "addon.failed_to_save", + "error", + extractApiErrorMessage(err) + ); } button.progress = false; } diff --git a/hassio/src/addon-view/documentation/hassio-addon-documentation-tab.ts b/hassio/src/addon-view/documentation/hassio-addon-documentation-tab.ts index 3d604e03bb..0cb15c1842 100644 --- a/hassio/src/addon-view/documentation/hassio-addon-documentation-tab.ts +++ b/hassio/src/addon-view/documentation/hassio-addon-documentation-tab.ts @@ -1,3 +1,4 @@ +import "../../../../src/components/ha-card"; import { css, CSSResult, @@ -19,11 +20,14 @@ import "../../../../src/layouts/hass-loading-screen"; import { haStyle } from "../../../../src/resources/styles"; import { HomeAssistant } from "../../../../src/types"; import { hassioStyle } from "../../resources/hassio-style"; +import { Supervisor } from "../../../../src/data/supervisor/supervisor"; @customElement("hassio-addon-documentation-tab") class HassioAddonDocumentationDashboard extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; + @property({ attribute: false }) public supervisor!: Supervisor; + @property({ attribute: false }) public addon?: HassioAddonDetails; @internalProperty() private _error?: string; @@ -81,9 +85,11 @@ class HassioAddonDocumentationDashboard extends LitElement { this.addon!.slug ); } catch (err) { - this._error = `Failed to get addon documentation, ${extractApiErrorMessage( - err - )}`; + this._error = this.supervisor.localize( + "addon.documentation.get_logs", + "error", + extractApiErrorMessage(err) + ); } } } diff --git a/hassio/src/addon-view/hassio-addon-dashboard.ts b/hassio/src/addon-view/hassio-addon-dashboard.ts index 291a5de2c0..c1c4942816 100644 --- a/hassio/src/addon-view/hassio-addon-dashboard.ts +++ b/hassio/src/addon-view/hassio-addon-dashboard.ts @@ -79,7 +79,6 @@ class HassioAddonDashboard extends LitElement { const addonTabs: PageNavigation[] = [ { - name: "Info", translationKey: "addon.panel.info", path: `/hassio/addon/${this.addon.slug}/info`, iconPath: mdiInformationVariant, @@ -88,7 +87,6 @@ class HassioAddonDashboard extends LitElement { if (this.addon.documentation) { addonTabs.push({ - name: "Documentation", translationKey: "addon.panel.documentation", path: `/hassio/addon/${this.addon.slug}/documentation`, iconPath: mdiFileDocument, @@ -98,13 +96,11 @@ class HassioAddonDashboard extends LitElement { if (this.addon.version) { addonTabs.push( { - name: "Configuration", translationKey: "addon.panel.configuration", path: `/hassio/addon/${this.addon.slug}/config`, iconPath: mdiCogs, }, { - name: "Log", translationKey: "addon.panel.log", path: `/hassio/addon/${this.addon.slug}/logs`, iconPath: mdiMathLog, diff --git a/hassio/src/addon-view/info/hassio-addon-info.ts b/hassio/src/addon-view/info/hassio-addon-info.ts index cfdd2fb439..88d4e92a19 100644 --- a/hassio/src/addon-view/info/hassio-addon-info.ts +++ b/hassio/src/addon-view/info/hassio-addon-info.ts @@ -79,63 +79,6 @@ const STAGE_ICON = { deprecated: mdiExclamationThick, }; -const PERMIS_DESC = { - stage: { - title: "Add-on Stage", - description: `Add-ons can have one of three stages:\n\n **Stable**: These are add-ons ready to be used in production.\n\n **Experimental**: These may contain bugs, and may be unfinished.\n\n **Deprecated**: These add-ons will no longer receive any updates.`, - }, - rating: { - title: "Add-on Security Rating", - description: - "Home Assistant provides a security rating to each of the add-ons, which indicates the risks involved when using this add-on. The more access an add-on requires on your system, the lower the score, thus raising the possible security risks.\n\nA score is on a scale from 1 to 6. Where 1 is the lowest score (considered the most insecure and highest risk) and a score of 6 is the highest score (considered the most secure and lowest risk).", - }, - host_network: { - title: "Host Network", - description: - "Add-ons usually run in their own isolated network layer, which prevents them from accessing the network of the host operating system. In some cases, this network isolation can limit add-ons in providing their services and therefore, the isolation can be lifted by the add-on author, giving the add-on full access to the network capabilities of the host machine. This gives the add-on more networking capabilities but lowers the security, hence, the security rating of the add-on will be lowered when this option is used by the add-on.", - }, - homeassistant_api: { - title: "Home Assistant API Access", - description: - "This add-on is allowed to access your running Home Assistant instance directly via the Home Assistant API. This mode handles authentication for the add-on as well, which enables an add-on to interact with Home Assistant without the need for additional authentication tokens.", - }, - full_access: { - title: "Full Hardware Access", - description: - "This add-on is given full access to the hardware of your system, by request of the add-on author. Access is comparable to the privileged mode in Docker. Since this opens up possible security risks, this feature impacts the add-on security score negatively.\n\nThis level of access is not granted automatically and needs to be confirmed by you. To do this, you need to disable the protection mode on the add-on manually. Only disable the protection mode if you know, need AND trust the source of this add-on.", - }, - hassio_api: { - title: "Supervisor API Access", - description: - "The add-on was given access to the Supervisor API, by request of the add-on author. By default, the add-on can access general version information of your system. When the add-on requests 'manager' or 'admin' level access to the API, it will gain access to control multiple parts of your Home Assistant system. This permission is indicated by this badge and will impact the security score of the addon negatively.", - }, - docker_api: { - title: "Full Docker Access", - description: - "The add-on author has requested the add-on to have management access to the Docker instance running on your system. This mode gives the add-on full access and control to your entire Home Assistant system, which adds security risks, and could damage your system when misused. Therefore, this feature impacts the add-on security score negatively.\n\nThis level of access is not granted automatically and needs to be confirmed by you. To do this, you need to disable the protection mode on the add-on manually. Only disable the protection mode if you know, need AND trust the source of this add-on.", - }, - host_pid: { - title: "Host Processes Namespace", - description: - "Usually, the processes the add-on runs, are isolated from all other system processes. The add-on author has requested the add-on to have access to the system processes running on the host system instance, and allow the add-on to spawn processes on the host system as well. This mode gives the add-on full access and control to your entire Home Assistant system, which adds security risks, and could damage your system when misused. Therefore, this feature impacts the add-on security score negatively.\n\nThis level of access is not granted automatically and needs to be confirmed by you. To do this, you need to disable the protection mode on the add-on manually. Only disable the protection mode if you know, need AND trust the source of this add-on.", - }, - apparmor: { - title: "AppArmor", - description: - "AppArmor ('Application Armor') is a Linux kernel security module that restricts add-ons capabilities like network access, raw socket access, and permission to read, write, or execute specific files.\n\nAdd-on authors can provide their security profiles, optimized for the add-on, or request it to be disabled. If AppArmor is disabled, it will raise security risks and therefore, has a negative impact on the security score of the add-on.", - }, - auth_api: { - title: "Home Assistant Authentication", - description: - "An add-on can authenticate users against Home Assistant, allowing add-ons to give users the possibility to log into applications running inside add-ons, using their Home Assistant username/password. This badge indicates if the add-on author requests this capability.", - }, - ingress: { - title: "Ingress", - description: - "This add-on is using Ingress to embed its interface securely into Home Assistant.", - }, -}; - @customElement("hassio-addon-info") class HassioAddonInfo extends LitElement { @property({ type: Boolean }) public narrow!: boolean; @@ -162,11 +105,11 @@ class HassioAddonInfo extends LitElement { : undefined; const metrics = [ { - description: "Add-on CPU Usage", + description: this.supervisor.localize("addon.dashboard.cpu_usage"), value: this._metrics?.cpu_percent, }, { - description: "Add-on RAM Usage", + description: this.supervisor.localize("addon.dashboard.ram_usage"), value: this._metrics?.memory_percent, tooltip: `${bytesToString(this._metrics?.memory_usage)}/${bytesToString( this._metrics?.memory_limit @@ -176,14 +119,28 @@ class HassioAddonInfo extends LitElement { return html` ${this.addon.update_available ? html` - +
@@ -194,29 +151,32 @@ class HassioAddonInfo extends LitElement { ) ? html`

- This add-on is not compatible with the processor of - your device or the operating system you have installed - on your device. + ${this.supervisor.localize( + "addon.dashboard.not_available_arch" + )}

` : html`

- You are running Home Assistant - ${this.supervisor.core.version}, to update to this - version of the add-on you need at least version - ${addonStoreInfo.homeassistant} of Home Assistant + ${this.supervisor.localize( + "addon.dashboard.not_available_arch", + "core_version_installed", + this.supervisor.core.version, + "core_version_needed", + addonStoreInfo.homeassistant + )}

` : ""}
- Update + ${this.supervisor.localize("common.update")} ${this.addon.changelog ? html` - Changelog + ${this.supervisor.localize("addon.dashboard.changelog")} ` : ""} @@ -227,12 +187,19 @@ class HassioAddonInfo extends LitElement { ${!this.addon.protected ? html` -

Warning: Protection mode is disabled!

+

${this.supervisor.localize( + "addon.dashboard.protection_mode.title" + )} +

- Protection mode on this add-on is disabled! This gives the add-on full access to the entire system, which adds security risks, and could damage your system when used incorrectly. Only disable the protection mode if you know, need AND trust the source of this add-on. + ${this.supervisor.localize("addon.dashboard.protection_mode.content")}
- Enable Protection mode + + ${this.supervisor.localize( + "addon.dashboard.protection_mode.enable" + )} +
@@ -249,14 +216,18 @@ class HassioAddonInfo extends LitElement { ${this._computeIsRunning ? html` ` : html` @@ -270,21 +241,29 @@ class HassioAddonInfo extends LitElement { ? html` Current version: ${this.addon.version}
- (changelog) + ( + ${this.supervisor.localize("addon.dashboard.changelog")} )
` - : html`Changelog`} + : html` + ${this.supervisor.localize("addon.dashboard.changelog")} + `}
${this.addon.description}.
- Visit - - ${this.addon.name} page - for details. + ${this.supervisor.localize( + "addon.dashboard.visit_addon_page", + "name", + html` + ${this.addon.name} + ` + )}
@@ -305,7 +284,9 @@ class HassioAddonInfo extends LitElement { })} @click=${this._showMoreInfo} id="stage" - label="stage" + .label=${this.supervisor.localize( + "addon.dashboard.capability.label.stage" + )} description="" > @@ -343,7 +326,9 @@ class HassioAddonInfo extends LitElement { @@ -355,7 +340,9 @@ class HassioAddonInfo extends LitElement { @@ -367,8 +354,12 @@ class HassioAddonInfo extends LitElement { @@ -379,7 +370,9 @@ class HassioAddonInfo extends LitElement { @@ -391,7 +384,9 @@ class HassioAddonInfo extends LitElement { @@ -404,7 +399,9 @@ class HassioAddonInfo extends LitElement { @click=${this._showMoreInfo} class=${this._computeApparmorClassName} id="apparmor" - label="apparmor" + .label=${this.supervisor.localize( + "addon.dashboard.capability.label.apparmor" + )} description="" > @@ -416,7 +413,9 @@ class HassioAddonInfo extends LitElement { @@ -428,7 +427,9 @@ class HassioAddonInfo extends LitElement { - Start on boot + ${this.supervisor.localize( + "addon.dashboard.option.boot.title" + )} - Make the add-on start during a system boot + ${this.supervisor.localize( + "addon.dashboard.option.boot.description" + )} - Watchdog + ${this.supervisor.localize( + "addon.dashboard.option.watchdog.title" + )} - This will start the add-on if it crashes + ${this.supervisor.localize( + "addon.dashboard.option.boot.description" + )} - Auto update + ${this.supervisor.localize( + "addon.dashboard.option.auto_update.title" + )} - Auto update the add-on when there is a new - version available + ${this.supervisor.localize( + "addon.dashboard.option.boot.description" + )} ` : ""} - ${this.addon.ingress + ${!this._computeCannotIngressSidebar && this.addon.ingress ? html` - Show in sidebar + ${this.supervisor.localize( + "addon.dashboard.option.ingress_panel.title" + )} - ${this._computeCannotIngressSidebar - ? "This option requires Home Assistant 0.92 or later." - : "Add this add-on to your sidebar"} + ${this.supervisor.localize( + "addon.dashboard.option.ingress_panel.description" + )} @@ -521,10 +534,14 @@ class HassioAddonInfo extends LitElement { ? html` - Protection mode + ${this.supervisor.localize( + "addon.dashboard.option.protected.title" + )} - Blocks elevated system access from the add-on + ${this.supervisor.localize( + "addon.dashboard.option.protected.description" + )} - Hostname + ${this.supervisor.localize("addon.dashboard.hostname")} ${this.addon.hostname} @@ -569,17 +586,20 @@ class HassioAddonInfo extends LitElement { ) ? html`

- This add-on is not compatible with the processor of your - device or the operating system you have installed on your - device. + ${this.supervisor.localize( + "addon.dashboard.not_available_arch" + )}

` : html`

- You are running Home Assistant - ${this.supervisor.core.version}, to install this add-on you - need at least version ${addonStoreInfo!.homeassistant} of - Home Assistant + ${this.supervisor.localize( + "addon.dashboard.not_available_version", + "core_version_installed", + this.supervisor.core.version, + "core_version_needed", + addonStoreInfo!.homeassistant + )}

` : ""} @@ -593,18 +613,18 @@ class HassioAddonInfo extends LitElement { class="warning" @click=${this._stopClicked} > - Stop + ${this.supervisor.localize("addon.dashboard.stop")} - Restart + ${this.supervisor.localize("addon.dashboard.restart")} ` : html` - Start + ${this.supervisor.localize("addon.dashboard.start")} ` : html` @@ -612,7 +632,7 @@ class HassioAddonInfo extends LitElement { .disabled=${!this.addon.available} @click=${this._installClicked} > - Install + ${this.supervisor.localize("addon.dashboard.install")} `}
@@ -627,7 +647,9 @@ class HassioAddonInfo extends LitElement { rel="noopener" > - Open web UI + ${this.supervisor.localize( + "addon.dashboard.open_web_ui" + )} ` @@ -635,7 +657,9 @@ class HassioAddonInfo extends LitElement { ${this._computeShowIngressUI ? html` - Open web UI + ${this.supervisor.localize( + "addon.dashboard.open_web_ui" + )} ` : ""} @@ -643,7 +667,7 @@ class HassioAddonInfo extends LitElement { class="warning" @click=${this._uninstallClicked} > - Uninstall + ${this.supervisor.localize("addon.dashboard.uninstall")} ${this.addon.build ? html` @@ -652,7 +676,7 @@ class HassioAddonInfo extends LitElement { .hass=${this.hass} .path="hassio/addons/${this.addon.slug}/rebuild" > - Rebuild + ${this.supervisor.localize("addon.dashboard.rebuild")} ` : ""}` @@ -712,8 +736,21 @@ class HassioAddonInfo extends LitElement { private _showMoreInfo(ev): void { const id = ev.currentTarget.id; showHassioMarkdownDialog(this, { - title: PERMIS_DESC[id].title, - content: PERMIS_DESC[id].description, + title: this.supervisor.localize(`addon.dashboard.capability.${id}.title`), + content: + id === "stage" + ? this.supervisor.localize( + `addon.dashboard.capability.${id}.description`, + "icon_stable", + ``, + "icon_experimental", + ``, + "icon_deprecated", + `` + ) + : this.supervisor.localize( + `addon.dashboard.capability.${id}.description` + ), }); } @@ -766,9 +803,11 @@ class HassioAddonInfo extends LitElement { }; fireEvent(this, "hass-api-called", eventdata); } catch (err) { - this._error = `Failed to set addon option, ${extractApiErrorMessage( - err - )}`; + this._error = this.supervisor.localize( + "addon.failed_to_save", + "error", + extractApiErrorMessage(err) + ); } } @@ -786,9 +825,11 @@ class HassioAddonInfo extends LitElement { }; fireEvent(this, "hass-api-called", eventdata); } catch (err) { - this._error = `Failed to set addon option, ${extractApiErrorMessage( - err - )}`; + this._error = this.supervisor.localize( + "addon.failed_to_save", + "error", + extractApiErrorMessage(err) + ); } } @@ -806,9 +847,11 @@ class HassioAddonInfo extends LitElement { }; fireEvent(this, "hass-api-called", eventdata); } catch (err) { - this._error = `Failed to set addon option, ${extractApiErrorMessage( - err - )}`; + this._error = this.supervisor.localize( + "addon.failed_to_save", + "error", + extractApiErrorMessage(err) + ); } } @@ -826,9 +869,11 @@ class HassioAddonInfo extends LitElement { }; fireEvent(this, "hass-api-called", eventdata); } catch (err) { - this._error = `Failed to set addon security option, ${extractApiErrorMessage( - err - )}`; + this._error = this.supervisor.localize( + "addon.failed_to_save", + "error", + extractApiErrorMessage(err) + ); } } @@ -846,9 +891,11 @@ class HassioAddonInfo extends LitElement { }; fireEvent(this, "hass-api-called", eventdata); } catch (err) { - this._error = `Failed to set addon option, ${extractApiErrorMessage( - err - )}`; + this._error = this.supervisor.localize( + "addon.failed_to_save", + "error", + extractApiErrorMessage(err) + ); } } @@ -859,12 +906,14 @@ class HassioAddonInfo extends LitElement { this.addon.slug ); showHassioMarkdownDialog(this, { - title: "Changelog", + title: this.supervisor.localize("addon.dashboard.changelog"), content, }); } catch (err) { showAlertDialog(this, { - title: "Failed to get addon changelog", + title: this.supervisor.localize( + "addon.dashboard.action_error.get_changelog" + ), text: extractApiErrorMessage(err), }); } @@ -884,7 +933,7 @@ class HassioAddonInfo extends LitElement { fireEvent(this, "hass-api-called", eventdata); } catch (err) { showAlertDialog(this, { - title: "Failed to install addon", + title: this.supervisor.localize("addon.dashboard.action_error.install"), text: extractApiErrorMessage(err), }); } @@ -905,7 +954,7 @@ class HassioAddonInfo extends LitElement { fireEvent(this, "hass-api-called", eventdata); } catch (err) { showAlertDialog(this, { - title: "Failed to stop addon", + title: this.supervisor.localize("addon.dashboard.action_error.stop"), text: extractApiErrorMessage(err), }); } @@ -926,7 +975,7 @@ class HassioAddonInfo extends LitElement { fireEvent(this, "hass-api-called", eventdata); } catch (err) { showAlertDialog(this, { - title: "Failed to restart addon", + title: this.supervisor.localize("addon.dashboard.action_error.restart"), text: extractApiErrorMessage(err), }); } @@ -947,11 +996,15 @@ class HassioAddonInfo extends LitElement { ); if (!validate.valid) { await showConfirmationDialog(this, { - title: "Failed to start addon - configuration validation failed!", + title: this.supervisor.localize( + "addon.dashboard.action_error.start_invalid_config" + ), text: validate.message.split(" Got ")[0], confirm: () => this._openConfiguration(), - confirmText: "Go to configuration", - dismissText: "Cancel", + confirmText: this.supervisor.localize( + "addon.dashboard.action_error.go_to_config" + ), + dismissText: this.supervisor.localize("common.cancel"), }); button.progress = false; return; @@ -976,7 +1029,7 @@ class HassioAddonInfo extends LitElement { fireEvent(this, "hass-api-called", eventdata); } catch (err) { showAlertDialog(this, { - title: "Failed to start addon", + title: this.supervisor.localize("addon.dashboard.action_error.start"), text: extractApiErrorMessage(err), }); } @@ -1014,7 +1067,9 @@ class HassioAddonInfo extends LitElement { fireEvent(this, "hass-api-called", eventdata); } catch (err) { showAlertDialog(this, { - title: "Failed to uninstall addon", + title: this.supervisor.localize( + "addon.dashboard.action_error.uninstall" + ), text: extractApiErrorMessage(err), }); } diff --git a/hassio/src/addon-view/log/hassio-addon-log-tab.ts b/hassio/src/addon-view/log/hassio-addon-log-tab.ts index 54bace246b..7b93e38a5b 100644 --- a/hassio/src/addon-view/log/hassio-addon-log-tab.ts +++ b/hassio/src/addon-view/log/hassio-addon-log-tab.ts @@ -9,6 +9,7 @@ import { } from "lit-element"; import "../../../../src/components/ha-circular-progress"; import { HassioAddonDetails } from "../../../../src/data/hassio/addon"; +import { Supervisor } from "../../../../src/data/supervisor/supervisor"; import { haStyle } from "../../../../src/resources/styles"; import { HomeAssistant } from "../../../../src/types"; import { hassioStyle } from "../../resources/hassio-style"; @@ -18,6 +19,8 @@ import "./hassio-addon-logs"; class HassioAddonLogDashboard extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; + @property({ attribute: false }) public supervisor!: Supervisor; + @property({ attribute: false }) public addon?: HassioAddonDetails; protected render(): TemplateResult { @@ -28,6 +31,7 @@ class HassioAddonLogDashboard extends LitElement {
diff --git a/hassio/src/addon-view/log/hassio-addon-logs.ts b/hassio/src/addon-view/log/hassio-addon-logs.ts index 314dc29c09..c380c0b92e 100644 --- a/hassio/src/addon-view/log/hassio-addon-logs.ts +++ b/hassio/src/addon-view/log/hassio-addon-logs.ts @@ -15,6 +15,7 @@ import { HassioAddonDetails, } from "../../../../src/data/hassio/addon"; import { extractApiErrorMessage } from "../../../../src/data/hassio/common"; +import { Supervisor } from "../../../../src/data/supervisor/supervisor"; import { haStyle } from "../../../../src/resources/styles"; import { HomeAssistant } from "../../../../src/types"; import "../../components/hassio-ansi-to-html"; @@ -24,6 +25,8 @@ import { hassioStyle } from "../../resources/hassio-style"; class HassioAddonLogs extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; + @property({ attribute: false }) public supervisor!: Supervisor; + @property({ attribute: false }) public addon!: HassioAddonDetails; @internalProperty() private _error?: string; @@ -48,7 +51,9 @@ class HassioAddonLogs extends LitElement { : ""}
- Refresh + + ${this.supervisor.localize("common.refresh")} +
`; @@ -76,7 +81,11 @@ class HassioAddonLogs extends LitElement { try { this._content = await fetchHassioAddonLogs(this.hass, this.addon.slug); } catch (err) { - this._error = `Failed to get addon logs, ${extractApiErrorMessage(err)}`; + this._error = this.supervisor.localize( + "addon.logs.get_logs", + "error", + extractApiErrorMessage(err) + ); } } diff --git a/hassio/src/components/hassio-card-content.ts b/hassio/src/components/hassio-card-content.ts index 1123aa9f5a..02d3fc7e1b 100644 --- a/hassio/src/components/hassio-card-content.ts +++ b/hassio/src/components/hassio-card-content.ts @@ -44,7 +44,7 @@ class HassioCardContent extends LitElement { ${this.iconImage ? html`
- +
` diff --git a/hassio/src/components/supervisor-metric.ts b/hassio/src/components/supervisor-metric.ts index b0af0fd9a2..116b137e0f 100644 --- a/hassio/src/components/supervisor-metric.ts +++ b/hassio/src/components/supervisor-metric.ts @@ -26,7 +26,7 @@ class SupervisorMetric extends LitElement { ${this.description} -
+
${roundedValue}% diff --git a/hassio/src/dashboard/hassio-update.ts b/hassio/src/dashboard/hassio-update.ts index c991a2bf12..e0c3a2f155 100644 --- a/hassio/src/dashboard/hassio-update.ts +++ b/hassio/src/dashboard/hassio-update.ts @@ -69,7 +69,7 @@ export class HassioUpdate extends LitElement {

${this.supervisor.localize( - "dashboard.update_available", + "common.update_available", "count", updatesAvailable )} @@ -211,7 +211,7 @@ export class HassioUpdate extends LitElement { !ignoredStatusCodes.has(err.status_code) ) { showAlertDialog(this, { - title: this.supervisor.localize("error.update_failed"), + title: this.supervisor.localize("common.error.update_failed"), text: extractApiErrorMessage(err), }); } diff --git a/hassio/src/dialogs/network/dialog-hassio-network.ts b/hassio/src/dialogs/network/dialog-hassio-network.ts index 6a8deb6088..64aadb1597 100644 --- a/hassio/src/dialogs/network/dialog-hassio-network.ts +++ b/hassio/src/dialogs/network/dialog-hassio-network.ts @@ -35,6 +35,7 @@ import { updateNetworkInterface, WifiConfiguration, } from "../../../../src/data/hassio/network"; +import { Supervisor } from "../../../../src/data/supervisor/supervisor"; import { showAlertDialog, showConfirmationDialog, @@ -51,6 +52,8 @@ export class DialogHassioNetwork extends LitElement implements HassDialog { @property({ attribute: false }) public hass!: HomeAssistant; + @property({ attribute: false }) public supervisor!: Supervisor; + @internalProperty() private _accessPoints?: AccessPoints; @internalProperty() private _curTabIndex = 0; @@ -73,7 +76,8 @@ export class DialogHassioNetwork extends LitElement this._params = params; this._dirty = false; this._curTabIndex = 0; - this._interfaces = params.network.interfaces.sort((a, b) => { + this.supervisor = params.supervisor; + this._interfaces = params.supervisor.network.interfaces.sort((a, b) => { return a.primary > b.primary ? -1 : 1; }); this._interface = { ...this._interfaces[this._curTabIndex] }; @@ -104,7 +108,7 @@ export class DialogHassioNetwork extends LitElement
- Network settings + ${this.supervisor.localize("dialog.network.title")} @@ -139,7 +143,13 @@ export class DialogHassioNetwork extends LitElement ? html` ${this._interface?.wifi?.ssid - ? html`

Connected to: ${this._interface?.wifi?.ssid}

` + ? html`

+ ${this.supervisor.localize( + "dialog.network.connected_to", + "ssid", + this._interface?.wifi?.ssid + )} +

` : ""} ` - : "Scan for accesspoints"} + : this.supervisor.localize("dialog.network.scan_ap")} ${this._accessPoints && this._accessPoints.accesspoints && @@ -181,7 +191,11 @@ export class DialogHassioNetwork extends LitElement ${this._wifiConfiguration ? html`
- + - + - + - If you are changing the Wi-Fi, IP or gateway addresses, you might - lose the connection! + ${this.supervisor.localize("dialog.network.warning")}
` : ""}
- + + ${this._processing ? html` ` - : "Save"} + : this.supervisor.localize("common.save")}
`; } @@ -285,7 +310,9 @@ export class DialogHassioNetwork extends LitElement outlined >
- + - + - + { if (this._dirty) { const confirm = await showConfirmationDialog(this, { - text: - "You have unsaved changes, these will get lost if you change tabs, do you want to continue?", - confirmText: "yes", - dismissText: "no", + text: this.supervisor.localize("dialog.network.unsaved"), + confirmText: this.supervisor.localize("common.yes"), + dismissText: this.supervisor.localize("common.no"), }); if (!confirm) { this.requestUpdate("_interface"); diff --git a/hassio/src/dialogs/network/show-dialog-network.ts b/hassio/src/dialogs/network/show-dialog-network.ts index 632f42c624..edf21edff5 100644 --- a/hassio/src/dialogs/network/show-dialog-network.ts +++ b/hassio/src/dialogs/network/show-dialog-network.ts @@ -1,9 +1,9 @@ import { fireEvent } from "../../../../src/common/dom/fire_event"; -import { NetworkInfo } from "../../../../src/data/hassio/network"; +import { Supervisor } from "../../../../src/data/supervisor/supervisor"; import "./dialog-hassio-network"; export interface HassioNetworkDialogParams { - network: NetworkInfo; + supervisor: Supervisor; loadData: () => Promise; } diff --git a/hassio/src/dialogs/registries/dialog-hassio-registries.ts b/hassio/src/dialogs/registries/dialog-hassio-registries.ts index fef6e3e0a8..292fab3f43 100644 --- a/hassio/src/dialogs/registries/dialog-hassio-registries.ts +++ b/hassio/src/dialogs/registries/dialog-hassio-registries.ts @@ -22,14 +22,18 @@ import { fetchHassioDockerRegistries, removeHassioDockerRegistry, } from "../../../../src/data/hassio/docker"; +import { Supervisor } from "../../../../src/data/supervisor/supervisor"; import { showAlertDialog } from "../../../../src/dialogs/generic/show-dialog-box"; import { haStyle, haStyleDialog } from "../../../../src/resources/styles"; import type { HomeAssistant } from "../../../../src/types"; +import { RegistriesDialogParams } from "./show-dialog-registries"; @customElement("dialog-hassio-registries") class HassioRegistriesDialog extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; + @property({ attribute: false }) public supervisor!: Supervisor; + @property({ attribute: false }) private _registries?: { registry: string; username: string; @@ -55,8 +59,8 @@ class HassioRegistriesDialog extends LitElement { .heading=${createCloseHeading( this.hass, this._addingRegistry - ? "Add New Docker Registry" - : "Manage Docker Registries" + ? this.supervisor.localize("dialog.registries.title_add") + : this.supervisor.localize("dialog.registries.title_manage") )} >
@@ -66,7 +70,9 @@ class HassioRegistriesDialog extends LitElement { @value-changed=${this._inputChanged} class="flex-auto" name="registry" - label="Registry" + .label=${this.supervisor.localize( + "dialog.registries.registry" + )} required auto-validate > @@ -74,7 +80,9 @@ class HassioRegistriesDialog extends LitElement { @value-changed=${this._inputChanged} class="flex-auto" name="username" - label="Username" + .label=${this.supervisor.localize( + "dialog.registries.username" + )} required auto-validate > @@ -82,7 +90,9 @@ class HassioRegistriesDialog extends LitElement { @value-changed=${this._inputChanged} class="flex-auto" name="password" - label="Password" + .label=${this.supervisor.localize( + "dialog.registries.password" + )} type="password" required auto-validate @@ -94,7 +104,7 @@ class HassioRegistriesDialog extends LitElement { )} @click=${this._addNewRegistry} > - Add registry + ${this.supervisor.localize("dialog.registries.add_registry")} ` : html`${this._registries?.length @@ -103,11 +113,16 @@ class HassioRegistriesDialog extends LitElement { ${entry.registry} Username: ${entry.username}${this.supervisor.localize( + "dialog.registries.username" + )}: + ${entry.username} @@ -118,11 +133,17 @@ class HassioRegistriesDialog extends LitElement { }) : html` - No registries configured + ${this.supervisor.localize( + "dialog.registries.no_registries" + )} `} - Add new registry + ${this.supervisor.localize( + "dialog.registries.add_new_registry" + )} `}
@@ -134,8 +155,9 @@ class HassioRegistriesDialog extends LitElement { this[`_${target.name}`] = target.value; } - public async showDialog(_dialogParams: any): Promise { + public async showDialog(dialogParams: RegistriesDialogParams): Promise { this._opened = true; + this.supervisor = dialogParams.supervisor; await this._loadRegistries(); await this.updateComplete; } @@ -178,7 +200,7 @@ class HassioRegistriesDialog extends LitElement { this._addingRegistry = false; } catch (err) { showAlertDialog(this, { - title: "Failed to add registry", + title: this.supervisor.localize("dialog.registries.failed_to_add"), text: extractApiErrorMessage(err), }); } @@ -192,7 +214,7 @@ class HassioRegistriesDialog extends LitElement { await this._loadRegistries(); } catch (err) { showAlertDialog(this, { - title: "Failed to remove registry", + title: this.supervisor.localize("dialog.registries.failed_to_remove"), text: extractApiErrorMessage(err), }); } diff --git a/hassio/src/dialogs/registries/show-dialog-registries.ts b/hassio/src/dialogs/registries/show-dialog-registries.ts index 15cf88c075..fd62edc7a7 100644 --- a/hassio/src/dialogs/registries/show-dialog-registries.ts +++ b/hassio/src/dialogs/registries/show-dialog-registries.ts @@ -1,10 +1,18 @@ import { fireEvent } from "../../../../src/common/dom/fire_event"; +import { Supervisor } from "../../../../src/data/supervisor/supervisor"; import "./dialog-hassio-registries"; -export const showRegistriesDialog = (element: HTMLElement): void => { +export interface RegistriesDialogParams { + supervisor: Supervisor; +} + +export const showRegistriesDialog = ( + element: HTMLElement, + dialogParams: RegistriesDialogParams +): void => { fireEvent(element, "show-dialog", { dialogTag: "dialog-hassio-registries", dialogImport: () => import("./dialog-hassio-registries"), - dialogParams: {}, + dialogParams, }); }; diff --git a/hassio/src/dialogs/repositories/dialog-hassio-repositories.ts b/hassio/src/dialogs/repositories/dialog-hassio-repositories.ts index 2d8d028cdf..35ea16957a 100644 --- a/hassio/src/dialogs/repositories/dialog-hassio-repositories.ts +++ b/hassio/src/dialogs/repositories/dialog-hassio-repositories.ts @@ -18,7 +18,7 @@ import { } from "lit-element"; import memoizeOne from "memoize-one"; import "../../../../src/components/ha-circular-progress"; -import "../../../../src/components/ha-dialog"; +import { createCloseHeading } from "../../../../src/components/ha-dialog"; import "../../../../src/components/ha-svg-icon"; import { fetchHassioAddonsInfo, @@ -26,6 +26,7 @@ import { } from "../../../../src/data/hassio/addon"; import { extractApiErrorMessage } from "../../../../src/data/hassio/common"; import { setSupervisorOption } from "../../../../src/data/hassio/supervisor"; +import { Supervisor } from "../../../../src/data/supervisor/supervisor"; import { haStyle, haStyleDialog } from "../../../../src/resources/styles"; import type { HomeAssistant } from "../../../../src/types"; import { HassioRepositoryDialogParams } from "./show-dialog-repositories"; @@ -34,6 +35,8 @@ import { HassioRepositoryDialogParams } from "./show-dialog-repositories"; class HassioRepositoriesDialog extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; + @property({ attribute: false }) public supervisor!: Supervisor; + @property({ attribute: false }) private _repos: HassioAddonRepository[] = []; @property({ attribute: false }) @@ -47,9 +50,11 @@ class HassioRepositoriesDialog extends LitElement { @internalProperty() private _error?: string; - public async showDialog(_dialogParams: any): Promise { - this._dialogParams = _dialogParams; - this._repos = _dialogParams.repos; + public async showDialog( + dialogParams: HassioRepositoryDialogParams + ): Promise { + this._dialogParams = dialogParams; + this.supervisor = dialogParams.supervisor; this._opened = true; await this.updateComplete; } @@ -66,14 +71,19 @@ class HassioRepositoriesDialog extends LitElement { ); protected render(): TemplateResult { - const repositories = this._filteredRepositories(this._repos); + const repositories = this._filteredRepositories( + this.supervisor.addon.repositories + ); return html` ${this._error ? html`
${this._error}
` : ""}
@@ -88,7 +98,9 @@ class HassioRepositoriesDialog extends LitElement { @@ -105,13 +117,13 @@ class HassioRepositoriesDialog extends LitElement { ${this._prosessing ? html`` - : "Add"} + : this.supervisor.localize("dialog.repositories.add")}
diff --git a/hassio/src/dialogs/repositories/show-dialog-repositories.ts b/hassio/src/dialogs/repositories/show-dialog-repositories.ts index 893d4fd4e6..63b3611de8 100644 --- a/hassio/src/dialogs/repositories/show-dialog-repositories.ts +++ b/hassio/src/dialogs/repositories/show-dialog-repositories.ts @@ -1,9 +1,9 @@ import { fireEvent } from "../../../../src/common/dom/fire_event"; -import { HassioAddonRepository } from "../../../../src/data/hassio/addon"; +import { Supervisor } from "../../../../src/data/supervisor/supervisor"; import "./dialog-hassio-repositories"; export interface HassioRepositoryDialogParams { - repos: HassioAddonRepository[]; + supervisor: Supervisor; loadData: () => Promise; } diff --git a/hassio/src/dialogs/suggestAddonRestart.ts b/hassio/src/dialogs/suggestAddonRestart.ts index de4343b379..12b8d383d7 100644 --- a/hassio/src/dialogs/suggestAddonRestart.ts +++ b/hassio/src/dialogs/suggestAddonRestart.ts @@ -4,6 +4,7 @@ import { restartHassioAddon, } from "../../../src/data/hassio/addon"; import { extractApiErrorMessage } from "../../../src/data/hassio/common"; +import { Supervisor } from "../../../src/data/supervisor/supervisor"; import { showAlertDialog, showConfirmationDialog, @@ -13,20 +14,25 @@ import { HomeAssistant } from "../../../src/types"; export const suggestAddonRestart = async ( element: LitElement, hass: HomeAssistant, + supervisor: Supervisor, addon: HassioAddonDetails ): Promise => { const confirmed = await showConfirmationDialog(element, { - title: addon.name, - text: "Do you want to restart the add-on with your changes?", - confirmText: "restart add-on", - dismissText: "no", + title: supervisor.localize("common.restart_name", "name", addon.name), + text: supervisor.localize("dialog.restart_addon.text"), + confirmText: supervisor.localize("dialog.restart_addon.confirm_text"), + dismissText: supervisor.localize("common.cancel"), }); if (confirmed) { try { await restartHassioAddon(hass, addon.slug); } catch (err) { showAlertDialog(element, { - title: "Failed to restart", + title: supervisor.localize( + "common.failed_to_restart_name", + "name", + addon.name + ), text: extractApiErrorMessage(err), }); } diff --git a/hassio/src/hassio-my-redirect.ts b/hassio/src/hassio-my-redirect.ts index 389816b435..33992391a0 100644 --- a/hassio/src/hassio-my-redirect.ts +++ b/hassio/src/hassio-my-redirect.ts @@ -19,6 +19,7 @@ import { } from "../../src/panels/my/ha-panel-my"; import { navigate } from "../../src/common/navigate"; import { HomeAssistant, Route } from "../../src/types"; +import { Supervisor } from "../../src/data/supervisor/supervisor"; const REDIRECTS: Redirects = { supervisor_logs: { @@ -48,7 +49,9 @@ const REDIRECTS: Redirects = { class HassioMyRedirect extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public route!: Route; + @property({ attribute: false }) public supervisor!: Supervisor; + + @property({ attribute: false }) public route!: Route; @internalProperty() public _error?: TemplateResult | string; @@ -58,15 +61,17 @@ class HassioMyRedirect extends LitElement { const redirect = REDIRECTS[path]; if (!redirect) { - this._error = html`This redirect is not supported by your Home Assistant - instance. Check the - My Home Assistant FAQ - for the supported redirects and the version they where introduced.`; + ${this.supervisor.localize("my.faq_link")} + ` + ); return; } @@ -74,7 +79,7 @@ class HassioMyRedirect extends LitElement { try { url = this._createRedirectUrl(redirect); } catch (err) { - this._error = "An unknown error occured"; + this._error = this.supervisor.localize("my.error"); return; } diff --git a/hassio/src/snapshots/hassio-snapshots.ts b/hassio/src/snapshots/hassio-snapshots.ts index 82e6d1c877..8081525d5f 100644 --- a/hassio/src/snapshots/hassio-snapshots.ts +++ b/hassio/src/snapshots/hassio-snapshots.ts @@ -55,8 +55,8 @@ import { hassioStyle } from "../resources/hassio-style"; interface CheckboxItem { slug: string; - name: string; checked: boolean; + name?: string; } @customElement("hassio-snapshots") @@ -84,13 +84,12 @@ class HassioSnapshots extends LitElement { @internalProperty() private _folderList: CheckboxItem[] = [ { slug: "homeassistant", - name: "Home Assistant configuration", checked: true, }, - { slug: "ssl", name: "SSL", checked: true }, - { slug: "share", name: "Share", checked: true }, - { slug: "media", name: "Media", checked: true }, - { slug: "addons/local", name: "Local add-ons", checked: true }, + { slug: "ssl", checked: true }, + { slug: "share", checked: true }, + { slug: "media", checked: true }, + { slug: "addons/local", checked: true }, ]; @internalProperty() private _error = ""; @@ -123,50 +122,50 @@ class HassioSnapshots extends LitElement { - Reload + ${this.supervisor.localize("common.reload")} ${atLeastVersion(this.hass.config.version, 0, 116) ? html` - Upload snapshot + ${this.supervisor.localize("snapshot.upload_snapshot")} ` : ""}

- Create Snapshot + ${this.supervisor.localize("snapshot.create_snapshot")}

- Snapshots allow you to easily backup and restore all data of your - Home Assistant instance. + ${this.supervisor.localize("snapshot.description")}

- Type: + ${this.supervisor.localize("snapshot.type")}: - Full snapshot + ${this.supervisor.localize("snapshot.full_snapshot")} - Partial snapshot + ${this.supervisor.localize("snapshot.partial_snapshot")} ${this._snapshotType === "full" ? undefined : html` - Folders: + ${this.supervisor.localize("snapshot.folders")}: ${this._folderList.map( (folder, idx) => html` - ${folder.name} + ${this.supervisor.localize( + `snapshot.folder.${folder.slug}` + )} ` )} - Add-ons: + ${this.supervisor.localize("snapshot.addons")}: ${this._addonList.map( (addon, idx) => html` - Password protection + ${this.supervisor.localize("snapshot.password_protection")} ${this._snapshotHasPassword ? html` - Create + ${this.supervisor.localize("snapshot.create")}
-

Available Snapshots

+

${this.supervisor.localize("snapshot.available_snapshots")}

${this._snapshots === undefined ? undefined @@ -236,7 +241,7 @@ class HassioSnapshots extends LitElement { ? html`
- You don't have any snapshots yet. + ${this.supervisor.localize("snapshot.no_snapshots")}
` @@ -337,8 +342,12 @@ class HassioSnapshots extends LitElement { private async _createSnapshot(ev: CustomEvent): Promise { if (this.supervisor.info.state !== "running") { await showAlertDialog(this, { - title: "Could not create snapshot", - text: `Creating a snapshot is not possible right now because the system is in ${this.supervisor.info.state} state.`, + title: this.supervisor.localize("snapshot.could_not_create"), + text: this.supervisor.localize( + "snapshot.create_blocked_not_running", + "state", + this.supervisor.info.state + ), }); } const button = ev.currentTarget as any; @@ -346,7 +355,7 @@ class HassioSnapshots extends LitElement { this._error = ""; if (this._snapshotHasPassword && !this._snapshotPassword.length) { - this._error = "Please enter a password."; + this._error = this.supervisor.localize("snapshot.enter_password"); button.progress = false; return; } @@ -395,7 +404,9 @@ class HassioSnapshots extends LitElement { private _computeDetails(snapshot: HassioSnapshot) { const type = - snapshot.type === "full" ? "Full snapshot" : "Partial snapshot"; + snapshot.type === "full" + ? this.supervisor.localize("snapshot.full_snapshot") + : this.supervisor.localize("snapshot.partial_snapshot"); return snapshot.protected ? `${type}, password protected` : type; } diff --git a/hassio/src/system/hassio-core-info.ts b/hassio/src/system/hassio-core-info.ts index 21ab1c84b6..a50c7dc4fa 100644 --- a/hassio/src/system/hassio-core-info.ts +++ b/hassio/src/system/hassio-core-info.ts @@ -43,11 +43,11 @@ class HassioCoreInfo extends LitElement { protected render(): TemplateResult | void { const metrics = [ { - description: "Core CPU Usage", + description: this.supervisor.localize("system.core.cpu_usage"), value: this._metrics?.cpu_percent, }, { - description: "Core RAM Usage", + description: this.supervisor.localize("system.core.ram_usage"), value: this._metrics?.memory_percent, tooltip: `${bytesToString(this._metrics?.memory_usage)}/${bytesToString( this._metrics?.memory_limit @@ -61,7 +61,7 @@ class HassioCoreInfo extends LitElement {
- Version + ${this.supervisor.localize("common.version")} core-${this.supervisor.core.version} @@ -69,7 +69,7 @@ class HassioCoreInfo extends LitElement { - Newest Version + ${this.supervisor.localize("common.newest_version")} core-${this.supervisor.core.version_latest} @@ -77,10 +77,10 @@ class HassioCoreInfo extends LitElement { ${this.supervisor.core.update_available ? html` - Update + ${this.supervisor.localize("common.update")} ` : ""} @@ -104,9 +104,13 @@ class HassioCoreInfo extends LitElement { slot="primaryAction" class="warning" @click=${this._coreRestart} - title="Restart Home Assistant Core" + .title=${this.supervisor.localize( + "common.restart_name", + "name", + "Core" + )} > - Restart Core + ${this.supervisor.localize("common.restart_name", "name", "Core")}
@@ -126,10 +130,18 @@ class HassioCoreInfo extends LitElement { button.progress = true; const confirmed = await showConfirmationDialog(this, { - title: "Restart Home Assistant Core", - text: "Are you sure you want to restart Home Assistant Core", - confirmText: "restart", - dismissText: "cancel", + title: this.supervisor.localize( + "confirm.restart.title", + "name", + "Home Assistant Core" + ), + text: this.supervisor.localize( + "confirm.restart.text", + "name", + "Home Assistant Core" + ), + confirmText: this.supervisor.localize("common.restart"), + dismissText: this.supervisor.localize("common.cancel"), }); if (!confirmed) { @@ -142,7 +154,11 @@ class HassioCoreInfo extends LitElement { } catch (err) { if (this.hass.connection.connected) { showAlertDialog(this, { - title: "Failed to restart Home Assistant Core", + title: this.supervisor.localize( + "common.failed_to_restart_name", + "name", + "Home AssistantCore" + ), text: extractApiErrorMessage(err), }); } diff --git a/hassio/src/system/hassio-host-info.ts b/hassio/src/system/hassio-host-info.ts index dd4b7932ca..a6b6bf3884 100644 --- a/hassio/src/system/hassio-host-info.ts +++ b/hassio/src/system/hassio-host-info.ts @@ -65,7 +65,7 @@ class HassioHostInfo extends LitElement { const metrics = [ { - description: "Used Space", + description: this.supervisor.localize("system.host.used_space"), value: this._getUsedSpace( this.supervisor.host.disk_used, this.supervisor.host.disk_total @@ -80,14 +80,13 @@ class HassioHostInfo extends LitElement { ${this.supervisor.host.features.includes("hostname") ? html` - Hostname + ${this.supervisor.localize("system.host.hostname")} ${this.supervisor.host.hostname} @@ -96,14 +95,13 @@ class HassioHostInfo extends LitElement { ${this.supervisor.host.features.includes("network") ? html` - IP Address + ${this.supervisor.localize("system.host.ip_address")} ${primaryIpAddress} @@ -112,18 +110,15 @@ class HassioHostInfo extends LitElement { - Operating System + ${this.supervisor.localize("system.host.operating_system")} ${this.supervisor.host.operating_system} ${this.supervisor.os.update_available ? html` - - Update + + ${this.supervisor.localize("commmon.update")} ` : ""} @@ -131,7 +126,7 @@ class HassioHostInfo extends LitElement { ${!this.supervisor.host.features.includes("hassos") ? html` - Docker version + ${this.supervisor.localize("system.host.docker_version")} ${this.supervisor.info.docker} @@ -141,7 +136,7 @@ class HassioHostInfo extends LitElement { ${this.supervisor.host.deployment ? html` - Deployment + ${this.supervisor.localize("system.host.deployment")} ${this.supervisor.host.deployment} @@ -154,7 +149,9 @@ class HassioHostInfo extends LitElement { this.supervisor.host.disk_life_time >= 10 ? html` - eMMC Lifetime Used + ${this.supervisor.localize( + "system.host.emmc_lifetime_used" + )} ${this.supervisor.host.disk_life_time - 10}% - @@ -177,23 +174,18 @@ class HassioHostInfo extends LitElement {
${this.supervisor.host.features.includes("reboot") ? html` - - Reboot Host + + ${this.supervisor.localize("system.host.reboot_host")} ` : ""} ${this.supervisor.host.features.includes("shutdown") ? html` - Shutdown Host + ${this.supervisor.localize("system.host.shutdown_host")} ` : ""} @@ -205,14 +197,12 @@ class HassioHostInfo extends LitElement { - - Hardware + + ${this.supervisor.localize("system.host.hardware")} ${this.supervisor.host.features.includes("hassos") - ? html` - Import from USB + ? html` + ${this.supervisor.localize("system.host.import_from_usb")} ` : ""} @@ -251,12 +241,14 @@ class HassioHostInfo extends LitElement { try { const content = await fetchHassioHardwareInfo(this.hass); showHassioMarkdownDialog(this, { - title: "Hardware", + title: this.supervisor.localize("system.host.hardware"), content: `
${safeDump(content, { indent: 2 })}
`, }); } catch (err) { showAlertDialog(this, { - title: "Failed to get hardware list", + title: this.supervisor.localize( + "system.host.failed_to_get_hardware_list" + ), text: extractApiErrorMessage(err), }); } @@ -267,10 +259,10 @@ class HassioHostInfo extends LitElement { button.progress = true; const confirmed = await showConfirmationDialog(this, { - title: "Reboot", - text: "Are you sure you want to reboot the host?", - confirmText: "reboot host", - dismissText: "no", + title: this.supervisor.localize("system.host.reboot_host"), + text: this.supervisor.localize("system.host.confirm_reboot"), + confirmText: this.supervisor.localize("system.host.reboot_host"), + dismissText: this.supervisor.localize("common.cancel"), }); if (!confirmed) { @@ -284,7 +276,7 @@ class HassioHostInfo extends LitElement { // Ignore connection errors, these are all expected if (err.status_code && !ignoredStatusCodes.has(err.status_code)) { showAlertDialog(this, { - title: "Failed to reboot", + title: this.supervisor.localize("system.host.failed_to_reboot"), text: extractApiErrorMessage(err), }); } @@ -297,10 +289,10 @@ class HassioHostInfo extends LitElement { button.progress = true; const confirmed = await showConfirmationDialog(this, { - title: "Shutdown", - text: "Are you sure you want to shutdown the host?", - confirmText: "shutdown host", - dismissText: "no", + title: this.supervisor.localize("system.host.shutdown_host"), + text: this.supervisor.localize("system.host.confirm_shutdown"), + confirmText: this.supervisor.localize("system.host.shutdown_host"), + dismissText: this.supervisor.localize("common.cancel"), }); if (!confirmed) { @@ -314,7 +306,7 @@ class HassioHostInfo extends LitElement { // Ignore connection errors, these are all expected if (err.status_code && !ignoredStatusCodes.has(err.status_code)) { showAlertDialog(this, { - title: "Failed to shutdown", + title: this.supervisor.localize("system.host.failed_to_shutdown"), text: extractApiErrorMessage(err), }); } @@ -327,9 +319,19 @@ class HassioHostInfo extends LitElement { button.progress = true; const confirmed = await showConfirmationDialog(this, { - title: "Update", - text: "Are you sure you want to update the OS?", - confirmText: "update os", + title: this.supervisor.localize( + "confirm.update.title", + "name", + "Home Assistant Operating System" + ), + text: this.supervisor.localize( + "confirm.update.text", + "name", + "Home Assistant Operating System", + "version", + this.supervisor.os.version_latest + ), + confirmText: this.supervisor.localize("common.update"), dismissText: "no", }); @@ -344,7 +346,11 @@ class HassioHostInfo extends LitElement { } catch (err) { if (this.hass.connection.connected) { showAlertDialog(this, { - title: "Failed to update", + title: this.supervisor.localize( + "common.failed_to_update_name", + "name", + "Home Assistant Operating System" + ), text: extractApiErrorMessage(err), }); } @@ -354,7 +360,7 @@ class HassioHostInfo extends LitElement { private async _changeNetworkClicked(): Promise { showNetworkDialog(this, { - network: this.supervisor.network!, + supervisor: this.supervisor, loadData: () => this._loadData(), }); } @@ -362,10 +368,11 @@ class HassioHostInfo extends LitElement { private async _changeHostnameClicked(): Promise { const curHostname: string = this.supervisor.host.hostname; const hostname = await showPromptDialog(this, { - title: "Change Hostname", - inputLabel: "Please enter a new hostname:", + title: this.supervisor.localize("system.host.change_hostname"), + inputLabel: this.supervisor.localize("system.host.new_hostname"), inputType: "string", defaultValue: curHostname, + confirmText: this.supervisor.localize("common.update"), }); if (hostname && hostname !== curHostname) { @@ -376,7 +383,7 @@ class HassioHostInfo extends LitElement { }); } catch (err) { showAlertDialog(this, { - title: "Setting hostname failed", + title: this.supervisor.localize("system.host.failed_to_set_hostname"), text: extractApiErrorMessage(err), }); } @@ -391,7 +398,9 @@ class HassioHostInfo extends LitElement { }); } catch (err) { showAlertDialog(this, { - title: "Failed to import from USB", + title: this.supervisor.localize( + "system.host.failed_to_import_from_usb" + ), text: extractApiErrorMessage(err), }); } diff --git a/hassio/src/system/hassio-supervisor-info.ts b/hassio/src/system/hassio-supervisor-info.ts index 3afc373e0b..a9b25a7ab7 100644 --- a/hassio/src/system/hassio-supervisor-info.ts +++ b/hassio/src/system/hassio-supervisor-info.ts @@ -37,54 +37,24 @@ import { documentationUrl } from "../../../src/util/documentation-url"; import "../components/supervisor-metric"; import { hassioStyle } from "../resources/hassio-style"; -const UNSUPPORTED_REASON = { - container: { - title: "Containers known to cause issues", - url: "/more-info/unsupported/container", - }, - dbus: { title: "DBUS", url: "/more-info/unsupported/dbus" }, - docker_configuration: { - title: "Docker Configuration", - url: "/more-info/unsupported/docker_configuration", - }, - docker_version: { - title: "Docker Version", - url: "/more-info/unsupported/docker_version", - }, - job_conditions: { - title: "Ignored job conditions", - url: "/more-info/unsupported/job_conditions", - }, - lxc: { title: "LXC", url: "/more-info/unsupported/lxc" }, - network_manager: { - title: "Network Manager", - url: "/more-info/unsupported/network_manager", - }, - os: { title: "Operating System", url: "/more-info/unsupported/os" }, - privileged: { - title: "Supervisor is not privileged", - url: "/more-info/unsupported/privileged", - }, - systemd: { title: "Systemd", url: "/more-info/unsupported/systemd" }, +const UNSUPPORTED_REASON_URL = { + container: "/more-info/unsupported/container", + dbus: "/more-info/unsupported/dbus", + docker_configuration: "/more-info/unsupported/docker_configuration", + docker_version: "/more-info/unsupported/docker_version", + job_conditions: "/more-info/unsupported/job_conditions", + lxc: "/more-info/unsupported/lxc", + network_manager: "/more-info/unsupported/network_manager", + os: "/more-info/unsupported/os", + privileged: "/more-info/unsupported/privileged", + systemd: "/more-info/unsupported/systemd", }; -const UNHEALTHY_REASON = { - privileged: { - title: "Supervisor is not privileged", - url: "/more-info/unsupported/privileged", - }, - supervisor: { - title: "Supervisor was not able to update", - url: "/more-info/unhealthy/supervisor", - }, - setup: { - title: "Setup of the Supervisor failed", - url: "/more-info/unhealthy/setup", - }, - docker: { - title: "The Docker environment is not working properly", - url: "/more-info/unhealthy/docker", - }, +const UNHEALTHY_REASON_URL = { + privileged: "/more-info/unsupported/privileged", + supervisor: "/more-info/unhealthy/supervisor", + setup: "/more-info/unhealthy/setup", + docker: "/more-info/unhealthy/docker", }; @customElement("hassio-supervisor-info") @@ -98,11 +68,11 @@ class HassioSupervisorInfo extends LitElement { protected render(): TemplateResult | void { const metrics = [ { - description: "Supervisor CPU Usage", + description: this.supervisor.localize("system.supervisor.cpu_usage"), value: this._metrics?.cpu_percent, }, { - description: "Supervisor RAM Usage", + description: this.supervisor.localize("system.supervisor.ram_usage"), value: this._metrics?.memory_percent, tooltip: `${bytesToString(this._metrics?.memory_usage)}/${bytesToString( this._metrics?.memory_limit @@ -115,7 +85,7 @@ class HassioSupervisorInfo extends LitElement {
- Version + ${this.supervisor.localize("common.version")} supervisor-${this.supervisor.supervisor.version} @@ -123,7 +93,7 @@ class HassioSupervisorInfo extends LitElement { - Newest Version + ${this.supervisor.localize("common.newest_version")} supervisor-${this.supervisor.supervisor.version_latest} @@ -131,17 +101,19 @@ class HassioSupervisorInfo extends LitElement { ${this.supervisor.supervisor.update_available ? html` - Update + ${this.supervisor.localize("common.update")} ` : ""} - Channel + ${this.supervisor.localize("system.supervisor.channel")} ${this.supervisor.supervisor.channel} @@ -150,18 +122,26 @@ class HassioSupervisorInfo extends LitElement { ? html` - Leave beta channel + ${this.supervisor.localize( + "system.supervisor.leave_beta_action" + )} ` : this.supervisor.supervisor.channel === "stable" ? html` - Join beta channel + ${this.supervisor.localize( + "system.supervisor.join_beta_action" + )} ` : ""} @@ -170,16 +150,20 @@ class HassioSupervisorInfo extends LitElement { ${this.supervisor.supervisor.supported ? html` - Share Diagnostics + ${this.supervisor.localize( + "system.supervisor.share_diagnostics" + )}
- Share crash reports and diagnostic information. + ${this.supervisor.localize( + "system.supervisor.share_diagnostics_description" + )}
` : html`
- You are running an unsupported installation. + ${this.supervisor.localize( + "system.supervisor.unsupported_title" + )}
`} ${!this.supervisor.supervisor.healthy ? html`
- Your installation is running in an unhealthy state. + ${this.supervisor.localize( + "system.supervisor.unhealthy_title" + )}
- +
`; diff --git a/src/translations/en.json b/src/translations/en.json index 1df9ec42d1..4c4ee6591a 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -3420,24 +3420,215 @@ }, "supervisor": { "addon": { + "failed_to_reset": "Failed to reset add-on configuration, {error}", + "failed_to_save": "Failed to save add-on configuration, {error}", + + "state": { + "installed": "Add-on is installed", + "not_installed": "Add-on is not installed", + "not_available": "Add-on is not available on your system" + }, "panel": { "configuration": "Configuration", "documentation": "Documentation", "info": "Info", "log": "Log" + }, + "configuration": { + "no_configuration": "This add-on does not expose configuration for you to mess with...", + "audio": { + "header": "Audio", + "default": "Default", + "input": "Input", + "output": "Output" + }, + "options": { + "header": "Options", + "edit_in_ui": "Edit in UI", + "edit_in_yaml": "Edit in YAML", + "invalid_yaml": "Invalid YAML", + "show_unused_optional": "Show unused optional configuration options" + }, + "network": { + "container": "Container", + "disabled": "Disabled", + "header": "Network", + "host": "Host" + } + }, + "dashboard": { + "changelog": "Changelog", + "cpu_usage": "Add-on CPU Usage", + "ram_usage": "Add-on RAM Usage", + "hostname": "Hostname", + "new_update_available": "{name} {version} is available", + "not_available_arch": "This add-on is not compatible with the processor of your device or the operating system you have installed on your device.", + "not_available_version": "You are unning Home Assistant {core_version_installed}, to update to this version of the add-on you need at least version {core_version_needed} of Home Assistan", + "visit_addon_page": "Visit the {name} page for more detals", + "restart": "restart", + "start": "start", + "stop": "stop", + "install": "install", + "uninstall": "uninstall", + "rebuild": "rebuild", + "open_web_ui": "Open web UI", + + "protection_mode": { + "title": "Warning: Protection mode is disabled!", + "content": "Protection mode on this add-on is disabled! This gives the add-on full access to the entire system, which adds security risks, and could damage your system when used incorrectly. Only disable the protection mode if you know, need AND trust the source of this add-on.", + "enable": "Enable Protection mode" + }, + + "capability": { + "stage": { + "title": "Add-on Stage", + "description": "Add-ons can have one of three stages:\n\n{icon_stable} **Stable**: These are add-ons ready to be used in production.\n\n{icon_experimental} **Experimental**: These may contain bugs, and may be unfinished.\n\n{icon_deprecated} **Deprecated**: These add-ons will no longer receive any updates." + }, + "rating": { + "title": "Add-on Security Rating", + "description": "Home Assistant provides a security rating to each of the add-ons, which indicates the risks involved when using this add-on. The more access an add-on requires on your system, the lower the score, thus raising the possible security risks.\n\nA score is on a scale from 1 to 6. Where 1 is the lowest score (considered the most insecure and highest risk) and a score of 6 is the highest score (considered the most secure and lowest risk)." + }, + "host_network": { + "title": "Host Network", + "description": "Add-ons usually run in their own isolated network layer, which prevents them from accessing the network of the host operating system. In some cases, this network isolation can limit add-ons in providing their services and therefore, the isolation can be lifted by the add-on author, giving the add-on full access to the network capabilities of the host machine. This gives the add-on more networking capabilities but lowers the security, hence, the security rating of the add-on will be lowered when this option is used by the add-on." + }, + "homeassistant_api": { + "title": "Home Assistant API Access", + "description": "This add-on is allowed to access your running Home Assistant instance directly via the Home Assistant API. This mode handles authentication for the add-on as well, which enables an add-on to interact with Home Assistant without the need for additional authentication tokens." + }, + "full_access": { + "title": "Full Hardware Access", + "description": "This add-on is given full access to the hardware of your system, by request of the add-on author. Access is comparable to the privileged mode in Docker. Since this opens up possible security risks, this feature impacts the add-on security score negatively.\n\nThis level of access is not granted automatically and needs to be confirmed by you. To do this, you need to disable the protection mode on the add-on manually. Only disable the protection mode if you know, need AND trust the source of this add-on." + }, + "hassio_api": { + "title": "Supervisor API Access", + "description": "The add-on was given access to the Supervisor API, by request of the add-on author. By default, the add-on can access general version information of your system. When the add-on requests 'manager' or 'admin' level access to the API, it will gain access to control multiple parts of your Home Assistant system. This permission is indicated by this badge and will impact the security score of the add-on negatively." + }, + "docker_api": { + "title": "Full Docker Access", + "description": "The add-on author has requested the add-on to have management access to the Docker instance running on your system. This mode gives the add-on full access and control to your entire Home Assistant system, which adds security risks, and could damage your system when misused. Therefore, this feature impacts the add-on security score negatively.\n\nThis level of access is not granted automatically and needs to be confirmed by you. To do this, you need to disable the protection mode on the add-on manually. Only disable the protection mode if you know, need AND trust the source of this add-on." + }, + "host_pid": { + "title": "Host Processes Namespace", + "description": "Usually, the processes the add-on runs, are isolated from all other system processes. The add-on author has requested the add-on to have access to the system processes running on the host system instance, and allow the add-on to spawn processes on the host system as well. This mode gives the add-on full access and control to your entire Home Assistant system, which adds security risks, and could damage your system when misused. Therefore, this feature impacts the add-on security score negatively.\n\nThis level of access is not granted automatically and needs to be confirmed by you. To do this, you need to disable the protection mode on the add-on manually. Only disable the protection mode if you know, need AND trust the source of this add-on." + }, + "apparmor": { + "title": "AppArmor", + "description": "AppArmor ('Application Armor') is a Linux kernel security module that restricts add-ons capabilities like network access, raw socket access, and permission to read, write, or execute specific files.\n\nAdd-on authors can provide their security profiles, optimized for the add-on, or request it to be disabled. If AppArmor is disabled, it will raise security risks and therefore, has a negative impact on the security score of the add-on." + }, + "auth_api": { + "title": "Home Assistant Authentication", + "description": "An add-on can authenticate users against Home Assistant, allowing add-ons to give users the possibility to log into applications running inside add-ons, using their Home Assistant username/password. This badge indicates if the add-on author requests this capability." + }, + "ingress": { + "title": "Ingress", + "description": "This add-on is using Ingress to embed its interface securely into Home Assistant." + }, + "label": { + "stage": "stage", + "rating": "rating", + "hardware": "hardware", + "host": "host", + "hass": "hass", + "hassio": "hassio", + "docker": "docker", + "host_pid": "host pid", + "apparmor": "apparmor", + "auth": "auth", + "ingress": "ingress" + }, + "role": { + "manager": "manager", + "default": "default", + "homeassistant": "homeassistant", + "backup": "backup", + "admin": "admin" + } + }, + + "option": { + "boot": { + "title": "Start on boot", + "description": "Make the add-on start during a system boot" + }, + "watchdog": { + "title": "Watchdog", + "description": "This will start the add-on if it crashes" + }, + "auto_update": { + "title": "Auto update", + "description": "Auto update the add-on when there is a new version available" + }, + "ingress_panel": { + "title": "Show in sidebar", + "description": "Add this add-on to your sidebar" + }, + "protected": { + "title": "Protection mode", + "description": "Blocks elevated system access from the add-on" + } + }, + + "action_error": { + "uninstall": "Failed to uninstall add-on", + "install": "Failed to install add-on", + "stop": "Failed to stop add-on", + "restart": "Failed to restart add-on", + "start": "Failed to start add-on", + "go_to_config": "Failed to start add-on - configuration validation failed!", + "start_invalid_config": "Go to configuration", + "validate_config": "Failed to validate add-on configuration", + "get_changelog": "Failed to get add-on changelog" + } + }, + "documentation": { + "get_documentation": "Failed to get add-on documentation, {error}" + }, + "logs": { + "get_logs": "Failed to get add-on logs, {error}" } }, "common": { - "cancel": "Cancel", + "cancel": "[%key:ui::common::cancel%]", + "yes": "[%key:ui::common::yes%]", + "no": "[%key:ui::common::no%]", + "description": "Description", + "failed_to_restart_name": "Failed to restart {name}", + "failed_to_update_name": "Failed to update {name}", + "learn_more": "Learn more", + "new_version_available": "New version available", "newest_version": "Newest Version", + "refresh": "[%key:ui::common::refresh%]", "release_notes": "Release notes", + "reload": "Reload", + "reset_defaults": "Reset to defaults", + "reset_options": "Reset options", + "restart_name": "Restart {name}", + "restart": "Restart", + "running_version": "You are currently running version {version}", + "save": "Save", + "show_more": "Show more information about this", + "update_available": "{count, plural,\n one {Update}\n other {{count} Updates}\n} pending", "update": "Update", - "version": "Version" + "version": "Version", + + "error": { + "unknown": "Unknown error", + "update_failed": "Update failed" + } }, "confirm": { "update": { - "title": "Update ${name}", + "title": "Update {name}", "text": "Are you sure you want to update {name} to version {version}?" + }, + "restart": { + "title": "[%key:supervisor::common::restart_name%]", + "text": "Are you sure you want to restart {name}?" + }, + "reset_options": { + "title": "Reset options", + "text": "Are you sure you want to reset all your options?" } }, "dashboard": { @@ -3445,18 +3636,172 @@ "addon_running": "Add-on is running", "addon_stopped": "Add-on is stopped", "addons": "Add-ons", - "no_addons": "You don't have any add-ons installed yet. Head over to the add-on store to get started!", - "update_available": "{count, plural,\n one {Update}\n other {{count} Updates}\n} pending" + "no_addons": "You don't have any add-ons installed yet. Head over to the add-on store to get started!" }, - "error": { - "unknown": "Unknown error", - "update_failed": "Update failed" + "store": { + "missing_addons": "Missing add-ons? Enable advanced mode in your user profile page", + "no_results_found": "No results found in {repository}.", + "registries": "Registries", + "repositories": "Repositories" }, "panel": { "dashboard": "Dashboard", "snapshots": "Snapshots", "store": "Add-on Store", "system": "System" + }, + "my": { + "not_supported": "[%key:ui::panel::my::not_supported%]", + "faq_link": "[%key:ui::panel::my::faq_link%]", + "error": "[%key:ui::panel::my::error%]" + }, + "system": { + "log": { + "log_provider": "Log Provider", + "get_logs": "Failed to get {provider} logs, {error}" + }, + "supervisor": { + "cpu_usage": "Supervisor CPU Usage", + "ram_usage": "Supervisor RAM Usage", + "failed_to_set_option": "Failed to set Supervisor option", + "failed_to_reload": "Failed to reload the Supervisor", + "failed_to_update": "Failed to update the Supervisor", + "unsupported_title": "You are running an unsupported installation", + "unsupported_description": "Below is a list of issues found with your installation, click on the links to learn how you can resolve the issues.", + "unhealthy_title": "Your installation is unhealthy", + "unhealthy_description": "Running an unhealthy installation will cause issues. Below is a list of issues found with your installation, click on the links to learn how you can resolve the issues.", + "update_supervisor": "Update the Supervisor", + "channel": "Channel", + "leave_beta_action": "Leave beta channel", + "leave_beta_description": "Get stable updates for Home Assistant, Supervisor and host", + "join_beta_action": "Join beta channel", + "join_beta_description": "Get beta updates for Home Assistant (RCs), Supervisor and host", + "share_diagnostics": "Share Diagnostics", + "share_diagnostics_description": "Share crash reports and diagnostic information.", + "reload_supervisor": "Reload Supervisor", + "warning": "WARNING", + "beta_warning": "Beta releases are for testers and early adopters and can contain unstable code changes", + "beta_backup": "Make sure you have backups of your data before you activate this feature.", + "beta_release_items": "This includes beta releases for:", + "beta_join_confirm": "Do you want to join the beta channel?", + "share_diagonstics_title": "Help Improve Home Assistant", + "share_diagonstics_description": "Would you want to automatically share crash reports and diagnostic information when the Supervisor encounters unexpected errors? {line_break} This will allow us to fix the problems, the information is only accessible to the Home Assistant Core team and will not be shared with others.{line_break} The data does not include any private/sensitive information and you can disable this in settings at any time you want.", + "unsupported_reason": { + "container": "Containers known to cause issues", + "dbus": "DBUS", + "docker_configuration": "Docker Configuration", + "docker_version": "Docker Version", + "job_conditions": "Ignored job conditions", + "lxc": "LXC", + "network_manager": "Network Manager", + "os": "Operating System", + "privileged": "Supervisor is not privileged", + "systemd": "Systemd" + }, + "unhealthy_reason": { + "privileged": "Supervisor is not privileged", + "supervisor": "Supervisor was not able to update", + "setup": "Setup of the Supervisor failed", + "docker": "The Docker environment is not working properly" + } + }, + "host": { + "failed_to_get_hardware_list": "Failed to get hardware list", + "failed_to_reboot": "Failed to reboot the host", + "failed_to_shutdown": "Failed to shutdown the host", + "failed_to_set_hostname": "Setting hostname failed", + "failed_to_import_from_usb": "Failed to import from USB", + "used_space": "Used space", + "hostname": "Hostname", + "change_hostname": "Change Hostname", + "new_hostname": "Please enter a new hostname:", + "ip_address": "IP Address", + "change": "Change", + "operating_system": "Operating System", + "docker_version": "Docker version", + "deployment": "Deployment", + "emmc_lifetime_used": "eMMC Lifetime Used", + "reboot_host": "Reboot host", + "confirm_reboot": "Are you sure you want to reboot the host?", + "confirm_shutdown": "Are you sure you want to shutdown the host?", + "shutdown_host": "Shutdown host", + "hardware": "Hardware", + "import_from_usb": "Import from USB" + }, + "core": { + "cpu_usage": "Core CPU Usage", + "ram_usage": "Core RAM Usage" + } + }, + "snapshot": { + "description": "Snapshots allow you to easily backup and restore all data of your Home Assistant instance.", + "available_snapshots": "Available Snapshots", + "no_snapshots": "You don't have any snapshots yet.", + "create_blocked_not_running": "Creating a snapshot is not possible right now because the system is in {state} state.", + "could_not_create": "Could not create snapshot", + "upload_snapshot": "Upload snapshot", + "create_snapshot": "Create snapshot", + "create": "Create", + "name": "Name", + "type": "Type", + "security": "Security", + "full_snapshot": "Full snapshot", + "partial_snapshot": "Partial snapshot", + "addons": "Add-ons", + "folders": "Folders", + "password": "Password", + "password_protection": "Password protection", + "password_protected": "password protected", + "enter_password": "Please enter a password.", + + "folder": { + "homeassistant": "Home Assistant configuration", + "ssl": "SSL", + "share": "Share", + "media": "Media", + "addons/local": "Local add-ons" + } + }, + "dialog": { + "network": { + "title": "Network settings", + "connected_to": "Connected to {ssid}", + "scan_ap": "Scan for accesspoints", + "open": "Open", + "wep": "WEP", + "wpa": "wpa-psk", + "warning": "If you are changing the Wi-Fi, IP or gateway addresses, you might lose the connection!", + "static": "Static", + "dhcp": "DHCP", + "disabled": "Disabled", + "ip_netmask": "IP address/Netmask", + "gateway": "Gateway address", + "dns_servers": "DNS Servers", + "unsaved": "You have unsaved changes, these will get lost if you change tabs, do you want to continue?", + "failed_to_change": "Failed to change network settings" + }, + "registries": { + "title_add": "Add New Container Registry", + "title_manage": "Manage Container Registries", + "registry": "Registry", + "username": "Username", + "password": "Password", + "no_registries": "No registries configured", + "add_registry": "Add registry", + "add_new_registry": "Add new registry", + "remove": "Remove", + "failed_to_add": "Failed to add registry", + "failed_to_remove": "Failed to remove registry" + }, + "repositories": { + "title": "Manage add-on repositories", + "add": "Add", + "remove": "Remove" + }, + "restart_addon": { + "confirm_text": "Restart add-on", + "text": "Do you want to restart the add-on with your changes?" + } } } }

ContainerHostDescription + ${this.supervisor.localize( + "addon.configuration.network.container" + )} + + ${this.supervisor.localize( + "addon.configuration.network.host" + )} + + ${this.supervisor.localize("common.description")} +
${item.description}${this._computeDescription(item)}