Dynamically load non-fallback languages.

This commit is contained in:
Dermot Duffy
2022-10-09 12:37:24 -07:00
parent ead0026650
commit 9af8eedb8a
3 changed files with 55 additions and 14 deletions
+11 -1
View File
@@ -8,7 +8,7 @@ import styles from 'rollup-plugin-styles';
import image from '@rollup/plugin-image'; import image from '@rollup/plugin-image';
import replace from '@rollup/plugin-replace'; import replace from '@rollup/plugin-replace';
import gitInfo from 'rollup-plugin-git-info'; import gitInfo from 'rollup-plugin-git-info';
import { visualizer } from "rollup-plugin-visualizer"; import { visualizer } from 'rollup-plugin-visualizer';
const watch = process.env.ROLLUP_WATCH === 'true' || process.env.ROLLUP_WATCH === '1'; const watch = process.env.ROLLUP_WATCH === 'true' || process.env.ROLLUP_WATCH === '1';
const dev = watch || process.env.DEV === 'true' || process.env.DEV === '1'; const dev = watch || process.env.DEV === 'true' || process.env.DEV === '1';
@@ -69,6 +69,16 @@ const config = {
output: { output: {
entryFileNames: 'frigate-hass-card.js', entryFileNames: 'frigate-hass-card.js',
dir: 'dist', dir: 'dist',
chunkFileNames: (chunk) => {
// Add "lang-" to the front of the language chunk names for readability.
if (
chunk.facadeModuleId &&
chunk.facadeModuleId.match(/localize\/languages\/.*\.json/)
) {
return 'lang-[name]-[hash].js';
}
return '[name]-[hash].js';
},
format: 'es', format: 'es',
...(dev && { ...(dev && {
sourcemap: true, sourcemap: true,
+16 -5
View File
@@ -37,7 +37,7 @@ import {
MEDIA_PLAYER_SUPPORT_BROWSE_MEDIA, MEDIA_PLAYER_SUPPORT_BROWSE_MEDIA,
REPO_URL, REPO_URL,
} from './const.js'; } from './const.js';
import { getLanguage, localize } from './localize/localize.js'; import { getLanguage, loadLanguages, localize } from './localize/localize.js';
import cardStyle from './scss/card.scss'; import cardStyle from './scss/card.scss';
import { import {
Actions, Actions,
@@ -206,7 +206,8 @@ export class FrigateCard extends LitElement {
protected _boundMouseHandler = throttle(this._mouseHandler.bind(this), 1 * 1000); protected _boundMouseHandler = throttle(this._mouseHandler.bind(this), 1 * 1000);
// Whether the card has been successfully initialized. // Whether the card has been successfully initialized.
protected _initialized = false; protected _loadedHAElements = false;
protected _loadedLanguages = false;
protected _triggers: Map<string, Date> = new Map(); protected _triggers: Map<string, Date> = new Map();
protected _untriggerTimerID: number | null = null; protected _untriggerTimerID: number | null = null;
@@ -1101,11 +1102,12 @@ export class FrigateCard extends LitElement {
* Called before each update. * Called before each update.
*/ */
protected willUpdate(changedProps: PropertyValues): void { protected willUpdate(changedProps: PropertyValues): void {
// Side load the necessary elements if not already initialized. // Side load the necessary elements if not already initialized (do not need
if (!this._initialized) { // to block for the loading to complete).
if (!this._loadedHAElements) {
sideLoadHomeAssistantElements().then((success) => { sideLoadHomeAssistantElements().then((success) => {
if (success) { if (success) {
this._initialized = true; this._loadedHAElements = true;
} }
}); });
} }
@@ -1244,6 +1246,15 @@ export class FrigateCard extends LitElement {
* @returns `true` if the element should be updated. * @returns `true` if the element should be updated.
*/ */
protected shouldUpdate(changedProps: PropertyValues): boolean { protected shouldUpdate(changedProps: PropertyValues): boolean {
// Load the relevant languages. Cannot do anything until then.
if (!this._loadedLanguages) {
loadLanguages().then(() => {
this._loadedLanguages = true;
this.requestUpdate();
});
return false;
}
const oldHass = changedProps.get('_hass') as HomeAssistant | undefined; const oldHass = changedProps.get('_hass') as HomeAssistant | undefined;
let shouldUpdate = !oldHass || changedProps.size != 1; let shouldUpdate = !oldHass || changedProps.size != 1;
+28 -8
View File
@@ -1,14 +1,16 @@
import * as en from './languages/en.json'; import * as en from './languages/en.json';
import * as pt_BR from './languages/pt-BR.json';
import * as it from './languages/it.json';
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
const languages: Record<string, any> = { const languages: Record<string, any> = {
// 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, en: en,
pt_BR: pt_BR, }
it: it,
};
/**
* Get the configured language.
*/
export function getLanguage(): string { export function getLanguage(): string {
const canonicalizeLanguage = (language?: string | null): string | null => { const canonicalizeLanguage = (language?: string | null): string | null => {
if (!language) { if (!language) {
@@ -39,14 +41,32 @@ export function getLanguage(): string {
return lang || 'en'; return lang || 'en';
} }
/**
* Load required languages.
*/
export const loadLanguages = async (): Promise<void> => {
const lang = getLanguage();
if (lang === 'it') {
languages['it'] = await import('./languages/it.json');
} else if (lang === 'pt_BR') {
languages['pt_BR'] = await import('./languages/pt-BR.json');
}
}
/**
* 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
*/
export function localize(string: string, search = '', replace = ''): string { export function localize(string: string, search = '', replace = ''): string {
const lang = getLanguage(); const lang = getLanguage();
let translated: string; let translated = '';
try { try {
translated = string.split('.').reduce((o, i) => o[i], languages[lang]); translated = string.split('.').reduce((o, i) => o[i], languages[lang]);
} catch (e) { } catch (_) {
translated = string.split('.').reduce((o, i) => o[i], languages['en']);
} }
if (!translated) { if (!translated) {