From 066a0771b37241af79bcdfad72a414441dff4688 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20S=C3=B8rensen?= Date: Thu, 7 Oct 2021 11:02:52 +0200 Subject: [PATCH] Move functions to common-translation (#10180) --- src/common/translations/localize.ts | 2 +- src/fake_data/provide_hass.ts | 2 +- src/mixins/lit-localize-lite-mixin.ts | 2 +- src/state/connection-mixin.ts | 2 +- src/state/translations-mixin.ts | 6 +- src/util/common-translation.ts | 108 +++++++++++++++++++++++ src/util/hass-translation.ts | 118 -------------------------- 7 files changed, 117 insertions(+), 123 deletions(-) delete mode 100644 src/util/hass-translation.ts diff --git a/src/common/translations/localize.ts b/src/common/translations/localize.ts index b88aae10f9..a094d48b3e 100644 --- a/src/common/translations/localize.ts +++ b/src/common/translations/localize.ts @@ -4,7 +4,7 @@ import { shouldPolyfill as shouldPolyfillRelativeTime } from "@formatjs/intl-rel import { shouldPolyfill as shouldPolyfillDateTime } from "@formatjs/intl-datetimeformat/lib/should-polyfill"; import IntlMessageFormat from "intl-messageformat"; import { Resources } from "../../types"; -import { getLocalLanguage } from "../../util/hass-translation"; +import { getLocalLanguage } from "../../util/common-translation"; export type LocalizeFunc = (key: string, ...args: any[]) => string; interface FormatType { diff --git a/src/fake_data/provide_hass.ts b/src/fake_data/provide_hass.ts index e90665542c..1be324de95 100644 --- a/src/fake_data/provide_hass.ts +++ b/src/fake_data/provide_hass.ts @@ -8,7 +8,7 @@ import { DEFAULT_PANEL } from "../data/panel"; import { NumberFormat, TimeFormat } from "../data/translation"; import { translationMetadata } from "../resources/translations-metadata"; import { HomeAssistant } from "../types"; -import { getLocalLanguage, getTranslation } from "../util/hass-translation"; +import { getLocalLanguage, getTranslation } from "../util/common-translation"; import { demoConfig } from "./demo_config"; import { demoPanels } from "./demo_panels"; import { demoServices } from "./demo_services"; diff --git a/src/mixins/lit-localize-lite-mixin.ts b/src/mixins/lit-localize-lite-mixin.ts index c9751e1837..864bcd43e7 100644 --- a/src/mixins/lit-localize-lite-mixin.ts +++ b/src/mixins/lit-localize-lite-mixin.ts @@ -2,7 +2,7 @@ import { LitElement, PropertyValues } from "lit"; import { property } from "lit/decorators"; import { computeLocalize, LocalizeFunc } from "../common/translations/localize"; import { Constructor, Resources } from "../types"; -import { getLocalLanguage, getTranslation } from "../util/hass-translation"; +import { getLocalLanguage, getTranslation } from "../util/common-translation"; const empty = () => ""; diff --git a/src/state/connection-mixin.ts b/src/state/connection-mixin.ts index 4de7103637..10dba5a617 100644 --- a/src/state/connection-mixin.ts +++ b/src/state/connection-mixin.ts @@ -22,7 +22,7 @@ import { Constructor, ServiceCallResponse } from "../types"; import { fetchWithAuth } from "../util/fetch-with-auth"; import { getState } from "../util/ha-pref-storage"; import hassCallApi from "../util/hass-call-api"; -import { getLocalLanguage } from "../util/hass-translation"; +import { getLocalLanguage } from "../util/common-translation"; import { HassBaseEl } from "./hass-base-mixin"; export const connectionMixin = >( diff --git a/src/state/translations-mixin.ts b/src/state/translations-mixin.ts index c7ec776b06..c26978ddc1 100644 --- a/src/state/translations-mixin.ts +++ b/src/state/translations-mixin.ts @@ -17,7 +17,7 @@ import { getLocalLanguage, getTranslation, getUserLocale, -} from "../util/hass-translation"; +} from "../util/common-translation"; import { HassBaseEl } from "./hass-base-mixin"; declare global { @@ -376,3 +376,7 @@ export default >(superClass: T) => } } }; + +// Load selected translation into memory immediately so it is ready when Polymer +// initializes. +getTranslation(null, getLocalLanguage()); diff --git a/src/util/common-translation.ts b/src/util/common-translation.ts index 7f7e99b3fa..ff7793d256 100644 --- a/src/util/common-translation.ts +++ b/src/util/common-translation.ts @@ -1,6 +1,12 @@ +import { + fetchTranslationPreferences, + FrontendLocaleData, +} from "../data/translation"; import { translationMetadata } from "../resources/translations-metadata"; +import { HomeAssistant } from "../types"; const DEFAULT_BASE_URL = "/static/translations"; +const STORAGE = window.localStorage || {}; // Store loaded translations in memory so translations are available immediately // when DOM is created in Polymer. Even a cache lookup creates noticeable latency. @@ -18,6 +24,108 @@ async function fetchTranslation(fingerprint: string, base_url: string) { return response.json(); } +// Chinese locales need map to Simplified or Traditional Chinese +const LOCALE_LOOKUP = { + "zh-cn": "zh-Hans", + "zh-sg": "zh-Hans", + "zh-my": "zh-Hans", + "zh-tw": "zh-Hant", + "zh-hk": "zh-Hant", + "zh-mo": "zh-Hant", + zh: "zh-Hant", // all other Chinese locales map to Traditional Chinese +}; + +/** + * Search for a matching translation from most specific to general + */ +export function findAvailableLanguage(language: string) { + // In most case, the language has the same format with our translation meta data + if (language in translationMetadata.translations) { + return language; + } + + // Perform case-insenstive comparison since browser isn't required to + // report languages with specific cases. + const langLower = language.toLowerCase(); + + if (langLower in LOCALE_LOOKUP) { + return LOCALE_LOOKUP[langLower]; + } + + const translation = Object.keys(translationMetadata.translations).find( + (lang) => lang.toLowerCase() === langLower + ); + if (translation) { + return translation; + } + + if (language.includes("-")) { + return findAvailableLanguage(language.split("-")[0]); + } + + return undefined; +} + +/** + * Get user selected locale data from backend + */ +export async function getUserLocale( + hass: HomeAssistant +): Promise> { + const result = await fetchTranslationPreferences(hass); + const language = result?.language; + const number_format = result?.number_format; + const time_format = result?.time_format; + if (language) { + const availableLanguage = findAvailableLanguage(language); + if (availableLanguage) { + return { + language: availableLanguage, + number_format, + time_format, + }; + } + } + return { + number_format, + time_format, + }; +} + +/** + * Get browser specific language + */ +export function getLocalLanguage() { + let language = null; + if (STORAGE.selectedLanguage) { + try { + const stored = JSON.parse(STORAGE.selectedLanguage); + if (stored) { + language = findAvailableLanguage(stored); + if (language) { + return language; + } + } + } catch (err: any) { + // Ignore parsing error. + } + } + if (navigator.languages) { + for (const locale of navigator.languages) { + language = findAvailableLanguage(locale); + if (language) { + return language; + } + } + } + language = findAvailableLanguage(navigator.language); + if (language) { + return language; + } + // Final fallback + return "en"; +} + export async function getTranslation( fragment: string | null, language: string, diff --git a/src/util/hass-translation.ts b/src/util/hass-translation.ts deleted file mode 100644 index 156c79fff7..0000000000 --- a/src/util/hass-translation.ts +++ /dev/null @@ -1,118 +0,0 @@ -import { - fetchTranslationPreferences, - FrontendLocaleData, -} from "../data/translation"; -import { translationMetadata } from "../resources/translations-metadata"; -import { HomeAssistant } from "../types"; -import { getTranslation as commonGetTranslation } from "./common-translation"; - -const STORAGE = window.localStorage || {}; - -// Chinese locales need map to Simplified or Traditional Chinese -const LOCALE_LOOKUP = { - "zh-cn": "zh-Hans", - "zh-sg": "zh-Hans", - "zh-my": "zh-Hans", - "zh-tw": "zh-Hant", - "zh-hk": "zh-Hant", - "zh-mo": "zh-Hant", - zh: "zh-Hant", // all other Chinese locales map to Traditional Chinese -}; - -/** - * Search for a matching translation from most specific to general - */ -export function findAvailableLanguage(language: string) { - // In most case, the language has the same format with our translation meta data - if (language in translationMetadata.translations) { - return language; - } - - // Perform case-insenstive comparison since browser isn't required to - // report languages with specific cases. - const langLower = language.toLowerCase(); - - if (langLower in LOCALE_LOOKUP) { - return LOCALE_LOOKUP[langLower]; - } - - const translation = Object.keys(translationMetadata.translations).find( - (lang) => lang.toLowerCase() === langLower - ); - if (translation) { - return translation; - } - - if (language.includes("-")) { - return findAvailableLanguage(language.split("-")[0]); - } - - return undefined; -} - -/** - * Get user selected locale data from backend - */ -export async function getUserLocale( - hass: HomeAssistant -): Promise> { - const result = await fetchTranslationPreferences(hass); - const language = result?.language; - const number_format = result?.number_format; - const time_format = result?.time_format; - if (language) { - const availableLanguage = findAvailableLanguage(language); - if (availableLanguage) { - return { - language: availableLanguage, - number_format, - time_format, - }; - } - } - return { - number_format, - time_format, - }; -} - -/** - * Get browser specific language - */ -export function getLocalLanguage() { - let language = null; - if (STORAGE.selectedLanguage) { - try { - const stored = JSON.parse(STORAGE.selectedLanguage); - if (stored) { - language = findAvailableLanguage(stored); - if (language) { - return language; - } - } - } catch (err: any) { - // Ignore parsing error. - } - } - if (navigator.languages) { - for (const locale of navigator.languages) { - language = findAvailableLanguage(locale); - if (language) { - return language; - } - } - } - language = findAvailableLanguage(navigator.language); - if (language) { - return language; - } - // Final fallback - return "en"; -} - -export const getTranslation = (fragment: string | null, language: string) => - commonGetTranslation(fragment, language); - -// Load selected translation into memory immediately so it is ready when Polymer -// initializes. -commonGetTranslation(null, getLocalLanguage());