Add support for service translations (#17264)

* Add support for service translations

* Add selector translation support
This commit is contained in:
Bram Kragten 2023-07-11 02:37:04 +02:00 committed by GitHub
parent bf4cf310f3
commit e46f0224c6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 67 additions and 48 deletions

View File

@ -89,6 +89,10 @@ export class HaServiceControl extends LitElement {
@query("ha-yaml-editor") private _yamlEditor?: HaYamlEditor; @query("ha-yaml-editor") private _yamlEditor?: HaYamlEditor;
protected willUpdate(changedProperties: PropertyValues<this>) { protected willUpdate(changedProperties: PropertyValues<this>) {
if (!this.hasUpdated) {
this.hass.loadBackendTranslation("services");
this.hass.loadBackendTranslation("selector");
}
if (!changedProperties.has("value")) { if (!changedProperties.has("value")) {
return; return;
} }
@ -342,6 +346,20 @@ export class HaServiceControl extends LitElement {
const filteredFields = this._filterFields(serviceData, this._value); const filteredFields = this._filterFields(serviceData, this._value);
const domain = this._value?.service
? computeDomain(this._value.service)
: undefined;
const serviceName = this._value?.service
? computeObjectId(this._value.service)
: undefined;
const description =
(serviceName &&
this.hass.localize(
`component.${domain}.services.${serviceName}.description`
)) ||
serviceData?.description;
return html`<ha-service-picker return html`<ha-service-picker
.hass=${this.hass} .hass=${this.hass}
.value=${this._value?.service} .value=${this._value?.service}
@ -349,9 +367,7 @@ export class HaServiceControl extends LitElement {
@value-changed=${this._serviceChanged} @value-changed=${this._serviceChanged}
></ha-service-picker> ></ha-service-picker>
<div class="description"> <div class="description">
${serviceData?.description ${description ? html`<p>${description}</p>` : ""}
? html`<p>${serviceData?.description}</p>`
: ""}
${this._manifest ${this._manifest
? html` <a ? html` <a
href=${this._manifest.is_built_in href=${this._manifest.is_built_in
@ -402,7 +418,9 @@ export class HaServiceControl extends LitElement {
.hass=${this.hass} .hass=${this.hass}
.disabled=${this.disabled} .disabled=${this.disabled}
.value=${this._value?.data?.entity_id} .value=${this._value?.data?.entity_id}
.label=${entityId.description} .label=${this.hass.localize(
`component.${domain}.services.${serviceName}.fields.entity_id.description`
) || entityId.description}
@value-changed=${this._entityPicked} @value-changed=${this._entityPicked}
allow-custom-entity allow-custom-entity
></ha-entity-picker>` ></ha-entity-picker>`
@ -437,8 +455,18 @@ export class HaServiceControl extends LitElement {
@change=${this._checkboxChanged} @change=${this._checkboxChanged}
slot="prefix" slot="prefix"
></ha-checkbox>`} ></ha-checkbox>`}
<span slot="heading">${dataField.name || dataField.key}</span> <span slot="heading"
<span slot="description">${dataField?.description}</span> >${this.hass.localize(
`component.${domain}.services.${serviceName}.fields.${dataField.key}.name`
) ||
dataField.name ||
dataField.key}</span
>
<span slot="description"
>${this.hass.localize(
`component.${domain}.services.${serviceName}.fields.${dataField.key}.description`
) || dataField?.description}</span
>
<ha-selector <ha-selector
.disabled=${this.disabled || .disabled=${this.disabled ||
(showOptional && (showOptional &&
@ -453,12 +481,22 @@ export class HaServiceControl extends LitElement {
? this._value.data[dataField.key] ? this._value.data[dataField.key]
: undefined} : undefined}
.placeholder=${dataField.default} .placeholder=${dataField.default}
.localizeValue=${this._localizeValueCallback}
></ha-selector> ></ha-selector>
</ha-settings-row>` </ha-settings-row>`
: ""; : "";
})}`; })}`;
} }
private _localizeValueCallback = (key: string) => {
if (!this._value?.service) {
return "";
}
return this.hass.localize(
`component.${computeDomain(this._value.service)}.selector.${key}`
);
};
private _checkboxChanged(ev) { private _checkboxChanged(ev) {
const checked = ev.currentTarget.checked; const checked = ev.currentTarget.checked;
const key = ev.currentTarget.key; const key = ev.currentTarget.key;

View File

@ -1,27 +0,0 @@
import { html } from "@polymer/polymer/lib/utils/html-tag";
/* eslint-plugin-disable lit */
import { PolymerElement } from "@polymer/polymer/polymer-element";
class HaServiceDescription extends PolymerElement {
static get template() {
return html` [[_getDescription(hass, domain, service)]] `;
}
static get properties() {
return {
hass: Object,
domain: String,
service: String,
};
}
_getDescription(hass, domain, service) {
const domainServices = hass.services[domain];
if (!domainServices) return "";
const serviceObject = domainServices[service];
if (!serviceObject) return "";
return serviceObject.description;
}
}
customElements.define("ha-service-description", HaServiceDescription);

View File

@ -27,6 +27,12 @@ class HaServicePicker extends LitElement {
@state() private _filter?: string; @state() private _filter?: string;
protected willUpdate() {
if (!this.hasUpdated) {
this.hass.loadBackendTranslation("services");
}
}
protected render() { protected render() {
return html` return html`
<ha-combo-box <ha-combo-box
@ -71,7 +77,11 @@ class HaServicePicker extends LitElement {
result.push({ result.push({
service: `${domain}.${service}`, service: `${domain}.${service}`,
name: `${domainToName(localize, domain)}: ${ name: `${domainToName(localize, domain)}: ${
services[domain][service].name || service this.hass.localize(
`component.${domain}.services.${service}.name`
) ||
services[domain][service].name ||
service
}`, }`,
}); });
} }

View File

@ -165,12 +165,14 @@ const tryDescribeAction = <T extends ActionType>(
if (config.service) { if (config.service) {
const [domain, serviceName] = config.service.split(".", 2); const [domain, serviceName] = config.service.split(".", 2);
const service = hass.services[domain][serviceName]; const service =
hass.localize(`component.${domain}.services.${serviceName}.name`) ||
hass.services[domain][serviceName]?.name;
return hass.localize( return hass.localize(
`${actionTranslationBaseKey}.service.description.service_based_on_name`, `${actionTranslationBaseKey}.service.description.service_based_on_name`,
{ {
name: service name: service
? `${domainToName(hass.localize, domain)}: ${service.name}` ? `${domainToName(hass.localize, domain)}: ${service}`
: config.service, : config.service,
targets: formatListWithAnds(hass.locale, targets), targets: formatListWithAnds(hass.locale, targets),
} }

View File

@ -69,7 +69,8 @@ export type TranslationCategory =
| "system_health" | "system_health"
| "application_credentials" | "application_credentials"
| "issues" | "issues"
| "selector"; | "selector"
| "services";
export const fetchTranslationPreferences = (hass: HomeAssistant) => export const fetchTranslationPreferences = (hass: HomeAssistant) =>
fetchFrontendUserData(hass.connection, "language"); fetchFrontendUserData(hass.connection, "language");

View File

@ -574,6 +574,7 @@ class HaPanelConfig extends SubscribeMixin(HassRouterPage) {
protected firstUpdated(changedProps: PropertyValues) { protected firstUpdated(changedProps: PropertyValues) {
super.firstUpdated(changedProps); super.firstUpdated(changedProps);
this.hass.loadBackendTranslation("title"); this.hass.loadBackendTranslation("title");
this.hass.loadBackendTranslation("services");
if (isComponentLoaded(this.hass, "cloud")) { if (isComponentLoaded(this.hass, "cloud")) {
this._updateCloudStatus(); this._updateCloudStatus();
this.addEventListener("connection-status", (ev) => { this.addEventListener("connection-status", (ev) => {

View File

@ -10,7 +10,6 @@ import {
} from "lit"; } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import "../../../../../components/ha-circular-progress"; import "../../../../../components/ha-circular-progress";
import "../../../../../components/ha-service-description";
import { import {
DEVICE_MESSAGE_TYPES, DEVICE_MESSAGE_TYPES,
LOG_OUTPUT, LOG_OUTPUT,
@ -259,12 +258,6 @@ class ZHAAddDevicesPage extends LitElement {
right: 0; right: 0;
color: var(--primary-color); color: var(--primary-color);
} }
ha-service-description {
margin-top: 16px;
margin-left: 16px;
display: block;
color: grey;
}
.search-button { .search-button {
margin-top: 16px; margin-top: 16px;
margin-left: 16px; margin-left: 16px;

View File

@ -11,7 +11,6 @@ import "../../../../../components/buttons/ha-call-service-button";
import "../../../../../components/entity/state-badge"; import "../../../../../components/entity/state-badge";
import "../../../../../components/ha-area-picker"; import "../../../../../components/ha-area-picker";
import "../../../../../components/ha-card"; import "../../../../../components/ha-card";
import "../../../../../components/ha-service-description";
import { updateDeviceRegistryEntry } from "../../../../../data/device_registry"; import { updateDeviceRegistryEntry } from "../../../../../data/device_registry";
import { import {
EntityRegistryEntry, EntityRegistryEntry,

View File

@ -6,7 +6,6 @@ import "../../../../../components/buttons/ha-call-service-button";
import "../../../../../components/entity/state-badge"; import "../../../../../components/entity/state-badge";
import "../../../../../components/ha-area-picker"; import "../../../../../components/ha-area-picker";
import "../../../../../components/ha-card"; import "../../../../../components/ha-card";
import "../../../../../components/ha-service-description";
import { import {
CONFIGURED, CONFIGURED,
INCOMPLETE_PAIRING_STATUSES, INCOMPLETE_PAIRING_STATUSES,

View File

@ -60,9 +60,12 @@ export const handleAction = async (
const [domain, service] = actionConfig.service.split(".", 2); const [domain, service] = actionConfig.service.split(".", 2);
const serviceDomains = hass.services; const serviceDomains = hass.services;
if (domain in serviceDomains && service in serviceDomains[domain]) { if (domain in serviceDomains && service in serviceDomains[domain]) {
const localize = await hass.loadBackendTranslation("title"); await hass.loadBackendTranslation("title");
const localize = await hass.loadBackendTranslation("services");
serviceName = `${domainToName(localize, domain)}: ${ serviceName = `${domainToName(localize, domain)}: ${
serviceDomains[domain][service].name || service localize(`component.${domain}.services.${serviceName}.name`) ||
serviceDomains[domain][service].name ||
service
}`; }`;
} }
} }