From 5a233d88782d858163ae0eaa7a7147b08823b9d4 Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Sat, 21 Sep 2024 23:35:44 +0200 Subject: [PATCH] Avoid too many types declaration indirections --- src/login/i18n/withJsx/GenericI18n.tsx | 73 +++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/src/login/i18n/withJsx/GenericI18n.tsx b/src/login/i18n/withJsx/GenericI18n.tsx index 1b37579e..f4a85e84 100644 --- a/src/login/i18n/withJsx/GenericI18n.tsx +++ b/src/login/i18n/withJsx/GenericI18n.tsx @@ -1,6 +1,77 @@ import type { GenericI18n_noJsx } from "../noJsx/GenericI18n_noJsx"; +import { assert, type Equals } from "tsafe/assert"; -export type GenericI18n = GenericI18n_noJsx & { +export type GenericI18n = { + /** + * e.g: "en", "fr", "zh-CN" + * + * The current language + */ + currentLanguageTag: LanguageTag; + /** + * Redirect to this url to change the language. + * After reload currentLanguageTag === newLanguageTag + */ + getChangeLocaleUrl: (newLanguageTag: string /*LanguageTag*/) => string; + /** + * e.g. "en" => "English", "fr" => "Français", ... + * + * Used to render a select that enable user to switch language. + * ex: https://user-images.githubusercontent.com/6702424/186044799-38801eec-4e89-483b-81dd-8e9233e8c0eb.png + * */ + labelBySupportedLanguageTag: Record; + /** + * + * Examples assuming currentLanguageTag === "en" + * { + * en: { + * "access-denied": "Access denied", + * "impersonateTitleHtml": "{0} Impersonate User", + * "bar": "Bar {0}" + * } + * } + * + * msgStr("access-denied") === "Access denied" + * msgStr("not-a-message-key") Throws an error + * msgStr("impersonateTitleHtml", "Foo") === "Foo Impersonate User" + * msgStr("${bar}", "c") === "Bar <strong>XXX</strong>" + * The html in the arg is partially escaped for security reasons, it might come from an untrusted source, it's not safe to render it as html. + */ + msgStr: (key: MessageKey, ...args: (string | undefined)[]) => string; + /** + * This is meant to be used when the key argument is variable, something that might have been configured by the user + * in the Keycloak admin for example. + * + * Examples assuming currentLanguageTag === "en" + * { + * en: { + * "access-denied": "Access denied", + * } + * } + * + * advancedMsgStr("${access-denied}") === advancedMsgStr("access-denied") === msgStr("access-denied") === "Access denied" + * advancedMsgStr("${not-a-message-key}") === advancedMsgStr("not-a-message-key") === "not-a-message-key" + */ + advancedMsgStr: (key: string, ...args: (string | undefined)[]) => string; + /** + * Initially the messages are in english (fallback language). + * The translations in the current language are being fetched dynamically. + * This property is true while the translations are being fetched. + */ + isFetchingTranslations: boolean; + /** + * Same as msgStr but returns a JSX.Element with the html string rendered as html. + */ msg: (key: MessageKey, ...args: (string | undefined)[]) => JSX.Element; + /** + * Same as advancedMsgStr but returns a JSX.Element with the html string rendered as html. + */ advancedMsg: (key: string, ...args: (string | undefined)[]) => JSX.Element; }; + +{ + type A = Omit, "msg" | "advancedMsg">; + type B = GenericI18n_noJsx; + + assert>; +}