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) {