diff --git a/src/components/ha-form/ha-form.ts b/src/components/ha-form/ha-form.ts index 7f962081c5..3f8553a21e 100644 --- a/src/components/ha-form/ha-form.ts +++ b/src/components/ha-form/ha-form.ts @@ -43,6 +43,8 @@ export class HaForm extends LitElement implements HaFormElement { @property() public computeHelper?: (schema: any) => string | undefined; + @property() public localizeValue?: (key: string) => string; + public focus() { const root = this.shadowRoot?.querySelector(".root"); if (!root) { @@ -88,6 +90,7 @@ export class HaForm extends LitElement implements HaFormElement { .disabled=${item.disabled || this.disabled || false} .placeholder=${item.required ? "" : item.default} .helper=${this._computeHelper(item)} + .localizeValue=${this.localizeValue} .required=${item.required || false} .context=${this._generateContext(item)} >` diff --git a/src/components/ha-selector/ha-selector-select.ts b/src/components/ha-selector/ha-selector-select.ts index aeff5d52a7..0d9222a266 100644 --- a/src/components/ha-selector/ha-selector-select.ts +++ b/src/components/ha-selector/ha-selector-select.ts @@ -28,6 +28,8 @@ export class HaSelectSelector extends LitElement { @property() public helper?: string; + @property() public localizeValue?: (key: string) => string; + @property({ type: Boolean }) public disabled = false; @property({ type: Boolean }) public required = true; @@ -39,9 +41,21 @@ export class HaSelectSelector extends LitElement { protected render() { const options = this.selector.select?.options.map((option) => - typeof option === "object" ? option : { value: option, label: option } + typeof option === "object" + ? (option as SelectOption) + : ({ value: option, label: option } as SelectOption) ) || []; + const translationKey = this.selector.select?.translation_key; + + if (this.localizeValue && translationKey) { + options.forEach((option) => { + option.label = + this.localizeValue!(`${translationKey}.options.${option.value}`) || + option.label; + }); + } + if (!this.selector.select?.custom_value && this._mode === "list") { if (!this.selector.select?.multiple) { return html` diff --git a/src/components/ha-selector/ha-selector.ts b/src/components/ha-selector/ha-selector.ts index e76253f057..1f44b3503f 100644 --- a/src/components/ha-selector/ha-selector.ts +++ b/src/components/ha-selector/ha-selector.ts @@ -51,6 +51,8 @@ export class HaSelector extends LitElement { @property() public helper?: string; + @property() public localizeValue?: (key: string) => string; + @property() public placeholder?: any; @property({ type: Boolean }) public disabled = false; @@ -86,6 +88,7 @@ export class HaSelector extends LitElement { required: this.required, helper: this.helper, context: this.context, + localizeValue: this.localizeValue, id: "selector", })} `; diff --git a/src/data/selector.ts b/src/data/selector.ts index b55c97a6b5..e8012b49d1 100644 --- a/src/data/selector.ts +++ b/src/data/selector.ts @@ -215,6 +215,7 @@ export interface SelectSelector { custom_value?: boolean; mode?: "list" | "dropdown"; options: readonly string[] | readonly SelectOption[]; + translation_key?: string; } | null; } diff --git a/src/data/translation.ts b/src/data/translation.ts index 1d3f5c2d71..b0030c0605 100644 --- a/src/data/translation.ts +++ b/src/data/translation.ts @@ -54,7 +54,8 @@ export type TranslationCategory = | "system_health" | "device_class" | "application_credentials" - | "issues"; + | "issues" + | "selector"; export const fetchTranslationPreferences = (hass: HomeAssistant) => fetchFrontendUserData(hass.connection, "language"); diff --git a/src/dialogs/config-flow/show-dialog-config-flow.ts b/src/dialogs/config-flow/show-dialog-config-flow.ts index f176cef51d..1eb007976c 100644 --- a/src/dialogs/config-flow/show-dialog-config-flow.ts +++ b/src/dialogs/config-flow/show-dialog-config-flow.ts @@ -24,6 +24,7 @@ export const showConfigFlowDialog = ( const [step] = await Promise.all([ createConfigFlow(hass, handler), hass.loadBackendTranslation("config", handler), + hass.loadBackendTranslation("selector", handler), // Used as fallback if no header defined for step hass.loadBackendTranslation("title", handler), ]); @@ -32,6 +33,7 @@ export const showConfigFlowDialog = ( fetchFlow: async (hass, flowId) => { const step = await fetchConfigFlow(hass, flowId); await hass.loadBackendTranslation("config", step.handler); + await hass.loadBackendTranslation("selector", step.handler); return step; }, handleFlowStep: handleConfigFlowStep, @@ -95,6 +97,10 @@ export const showConfigFlowDialog = ( ); }, + renderShowFormStepFieldLocalizeValue(hass, step, key) { + return hass.localize(`component.${step.handler}.selector.${key}`); + }, + renderExternalStepHeader(hass, step) { return ( hass.localize( diff --git a/src/dialogs/config-flow/show-dialog-data-entry-flow.ts b/src/dialogs/config-flow/show-dialog-data-entry-flow.ts index a3de1caf34..d685cf228b 100644 --- a/src/dialogs/config-flow/show-dialog-data-entry-flow.ts +++ b/src/dialogs/config-flow/show-dialog-data-entry-flow.ts @@ -61,6 +61,12 @@ export interface FlowConfig { error: string ): string; + renderShowFormStepFieldLocalizeValue( + hass: HomeAssistant, + step: DataEntryFlowStepForm, + key: string + ): string; + renderExternalStepHeader( hass: HomeAssistant, step: DataEntryFlowStepExternal diff --git a/src/dialogs/config-flow/show-dialog-options-flow.ts b/src/dialogs/config-flow/show-dialog-options-flow.ts index 3fe29126bb..42aa2a25ab 100644 --- a/src/dialogs/config-flow/show-dialog-options-flow.ts +++ b/src/dialogs/config-flow/show-dialog-options-flow.ts @@ -32,6 +32,7 @@ export const showOptionsFlowDialog = ( const [step] = await Promise.all([ createOptionsFlow(hass, handler), hass.loadBackendTranslation("options", configEntry.domain), + hass.loadBackendTranslation("selector", configEntry.domain), ]); return step; }, @@ -39,6 +40,7 @@ export const showOptionsFlowDialog = ( const [step] = await Promise.all([ fetchOptionsFlow(hass, flowId), hass.loadBackendTranslation("options", configEntry.domain), + hass.loadBackendTranslation("selector", configEntry.domain), ]); return step; }, @@ -109,6 +111,10 @@ export const showOptionsFlowDialog = ( ); }, + renderShowFormStepFieldLocalizeValue(hass, _step, key) { + return hass.localize(`component.${configEntry.domain}.selector.${key}`); + }, + renderExternalStepHeader(_hass, _step) { return ""; }, diff --git a/src/dialogs/config-flow/step-flow-form.ts b/src/dialogs/config-flow/step-flow-form.ts index 1a5581db86..21511ef6e6 100644 --- a/src/dialogs/config-flow/step-flow-form.ts +++ b/src/dialogs/config-flow/step-flow-form.ts @@ -57,6 +57,7 @@ class StepFlowForm extends LitElement { .computeLabel=${this._labelCallback} .computeHelper=${this._helperCallback} .computeError=${this._errorCallback} + .localizeValue=${this._localizeValueCallback} >
@@ -174,6 +175,13 @@ class StepFlowForm extends LitElement { private _errorCallback = (error: string) => this.flowConfig.renderShowFormStepFieldError(this.hass, this.step, error); + private _localizeValueCallback = (key: string) => + this.flowConfig.renderShowFormStepFieldLocalizeValue( + this.hass, + this.step, + key + ); + static get styles(): CSSResultGroup { return [ configFlowContentStyles, diff --git a/src/panels/config/repairs/show-dialog-repair-flow.ts b/src/panels/config/repairs/show-dialog-repair-flow.ts index 3e3b3b354a..575530eaf3 100644 --- a/src/panels/config/repairs/show-dialog-repair-flow.ts +++ b/src/panels/config/repairs/show-dialog-repair-flow.ts @@ -32,6 +32,7 @@ export const showRepairsFlowDialog = ( const [step] = await Promise.all([ createRepairsFlow(hass, handler, issue.issue_id), hass.loadBackendTranslation("issues", issue.domain), + hass.loadBackendTranslation("selector", issue.domain), ]); return step; }, @@ -39,6 +40,7 @@ export const showRepairsFlowDialog = ( const [step] = await Promise.all([ fetchRepairsFlow(hass, flowId), hass.loadBackendTranslation("issues", issue.domain), + hass.loadBackendTranslation("selector", issue.domain), ]); return step; }, @@ -122,6 +124,10 @@ export const showRepairsFlowDialog = ( ); }, + renderShowFormStepFieldLocalizeValue(hass, _step, key) { + return hass.localize(`component.${issue.domain}.selector.${key}`); + }, + renderExternalStepHeader(_hass, _step) { return ""; },