Setup stronger type for localize key (#13244)

This commit is contained in:
Steve Repsher 2022-07-21 09:13:11 -04:00 committed by GitHub
parent ce5776f59d
commit c99f00ba50
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 49 additions and 10 deletions

View File

@ -25,7 +25,7 @@ import {
} from "../../src/data/supervisor/supervisor"; } from "../../src/data/supervisor/supervisor";
import { ProvideHassLitMixin } from "../../src/mixins/provide-hass-lit-mixin"; import { ProvideHassLitMixin } from "../../src/mixins/provide-hass-lit-mixin";
import { urlSyncMixin } from "../../src/state/url-sync-mixin"; import { urlSyncMixin } from "../../src/state/url-sync-mixin";
import { HomeAssistant, Route } from "../../src/types"; import { HomeAssistant, Route, TranslationDict } from "../../src/types";
import { getTranslation } from "../../src/util/common-translation"; import { getTranslation } from "../../src/util/common-translation";
declare global { declare global {
@ -124,9 +124,13 @@ export class SupervisorBaseElement extends urlSyncMixin(
this.supervisor = { this.supervisor = {
...this.supervisor, ...this.supervisor,
localize: await computeLocalize(this.constructor.prototype, language, { localize: await computeLocalize<TranslationDict["supervisor"]>(
[language]: data, this.constructor.prototype,
}), language,
{
[language]: data,
}
),
}; };
} }

View File

@ -3,10 +3,41 @@ import { shouldPolyfill as shouldPolyfillPluralRules } from "@formatjs/intl-plur
import { shouldPolyfill as shouldPolyfillRelativeTime } from "@formatjs/intl-relativetimeformat/lib/should-polyfill"; import { shouldPolyfill as shouldPolyfillRelativeTime } from "@formatjs/intl-relativetimeformat/lib/should-polyfill";
import { shouldPolyfill as shouldPolyfillDateTime } from "@formatjs/intl-datetimeformat/lib/should-polyfill"; import { shouldPolyfill as shouldPolyfillDateTime } from "@formatjs/intl-datetimeformat/lib/should-polyfill";
import IntlMessageFormat from "intl-messageformat"; import IntlMessageFormat from "intl-messageformat";
import { Resources } from "../../types"; import { Resources, TranslationDict } from "../../types";
import { getLocalLanguage } from "../../util/common-translation"; import { getLocalLanguage } from "../../util/common-translation";
export type LocalizeFunc = (key: string, ...args: any[]) => string; // Exclude some patterns from key type checking for now
// These are intended to be removed as errors are fixed
// Fixing component category will require tighter definition of types from backend and/or web socket
type LocalizeKeyExceptions =
| `${string}`
| `panel.${string}`
| `state.${string}`
| `state_attributes.${string}`
| `state_badge.${string}`
| `groups.${string}`
| `config_entry.${string}`
| `ui.${string}`
| `${keyof TranslationDict["supervisor"]}.${string}`
| `component.${string}`;
// Tweaked from https://www.raygesualdo.com/posts/flattening-object-keys-with-typescript-types
type FlattenObjectKeys<
T extends Record<string, any>,
Key extends keyof T = keyof T
> = Key extends string
? T[Key] extends Record<string, unknown>
? `${Key}.${FlattenObjectKeys<T[Key]>}`
: `${Key}`
: never;
export type LocalizeFunc<
Dict extends Record<string, unknown> = TranslationDict
> = (
key: FlattenObjectKeys<Dict> | LocalizeKeyExceptions,
...args: any[]
) => string;
interface FormatType { interface FormatType {
[format: string]: any; [format: string]: any;
} }
@ -65,12 +96,14 @@ export const polyfillsLoaded =
* } * }
*/ */
export const computeLocalize = async ( export const computeLocalize = async <
Dict extends Record<string, unknown> = TranslationDict
>(
cache: any, cache: any,
language: string, language: string,
resources: Resources, resources: Resources,
formats?: FormatsType formats?: FormatsType
): Promise<LocalizeFunc> => { ): Promise<LocalizeFunc<Dict>> => {
if (polyfillsLoaded) { if (polyfillsLoaded) {
await polyfillsLoaded; await polyfillsLoaded;
} }

View File

@ -1,7 +1,7 @@
import { Connection, getCollection } from "home-assistant-js-websocket"; import { Connection, getCollection } from "home-assistant-js-websocket";
import { Store } from "home-assistant-js-websocket/dist/store"; import { Store } from "home-assistant-js-websocket/dist/store";
import { LocalizeFunc } from "../../common/translations/localize"; import { LocalizeFunc } from "../../common/translations/localize";
import { HomeAssistant } from "../../types"; import { HomeAssistant, TranslationDict } from "../../types";
import { HassioAddonsInfo } from "../hassio/addon"; import { HassioAddonsInfo } from "../hassio/addon";
import { HassioHassOSInfo, HassioHostInfo } from "../hassio/host"; import { HassioHassOSInfo, HassioHostInfo } from "../hassio/host";
import { NetworkInfo } from "../hassio/network"; import { NetworkInfo } from "../hassio/network";
@ -67,7 +67,7 @@ export interface Supervisor {
os: HassioHassOSInfo; os: HassioHassOSInfo;
addon: HassioAddonsInfo; addon: HassioAddonsInfo;
store: SupervisorStore; store: SupervisorStore;
localize: LocalizeFunc; localize: LocalizeFunc<TranslationDict["supervisor"]>;
} }
export const supervisorApiWsRequest = <T>( export const supervisorApiWsRequest = <T>(

View File

@ -151,6 +151,8 @@ export interface TranslationMetadata {
}; };
} }
export type TranslationDict = typeof import("./translations/en.json");
export interface IconMetaFile { export interface IconMetaFile {
version: string; version: string;
parts: IconMeta[]; parts: IconMeta[];