mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-16 05:46:35 +00:00
Uses backend translation for climate attributes (#14827)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
This commit is contained in:
parent
c6aa2886ed
commit
0e70b866ae
52
src/common/entity/compute_attribute_display.ts
Normal file
52
src/common/entity/compute_attribute_display.ts
Normal file
@ -0,0 +1,52 @@
|
||||
import { HassEntity } from "home-assistant-js-websocket";
|
||||
import { EntityRegistryEntry } from "../../data/entity_registry";
|
||||
import { HomeAssistant } from "../../types";
|
||||
import { LocalizeFunc } from "../translations/localize";
|
||||
import { computeDomain } from "./compute_domain";
|
||||
|
||||
export const computeAttributeValueDisplay = (
|
||||
localize: LocalizeFunc,
|
||||
stateObj: HassEntity,
|
||||
entities: HomeAssistant["entities"],
|
||||
attribute: string,
|
||||
value?: any
|
||||
): string => {
|
||||
const entityId = stateObj.entity_id;
|
||||
const attributeValue =
|
||||
value !== undefined ? value : stateObj.attributes[attribute];
|
||||
const domain = computeDomain(entityId);
|
||||
const entity = entities[entityId] as EntityRegistryEntry | undefined;
|
||||
const translationKey = entity?.translation_key;
|
||||
|
||||
return (
|
||||
(translationKey &&
|
||||
localize(
|
||||
`component.${entity.platform}.entity.${domain}.${translationKey}.state_attributes.${attribute}.state.${attributeValue}`
|
||||
)) ||
|
||||
localize(
|
||||
`component.${domain}.state_attributes._.${attribute}.state.${attributeValue}`
|
||||
) ||
|
||||
attributeValue
|
||||
);
|
||||
};
|
||||
|
||||
export const computeAttributeNameDisplay = (
|
||||
localize: LocalizeFunc,
|
||||
stateObj: HassEntity,
|
||||
entities: HomeAssistant["entities"],
|
||||
attribute: string
|
||||
): string => {
|
||||
const entityId = stateObj.entity_id;
|
||||
const domain = computeDomain(entityId);
|
||||
const entity = entities[entityId] as EntityRegistryEntry | undefined;
|
||||
const translationKey = entity?.translation_key;
|
||||
|
||||
return (
|
||||
(translationKey &&
|
||||
localize(
|
||||
`component.${entity.platform}.entity.${domain}.${translationKey}.state_attributes.${attribute}.name`
|
||||
)) ||
|
||||
localize(`component.${domain}.state_attributes._.${attribute}.name`) ||
|
||||
attribute
|
||||
);
|
||||
};
|
@ -1,5 +1,7 @@
|
||||
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import { computeAttributeValueDisplay } from "../common/entity/compute_attribute_display";
|
||||
import { computeStateDisplay } from "../common/entity/compute_state_display";
|
||||
import { formatNumber } from "../common/number/format_number";
|
||||
import { ClimateEntity, CLIMATE_PRESET_NONE } from "../data/climate";
|
||||
import { isUnavailableState } from "../data/entity";
|
||||
@ -21,9 +23,12 @@ class HaClimateState extends LitElement {
|
||||
${this.stateObj.attributes.preset_mode &&
|
||||
this.stateObj.attributes.preset_mode !== CLIMATE_PRESET_NONE
|
||||
? html`-
|
||||
${this.hass.localize(
|
||||
`state_attributes.climate.preset_mode.${this.stateObj.attributes.preset_mode}`
|
||||
) || this.stateObj.attributes.preset_mode}`
|
||||
${computeAttributeValueDisplay(
|
||||
this.hass.localize,
|
||||
this.stateObj,
|
||||
this.hass.entities,
|
||||
"preset_mode"
|
||||
)}`
|
||||
: ""}
|
||||
</span>
|
||||
<div class="unit">${this._computeTarget()}</div>`
|
||||
@ -112,13 +117,19 @@ class HaClimateState extends LitElement {
|
||||
return this.hass.localize(`state.default.${this.stateObj.state}`);
|
||||
}
|
||||
|
||||
const stateString = this.hass.localize(
|
||||
`component.climate.state._.${this.stateObj.state}`
|
||||
const stateString = computeStateDisplay(
|
||||
this.hass.localize,
|
||||
this.stateObj,
|
||||
this.hass.locale,
|
||||
this.hass.entities
|
||||
);
|
||||
|
||||
return this.stateObj.attributes.hvac_action
|
||||
? `${this.hass.localize(
|
||||
`state_attributes.climate.hvac_action.${this.stateObj.attributes.hvac_action}`
|
||||
? `${computeAttributeValueDisplay(
|
||||
this.hass.localize,
|
||||
this.stateObj,
|
||||
this.hass.entities,
|
||||
"hvac_action"
|
||||
)} (${stateString})`
|
||||
: stateString;
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ import {
|
||||
HassEntityAttributeBase,
|
||||
HassEntityBase,
|
||||
} from "home-assistant-js-websocket";
|
||||
import { TranslationDict } from "../types";
|
||||
|
||||
export type HvacMode =
|
||||
| "off"
|
||||
@ -15,12 +14,13 @@ export type HvacMode =
|
||||
|
||||
export const CLIMATE_PRESET_NONE = "none";
|
||||
|
||||
type ClimateAttributes = TranslationDict["state_attributes"]["climate"];
|
||||
export type HvacAction = keyof ClimateAttributes["hvac_action"];
|
||||
export type FanMode = keyof ClimateAttributes["fan_mode"];
|
||||
export type PresetMode =
|
||||
| keyof ClimateAttributes["preset_mode"]
|
||||
| typeof CLIMATE_PRESET_NONE;
|
||||
export type HvacAction =
|
||||
| "off"
|
||||
| "heating"
|
||||
| "cooling"
|
||||
| "drying"
|
||||
| "idle"
|
||||
| "fan";
|
||||
|
||||
export type ClimateEntity = HassEntityBase & {
|
||||
attributes: HassEntityAttributeBase & {
|
||||
@ -40,23 +40,25 @@ export type ClimateEntity = HassEntityBase & {
|
||||
target_humidity_high?: number;
|
||||
min_humidity?: number;
|
||||
max_humidity?: number;
|
||||
fan_mode?: FanMode;
|
||||
fan_modes?: FanMode[];
|
||||
preset_mode?: PresetMode;
|
||||
preset_modes?: PresetMode[];
|
||||
fan_mode?: string;
|
||||
fan_modes?: string[];
|
||||
preset_mode?: string;
|
||||
preset_modes?: string[];
|
||||
swing_mode?: string;
|
||||
swing_modes?: string[];
|
||||
aux_heat?: "on" | "off";
|
||||
};
|
||||
};
|
||||
|
||||
export const CLIMATE_SUPPORT_TARGET_TEMPERATURE = 1;
|
||||
export const CLIMATE_SUPPORT_TARGET_TEMPERATURE_RANGE = 2;
|
||||
export const CLIMATE_SUPPORT_TARGET_HUMIDITY = 4;
|
||||
export const CLIMATE_SUPPORT_FAN_MODE = 8;
|
||||
export const CLIMATE_SUPPORT_PRESET_MODE = 16;
|
||||
export const CLIMATE_SUPPORT_SWING_MODE = 32;
|
||||
export const CLIMATE_SUPPORT_AUX_HEAT = 64;
|
||||
export const enum ClimateEntityFeature {
|
||||
TARGET_TEMPERATURE = 1,
|
||||
TARGET_TEMPERATURE_RANGE = 2,
|
||||
TARGET_HUMIDITY = 4,
|
||||
FAN_MODE = 8,
|
||||
PRESET_MODE = 16,
|
||||
SWING_MODE = 32,
|
||||
AUX_HEAT = 64,
|
||||
}
|
||||
|
||||
const hvacModeOrdering: { [key in HvacMode]: number } = {
|
||||
auto: 1,
|
||||
|
@ -44,6 +44,7 @@ declare global {
|
||||
export type TranslationCategory =
|
||||
| "title"
|
||||
| "state"
|
||||
| "state_attributes"
|
||||
| "entity"
|
||||
| "config"
|
||||
| "config_panel"
|
||||
|
@ -11,6 +11,11 @@ import { property } from "lit/decorators";
|
||||
import { classMap } from "lit/directives/class-map";
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
import { stopPropagation } from "../../../common/dom/stop_propagation";
|
||||
import {
|
||||
computeAttributeNameDisplay,
|
||||
computeAttributeValueDisplay,
|
||||
} from "../../../common/entity/compute_attribute_display";
|
||||
import { computeStateDisplay } from "../../../common/entity/compute_state_display";
|
||||
import { supportsFeature } from "../../../common/entity/supports-feature";
|
||||
import { computeRTLDirection } from "../../../common/util/compute_rtl";
|
||||
import "../../../components/ha-climate-control";
|
||||
@ -19,13 +24,7 @@ import "../../../components/ha-slider";
|
||||
import "../../../components/ha-switch";
|
||||
import {
|
||||
ClimateEntity,
|
||||
CLIMATE_SUPPORT_AUX_HEAT,
|
||||
CLIMATE_SUPPORT_FAN_MODE,
|
||||
CLIMATE_SUPPORT_PRESET_MODE,
|
||||
CLIMATE_SUPPORT_SWING_MODE,
|
||||
CLIMATE_SUPPORT_TARGET_HUMIDITY,
|
||||
CLIMATE_SUPPORT_TARGET_TEMPERATURE,
|
||||
CLIMATE_SUPPORT_TARGET_TEMPERATURE_RANGE,
|
||||
ClimateEntityFeature,
|
||||
compareClimateHvacModes,
|
||||
} from "../../../data/climate";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
@ -47,26 +46,32 @@ class MoreInfoClimate extends LitElement {
|
||||
|
||||
const supportTargetTemperature = supportsFeature(
|
||||
stateObj,
|
||||
CLIMATE_SUPPORT_TARGET_TEMPERATURE
|
||||
ClimateEntityFeature.TARGET_TEMPERATURE
|
||||
);
|
||||
const supportTargetTemperatureRange = supportsFeature(
|
||||
stateObj,
|
||||
CLIMATE_SUPPORT_TARGET_TEMPERATURE_RANGE
|
||||
ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
|
||||
);
|
||||
const supportTargetHumidity = supportsFeature(
|
||||
stateObj,
|
||||
CLIMATE_SUPPORT_TARGET_HUMIDITY
|
||||
ClimateEntityFeature.TARGET_HUMIDITY
|
||||
);
|
||||
const supportFanMode = supportsFeature(
|
||||
stateObj,
|
||||
ClimateEntityFeature.FAN_MODE
|
||||
);
|
||||
const supportFanMode = supportsFeature(stateObj, CLIMATE_SUPPORT_FAN_MODE);
|
||||
const supportPresetMode = supportsFeature(
|
||||
stateObj,
|
||||
CLIMATE_SUPPORT_PRESET_MODE
|
||||
ClimateEntityFeature.PRESET_MODE
|
||||
);
|
||||
const supportSwingMode = supportsFeature(
|
||||
stateObj,
|
||||
CLIMATE_SUPPORT_SWING_MODE
|
||||
ClimateEntityFeature.SWING_MODE
|
||||
);
|
||||
const supportAuxHeat = supportsFeature(
|
||||
stateObj,
|
||||
ClimateEntityFeature.AUX_HEAT
|
||||
);
|
||||
const supportAuxHeat = supportsFeature(stateObj, CLIMATE_SUPPORT_AUX_HEAT);
|
||||
|
||||
const temperatureStepSize =
|
||||
stateObj.attributes.target_temp_step ||
|
||||
@ -94,7 +99,12 @@ class MoreInfoClimate extends LitElement {
|
||||
${supportTargetTemperature || supportTargetTemperatureRange
|
||||
? html`
|
||||
<div>
|
||||
${hass.localize("ui.card.climate.target_temperature")}
|
||||
${computeAttributeNameDisplay(
|
||||
hass.localize,
|
||||
stateObj,
|
||||
hass.entities,
|
||||
"temperature"
|
||||
)}
|
||||
</div>
|
||||
`
|
||||
: ""}
|
||||
@ -145,7 +155,14 @@ class MoreInfoClimate extends LitElement {
|
||||
${supportTargetHumidity
|
||||
? html`
|
||||
<div class="container-humidity">
|
||||
<div>${hass.localize("ui.card.climate.target_humidity")}</div>
|
||||
<div>
|
||||
${computeAttributeNameDisplay(
|
||||
hass.localize,
|
||||
stateObj,
|
||||
hass.entities,
|
||||
"humidity"
|
||||
)}
|
||||
</div>
|
||||
<div class="single-row">
|
||||
<div class="target-humidity">
|
||||
${stateObj.attributes.humidity} %
|
||||
@ -182,7 +199,13 @@ class MoreInfoClimate extends LitElement {
|
||||
.map(
|
||||
(mode) => html`
|
||||
<mwc-list-item .value=${mode}>
|
||||
${hass.localize(`component.climate.state._.${mode}`)}
|
||||
${computeStateDisplay(
|
||||
hass.localize,
|
||||
stateObj,
|
||||
hass.locale,
|
||||
hass.entities,
|
||||
mode
|
||||
)}
|
||||
</mwc-list-item>
|
||||
`
|
||||
)}
|
||||
@ -194,7 +217,12 @@ class MoreInfoClimate extends LitElement {
|
||||
? html`
|
||||
<div class="container-preset_modes">
|
||||
<ha-select
|
||||
.label=${hass.localize("ui.card.climate.preset_mode")}
|
||||
.label=${computeAttributeNameDisplay(
|
||||
hass.localize,
|
||||
stateObj,
|
||||
hass.entities,
|
||||
"preset_mode"
|
||||
)}
|
||||
.value=${stateObj.attributes.preset_mode}
|
||||
fixedMenuPosition
|
||||
naturalMenuWidth
|
||||
@ -204,9 +232,13 @@ class MoreInfoClimate extends LitElement {
|
||||
${stateObj.attributes.preset_modes!.map(
|
||||
(mode) => html`
|
||||
<mwc-list-item .value=${mode}>
|
||||
${hass.localize(
|
||||
`state_attributes.climate.preset_mode.${mode}`
|
||||
) || mode}
|
||||
${computeAttributeValueDisplay(
|
||||
hass.localize,
|
||||
stateObj,
|
||||
hass.entities,
|
||||
"preset_mode",
|
||||
mode
|
||||
)}
|
||||
</mwc-list-item>
|
||||
`
|
||||
)}
|
||||
@ -218,7 +250,12 @@ class MoreInfoClimate extends LitElement {
|
||||
? html`
|
||||
<div class="container-fan_list">
|
||||
<ha-select
|
||||
.label=${hass.localize("ui.card.climate.fan_mode")}
|
||||
.label=${computeAttributeNameDisplay(
|
||||
hass.localize,
|
||||
stateObj,
|
||||
hass.entities,
|
||||
"fan_mode"
|
||||
)}
|
||||
.value=${stateObj.attributes.fan_mode}
|
||||
fixedMenuPosition
|
||||
naturalMenuWidth
|
||||
@ -228,9 +265,13 @@ class MoreInfoClimate extends LitElement {
|
||||
${stateObj.attributes.fan_modes!.map(
|
||||
(mode) => html`
|
||||
<mwc-list-item .value=${mode}>
|
||||
${hass.localize(
|
||||
`state_attributes.climate.fan_mode.${mode}`
|
||||
) || mode}
|
||||
${computeAttributeValueDisplay(
|
||||
hass.localize,
|
||||
stateObj,
|
||||
hass.entities,
|
||||
"fan_mode",
|
||||
mode
|
||||
)}
|
||||
</mwc-list-item>
|
||||
`
|
||||
)}
|
||||
@ -242,7 +283,12 @@ class MoreInfoClimate extends LitElement {
|
||||
? html`
|
||||
<div class="container-swing_list">
|
||||
<ha-select
|
||||
.label=${hass.localize("ui.card.climate.swing_mode")}
|
||||
.label=${computeAttributeNameDisplay(
|
||||
hass.localize,
|
||||
stateObj,
|
||||
hass.entities,
|
||||
"swing_mode"
|
||||
)}
|
||||
.value=${stateObj.attributes.swing_mode}
|
||||
fixedMenuPosition
|
||||
naturalMenuWidth
|
||||
@ -251,7 +297,15 @@ class MoreInfoClimate extends LitElement {
|
||||
>
|
||||
${stateObj.attributes.swing_modes!.map(
|
||||
(mode) => html`
|
||||
<mwc-list-item .value=${mode}>${mode}</mwc-list-item>
|
||||
<mwc-list-item .value=${mode}>
|
||||
${computeAttributeValueDisplay(
|
||||
hass.localize,
|
||||
stateObj,
|
||||
hass.entities,
|
||||
"swing_mode",
|
||||
mode
|
||||
)}
|
||||
</mwc-list-item>
|
||||
`
|
||||
)}
|
||||
</ha-select>
|
||||
@ -263,7 +317,12 @@ class MoreInfoClimate extends LitElement {
|
||||
<div class="container-aux_heat">
|
||||
<div class="center horizontal layout single-row">
|
||||
<div class="flex">
|
||||
${hass.localize("ui.card.climate.aux_heat")}
|
||||
${computeAttributeNameDisplay(
|
||||
hass.localize,
|
||||
stateObj,
|
||||
hass.entities,
|
||||
"aux_heat"
|
||||
)}
|
||||
</div>
|
||||
<ha-switch
|
||||
.checked=${stateObj.attributes.aux_heat === "on"}
|
||||
|
@ -138,6 +138,8 @@ export class HomeAssistantAppEl extends QuickBarMixin(HassElement) {
|
||||
// @ts-ignore
|
||||
this._loadHassTranslations(this.hass!.language, "state");
|
||||
// @ts-ignore
|
||||
this._loadHassTranslations(this.hass!.language, "state_attributes");
|
||||
// @ts-ignore
|
||||
this._loadHassTranslations(this.hass!.language, "entity");
|
||||
|
||||
document.addEventListener(
|
||||
|
@ -24,6 +24,8 @@ import { classMap } from "lit/directives/class-map";
|
||||
import { UNIT_F } from "../../../common/const";
|
||||
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
import { computeAttributeValueDisplay } from "../../../common/entity/compute_attribute_display";
|
||||
import { computeStateDisplay } from "../../../common/entity/compute_state_display";
|
||||
import { computeStateName } from "../../../common/entity/compute_state_name";
|
||||
import { formatNumber } from "../../../common/number/format_number";
|
||||
import "../../../components/ha-card";
|
||||
@ -213,11 +215,17 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
|
||||
>
|
||||
${
|
||||
stateObj.attributes.hvac_action
|
||||
? this.hass!.localize(
|
||||
`state_attributes.climate.hvac_action.${stateObj.attributes.hvac_action}`
|
||||
? computeAttributeValueDisplay(
|
||||
this.hass.localize,
|
||||
stateObj,
|
||||
this.hass.entities,
|
||||
"hvac_action"
|
||||
)
|
||||
: this.hass!.localize(
|
||||
`component.climate.state._.${stateObj.state}`
|
||||
: computeStateDisplay(
|
||||
this.hass.localize,
|
||||
stateObj,
|
||||
this.hass.locale,
|
||||
this.hass.entities
|
||||
)
|
||||
}
|
||||
${
|
||||
@ -225,9 +233,12 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
|
||||
stateObj.attributes.preset_mode !== CLIMATE_PRESET_NONE
|
||||
? html`
|
||||
-
|
||||
${this.hass!.localize(
|
||||
`state_attributes.climate.preset_mode.${stateObj.attributes.preset_mode}`
|
||||
) || stateObj.attributes.preset_mode}
|
||||
${computeAttributeValueDisplay(
|
||||
this.hass.localize,
|
||||
stateObj,
|
||||
this.hass.entities,
|
||||
"preset_mode"
|
||||
)}
|
||||
`
|
||||
: ""
|
||||
}
|
||||
|
@ -22,31 +22,6 @@
|
||||
}
|
||||
},
|
||||
"state_attributes": {
|
||||
"climate": {
|
||||
"fan_mode": {
|
||||
"off": "Off",
|
||||
"on": "On",
|
||||
"auto": "Auto"
|
||||
},
|
||||
"preset_mode": {
|
||||
"none": "None",
|
||||
"eco": "Eco",
|
||||
"away": "Away",
|
||||
"boost": "Boost",
|
||||
"comfort": "Comfort",
|
||||
"home": "Home",
|
||||
"sleep": "Sleep",
|
||||
"activity": "Activity"
|
||||
},
|
||||
"hvac_action": {
|
||||
"off": "Off",
|
||||
"heating": "Heating",
|
||||
"cooling": "Cooling",
|
||||
"drying": "Drying",
|
||||
"idle": "Idle",
|
||||
"fan": "Fan"
|
||||
}
|
||||
},
|
||||
"humidifier": {
|
||||
"mode": {
|
||||
"normal": "Normal",
|
||||
@ -140,7 +115,6 @@
|
||||
"climate": {
|
||||
"currently": "Currently",
|
||||
"on_off": "On / off",
|
||||
"target_temperature": "Target temperature",
|
||||
"target_temperature_entity": "{name} target temperature",
|
||||
"target_temperature_mode": "{name} target temperature {mode}",
|
||||
"current_temperature": "{name} current temperature",
|
||||
@ -148,13 +122,8 @@
|
||||
"cooling": "{name} cooling",
|
||||
"high": "high",
|
||||
"low": "low",
|
||||
"target_humidity": "Target humidity",
|
||||
"operation": "Operation",
|
||||
"fan_mode": "Fan mode",
|
||||
"swing_mode": "Swing mode",
|
||||
"preset_mode": "Preset",
|
||||
"away_mode": "Away mode",
|
||||
"aux_heat": "Aux heat"
|
||||
"away_mode": "Away mode"
|
||||
},
|
||||
"counter": {
|
||||
"actions": {
|
||||
|
Loading…
x
Reference in New Issue
Block a user