Enable to add label to extra message not in the default set

This commit is contained in:
Joseph Garrone 2024-09-21 21:33:04 +02:00
parent 2a3ad58c18
commit 801a5cce17
7 changed files with 179 additions and 76 deletions

View File

@ -13,6 +13,7 @@ import { downloadKeycloakDefaultTheme } from "./shared/downloadKeycloakDefaultTh
import { getThisCodebaseRootDirPath } from "../src/bin/tools/getThisCodebaseRootDirPath";
import { deepAssign } from "../src/tools/deepAssign";
import { THEME_TYPES } from "../src/bin/shared/constants";
import { transformCodebase } from "../src/bin/tools/transformCodebase";
const propertiesParser: any = require("properties-parser");
if (require.main === module) {

View File

@ -3,6 +3,8 @@ import { WELL_KNOWN_DIRECTORY_BASE_NAME } from "keycloakify/bin/shared/constants
import { id } from "tsafe/id";
import type { KcContext } from "./KcContext";
import { BASE_URL } from "keycloakify/lib/BASE_URL";
import { assert, type Equals } from "tsafe/assert";
import type { LanguageTag } from "keycloakify/account/i18n/messages_defaultSet/types";
const resourcesPath = `${BASE_URL}${WELL_KNOWN_DIRECTORY_BASE_NAME.DOT_KEYCLOAKIFY}/account`;
@ -38,35 +40,53 @@ export const kcContextCommonMock: KcContext.Common = {
exists: () => false
},
locale: {
supported: [
/* spell-checker: disable */
["de", "Deutsch"],
["no", "Norsk"],
["ru", "Русский"],
["sv", "Svenska"],
["pt-BR", "Português (Brasil)"],
["lt", "Lietuvių"],
["en", "English"],
["it", "Italiano"],
["fr", "Français"],
["zh-CN", "中文简体"],
["es", "Español"],
["cs", "Čeština"],
["ja", "日本語"],
["sk", "Slovenčina"],
["pl", "Polski"],
["ca", "Català"],
["nl", "Nederlands"],
["tr", "Türkçe"]
/* spell-checker: enable */
].map(
([languageTag, label]) =>
({
languageTag,
label,
url: "https://gist.github.com/garronej/52baaca1bb925f2296ab32741e062b8e"
}) as const
),
supported: (
[
/* spell-checker: disable */
["de", "Deutsch"],
["no", "Norsk"],
["ru", "Русский"],
["sv", "Svenska"],
["pt-BR", "Português (Brasil)"],
["lt", "Lietuvių"],
["en", "English"],
["it", "Italiano"],
["fr", "Français"],
["zh-CN", "中文简体"],
["es", "Español"],
["cs", "Čeština"],
["ja", "日本語"],
["sk", "Slovenčina"],
["pl", "Polski"],
["ca", "Català"],
["nl", "Nederlands"],
["tr", "Türkçe"],
["ar", "العربية"],
["da", "Dansk"],
["fi", "Suomi"],
["hu", "Magyar"],
["lv", "Latviešu"]
/* spell-checker: enable */
] as const
).map(([languageTag, label]) => {
{
type Got = typeof languageTag;
type Expected = LanguageTag;
type Missing = Exclude<Expected, Got>;
type Unexpected = Exclude<Got, Expected>;
assert<Equals<Missing, never>>;
assert<Equals<Unexpected, never>>;
}
return {
languageTag,
label,
url: "https://gist.github.com/garronej/52baaca1bb925f2296ab32741e062b8e"
} as const;
}),
currentLanguageTag: "en"
},
features: {

View File

@ -7,6 +7,7 @@ import {
import { id } from "tsafe/id";
import { assert, type Equals } from "tsafe/assert";
import { BASE_URL } from "keycloakify/lib/BASE_URL";
import type { LanguageTag } from "keycloakify/login/i18n/messages_defaultSet/types";
const attributesByName = Object.fromEntries(
id<Attribute[]>([
@ -116,35 +117,59 @@ export const kcContextCommonMock: KcContext.Common = {
}
},
locale: {
supported: [
/* spell-checker: disable */
["de", "Deutsch"],
["no", "Norsk"],
["ru", "Русский"],
["sv", "Svenska"],
["pt-BR", "Português (Brasil)"],
["lt", "Lietuvių"],
["en", "English"],
["it", "Italiano"],
["fr", "Français"],
["zh-CN", "中文简体"],
["es", "Español"],
["cs", "Čeština"],
["ja", "日本語"],
["sk", "Slovenčina"],
["pl", "Polski"],
["ca", "Català"],
["nl", "Nederlands"],
["tr", "Türkçe"]
/* spell-checker: enable */
].map(
([languageTag, label]) =>
({
languageTag,
label,
url: "https://gist.github.com/garronej/52baaca1bb925f2296ab32741e062b8e"
}) as const
),
supported: (
[
/* spell-checker: disable */
["de", "Deutsch"],
["no", "Norsk"],
["ru", "Русский"],
["sv", "Svenska"],
["pt-BR", "Português (Brasil)"],
["lt", "Lietuvių"],
["en", "English"],
["it", "Italiano"],
["fr", "Français"],
["zh-CN", "中文简体"],
["es", "Español"],
["cs", "Čeština"],
["ja", "日本語"],
["sk", "Slovenčina"],
["pl", "Polski"],
["ca", "Català"],
["nl", "Nederlands"],
["tr", "Türkçe"],
["ar", "العربية"],
["da", "Dansk"],
["el", "Ελληνικά"],
["fa", "فارسی"],
["fi", "Suomi"],
["hu", "Magyar"],
["ka", "ქართული"],
["lv", "Latviešu"],
["pt", "Português"],
["th", "ไทย"],
["uk", "Українська"],
["zh-TW", "中文繁體"]
/* spell-checker: enable */
] as const
).map(([languageTag, label]) => {
{
type Got = typeof languageTag;
type Expected = LanguageTag;
type Missing = Exclude<Expected, Got>;
type Unexpected = Exclude<Got, Expected>;
assert<Equals<Missing, never>>;
assert<Equals<Unexpected, never>>;
}
return {
languageTag,
label,
url: "https://gist.github.com/garronej/52baaca1bb925f2296ab32741e062b8e"
} as const;
}),
currentLanguageTag: "en"
},

View File

@ -43,7 +43,10 @@ export function createGetI18n<
LanguageTag_notInDefaultSet extends string = never
>(params: {
extraLanguageTranslations: {
[languageTag in LanguageTag_notInDefaultSet]: () => Promise<{ default: Record<MessageKey_defaultSet, string> }>;
[languageTag in LanguageTag_notInDefaultSet]: {
label: string;
getMessages: () => Promise<{ default: Record<MessageKey_defaultSet, string> }>;
};
};
messagesByLanguageTag_themeDefined: Partial<{
[languageTag in LanguageTag_defaultSet | LanguageTag_notInDefaultSet]: {
@ -100,7 +103,44 @@ export function createGetI18n<
return targetSupportedLocale.url;
},
labelBySupportedLanguageTag: Object.fromEntries((kcContext.locale?.supported ?? []).map(({ languageTag, label }) => [languageTag, label]))
labelBySupportedLanguageTag: (() => {
const labelBySupportedLanguageTag = Object.fromEntries(
(kcContext.locale?.supported ?? []).map(({ languageTag, label }) => [languageTag, label])
);
// NOTE: For IE11
if (typeof Proxy === undefined) {
return labelBySupportedLanguageTag;
}
// NOTE: This is for convenience in Storybook
return new Proxy<Record<string, string>>(
{},
{
get: function (...args) {
const [, languageTag] = args;
if (typeof languageTag !== "string") {
return window.Reflect.get(...args);
}
let label = labelBySupportedLanguageTag[languageTag];
if (label === undefined) {
assert(is<Exclude<LanguageTag, LanguageTag_defaultSet>>(languageTag));
const entry = extraLanguageTranslations[languageTag];
assert(entry !== undefined);
label = entry.label;
}
return label;
}
}
);
})()
};
const { createI18nTranslationFunctions } = createI18nTranslationFunctionsFactory<MessageKey_themeDefined>({
@ -147,12 +187,14 @@ export function createGetI18n<
if (isEmpty) {
assert(is<Exclude<LanguageTag, LanguageTag_defaultSet>>(currentLanguageTag));
const asyncFunction = extraLanguageTranslations[currentLanguageTag];
const entry = extraLanguageTranslations[currentLanguageTag];
assert(asyncFunction !== undefined);
assert(entry !== undefined);
return asyncFunction().then(({ default: messages }) => messages);
return entry.getMessages().then(({ default: messages }) => messages);
}
return fromDefaultSet;
})();
const i18n_currentLanguage: I18n = {

View File

@ -23,9 +23,12 @@ export type I18nInitializer<
withExtraLanguages: <
LanguageTag_notInDefaultSet extends string
>(extraLanguageTranslations: {
[LanguageTag in LanguageTag_notInDefaultSet]: () => Promise<{
default: Record<MessageKey_defaultSet, string>;
}>;
[LanguageTag in LanguageTag_notInDefaultSet]: {
label: string;
getMessages: () => Promise<{
default: Record<MessageKey_defaultSet, string>;
}>;
};
}) => I18nInitializer<
ThemeName,
MessageKey_themeDefined,
@ -61,9 +64,12 @@ function createI18nInitializer<
LanguageTag_notInDefaultSet extends string = never
>(params: {
extraLanguageTranslations: {
[LanguageTag in LanguageTag_notInDefaultSet]: () => Promise<{
default: Record<MessageKey_defaultSet, string>;
}>;
[LanguageTag in LanguageTag_notInDefaultSet]: {
label: string;
getMessages: () => Promise<{
default: Record<MessageKey_defaultSet, string>;
}>;
};
};
messagesByLanguageTag_themeDefined: Partial<{
[LanguageTag in LanguageTag_defaultSet | LanguageTag_notInDefaultSet]: Record<

View File

@ -23,9 +23,12 @@ export type I18nInitializer<
withExtraLanguages: <
LanguageTag_notInDefaultSet extends string
>(extraLanguageTranslations: {
[LanguageTag in LanguageTag_notInDefaultSet]: () => Promise<{
default: Record<MessageKey_defaultSet, string>;
}>;
[LanguageTag in LanguageTag_notInDefaultSet]: {
label: string;
getMessages: () => Promise<{
default: Record<MessageKey_defaultSet, string>;
}>;
};
}) => I18nInitializer<
ThemeName,
MessageKey_themeDefined,
@ -61,9 +64,12 @@ function createI18nInitializer<
LanguageTag_notInDefaultSet extends string = never
>(params: {
extraLanguageTranslations: {
[LanguageTag in LanguageTag_notInDefaultSet]: () => Promise<{
default: Record<MessageKey_defaultSet, string>;
}>;
[LanguageTag in LanguageTag_notInDefaultSet]: {
label: string;
getMessages: () => Promise<{
default: Record<MessageKey_defaultSet, string>;
}>;
};
};
messagesByLanguageTag_themeDefined: Partial<{
[LanguageTag in LanguageTag_defaultSet | LanguageTag_notInDefaultSet]: Record<

View File

@ -18,7 +18,10 @@ export function createUseI18n<
LanguageTag_notInDefaultSet extends string = never
>(params: {
extraLanguageTranslations: {
[languageTag in LanguageTag_notInDefaultSet]: () => Promise<{ default: Record<MessageKey_defaultSet, string> }>;
[languageTag in LanguageTag_notInDefaultSet]: {
label: string;
getMessages: () => Promise<{ default: Record<MessageKey_defaultSet, string> }>;
};
};
messagesByLanguageTag_themeDefined: Partial<{
[languageTag in LanguageTag_defaultSet | LanguageTag_notInDefaultSet]: {