diff --git a/src/card.ts b/src/card.ts index aeddda8c..683f4edd 100644 --- a/src/card.ts +++ b/src/card.ts @@ -1159,7 +1159,7 @@ class FrigateCard extends LitElement { .initializeMultipleIfNecessary({ // Caution: Ensure nothing in this set of initializers requires // languages since they will not yet have been initialized. - [InitializationAspect.LANGUAGES]: async () => loadLanguages, + [InitializationAspect.LANGUAGES]: async () => loadLanguages(hass), [InitializationAspect.SIDE_LOAD_ELEMENTS]: async () => sideLoadHomeAssistantElements, }) diff --git a/src/localize/localize.ts b/src/localize/localize.ts index e74cff88..af74e995 100644 --- a/src/localize/localize.ts +++ b/src/localize/localize.ts @@ -1,76 +1,85 @@ +import { HomeAssistant } from 'custom-card-helpers'; import * as en from './languages/en.json'; +const DEFAULT_LANG = 'en' as const; + // eslint-disable-next-line @typescript-eslint/no-explicit-any const languages: Record = { // English as always loaded as it's the fallback language that will be used // when translations are not found or before they are loaded (via // loadLanguages()). - en: en, -} + [DEFAULT_LANG]: en, +}; + +// The language is calculated and stored once, then re-used to avoid needing to +// repeat the lookups and to ensure minimal information needs to be plumbed +// through on each localization call. +let frigateCardLanguage: string | undefined; /** * Get the configured language. */ -export function getLanguage(): string { - const canonicalizeLanguage = (language?: string | null): string | null => { - if (!language) { - return null; - } +export function getLanguage(hass?: HomeAssistant): string { + const canonicalizeLanguage = (language: string): string => { return language.replace('-', '_'); }; - // Try the HA language first... - let lang: string | null = null; - const HALanguage = localStorage.getItem('selectedLanguage'); - if (HALanguage) { - const selectedLanguage = canonicalizeLanguage(JSON.parse(HALanguage)); - if (selectedLanguage) { - lang = selectedLanguage; - } + // Try the hass language first... + const hassLanguage = hass?.language ?? hass?.selectedLanguage; + if (hassLanguage) { + return canonicalizeLanguage(hassLanguage); + } + + // Then the language that hass may have stored locally. + const storageLanguage = localStorage.getItem('selectedLanguage'); + if (storageLanguage) { + return canonicalizeLanguage(JSON.parse(storageLanguage)); } // Then fall back to the browser language. - if (!lang) { - for (const language of navigator.languages) { - const canonicalLanguage = canonicalizeLanguage(language); - if (canonicalLanguage && canonicalLanguage in languages) { - lang = language; - } + for (const language of navigator.languages) { + const canonicalLanguage = canonicalizeLanguage(language); + if (canonicalLanguage && canonicalLanguage in languages) { + return canonicalLanguage; } } - return lang || 'en'; + return DEFAULT_LANG; } /** * Load required languages. */ -export const loadLanguages = async (): Promise => { - const lang = getLanguage(); +export const loadLanguages = async (hass: HomeAssistant): Promise => { + const lang = getLanguage(hass); if (lang === 'it') { languages['it'] = await import('./languages/it.json'); } else if (lang === 'pt_BR') { languages['pt_BR'] = await import('./languages/pt-BR.json'); } -} + + if (lang) { + frigateCardLanguage = lang; + } +}; /** * Get a localized version of a given string key. * @param string The key. * @param search An optional search key to be used with 'replace'. * @param replace An optional replacement text to be used with 'search'. - * @returns + * @returns */ export function localize(string: string, search = '', replace = ''): string { - const lang = getLanguage(); let translated = ''; try { - translated = string.split('.').reduce((o, i) => o[i], languages[lang]); - } catch (_) { - } + translated = string + .split('.') + .reduce((o, i) => o[i], languages[frigateCardLanguage ?? DEFAULT_LANG]); + } catch (_) {} if (!translated) { - translated = string.split('.').reduce((o, i) => o[i], languages['en']); + translated = string.split('.').reduce((o, i) => o[i], languages[DEFAULT_LANG]); } if (search !== '' && replace !== '') {