Fix localize key types related to form schemas (Group 3) (#13400)

* Fix key type errors for card editors (Round 4)

* Fix key type errors for remaining form schemas
This commit is contained in:
Steve Repsher 2022-08-17 23:57:26 -04:00 committed by GitHub
parent 12e57dfcae
commit d7b888f761
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 503 additions and 457 deletions

View File

@ -4,7 +4,7 @@ import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import { createCloseHeading } from "../../../../src/components/ha-dialog"; import { createCloseHeading } from "../../../../src/components/ha-dialog";
import "../../../../src/components/ha-form/ha-form"; import "../../../../src/components/ha-form/ha-form";
import { HaFormSchema } from "../../../../src/components/ha-form/types"; import type { SchemaUnion } from "../../../../src/components/ha-form/types";
import "../../../../src/components/ha-icon-button"; import "../../../../src/components/ha-icon-button";
import "../../../../src/components/ha-settings-row"; import "../../../../src/components/ha-settings-row";
import { extractApiErrorMessage } from "../../../../src/data/hassio/common"; import { extractApiErrorMessage } from "../../../../src/data/hassio/common";
@ -19,7 +19,7 @@ import { haStyle, haStyleDialog } from "../../../../src/resources/styles";
import type { HomeAssistant } from "../../../../src/types"; import type { HomeAssistant } from "../../../../src/types";
import { RegistriesDialogParams } from "./show-dialog-registries"; import { RegistriesDialogParams } from "./show-dialog-registries";
const SCHEMA: HaFormSchema[] = [ const SCHEMA = [
{ {
name: "registry", name: "registry",
required: true, required: true,
@ -35,7 +35,7 @@ const SCHEMA: HaFormSchema[] = [
required: true, required: true,
selector: { text: { type: "password" } }, selector: { text: { type: "password" } },
}, },
]; ] as const;
@customElement("dialog-hassio-registries") @customElement("dialog-hassio-registries")
class HassioRegistriesDialog extends LitElement { class HassioRegistriesDialog extends LitElement {
@ -135,8 +135,8 @@ class HassioRegistriesDialog extends LitElement {
`; `;
} }
private _computeLabel = (schema: HaFormSchema) => private _computeLabel = (schema: SchemaUnion<typeof SCHEMA>) =>
this.supervisor.localize(`dialog.registries.${schema.name}`) || schema.name; this.supervisor.localize(`dialog.registries.${schema.name}`);
private _valueChanged(ev: CustomEvent) { private _valueChanged(ev: CustomEvent) {
this._input = ev.detail.value; this._input = ev.detail.value;

View File

@ -41,14 +41,14 @@ export class HaForm extends LitElement implements HaFormElement {
@property({ type: Boolean }) public disabled = false; @property({ type: Boolean }) public disabled = false;
@property() public computeError?: (schema: HaFormSchema, error) => string; @property() public computeError?: (schema: any, error) => string;
@property() public computeLabel?: ( @property() public computeLabel?: (
schema: any, schema: any,
data?: HaFormDataContainer data: HaFormDataContainer
) => string; ) => string;
@property() public computeHelper?: (schema: HaFormSchema) => string; @property() public computeHelper?: (schema: any) => string | undefined;
public focus() { public focus() {
const root = this.shadowRoot?.querySelector(".root"); const root = this.shadowRoot?.querySelector(".root");

View File

@ -15,13 +15,13 @@ import type { HomeAssistant } from "../../types";
import { brandsUrl, extractDomainFromBrandUrl } from "../../util/brands-url"; import { brandsUrl, extractDomainFromBrandUrl } from "../../util/brands-url";
import "../ha-alert"; import "../ha-alert";
import "../ha-form/ha-form"; import "../ha-form/ha-form";
import type { HaFormSchema } from "../ha-form/types"; import type { SchemaUnion } from "../ha-form/types";
import { showMediaBrowserDialog } from "../media-player/show-media-browser-dialog"; import { showMediaBrowserDialog } from "../media-player/show-media-browser-dialog";
const MANUAL_SCHEMA = [ const MANUAL_SCHEMA = [
{ name: "media_content_id", required: false, selector: { text: {} } }, { name: "media_content_id", required: false, selector: { text: {} } },
{ name: "media_content_type", required: false, selector: { text: {} } }, { name: "media_content_type", required: false, selector: { text: {} } },
]; ] as const;
@customElement("ha-selector-media") @customElement("ha-selector-media")
export class HaMediaSelector extends LitElement { export class HaMediaSelector extends LitElement {
@ -163,7 +163,9 @@ export class HaMediaSelector extends LitElement {
</ha-card>`}`; </ha-card>`}`;
} }
private _computeLabelCallback = (schema: HaFormSchema): string => private _computeLabelCallback = (
schema: SchemaUnion<typeof MANUAL_SCHEMA>
): string =>
this.hass.localize(`ui.components.selectors.media.${schema.name}`); this.hass.localize(`ui.components.selectors.media.${schema.name}`);
private _entityChanged(ev: CustomEvent) { private _entityChanged(ev: CustomEvent) {

View File

@ -8,7 +8,7 @@ import { BlueprintInput } from "./blueprint";
import { DeviceCondition, DeviceTrigger } from "./device_automation"; import { DeviceCondition, DeviceTrigger } from "./device_automation";
import { Action, MODES } from "./script"; import { Action, MODES } from "./script";
export const AUTOMATION_DEFAULT_MODE: ManualAutomationConfig["mode"] = "single"; export const AUTOMATION_DEFAULT_MODE: typeof MODES[number] = "single";
export interface AutomationEntity extends HassEntityBase { export interface AutomationEntity extends HassEntityBase {
attributes: HassEntityAttributeBase & { attributes: HassEntityAttributeBase & {

View File

@ -28,7 +28,12 @@ import {
import { BlueprintInput } from "./blueprint"; import { BlueprintInput } from "./blueprint";
export const MODES = ["single", "restart", "queued", "parallel"] as const; export const MODES = ["single", "restart", "queued", "parallel"] as const;
export const MODES_MAX = ["queued", "parallel"]; export const MODES_MAX = ["queued", "parallel"] as const;
export const isMaxMode = (
mode: typeof MODES[number]
): mode is typeof MODES_MAX[number] =>
MODES_MAX.includes(mode as typeof MODES_MAX[number]);
export const baseActionStruct = object({ export const baseActionStruct = object({
alias: optional(string()), alias: optional(string()),
@ -275,7 +280,7 @@ export const canRun = (state: ScriptEntity) => {
} }
if ( if (
state.state === "on" && state.state === "on" &&
MODES_MAX.includes(state.attributes.mode) && isMaxMode(state.attributes.mode) &&
state.attributes.current! < state.attributes.max! state.attributes.current! < state.attributes.max!
) { ) {
return true; return true;

View File

@ -14,7 +14,7 @@ import {
Trigger, Trigger,
triggerAutomationActions, triggerAutomationActions,
} from "../../../data/automation"; } from "../../../data/automation";
import { Action, MODES, MODES_MAX } from "../../../data/script"; import { Action, isMaxMode, MODES } from "../../../data/script";
import { haStyle } from "../../../resources/styles"; import { haStyle } from "../../../resources/styles";
import type { HomeAssistant } from "../../../types"; import type { HomeAssistant } from "../../../types";
import { documentationUrl } from "../../../util/documentation-url"; import { documentationUrl } from "../../../util/documentation-url";
@ -27,13 +27,13 @@ import "./trigger/ha-automation-trigger";
export class HaManualAutomationEditor extends LitElement { export class HaManualAutomationEditor extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant; @property({ attribute: false }) public hass!: HomeAssistant;
@property() public isWide!: boolean; @property({ type: Boolean }) public isWide!: boolean;
@property() public narrow!: boolean; @property({ type: Boolean }) public narrow!: boolean;
@property() public config!: ManualAutomationConfig; @property({ attribute: false }) public config!: ManualAutomationConfig;
@property() public stateObj?: HassEntity; @property({ attribute: false }) public stateObj?: HassEntity;
@state() private _showDescription = false; @state() private _showDescription = false;
@ -114,7 +114,7 @@ export class HaManualAutomationEditor extends LitElement {
` `
)} )}
</ha-select> </ha-select>
${this.config.mode && MODES_MAX.includes(this.config.mode) ${this.config.mode && isMaxMode(this.config.mode)
? html` ? html`
<br /><ha-textfield <br /><ha-textfield
.label=${this.hass.localize( .label=${this.hass.localize(
@ -300,7 +300,7 @@ export class HaManualAutomationEditor extends LitElement {
mode, mode,
}; };
if (!MODES_MAX.includes(mode)) { if (!isMaxMode(mode)) {
delete value.max; delete value.max;
} }

View File

@ -6,7 +6,7 @@ import { fireEvent } from "../../../../common/dom/fire_event";
import { slugify } from "../../../../common/string/slugify"; import { slugify } from "../../../../common/string/slugify";
import { createCloseHeading } from "../../../../components/ha-dialog"; import { createCloseHeading } from "../../../../components/ha-dialog";
import "../../../../components/ha-form/ha-form"; import "../../../../components/ha-form/ha-form";
import { HaFormSchema } from "../../../../components/ha-form/types"; import { SchemaUnion } from "../../../../components/ha-form/types";
import { CoreFrontendUserData } from "../../../../data/frontend"; import { CoreFrontendUserData } from "../../../../data/frontend";
import { import {
LovelaceDashboard, LovelaceDashboard,
@ -174,12 +174,15 @@ export class DialogLovelaceDashboardDetail extends LitElement {
icon: {}, icon: {},
}, },
}, },
!params.dashboard && ...(!params.dashboard && userData?.showAdvanced
userData?.showAdvanced && { ? ([
name: "url_path", {
required: true, name: "url_path",
selector: { text: {} }, required: true,
}, selector: { text: {} },
},
] as const)
: []),
{ {
name: "require_admin", name: "require_admin",
required: true, required: true,
@ -194,10 +197,12 @@ export class DialogLovelaceDashboardDetail extends LitElement {
boolean: {}, boolean: {},
}, },
}, },
].filter(Boolean) ] as const
); );
private _computeLabel = (entry: HaFormSchema): string => private _computeLabel = (
entry: SchemaUnion<ReturnType<typeof this._schema>>
): string =>
this.hass.localize( this.hass.localize(
`ui.panel.config.lovelace.dashboards.detail.${ `ui.panel.config.lovelace.dashboards.detail.${
entry.name === "show_in_sidebar" entry.name === "show_in_sidebar"

View File

@ -5,7 +5,7 @@ import memoizeOne from "memoize-one";
import { fireEvent } from "../../../../common/dom/fire_event"; import { fireEvent } from "../../../../common/dom/fire_event";
import { createCloseHeading } from "../../../../components/ha-dialog"; import { createCloseHeading } from "../../../../components/ha-dialog";
import "../../../../components/ha-form/ha-form"; import "../../../../components/ha-form/ha-form";
import { HaFormSchema } from "../../../../components/ha-form/types"; import { SchemaUnion } from "../../../../components/ha-form/types";
import { LovelaceResourcesMutableParams } from "../../../../data/lovelace"; import { LovelaceResourcesMutableParams } from "../../../../data/lovelace";
import { haStyleDialog } from "../../../../resources/styles"; import { haStyleDialog } from "../../../../resources/styles";
import { HomeAssistant } from "../../../../types"; import { HomeAssistant } from "../../../../types";
@ -132,53 +132,68 @@ export class DialogLovelaceResourceDetail extends LitElement {
`; `;
} }
private _schema = memoizeOne((data) => [ private _schema = memoizeOne(
{ (data) =>
name: "url", [
required: true, {
selector: { name: "url",
text: {}, required: true,
}, selector: {
}, text: {},
{ },
name: "res_type",
required: true,
selector: {
select: {
options: [
{
value: "module",
label: this.hass!.localize(
"ui.panel.config.lovelace.resources.types.module"
),
},
{
value: "css",
label: this.hass!.localize(
"ui.panel.config.lovelace.resources.types.css"
),
},
data.type === "js" && {
value: "js",
label: this.hass!.localize(
"ui.panel.config.lovelace.resources.types.js"
),
},
data.type === "html" && {
value: "html",
label: this.hass!.localize(
"ui.panel.config.lovelace.resources.types.html"
),
},
].filter(Boolean),
}, },
}, {
}, name: "res_type",
]); required: true,
selector: {
select: {
options: [
{
value: "module",
label: this.hass!.localize(
"ui.panel.config.lovelace.resources.types.module"
),
},
{
value: "css",
label: this.hass!.localize(
"ui.panel.config.lovelace.resources.types.css"
),
},
...(data.type === "js"
? ([
{
value: "js",
label: this.hass!.localize(
"ui.panel.config.lovelace.resources.types.js"
),
},
] as const)
: []),
...(data.type === "html"
? ([
{
value: "html",
label: this.hass!.localize(
"ui.panel.config.lovelace.resources.types.html"
),
},
] as const)
: []),
],
},
},
},
] as const
);
private _computeLabel = (entry: HaFormSchema): string => private _computeLabel = (
entry: SchemaUnion<ReturnType<typeof this._schema>>
): string =>
this.hass.localize( this.hass.localize(
`ui.panel.config.lovelace.resources.detail.${entry.name}` `ui.panel.config.lovelace.resources.detail.${
entry.name === "res_type" ? "type" : entry.name
}`
); );
private _valueChanged(ev: CustomEvent) { private _valueChanged(ev: CustomEvent) {

View File

@ -30,8 +30,7 @@ import "../../../components/ha-card";
import "../../../components/ha-fab"; import "../../../components/ha-fab";
import type { import type {
HaFormDataContainer, HaFormDataContainer,
HaFormSchema, SchemaUnion,
HaFormSelector,
} from "../../../components/ha-form/types"; } from "../../../components/ha-form/types";
import "../../../components/ha-icon-button"; import "../../../components/ha-icon-button";
import "../../../components/ha-svg-icon"; import "../../../components/ha-svg-icon";
@ -41,6 +40,7 @@ import {
Action, Action,
deleteScript, deleteScript,
getScriptEditorInitData, getScriptEditorInitData,
isMaxMode,
ManualScriptConfig, ManualScriptConfig,
MODES, MODES,
MODES_MAX, MODES_MAX,
@ -65,11 +65,11 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) {
@property() public scriptEntityId: string | null = null; @property() public scriptEntityId: string | null = null;
@property() public route!: Route; @property({ attribute: false }) public route!: Route;
@property() public isWide?: boolean; @property({ type: Boolean }) public isWide = false;
@property() public narrow!: boolean; @property({ type: Boolean }) public narrow!: boolean;
@state() private _config?: ScriptConfig; @state() private _config?: ScriptConfig;
@ -86,8 +86,12 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) {
@query("ha-yaml-editor", true) private _editor?: HaYamlEditor; @query("ha-yaml-editor", true) private _editor?: HaYamlEditor;
private _schema = memoizeOne( private _schema = memoizeOne(
(hasID: boolean, useBluePrint?: boolean, currentMode?: string) => { (
const schema: HaFormSchema[] = [ hasID: boolean,
useBluePrint?: boolean,
currentMode?: typeof MODES[number]
) =>
[
{ {
name: "alias", name: "alias",
selector: { selector: {
@ -102,49 +106,45 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) {
icon: {}, icon: {},
}, },
}, },
]; ...(!hasID
? ([
if (!hasID) { {
schema.push({ name: "id",
name: "id", selector: {
selector: { text: {},
text: {}, },
}, },
}); ] as const)
} : []),
...(!useBluePrint
if (!useBluePrint) { ? ([
schema.push({ {
name: "mode", name: "mode",
selector: { selector: {
select: { select: {
options: MODES.map((mode) => ({ options: MODES.map((mode) => ({
label: ` label: this.hass.localize(
${ `ui.panel.config.script.editor.modes.${mode}`
this.hass.localize( ),
`ui.panel.config.script.editor.modes.${mode}` value: mode,
) || mode })),
} },
`, },
value: mode, },
})), ] as const)
}, : []),
}, ...(currentMode && isMaxMode(currentMode)
}); ? ([
} {
name: "max",
if (currentMode && MODES_MAX.includes(currentMode)) { required: true,
schema.push({ selector: {
name: "max", number: { mode: "box", min: 1, max: Infinity },
required: true, },
selector: { },
number: { mode: "box", min: 1, max: Infinity }, ] as const)
}, : []),
}); ] as const
}
return schema;
}
); );
protected render(): TemplateResult { protected render(): TemplateResult {
@ -161,10 +161,7 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) {
const data = { const data = {
mode: MODES[0], mode: MODES[0],
icon: undefined, icon: undefined,
max: max: this._config.mode && isMaxMode(this._config.mode) ? 10 : undefined,
this._config.mode && MODES_MAX.includes(this._config.mode)
? 10
: undefined,
...this._config, ...this._config,
id: this._entityId, id: this._entityId,
}; };
@ -506,15 +503,18 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) {
} }
private _computeLabelCallback = ( private _computeLabelCallback = (
schema: HaFormSelector, schema: SchemaUnion<ReturnType<typeof this._schema>>,
data: HaFormDataContainer data: HaFormDataContainer
): string => { ): string => {
switch (schema.name) { switch (schema.name) {
case "mode": case "mode":
return this.hass.localize("ui.panel.config.script.editor.modes.label"); return this.hass.localize("ui.panel.config.script.editor.modes.label");
case "max": case "max":
// Mode must be one of max modes per schema definition above
return this.hass.localize( return this.hass.localize(
`ui.panel.config.script.editor.max.${data.mode}` `ui.panel.config.script.editor.max.${
data.mode as typeof MODES_MAX[number]
}`
); );
default: default:
return this.hass.localize( return this.hass.localize(
@ -524,7 +524,7 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) {
}; };
private _computeHelperCallback = ( private _computeHelperCallback = (
schema: HaFormSelector schema: SchemaUnion<ReturnType<typeof this._schema>>
): string | undefined => { ): string | undefined => {
if (schema.name === "mode") { if (schema.name === "mode") {
return this.hass.localize( return this.hass.localize(
@ -562,7 +562,7 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) {
private _modeChanged(mode) { private _modeChanged(mode) {
this._config = { ...this._config!, mode }; this._config = { ...this._config!, mode };
if (!MODES_MAX.includes(mode)) { if (!isMaxMode(mode)) {
delete this._config.max; delete this._config.max;
} }
this._dirty = true; this._dirty = true;

View File

@ -6,7 +6,7 @@ import { fireEvent } from "../../../common/dom/fire_event";
import { addDistanceToCoord } from "../../../common/location/add_distance_to_coord"; import { addDistanceToCoord } from "../../../common/location/add_distance_to_coord";
import { createCloseHeading } from "../../../components/ha-dialog"; import { createCloseHeading } from "../../../components/ha-dialog";
import "../../../components/ha-form/ha-form"; import "../../../components/ha-form/ha-form";
import { HaFormSchema } from "../../../components/ha-form/types"; import { SchemaUnion } from "../../../components/ha-form/types";
import { getZoneEditorInitData, ZoneMutableParams } from "../../../data/zone"; import { getZoneEditorInitData, ZoneMutableParams } from "../../../data/zone";
import { haStyleDialog } from "../../../resources/styles"; import { haStyleDialog } from "../../../resources/styles";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
@ -123,51 +123,54 @@ class DialogZoneDetail extends LitElement {
`; `;
} }
private _schema = memoizeOne((icon?: string): HaFormSchema[] => [ private _schema = memoizeOne(
{ (icon?: string) =>
name: "name", [
required: true,
selector: {
text: {},
},
},
{
name: "icon",
required: false,
selector: {
icon: {},
},
},
{
name: "location",
required: true,
selector: { location: { radius: true, icon } },
},
{
name: "",
type: "grid",
schema: [
{ {
name: "latitude", name: "name",
required: true, required: true,
selector: { text: {} }, selector: {
text: {},
},
}, },
{ {
name: "longitude", name: "icon",
required: false,
selector: {
icon: {},
},
},
{
name: "location",
required: true, required: true,
selector: { location: { radius: true, icon } },
},
{
name: "",
type: "grid",
schema: [
{
name: "latitude",
required: true,
selector: { text: {} },
},
{
name: "longitude",
required: true,
selector: { text: {} }, selector: { text: {} },
},
],
}, },
], { name: "passive_note", type: "constant" },
}, { name: "passive", selector: { boolean: {} } },
{ name: "passive_note", type: "constant" }, {
{ name: "passive", selector: { boolean: {} } }, name: "radius",
{ required: false,
name: "radius", selector: { number: { min: 0, max: 999999, mode: "box" } },
required: false, },
selector: { number: { min: 0, max: 999999, mode: "box" } }, ] as const
}, );
]);
private _formData = memoizeOne((data: ZoneMutableParams) => ({ private _formData = memoizeOne((data: ZoneMutableParams) => ({
...data, ...data,
@ -197,8 +200,9 @@ class DialogZoneDetail extends LitElement {
this._data = value; this._data = value;
} }
private _computeLabel = (entry: HaFormSchema): string => private _computeLabel = (
this.hass.localize(`ui.panel.config.zone.detail.${entry.name}`); entry: SchemaUnion<ReturnType<typeof this._schema>>
): string => this.hass.localize(`ui.panel.config.zone.detail.${entry.name}`);
private async _updateEntry() { private async _updateEntry() {
this._submitting = true; this._submitting = true;

View File

@ -8,13 +8,13 @@ import { fireEvent } from "../../../../common/dom/fire_event";
import { computeDomain } from "../../../../common/entity/compute_domain"; import { computeDomain } from "../../../../common/entity/compute_domain";
import { domainIcon } from "../../../../common/entity/domain_icon"; import { domainIcon } from "../../../../common/entity/domain_icon";
import type { LocalizeFunc } from "../../../../common/translations/localize"; import type { LocalizeFunc } from "../../../../common/translations/localize";
import type { HaFormSchema } from "../../../../components/ha-form/types"; import type { SchemaUnion } from "../../../../components/ha-form/types";
import type { HomeAssistant } from "../../../../types"; import type { HomeAssistant } from "../../../../types";
import type { EntitiesCardEntityConfig } from "../../cards/types"; import type { EntitiesCardEntityConfig } from "../../cards/types";
import type { LovelaceRowEditor } from "../../types"; import type { LovelaceRowEditor } from "../../types";
import { entitiesConfigStruct } from "../structs/entities-struct"; import { entitiesConfigStruct } from "../structs/entities-struct";
const SecondaryInfoValues: { [key: string]: { domains?: string[] } } = { const SecondaryInfoValues = {
none: {}, none: {},
"entity-id": {}, "entity-id": {},
"last-changed": {}, "last-changed": {},
@ -23,7 +23,7 @@ const SecondaryInfoValues: { [key: string]: { domains?: string[] } } = {
position: { domains: ["cover"] }, position: { domains: ["cover"] },
"tilt-position": { domains: ["cover"] }, "tilt-position": { domains: ["cover"] },
brightness: { domains: ["light"] }, brightness: { domains: ["light"] },
}; } as const;
@customElement("hui-generic-entity-row-editor") @customElement("hui-generic-entity-row-editor")
export class HuiGenericEntityRowEditor export class HuiGenericEntityRowEditor
@ -45,7 +45,7 @@ export class HuiGenericEntityRowEditor
icon: string | undefined, icon: string | undefined,
entityState: HassEntity, entityState: HassEntity,
localize: LocalizeFunc localize: LocalizeFunc
): HaFormSchema[] => { ) => {
const domain = computeDomain(entity); const domain = computeDomain(entity);
return [ return [
@ -73,23 +73,23 @@ export class HuiGenericEntityRowEditor
name: "secondary_info", name: "secondary_info",
selector: { selector: {
select: { select: {
options: Object.keys(SecondaryInfoValues) options: (
.filter( Object.keys(SecondaryInfoValues).filter(
(info) => (info) =>
!("domains" in SecondaryInfoValues[info]) || !("domains" in SecondaryInfoValues[info]) ||
("domains" in SecondaryInfoValues[info] && ("domains" in SecondaryInfoValues[info] &&
SecondaryInfoValues[info].domains!.includes(domain)) SecondaryInfoValues[info].domains!.includes(domain))
) ) as Array<keyof typeof SecondaryInfoValues>
.map((info) => ({ ).map((info) => ({
value: info, value: info,
label: localize( label: localize(
`ui.panel.lovelace.editor.card.entities.secondary_info_values.${info}` `ui.panel.lovelace.editor.card.entities.secondary_info_values.${info}`
), ),
})), })),
}, },
}, },
}, },
]; ] as const;
} }
); );
@ -122,21 +122,19 @@ export class HuiGenericEntityRowEditor
fireEvent(this, "config-changed", { config: ev.detail.value }); fireEvent(this, "config-changed", { config: ev.detail.value });
} }
private _computeLabelCallback = (schema: HaFormSchema) => { private _computeLabelCallback = (
if (schema.name === "entity") { schema: SchemaUnion<ReturnType<typeof this._schema>>
return this.hass!.localize( ) => {
"ui.panel.lovelace.editor.card.generic.entity" switch (schema.name) {
); case "secondary_info":
return this.hass!.localize(
`ui.panel.lovelace.editor.card.entity-row.${schema.name}`
);
default:
return this.hass!.localize(
`ui.panel.lovelace.editor.card.generic.${schema.name}`
);
} }
return (
this.hass!.localize(
`ui.panel.lovelace.editor.card.generic.${schema.name}`
) ||
this.hass!.localize(
`ui.panel.lovelace.editor.card.entity-row.${schema.name}`
)
);
}; };
} }

View File

@ -12,7 +12,7 @@ import {
} from "superstruct"; } from "superstruct";
import { fireEvent } from "../../../../common/dom/fire_event"; import { fireEvent } from "../../../../common/dom/fire_event";
import "../../../../components/entity/ha-entities-picker"; import "../../../../components/entity/ha-entities-picker";
import type { HaFormSchema } from "../../../../components/ha-form/types"; import type { SchemaUnion } from "../../../../components/ha-form/types";
import type { HomeAssistant } from "../../../../types"; import type { HomeAssistant } from "../../../../types";
import type { LogbookCardConfig } from "../../cards/types"; import type { LogbookCardConfig } from "../../cards/types";
import type { LovelaceCardEditor } from "../../types"; import type { LovelaceCardEditor } from "../../types";
@ -29,7 +29,7 @@ const cardConfigStruct = assign(
}) })
); );
const SCHEMA: HaFormSchema[] = [ const SCHEMA = [
{ name: "title", selector: { text: {} } }, { name: "title", selector: { text: {} } },
{ {
name: "", name: "",
@ -39,7 +39,7 @@ const SCHEMA: HaFormSchema[] = [
{ name: "hours_to_show", selector: { number: { mode: "box", min: 1 } } }, { name: "hours_to_show", selector: { number: { mode: "box", min: 1 } } },
], ],
}, },
]; ] as const;
@customElement("hui-logbook-card-editor") @customElement("hui-logbook-card-editor")
export class HuiLogbookCardEditor export class HuiLogbookCardEditor
@ -98,23 +98,19 @@ export class HuiLogbookCardEditor
fireEvent(this, "config-changed", { config: ev.detail.value }); fireEvent(this, "config-changed", { config: ev.detail.value });
} }
private _computeLabelCallback = (schema: HaFormSchema) => { private _computeLabelCallback = (schema: SchemaUnion<typeof SCHEMA>) => {
if (schema.name === "theme") { switch (schema.name) {
return `${this.hass!.localize( case "theme":
"ui.panel.lovelace.editor.card.generic.theme" return `${this.hass!.localize(
)} (${this.hass!.localize( "ui.panel.lovelace.editor.card.generic.theme"
"ui.panel.lovelace.editor.card.config.optional" )} (${this.hass!.localize(
)})`; "ui.panel.lovelace.editor.card.config.optional"
)})`;
default:
return this.hass!.localize(
`ui.panel.lovelace.editor.card.generic.${schema.name}`
);
} }
return (
this.hass!.localize(
`ui.panel.lovelace.editor.card.generic.${schema.name}`
) ||
this.hass!.localize(
`ui.panel.lovelace.editor.card.logbook.${schema.name}`
)
);
}; };
} }

View File

@ -26,7 +26,7 @@ import { entitiesConfigStruct } from "../structs/entities-struct";
import { EntitiesEditorEvent } from "../types"; import { EntitiesEditorEvent } from "../types";
import { configElementStyle } from "./config-elements-style"; import { configElementStyle } from "./config-elements-style";
import { baseLovelaceCardConfig } from "../structs/base-card-struct"; import { baseLovelaceCardConfig } from "../structs/base-card-struct";
import { HaFormSchema } from "../../../../components/ha-form/types"; import { SchemaUnion } from "../../../../components/ha-form/types";
const cardConfigStruct = assign( const cardConfigStruct = assign(
baseLovelaceCardConfig, baseLovelaceCardConfig,
@ -41,7 +41,7 @@ const cardConfigStruct = assign(
}) })
); );
const SCHEMA: HaFormSchema[] = [ const SCHEMA = [
{ name: "title", selector: { text: {} } }, { name: "title", selector: { text: {} } },
{ {
name: "", name: "",
@ -53,7 +53,7 @@ const SCHEMA: HaFormSchema[] = [
{ name: "hours_to_show", selector: { number: { mode: "box", min: 1 } } }, { name: "hours_to_show", selector: { number: { mode: "box", min: 1 } } },
], ],
}, },
]; ] as const;
@customElement("hui-map-card-editor") @customElement("hui-map-card-editor")
export class HuiMapCardEditor extends LitElement implements LovelaceCardEditor { export class HuiMapCardEditor extends LitElement implements LovelaceCardEditor {
@ -149,11 +149,19 @@ export class HuiMapCardEditor extends LitElement implements LovelaceCardEditor {
fireEvent(this, "config-changed", { config: ev.detail.value }); fireEvent(this, "config-changed", { config: ev.detail.value });
} }
private _computeLabelCallback = (schema: HaFormSchema) => private _computeLabelCallback = (schema: SchemaUnion<typeof SCHEMA>) => {
this.hass!.localize( switch (schema.name) {
`ui.panel.lovelace.editor.card.generic.${schema.name}` case "dark_mode":
) || case "default_zoom":
this.hass!.localize(`ui.panel.lovelace.editor.card.map.${schema.name}`); return this.hass!.localize(
`ui.panel.lovelace.editor.card.map.${schema.name}`
);
default:
return this.hass!.localize(
`ui.panel.lovelace.editor.card.generic.${schema.name}`
);
}
};
static get styles(): CSSResultGroup { static get styles(): CSSResultGroup {
return [ return [

View File

@ -16,7 +16,7 @@ import {
import { fireEvent } from "../../../../common/dom/fire_event"; import { fireEvent } from "../../../../common/dom/fire_event";
import { computeDomain } from "../../../../common/entity/compute_domain"; import { computeDomain } from "../../../../common/entity/compute_domain";
import { domainIcon } from "../../../../common/entity/domain_icon"; import { domainIcon } from "../../../../common/entity/domain_icon";
import type { HaFormSchema } from "../../../../components/ha-form/types"; import type { SchemaUnion } from "../../../../components/ha-form/types";
import type { HomeAssistant } from "../../../../types"; import type { HomeAssistant } from "../../../../types";
import type { SensorCardConfig } from "../../cards/types"; import type { SensorCardConfig } from "../../cards/types";
import type { LovelaceCardEditor } from "../../types"; import type { LovelaceCardEditor } from "../../types";
@ -52,61 +52,58 @@ export class HuiSensorCardEditor
} }
private _schema = memoizeOne( private _schema = memoizeOne(
( (entity: string, icon: string | undefined, entityState: HassEntity) =>
entity: string, [
icon: string | undefined, {
entityState: HassEntity name: "entity",
): HaFormSchema[] => [ selector: {
{ entity: { domain: ["counter", "input_number", "number", "sensor"] },
name: "entity", },
selector: {
entity: { domain: ["counter", "input_number", "number", "sensor"] },
}, },
}, { name: "name", selector: { text: {} } },
{ name: "name", selector: { text: {} } }, {
{ type: "grid",
type: "grid", name: "",
name: "", schema: [
schema: [ {
{ name: "icon",
name: "icon", selector: {
selector: { icon: {
icon: { placeholder: icon || entityState?.attributes.icon,
placeholder: icon || entityState?.attributes.icon, fallbackPath:
fallbackPath: !icon && !entityState?.attributes.icon && entityState
!icon && !entityState?.attributes.icon && entityState ? domainIcon(computeDomain(entity), entityState)
? domainIcon(computeDomain(entity), entityState) : undefined,
: undefined, },
}, },
}, },
}, {
{ name: "graph",
name: "graph", selector: {
selector: { select: {
select: { options: [
options: [ {
{ value: "none",
value: "none", label: "None",
label: "None", },
}, {
{ value: "line",
value: "line", label: "Line",
label: "Line", },
}, ],
], },
}, },
}, },
}, { name: "unit", selector: { text: {} } },
{ name: "unit", selector: { text: {} } }, { name: "detail", selector: { boolean: {} } },
{ name: "detail", selector: { boolean: {} } }, { name: "theme", selector: { theme: {} } },
{ name: "theme", selector: { theme: {} } }, {
{ name: "hours_to_show",
name: "hours_to_show", selector: { number: { min: 1, mode: "box" } },
selector: { number: { min: 1, mode: "box" } }, },
}, ],
], },
}, ] as const
]
); );
protected render(): TemplateResult { protected render(): TemplateResult {
@ -146,33 +143,29 @@ export class HuiSensorCardEditor
fireEvent(this, "config-changed", { config }); fireEvent(this, "config-changed", { config });
} }
private _computeLabelCallback = (schema: HaFormSchema) => { private _computeLabelCallback = (
if (schema.name === "entity") { schema: SchemaUnion<ReturnType<typeof this._schema>>
return this.hass!.localize( ) => {
"ui.panel.lovelace.editor.card.generic.entity" switch (schema.name) {
); case "theme":
return `${this.hass!.localize(
"ui.panel.lovelace.editor.card.generic.theme"
)} (${this.hass!.localize(
"ui.panel.lovelace.editor.card.config.optional"
)})`;
case "detail":
return this.hass!.localize(
"ui.panel.lovelace.editor.card.sensor.show_more_detail"
);
case "graph":
return this.hass!.localize(
"ui.panel.lovelace.editor.card.sensor.graph_type"
);
default:
return this.hass!.localize(
`ui.panel.lovelace.editor.card.generic.${schema.name}`
);
} }
if (schema.name === "theme") {
return `${this.hass!.localize(
"ui.panel.lovelace.editor.card.generic.theme"
)} (${this.hass!.localize(
"ui.panel.lovelace.editor.card.config.optional"
)})`;
}
if (schema.name === "detail") {
return this.hass!.localize(
"ui.panel.lovelace.editor.card.sensor.show_more_detail"
);
}
return (
this.hass!.localize(
`ui.panel.lovelace.editor.card.generic.${schema.name}`
) ||
this.hass!.localize(`ui.panel.lovelace.editor.card.sensor.${schema.name}`)
);
}; };
static get styles(): CSSResultGroup { static get styles(): CSSResultGroup {

View File

@ -16,7 +16,7 @@ import {
import { fireEvent } from "../../../../common/dom/fire_event"; import { fireEvent } from "../../../../common/dom/fire_event";
import type { LocalizeFunc } from "../../../../common/translations/localize"; import type { LocalizeFunc } from "../../../../common/translations/localize";
import "../../../../components/entity/ha-statistics-picker"; import "../../../../components/entity/ha-statistics-picker";
import type { HaFormSchema } from "../../../../components/ha-form/types"; import type { SchemaUnion } from "../../../../components/ha-form/types";
import type { HomeAssistant } from "../../../../types"; import type { HomeAssistant } from "../../../../types";
import type { StatisticsGraphCardConfig } from "../../cards/types"; import type { StatisticsGraphCardConfig } from "../../cards/types";
import { processConfigEntities } from "../../common/process-config-entities"; import { processConfigEntities } from "../../common/process-config-entities";
@ -50,7 +50,7 @@ const cardConfigStruct = assign(
}) })
); );
const periods = ["5minute", "hour", "day", "month"]; const periods = ["5minute", "hour", "day", "month"] as const;
@customElement("hui-statistics-graph-card-editor") @customElement("hui-statistics-graph-card-editor")
export class HuiStatisticsGraphCardEditor export class HuiStatisticsGraphCardEditor
@ -71,54 +71,57 @@ export class HuiStatisticsGraphCardEditor
: []; : [];
} }
private _schema = memoizeOne((localize: LocalizeFunc) => [ private _schema = memoizeOne(
{ name: "title", selector: { text: {} } }, (localize: LocalizeFunc) =>
{ [
name: "", { name: "title", selector: { text: {} } },
type: "grid",
schema: [
{ {
name: "period", name: "",
required: true, type: "grid",
selector: { schema: [
select: { {
options: periods.map((period) => ({ name: "period",
value: period, required: true,
label: localize( selector: {
`ui.panel.lovelace.editor.card.statistics-graph.periods.${period}` select: {
), options: periods.map((period) => ({
})), value: period,
label: localize(
`ui.panel.lovelace.editor.card.statistics-graph.periods.${period}`
),
})),
},
},
},
{
name: "days_to_show",
required: true,
selector: { number: { min: 1, mode: "box" } },
},
{
name: "stat_types",
required: true,
type: "multi_select",
options: [
["mean", "Mean"],
["min", "Min"],
["max", "Max"],
["sum", "Sum"],
],
},
{
name: "chart_type",
required: true,
type: "select",
options: [
["line", "Line"],
["bar", "Bar"],
],
}, },
},
},
{
name: "days_to_show",
required: true,
selector: { number: { min: 1, mode: "box" } },
},
{
name: "stat_types",
required: true,
type: "multi_select",
options: [
["mean", "Mean"],
["min", "Min"],
["max", "Max"],
["sum", "Sum"],
], ],
}, },
{ ] as const
name: "chart_type", );
required: true,
type: "select",
options: [
["line", "Line"],
["bar", "Bar"],
],
},
],
},
]);
protected render(): TemplateResult { protected render(): TemplateResult {
if (!this.hass || !this._config) { if (!this.hass || !this._config) {
@ -169,13 +172,22 @@ export class HuiStatisticsGraphCardEditor
}); });
} }
private _computeLabelCallback = (schema: HaFormSchema) => private _computeLabelCallback = (
this.hass!.localize( schema: SchemaUnion<ReturnType<typeof this._schema>>
`ui.panel.lovelace.editor.card.generic.${schema.name}` ) => {
) || switch (schema.name) {
this.hass!.localize( case "chart_type":
`ui.panel.lovelace.editor.card.statistics-graph.${schema.name}` case "stat_types":
); case "period":
return this.hass!.localize(
`ui.panel.lovelace.editor.card.statistics-graph.${schema.name}`
);
default:
return this.hass!.localize(
`ui.panel.lovelace.editor.card.generic.${schema.name}`
);
}
};
static styles: CSSResultGroup = css` static styles: CSSResultGroup = css`
ha-statistics-picker { ha-statistics-picker {

View File

@ -12,7 +12,7 @@ import { baseLovelaceCardConfig } from "../structs/base-card-struct";
import { UNAVAILABLE } from "../../../../data/entity"; import { UNAVAILABLE } from "../../../../data/entity";
import type { WeatherEntity } from "../../../../data/weather"; import type { WeatherEntity } from "../../../../data/weather";
import type { LocalizeFunc } from "../../../../common/translations/localize"; import type { LocalizeFunc } from "../../../../common/translations/localize";
import type { HaFormSchema } from "../../../../components/ha-form/types"; import type { SchemaUnion } from "../../../../components/ha-form/types";
const cardConfigStruct = assign( const cardConfigStruct = assign(
baseLovelaceCardConfig, baseLovelaceCardConfig,
@ -66,12 +66,8 @@ export class HuiWeatherForecastCardEditor
} }
private _schema = memoize( private _schema = memoize(
( (entity: string, localize: LocalizeFunc, hasForecast?: boolean) =>
entity: string, [
localize: LocalizeFunc,
hasForecast?: boolean
): HaFormSchema[] => {
const schema: HaFormSchema[] = [
{ {
name: "entity", name: "entity",
required: true, required: true,
@ -89,38 +85,38 @@ export class HuiWeatherForecastCardEditor
{ name: "theme", selector: { theme: {} } }, { name: "theme", selector: { theme: {} } },
], ],
}, },
]; ...(hasForecast
if (hasForecast) { ? ([
schema.push({ {
name: "forecast", name: "forecast",
selector: { selector: {
select: { select: {
options: [ options: [
{ {
value: "show_both", value: "show_both",
label: localize( label: localize(
"ui.panel.lovelace.editor.card.weather-forecast.show_both" "ui.panel.lovelace.editor.card.weather-forecast.show_both"
), ),
},
{
value: "show_current",
label: localize(
"ui.panel.lovelace.editor.card.weather-forecast.show_only_current"
),
},
{
value: "show_forecast",
label: localize(
"ui.panel.lovelace.editor.card.weather-forecast.show_only_forecast"
),
},
],
},
}, },
{ },
value: "show_current", ] as const)
label: localize( : []),
"ui.panel.lovelace.editor.card.weather-forecast.show_only_current" ] as const
),
},
{
value: "show_forecast",
label: localize(
"ui.panel.lovelace.editor.card.weather-forecast.show_only_forecast"
),
},
],
},
},
});
}
return schema;
}
); );
protected render(): TemplateResult { protected render(): TemplateResult {
@ -175,31 +171,31 @@ export class HuiWeatherForecastCardEditor
fireEvent(this, "config-changed", { config }); fireEvent(this, "config-changed", { config });
} }
private _computeLabelCallback = (schema: HaFormSchema) => { private _computeLabelCallback = (
if (schema.name === "entity") { schema: SchemaUnion<ReturnType<typeof this._schema>>
return `${this.hass!.localize( ) => {
"ui.panel.lovelace.editor.card.generic.entity" switch (schema.name) {
)} (${this.hass!.localize( case "entity":
"ui.panel.lovelace.editor.card.config.required" return `${this.hass!.localize(
)})`; "ui.panel.lovelace.editor.card.generic.entity"
)} (${this.hass!.localize(
"ui.panel.lovelace.editor.card.config.required"
)})`;
case "theme":
return `${this.hass!.localize(
"ui.panel.lovelace.editor.card.generic.theme"
)} (${this.hass!.localize(
"ui.panel.lovelace.editor.card.config.optional"
)})`;
case "forecast":
return this.hass!.localize(
"ui.panel.lovelace.editor.card.weather-forecast.weather_to_show"
);
default:
return this.hass!.localize(
`ui.panel.lovelace.editor.card.generic.${schema.name}`
);
} }
if (schema.name === "theme") {
return `${this.hass!.localize(
"ui.panel.lovelace.editor.card.generic.theme"
)} (${this.hass!.localize(
"ui.panel.lovelace.editor.card.config.optional"
)})`;
}
return (
this.hass!.localize(
`ui.panel.lovelace.editor.card.generic.${schema.name}`
) ||
this.hass!.localize(
`ui.panel.lovelace.editor.card.weather_forecast.${schema.name}`
)
);
}; };
} }

View File

@ -4,7 +4,8 @@ import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one"; import memoizeOne from "memoize-one";
import { fireEvent } from "../../../../common/dom/fire_event"; import { fireEvent } from "../../../../common/dom/fire_event";
import { slugify } from "../../../../common/string/slugify"; import { slugify } from "../../../../common/string/slugify";
import type { HaFormSchema } from "../../../../components/ha-form/types"; import type { LocalizeFunc } from "../../../../common/translations/localize";
import type { SchemaUnion } from "../../../../components/ha-form/types";
import type { LovelaceViewConfig } from "../../../../data/lovelace"; import type { LovelaceViewConfig } from "../../../../data/lovelace";
import type { HomeAssistant } from "../../../../types"; import type { HomeAssistant } from "../../../../types";
import { import {
@ -25,38 +26,43 @@ declare global {
export class HuiViewEditor extends LitElement { export class HuiViewEditor extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant; @property({ attribute: false }) public hass!: HomeAssistant;
@property() public isNew!: boolean; @property({ type: Boolean }) public isNew!: boolean;
@state() private _config!: LovelaceViewConfig; @state() private _config!: LovelaceViewConfig;
private _suggestedPath = false; private _suggestedPath = false;
private _schema = memoizeOne((localize): HaFormSchema[] => [ private _schema = memoizeOne(
{ name: "title", selector: { text: {} } }, (localize: LocalizeFunc) =>
{ [
name: "icon", { name: "title", selector: { text: {} } },
selector: { {
icon: {}, name: "icon",
}, selector: {
}, icon: {},
{ name: "path", selector: { text: {} } }, },
{ name: "theme", selector: { theme: {} } },
{
name: "type",
selector: {
select: {
options: [
DEFAULT_VIEW_LAYOUT,
SIDEBAR_VIEW_LAYOUT,
PANEL_VIEW_LAYOUT,
].map((type) => ({
value: type,
label: localize(`ui.panel.lovelace.editor.edit_view.types.${type}`),
})),
}, },
}, { name: "path", selector: { text: {} } },
}, { name: "theme", selector: { theme: {} } },
]); {
name: "type",
selector: {
select: {
options: [
DEFAULT_VIEW_LAYOUT,
SIDEBAR_VIEW_LAYOUT,
PANEL_VIEW_LAYOUT,
].map((type) => ({
value: type,
label: localize(
`ui.panel.lovelace.editor.edit_view.types.${type}`
),
})),
},
},
},
] as const
);
set config(config: LovelaceViewConfig) { set config(config: LovelaceViewConfig) {
this._config = config; this._config = config;
@ -114,15 +120,19 @@ export class HuiViewEditor extends LitElement {
fireEvent(this, "view-config-changed", { config }); fireEvent(this, "view-config-changed", { config });
} }
private _computeLabelCallback = (schema: HaFormSchema) => { private _computeLabelCallback = (
if (schema.name === "path") { schema: SchemaUnion<ReturnType<typeof this._schema>>
return this.hass!.localize(`ui.panel.lovelace.editor.card.generic.url`); ) => {
switch (schema.name) {
case "path":
return this.hass!.localize("ui.panel.lovelace.editor.card.generic.url");
case "type":
return this.hass.localize("ui.panel.lovelace.editor.edit_view.type");
default:
return this.hass!.localize(
`ui.panel.lovelace.editor.card.generic.${schema.name}`
);
} }
return (
this.hass!.localize(
`ui.panel.lovelace.editor.card.generic.${schema.name}`
) || this.hass.localize("ui.panel.lovelace.editor.edit_view.type")
);
}; };
} }

View File

@ -2274,6 +2274,7 @@
"parallel": "Max number of parallel runs" "parallel": "Max number of parallel runs"
}, },
"load_error_not_editable": "Only scripts inside scripts.yaml are editable.", "load_error_not_editable": "Only scripts inside scripts.yaml are editable.",
"load_error_unknown": "Error loading script ({err_no}).",
"delete_confirm": "Are you sure you want to delete this script?", "delete_confirm": "Are you sure you want to delete this script?",
"delete_script": "Delete script", "delete_script": "Delete script",
"save_script": "Save script", "save_script": "Save script",
@ -2756,6 +2757,7 @@
"name": "Name", "name": "Name",
"icon": "Icon", "icon": "Icon",
"icon_error_msg": "Icon should be in the format ''prefix:iconname'', for example: ''mdi:home''", "icon_error_msg": "Icon should be in the format ''prefix:iconname'', for example: ''mdi:home''",
"location": "Map Location",
"radius": "Radius", "radius": "Radius",
"latitude": "Latitude", "latitude": "Latitude",
"longitude": "Longitude", "longitude": "Longitude",
@ -3936,7 +3938,6 @@
"geo_location_sources": "Geolocation Sources", "geo_location_sources": "Geolocation Sources",
"dark_mode": "Dark Mode?", "dark_mode": "Dark Mode?",
"default_zoom": "Default Zoom", "default_zoom": "Default Zoom",
"hours_to_show": "Hours to Show",
"source": "Source", "source": "Source",
"description": "The Map card that allows you to display entities on a map." "description": "The Map card that allows you to display entities on a map."
}, },
@ -3992,6 +3993,7 @@
"weather-forecast": { "weather-forecast": {
"name": "Weather Forecast", "name": "Weather Forecast",
"description": "The Weather Forecast card displays the weather. Very useful to include on interfaces that people display on the wall.", "description": "The Weather Forecast card displays the weather. Very useful to include on interfaces that people display on the wall.",
"weather_to_show": "Weather to Show",
"show_both": "Show current Weather and Forecast", "show_both": "Show current Weather and Forecast",
"show_only_current": "Show only current Weather", "show_only_current": "Show only current Weather",
"show_only_forecast": "Show only Forecast" "show_only_forecast": "Show only Forecast"