Add Learn how it works link to cloud account (#13693)

This commit is contained in:
Paul Bottein 2022-09-28 15:05:50 +02:00 committed by GitHub
parent da38cbccf1
commit dddb922593
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 321 additions and 291 deletions

View File

@ -1,11 +1,13 @@
import "@material/mwc-button";
import { mdiHelpCircle } from "@mdi/js";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { property, state } from "lit/decorators";
import { property } from "lit/decorators";
import { fireEvent } from "../../../../common/dom/fire_event";
import "../../../../components/ha-alert";
import "../../../../components/ha-card";
import "../../../../components/ha-settings-row";
import "../../../../components/ha-switch";
import type { HaSwitch } from "../../../../components/ha-switch";
import { syncCloudAlexaEntities } from "../../../../data/alexa";
import { CloudStatusLoggedIn, updateCloudPref } from "../../../../data/cloud";
import type { HomeAssistant } from "../../../../types";
@ -14,8 +16,6 @@ export class CloudAlexaPref extends LitElement {
@property() public cloudStatus?: CloudStatusLoggedIn;
@state() private _syncing = false;
protected render(): TemplateResult {
if (!this.cloudStatus) {
return html``;
@ -31,7 +31,20 @@ export class CloudAlexaPref extends LitElement {
"ui.panel.config.cloud.account.alexa.title"
)}
>
<div class="switch">
<div class="header-actions">
<a
href="https://www.nabucasa.com/config/amazon_alexa/"
target="_blank"
rel="noreferrer"
class="icon-link"
>
<ha-icon-button
.label=${this.hass.localize(
"ui.panel.config.cloud.account.alexa.link_learn_how_it_works"
)}
.path=${mdiHelpCircle}
></ha-icon-button>
</a>
<ha-switch
.checked=${alexa_enabled}
@change=${this._enabledToggleChanged}
@ -81,40 +94,25 @@ export class CloudAlexaPref extends LitElement {
</ha-alert>
`
: html`
<div class="state-reporting">
<h3>
<ha-settings-row>
<span slot="heading">
${this.hass!.localize(
"ui.panel.config.cloud.account.alexa.enable_state_reporting"
)}
</h3>
<div class="state-reporting-switch">
<ha-switch
.checked=${alexa_report_state}
@change=${this._reportToggleChanged}
></ha-switch>
</div>
</div>
<p>
${this.hass!.localize(
"ui.panel.config.cloud.account.alexa.info_state_reporting"
)}
</p>
</span>
<span slot="description">
${this.hass!.localize(
"ui.panel.config.cloud.account.alexa.info_state_reporting"
)}
</span>
<ha-switch
.checked=${alexa_report_state}
@change=${this._reportToggleChanged}
></ha-switch>
</ha-settings-row>
`}
</div>
<div class="card-actions">
${alexa_registered
? html`
<mwc-button
@click=${this._handleSync}
.disabled=${!alexa_enabled || this._syncing}
>
${this.hass!.localize(
"ui.panel.config.cloud.account.alexa.sync_entities"
)}
</mwc-button>
`
: ""}
<div class="spacer"></div>
<a href="/config/cloud/alexa">
<mwc-button
>${this.hass!.localize(
@ -127,21 +125,6 @@ export class CloudAlexaPref extends LitElement {
`;
}
private async _handleSync() {
this._syncing = true;
try {
await syncCloudAlexaEntities(this.hass!);
} catch (err: any) {
alert(
`${this.hass!.localize(
"ui.panel.config.cloud.account.alexa.sync_entities_error"
)} ${err.body.message}`
);
} finally {
this._syncing = false;
}
}
private async _enabledToggleChanged(ev) {
const toggle = ev.target as HaSwitch;
try {
@ -180,40 +163,33 @@ export class CloudAlexaPref extends LitElement {
a {
color: var(--primary-color);
}
.switch {
ha-settings-row {
padding: 0;
}
.header-actions {
position: absolute;
right: 24px;
top: 24px;
display: flex;
flex-direction: row;
}
:host([dir="rtl"]) .switch {
:host([dir="rtl"]) .header-actions {
right: auto;
left: 24px;
}
.header-actions .icon-link {
margin-top: -16px;
margin-inline-end: 8px;
margin-right: 8px;
direction: var(--direction);
color: var(--secondary-text-color);
}
.card-actions {
display: flex;
}
.card-actions a {
text-decoration: none;
}
.spacer {
flex-grow: 1;
}
.state-reporting {
display: flex;
margin-top: 1.5em;
}
.state-reporting + p {
margin-top: 0.5em;
}
.state-reporting h3 {
flex-grow: 1;
margin: 0;
}
.state-reporting-switch {
margin-top: 0.25em;
margin-right: 7px;
margin-left: 0.5em;
}
`;
}
}

View File

@ -1,15 +1,15 @@
import "@material/mwc-button";
import { mdiHelpCircle } from "@mdi/js";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { property, state } from "lit/decorators";
import { property } from "lit/decorators";
import { fireEvent } from "../../../../common/dom/fire_event";
import "../../../../components/ha-alert";
import "../../../../components/ha-card";
import "../../../../components/ha-settings-row";
import type { HaSwitch } from "../../../../components/ha-switch";
import "../../../../components/ha-textfield";
import type { HaTextField } from "../../../../components/ha-textfield";
import { CloudStatusLoggedIn, updateCloudPref } from "../../../../data/cloud";
import { syncCloudGoogleEntities } from "../../../../data/google_assistant";
import { showAlertDialog } from "../../../../dialogs/generic/show-dialog-box";
import type { HomeAssistant } from "../../../../types";
import { showSaveSuccessToast } from "../../../../util/toast-saved-success";
@ -18,8 +18,6 @@ export class CloudGooglePref extends LitElement {
@property({ attribute: false }) public cloudStatus?: CloudStatusLoggedIn;
@state() private _syncing = false;
protected render(): TemplateResult {
if (!this.cloudStatus) {
return html``;
@ -36,11 +34,23 @@ export class CloudGooglePref extends LitElement {
"ui.panel.config.cloud.account.google.title"
)}
>
<div class="switch">
<div class="header-actions">
<a
href="https://www.nabucasa.com/config/google_assistant/"
target="_blank"
rel="noreferrer"
class="icon-link"
>
<ha-icon-button
.label=${this.hass.localize(
"ui.panel.config.cloud.account.google.link_learn_how_it_works"
)}
.path=${mdiHelpCircle}
></ha-icon-button>
</a>
<ha-switch
id="google_enabled"
.checked=${google_enabled}
@change=${this._enableToggleChanged}
@change=${this._enabledToggleChanged}
></ha-switch>
</div>
<div class="card-content">
@ -110,61 +120,50 @@ export class CloudGooglePref extends LitElement {
`
: ""}
<div class="state-reporting">
<h3>
${this.hass.localize(
<ha-settings-row>
<span slot="heading">
${this.hass!.localize(
"ui.panel.config.cloud.account.google.enable_state_reporting"
)}
</h3>
<div class="state-reporting-switch">
<ha-switch
.checked=${google_report_state}
@change=${this._reportToggleChanged}
></ha-switch>
</div>
</div>
<p>
${this.hass.localize(
"ui.panel.config.cloud.account.google.info_state_reporting"
)}
</p>
<div class="secure_devices">
<h3>
</span>
<span slot="description">
${this.hass!.localize(
"ui.panel.config.cloud.account.google.info_state_reporting"
)}
</span>
<ha-switch
.checked=${google_report_state}
@change=${this._reportToggleChanged}
></ha-switch>
</ha-settings-row>
<ha-settings-row>
<span slot="heading">
${this.hass.localize(
"ui.panel.config.cloud.account.google.security_devices"
)}
</h3>
${this.hass.localize(
"ui.panel.config.cloud.account.google.enter_pin_info"
</span>
<span slot="description">
${this.hass.localize(
"ui.panel.config.cloud.account.google.enter_pin_info"
)}
</span>
</ha-settings-row>
<ha-textfield
id="google_secure_devices_pin"
.label=${this.hass.localize(
"ui.panel.config.cloud.account.google.devices_pin"
)}
<ha-textfield
id="google_secure_devices_pin"
.label=${this.hass.localize(
"ui.panel.config.cloud.account.google.devices_pin"
)}
.placeholder=${this.hass.localize(
"ui.panel.config.cloud.account.google.enter_pin_hint"
)}
.value=${google_secure_devices_pin || ""}
@change=${this._pinChanged}
></ha-textfield>
</div>
.placeholder=${this.hass.localize(
"ui.panel.config.cloud.account.google.enter_pin_hint"
)}
.value=${google_secure_devices_pin || ""}
@change=${this._pinChanged}
></ha-textfield>
`}
</div>
<div class="card-actions">
${google_registered
? html`
<mwc-button
@click=${this._handleSync}
.disabled=${!google_enabled || this._syncing}
>
${this.hass.localize(
"ui.panel.config.cloud.account.google.sync_entities"
)}
</mwc-button>
`
: ""}
<div class="spacer"></div>
<a href="/config/cloud/google-assistant">
<mwc-button>
${this.hass.localize(
@ -177,32 +176,7 @@ export class CloudGooglePref extends LitElement {
`;
}
private async _handleSync() {
this._syncing = true;
try {
await syncCloudGoogleEntities(this.hass!);
} catch (err: any) {
showAlertDialog(this, {
title: this.hass.localize(
`ui.panel.config.cloud.account.google.${
err.status_code === 404
? "not_configured_title"
: "sync_failed_title"
}`
),
text: this.hass.localize(
`ui.panel.config.cloud.account.google.${
err.status_code === 404 ? "not_configured_text" : "sync_failed_text"
}`
),
});
fireEvent(this, "ha-refresh-cloud-status");
} finally {
this._syncing = false;
}
}
private async _enableToggleChanged(ev) {
private async _enabledToggleChanged(ev) {
const toggle = ev.target as HaSwitch;
try {
await updateCloudPref(this.hass, { [toggle.id]: toggle.checked! });
@ -252,15 +226,27 @@ export class CloudGooglePref extends LitElement {
a {
color: var(--primary-color);
}
.switch {
.header-actions {
position: absolute;
right: 24px;
top: 24px;
display: flex;
flex-direction: row;
}
:host([dir="rtl"]) .switch {
:host([dir="rtl"]) .header-actions {
right: auto;
left: 24px;
}
.header-actions .icon-link {
margin-top: -16px;
margin-inline-end: 8px;
margin-right: 8px;
direction: var(--direction);
color: var(--secondary-text-color);
}
ha-settings-row {
padding: 0;
}
ha-textfield {
width: 250px;
display: block;
@ -275,32 +261,6 @@ export class CloudGooglePref extends LitElement {
.warning {
color: var(--error-color);
}
.secure_devices {
padding-top: 8px;
}
.spacer {
flex-grow: 1;
}
.state-reporting {
display: flex;
margin-top: 1.5em;
}
.state-reporting + p {
margin-top: 0.5em;
}
h3 {
margin: 0 0 8px 0;
}
.state-reporting h3 {
flex-grow: 1;
margin: 0;
}
.state-reporting-switch {
margin-top: 0.25em;
margin-right: 7px;
margin-left: 0.5em;
}
`;
}
}

View File

@ -1,5 +1,5 @@
import "@material/mwc-button";
import { mdiContentCopy } from "@mdi/js";
import { mdiContentCopy, mdiHelpCircle } from "@mdi/js";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
import { fireEvent } from "../../../../common/dom/fire_event";
@ -58,12 +58,26 @@ export class CloudRemotePref extends LitElement {
"ui.panel.config.cloud.account.remote.title"
)}
>
<div class="switch">
<div class="header-actions">
<a
href="https://www.nabucasa.com/config/remote/"
target="_blank"
rel="noreferrer"
class="icon-link"
>
<ha-icon-button
.label=${this.hass.localize(
"ui.panel.config.cloud.account.remote.link_learn_how_it_works"
)}
.path=${mdiHelpCircle}
></ha-icon-button>
</a>
<ha-switch
.checked=${remote_enabled}
@change=${this._toggleChanged}
></ha-switch>
</div>
<div class="card-content">
${!remote_connected && remote_enabled
? html`
@ -98,18 +112,6 @@ export class CloudRemotePref extends LitElement {
></ha-svg-icon>
</div>
<div class="card-actions">
<a
href="https://www.nabucasa.com/config/remote/"
target="_blank"
rel="noreferrer"
>
<mwc-button
>${this.hass.localize(
"ui.panel.config.cloud.account.remote.link_learn_how_it_works"
)}</mwc-button
>
</a>
<div class="spacer"></div>
<mwc-button @click=${this._openCertInfo}>
${this.hass.localize(
"ui.panel.config.cloud.account.remote.certificate_info"
@ -158,15 +160,24 @@ export class CloudRemotePref extends LitElement {
a {
color: var(--primary-color);
}
.switch {
.header-actions {
position: absolute;
right: 24px;
top: 24px;
display: flex;
flex-direction: row;
}
:host([dir="rtl"]) .switch {
:host([dir="rtl"]) .header-actions {
right: auto;
left: 24px;
}
.header-actions .icon-link {
margin-top: -16px;
margin-inline-end: 8px;
margin-right: 8px;
direction: var(--direction);
color: var(--secondary-text-color);
}
.warning {
font-weight: bold;
margin-bottom: 1em;
@ -179,19 +190,12 @@ export class CloudRemotePref extends LitElement {
right: 24px;
top: 24px;
}
:host([dir="rtl"]) .switch {
right: auto;
left: 24px;
}
.card-actions {
display: flex;
}
.card-actions a {
text-decoration: none;
}
.spacer {
flex-grow: 1;
}
ha-svg-icon {
--mdc-icon-size: 18px;
color: var(--secondary-text-color);

View File

@ -5,6 +5,9 @@ import {
mdiCheckboxMultipleMarked,
mdiCloseBox,
mdiCloseBoxMultiple,
mdiDotsVertical,
mdiFormatListChecks,
mdiSync,
} from "@mdi/js";
import type { UnsubscribeFunc } from "home-assistant-js-websocket";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
@ -26,7 +29,11 @@ import "../../../../components/ha-card";
import "../../../../components/ha-formfield";
import "../../../../components/ha-icon-button";
import "../../../../components/ha-switch";
import { AlexaEntity, fetchCloudAlexaEntities } from "../../../../data/alexa";
import {
AlexaEntity,
fetchCloudAlexaEntities,
syncCloudAlexaEntities,
} from "../../../../data/alexa";
import {
AlexaEntityConfig,
CloudPreferences,
@ -59,6 +66,8 @@ class CloudAlexa extends SubscribeMixin(LitElement) {
@state() private _entities?: AlexaEntity[];
@state() private _syncing = false;
@state()
private _entityConfigs: CloudPreferences["alexa_entity_configs"] = {};
@ -222,74 +231,84 @@ class CloudAlexa extends SubscribeMixin(LitElement) {
}
return html`
<hass-subpage .hass=${this.hass} .narrow=${
this.narrow
} .header=${this.hass!.localize("ui.panel.config.cloud.alexa.title")}>
${
emptyFilter
? html`
<mwc-button
slot="toolbar-icon"
@click=${this._openDomainToggler}
>${this.hass!.localize(
"ui.panel.config.cloud.alexa.manage_defaults"
)}</mwc-button
>
`
: ""
}
${
!emptyFilter
? html`
<div class="banner">
${this.hass!.localize("ui.panel.config.cloud.alexa.banner")}
</div>
`
: ""
}
${
exposedCards.length > 0
? html`
<div class="header">
<h3>
${this.hass!.localize(
"ui.panel.config.cloud.alexa.exposed_entities"
)}
</h3>
${!this.narrow
? this.hass!.localize(
"ui.panel.config.cloud.alexa.exposed",
"selected",
selected
)
: selected}
</div>
<div class="content">${exposedCards}</div>
`
: ""
}
${
notExposedCards.length > 0
? html`
<div class="header second">
<h3>
${this.hass!.localize(
"ui.panel.config.cloud.alexa.not_exposed_entities"
)}
</h3>
${!this.narrow
? this.hass!.localize(
"ui.panel.config.cloud.alexa.not_exposed",
"selected",
this._entities.length - selected
)
: this._entities.length - selected}
</div>
<div class="content">${notExposedCards}</div>
`
: ""
}
</div>
<hass-subpage
.hass=${this.hass}
.narrow=${this.narrow}
.header=${this.hass!.localize("ui.panel.config.cloud.alexa.title")}
>
<ha-button-menu corner="BOTTOM_START" slot="toolbar-icon">
<ha-icon-button
slot="trigger"
.label=${this.hass.localize("ui.common.menu")}
.path=${mdiDotsVertical}
></ha-icon-button>
<mwc-list-item
graphic="icon"
.disabled=${!emptyFilter}
@click=${this._openDomainToggler}
>
${this.hass.localize("ui.panel.config.cloud.alexa.manage_defaults")}
<ha-svg-icon
slot="graphic"
.path=${mdiFormatListChecks}
></ha-svg-icon>
</mwc-list-item>
<mwc-list-item
graphic="icon"
.disabled=${this._syncing}
@click=${this._handleSync}
>
${this.hass.localize("ui.panel.config.cloud.alexa.sync_entities")}
<ha-svg-icon slot="graphic" .path=${mdiSync}></ha-svg-icon>
</mwc-list-item>
</ha-button-menu>
${!emptyFilter
? html`
<div class="banner">
${this.hass!.localize("ui.panel.config.cloud.alexa.banner")}
</div>
`
: ""}
${exposedCards.length > 0
? html`
<div class="header">
<h3>
${this.hass!.localize(
"ui.panel.config.cloud.alexa.exposed_entities"
)}
</h3>
${!this.narrow
? this.hass!.localize(
"ui.panel.config.cloud.alexa.exposed",
"selected",
selected
)
: selected}
</div>
<div class="content">${exposedCards}</div>
`
: ""}
${notExposedCards.length > 0
? html`
<div class="header second">
<h3>
${this.hass!.localize(
"ui.panel.config.cloud.alexa.not_exposed_entities"
)}
</h3>
${!this.narrow
? this.hass!.localize(
"ui.panel.config.cloud.alexa.not_exposed",
"selected",
this._entities.length - selected
)
: this._entities.length - selected}
</div>
<div class="content">${notExposedCards}</div>
`
: ""}
</hass-subpage>
`;
}
@ -423,6 +442,21 @@ class CloudAlexa extends SubscribeMixin(LitElement) {
});
}
private async _handleSync() {
this._syncing = true;
try {
await syncCloudAlexaEntities(this.hass!);
} catch (err: any) {
alert(
`${this.hass!.localize(
"ui.panel.config.cloud.alexa.sync_entities_error"
)} ${err.body.message}`
);
} finally {
this._syncing = false;
}
}
private async _updateDomainExposed(domain: string, expose: boolean) {
const defaultExpose =
this.cloudStatus.prefs.alexa_default_expose ||

View File

@ -5,6 +5,9 @@ import {
mdiCheckboxMultipleMarked,
mdiCloseBox,
mdiCloseBoxMultiple,
mdiDotsVertical,
mdiFormatListChecks,
mdiSync,
} from "@mdi/js";
import type { UnsubscribeFunc } from "home-assistant-js-websocket";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
@ -45,6 +48,7 @@ import {
GoogleEntity,
} from "../../../../data/google_assistant";
import { showDomainTogglerDialog } from "../../../../dialogs/domain-toggler/show-dialog-domain-toggler";
import { showAlertDialog } from "../../../../dialogs/generic/show-dialog-box";
import "../../../../layouts/hass-loading-screen";
import "../../../../layouts/hass-subpage";
import { SubscribeMixin } from "../../../../mixins/subscribe-mixin";
@ -64,6 +68,8 @@ class CloudGoogleAssistant extends SubscribeMixin(LitElement) {
@state() private _entities?: GoogleEntity[];
@state() private _syncing = false;
@state()
private _entityConfigs: CloudPreferences["google_entity_configs"] = {};
@ -249,19 +255,39 @@ class CloudGoogleAssistant extends SubscribeMixin(LitElement) {
.hass=${this.hass}
.header=${this.hass!.localize("ui.panel.config.cloud.google.title")}
.narrow=${this.narrow}>
${
emptyFilter
? html`
<mwc-button
slot="toolbar-icon"
@click=${this._openDomainToggler}
>${this.hass!.localize(
"ui.panel.config.cloud.google.manage_defaults"
)}</mwc-button
>
`
: ""
}
<ha-button-menu corner="BOTTOM_START" slot="toolbar-icon">
<ha-icon-button
slot="trigger"
.label=${this.hass.localize("ui.common.menu")}
.path=${mdiDotsVertical}
></ha-icon-button>
<mwc-list-item
graphic="icon"
.disabled=${!emptyFilter}
@click=${this._openDomainToggler}
>
${this.hass.localize(
"ui.panel.config.cloud.google.manage_defaults"
)}
<ha-svg-icon
slot="graphic"
.path=${mdiFormatListChecks}
></ha-svg-icon>
</mwc-list-item>
<mwc-list-item
graphic="icon"
.disabled=${this._syncing}
@click=${this._handleSync}
>
${this.hass.localize("ui.panel.config.cloud.google.sync_entities")}
<ha-svg-icon
slot="graphic"
.path=${mdiSync}
></ha-svg-icon>
</mwc-list-item>
</ha-button-menu>
${
!emptyFilter
? html`
@ -506,6 +532,31 @@ class CloudGoogleAssistant extends SubscribeMixin(LitElement) {
);
}
private async _handleSync() {
this._syncing = true;
try {
await cloudSyncGoogleAssistant(this.hass!);
} catch (err: any) {
showAlertDialog(this, {
title: this.hass.localize(
`ui.panel.config.cloud.google.${
err.status_code === 404
? "not_configured_title"
: "sync_failed_title"
}`
),
text: this.hass.localize(
`ui.panel.config.cloud.google.${
err.status_code === 404 ? "not_configured_text" : "sync_failed_text"
}`
),
});
fireEvent(this, "ha-refresh-cloud-status");
} finally {
this._syncing = false;
}
}
private _ensureEntitySync() {
if (this._popstateSyncAttached) {
return;

View File

@ -2494,14 +2494,13 @@
"config_documentation": "Configuration documentation",
"enable_state_reporting": "Enable State Reporting",
"info_state_reporting": "If you enable state reporting, Home Assistant will send all state changes of exposed entities to Amazon. This allows you to always see the latest states in the Alexa app and use the state changes to create routines.",
"sync_entities": "Sync Entities to Amazon",
"manage_entities": "Manage Entities",
"sync_entities_error": "Failed to sync entities:",
"state_reporting_error": "Unable to {enable_disable} report state.",
"manage_entities": "Manage Entities",
"enable": "enable",
"disable": "disable",
"not_configured_title": "Alexa is not activated",
"not_configured_text": "Before you can use Alexa, you need to activate the Home Assistant skill for Alexa in the Alexa app."
"not_configured_text": "Before you can use Alexa, you need to activate the Home Assistant skill for Alexa in the Alexa app.",
"link_learn_how_it_works": "[%key:ui::panel::config::cloud::account::remote::link_learn_how_it_works%]"
},
"google": {
"title": "Google Assistant",
@ -2516,13 +2515,11 @@
"enter_pin_info": "Please enter a PIN to interact with security devices. Security devices are doors, garage doors and locks. You will be asked to say/enter this PIN when interacting with such devices via Google Assistant.",
"devices_pin": "Security Devices PIN",
"enter_pin_hint": "Enter a PIN to use security devices",
"sync_entities": "Sync Entities to Google",
"manage_entities": "Manage Entities",
"enter_pin_error": "Unable to store PIN:",
"not_configured_title": "Google Assistant is not activated",
"not_configured_text": "Before you can use Google Assistant, you need to activate the Home Assistant Cloud skill for Google Assistant in the Google Home app.",
"sync_failed_title": "Syncing failed",
"sync_failed_text": "Syncing your entities failed, try again or check the logs."
"link_learn_how_it_works": "[%key:ui::panel::config::cloud::account::remote::link_learn_how_it_works%]"
},
"webhooks": {
"title": "Webhooks",
@ -2549,7 +2546,9 @@
"follow_domain": "[%key:ui::panel::config::cloud::google::follow_domain%]",
"exposed": "[%key:ui::panel::config::cloud::google::exposed%]",
"not_exposed": "[%key:ui::panel::config::cloud::google::not_exposed%]",
"expose": "Expose to Alexa"
"expose": "Expose to Alexa",
"sync_entities": "Synchronize entities",
"sync_entities_error": "Failed to sync entities:"
},
"dialog_certificate": {
"certificate_information": "Certificate Information",
@ -2572,7 +2571,13 @@
"follow_domain": "Follow domain",
"exposed": "{selected} exposed",
"not_exposed": "{selected} not exposed",
"sync_to_google": "Synchronizing changes to Google."
"sync_to_google": "Synchronizing changes to Google.",
"sync_entities": "Synchronize entities",
"sync_entities_error": "Failed to sync entities:",
"not_configured_title": "[%key:ui::panel::config::cloud::account::google::not_configured_title%]",
"not_configured_text": "[%key:ui::panel::config::cloud::account::google::not_configured_text%]",
"sync_failed_title": "Syncing failed",
"sync_failed_text": "Syncing your entities failed, try again or check the logs."
},
"dialog_cloudhook": {
"webhook_for": "Webhook for {name}",