From 4190ff5a2b214719176c18f71f0c1f31354c8617 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 1 Dec 2022 13:38:50 +0100 Subject: [PATCH] Sort language, country, currency (#14500) --- src/components/country-datalist.ts | 37 +++++++---- src/components/currency-datalist.ts | 35 +++++++---- .../config/core/ha-config-section-general.ts | 62 ++++++++++--------- 3 files changed, 80 insertions(+), 54 deletions(-) diff --git a/src/components/country-datalist.ts b/src/components/country-datalist.ts index c972a77fd6..b4295f99ad 100644 --- a/src/components/country-datalist.ts +++ b/src/components/country-datalist.ts @@ -1,4 +1,7 @@ -export const countries = [ +import memoizeOne from "memoize-one"; +import { caseInsensitiveStringCompare } from "../common/string/compare"; + +export const COUNTRIES = [ "AD", "AE", "AF", @@ -250,23 +253,31 @@ export const countries = [ "ZW", ]; -export const countryDisplayNames = - Intl && "DisplayNames" in Intl - ? new Intl.DisplayNames(undefined, { - type: "region", - fallback: "code", - }) - : undefined; +export const getCountryOptions = memoizeOne((language?: string) => { + const countryDisplayNames = + Intl && "DisplayNames" in Intl + ? new Intl.DisplayNames(language, { + type: "region", + fallback: "code", + }) + : undefined; + + const options = COUNTRIES.map((country) => ({ + value: country, + label: countryDisplayNames ? countryDisplayNames.of(country)! : country, + })); + options.sort((a, b) => caseInsensitiveStringCompare(a.label, b.label)); + return options; +}); export const createCountryListEl = () => { const list = document.createElement("datalist"); list.id = "countries"; - for (const country of countries) { + const options = getCountryOptions(); + for (const country of options) { const option = document.createElement("option"); - option.value = country; - option.innerText = countryDisplayNames - ? countryDisplayNames.of(country)! - : country; + option.value = country.value; + option.innerText = country.label; list.appendChild(option); } return list; diff --git a/src/components/currency-datalist.ts b/src/components/currency-datalist.ts index c725b8258c..1339c47520 100644 --- a/src/components/currency-datalist.ts +++ b/src/components/currency-datalist.ts @@ -1,4 +1,7 @@ -export const currencies = [ +import memoizeOne from "memoize-one"; +import { caseInsensitiveStringCompare } from "../common/string/compare"; + +export const CURRENCIES = [ "AED", "AFN", "ALL", @@ -158,23 +161,29 @@ export const currencies = [ "ZWL", ]; -export const currencyDisplayNames = - Intl && "DisplayNames" in Intl - ? new Intl.DisplayNames(undefined, { - type: "currency", - fallback: "code", - }) - : undefined; +export const getCurrencyOptions = memoizeOne((language?: string) => { + const currencyDisplayNames = + Intl && "DisplayNames" in Intl + ? new Intl.DisplayNames(language, { + type: "currency", + fallback: "code", + }) + : undefined; + const options = CURRENCIES.map((currency) => ({ + value: currency, + label: currencyDisplayNames ? currencyDisplayNames.of(currency)! : currency, + })); + options.sort((a, b) => caseInsensitiveStringCompare(a.label, b.label)); + return options; +}); export const createCurrencyListEl = () => { const list = document.createElement("datalist"); list.id = "currencies"; - for (const currency of currencies) { + for (const currency of getCurrencyOptions()) { const option = document.createElement("option"); - option.value = currency; - option.innerText = currencyDisplayNames - ? currencyDisplayNames.of(currency)! - : currency; + option.value = currency.value; + option.innerText = currency.label; list.appendChild(option); } return list; diff --git a/src/panels/config/core/ha-config-section-general.ts b/src/panels/config/core/ha-config-section-general.ts index 3e93ce8ec3..f3857b1bb7 100644 --- a/src/panels/config/core/ha-config-section-general.ts +++ b/src/panels/config/core/ha-config-section-general.ts @@ -6,16 +6,11 @@ import memoizeOne from "memoize-one"; import { UNIT_C } from "../../../common/const"; import { stopPropagation } from "../../../common/dom/stop_propagation"; import { navigate } from "../../../common/navigate"; +import { caseInsensitiveStringCompare } from "../../../common/string/compare"; import "../../../components/buttons/ha-progress-button"; import type { HaProgressButton } from "../../../components/buttons/ha-progress-button"; -import { - countries, - countryDisplayNames, -} from "../../../components/country-datalist"; -import { - currencies, - currencyDisplayNames, -} from "../../../components/currency-datalist"; +import { getCountryOptions } from "../../../components/country-datalist"; +import { getCurrencyOptions } from "../../../components/currency-datalist"; import "../../../components/ha-card"; import "../../../components/ha-formfield"; import "../../../components/ha-radio"; @@ -55,6 +50,8 @@ class HaConfigSectionGeneral extends LitElement { @state() private _location?: [number, number]; + @state() private _languages?: { value: string; label: string }[]; + protected render(): TemplateResult { const canEdit = ["storage", "default"].includes( this.hass.config.config_source @@ -187,13 +184,11 @@ class HaConfigSectionGeneral extends LitElement { @closed=${stopPropagation} @change=${this._handleChange} > - ${currencies.map( - (currency) => - html`${currencyDisplayNames - ? currencyDisplayNames.of(currency) - : currency}` + ${getCurrencyOptions(this.hass.locale.language).map( + ({ value, label }) => + html` + ${label} + ` )} - ${countries.map( - (country) => - html`${countryDisplayNames - ? countryDisplayNames.of(country) - : country}` + ${getCountryOptions(this.hass.locale.language).map( + ({ value, label }) => + html` + ${label} + ` )} - ${Object.entries( - this.hass.translationMetadata.translations - ).map( - ([code, metadata]) => - html`${metadata.nativeName} + html`${label}` )} @@ -300,6 +291,21 @@ class HaConfigSectionGeneral extends LitElement { this._elevation = this.hass.config.elevation; this._timeZone = this.hass.config.time_zone; this._name = this.hass.config.location_name; + this._computeLanguages(); + } + + private _computeLanguages() { + if (!this.hass.translationMetadata?.translations) { + return; + } + this._languages = Object.entries(this.hass.translationMetadata.translations) + .sort((a, b) => + caseInsensitiveStringCompare(a[1].nativeName, b[1].nativeName) + ) + .map(([value, metaData]) => ({ + value, + label: metaData.nativeName, + })); } private _handleChange(ev) {