keycloakify 10.0.0-rc.37 → 10.0.0-rc.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/account/Fallback.d.ts +1 -2
- package/account/Fallback.js.map +1 -1
- package/account/KcContext/KcContext.d.ts +6 -6
- package/account/KcContext/getKcContextMock.d.ts +9 -9
- package/account/KcContext/getKcContextMock.js +3 -3
- package/account/KcContext/getKcContextMock.js.map +1 -1
- package/account/Template.d.ts +1 -2
- package/account/Template.js +7 -6
- package/account/Template.js.map +1 -1
- package/account/TemplateProps.d.ts +1 -3
- package/account/i18n/i18n.d.ts +9 -4
- package/account/i18n/i18n.js +132 -87
- package/account/i18n/i18n.js.map +1 -1
- package/account/i18n/index.d.ts +9 -2
- package/account/i18n/index.js +5 -1
- package/account/i18n/index.js.map +1 -1
- package/account/lib/kcClsx.d.ts +9 -0
- package/account/lib/{useGetClassName.js → kcClsx.js} +3 -3
- package/account/lib/kcClsx.js.map +1 -0
- package/account/pages/Account.d.ts +1 -2
- package/account/pages/Account.js +9 -7
- package/account/pages/Account.js.map +1 -1
- package/account/pages/Applications.d.ts +1 -2
- package/account/pages/Applications.js +7 -7
- package/account/pages/Applications.js.map +1 -1
- package/account/pages/FederatedIdentity.d.ts +1 -2
- package/account/pages/FederatedIdentity.js +4 -3
- package/account/pages/FederatedIdentity.js.map +1 -1
- package/account/pages/Log.d.ts +1 -2
- package/account/pages/Log.js +6 -5
- package/account/pages/Log.js.map +1 -1
- package/account/pages/PageProps.d.ts +2 -4
- package/account/pages/Password.d.ts +1 -2
- package/account/pages/Password.js +10 -9
- package/account/pages/Password.js.map +1 -1
- package/account/pages/Sessions.d.ts +1 -2
- package/account/pages/Sessions.js +6 -6
- package/account/pages/Sessions.js.map +1 -1
- package/account/pages/Totp.d.ts +1 -2
- package/account/pages/Totp.js +6 -5
- package/account/pages/Totp.js.map +1 -1
- package/bin/{314.index.js → 21.index.js} +162 -4
- package/bin/{430.index.js → 214.index.js} +161 -2
- package/bin/3.index.js +81 -65
- package/bin/526.index.js +3 -2
- package/bin/538.index.js +552 -0
- package/bin/795.index.js +3 -2
- package/bin/{890.index.js → 941.index.js} +2 -159
- package/bin/main.js +19 -7
- package/lib/getKcClsx.d.ts +11 -0
- package/lib/getKcClsx.js +44 -0
- package/lib/getKcClsx.js.map +1 -0
- package/login/Fallback.d.ts +1 -2
- package/login/Fallback.js.map +1 -1
- package/login/KcContext/KcContext.d.ts +6 -6
- package/login/KcContext/getKcContextMock.d.ts +9 -9
- package/login/KcContext/getKcContextMock.js +3 -3
- package/login/KcContext/getKcContextMock.js.map +1 -1
- package/login/Template.d.ts +1 -2
- package/login/Template.js +10 -9
- package/login/Template.js.map +1 -1
- package/login/TemplateProps.d.ts +1 -3
- package/login/UserProfileFormFields.d.ts +5 -5
- package/login/UserProfileFormFields.js +35 -34
- package/login/UserProfileFormFields.js.map +1 -1
- package/login/i18n/i18n.d.ts +9 -4
- package/login/i18n/i18n.js +136 -91
- package/login/i18n/i18n.js.map +1 -1
- package/login/i18n/index.d.ts +9 -2
- package/login/i18n/index.js +5 -1
- package/login/i18n/index.js.map +1 -1
- package/login/lib/kcClsx.d.ts +9 -0
- package/login/lib/{useGetClassName.js → kcClsx.js} +3 -3
- package/login/lib/kcClsx.js.map +1 -0
- package/login/lib/useUserProfileForm.d.ts +9 -6
- package/login/lib/useUserProfileForm.js +7 -5
- package/login/lib/useUserProfileForm.js.map +1 -1
- package/login/pages/Code.d.ts +1 -2
- package/login/pages/Code.js +6 -5
- package/login/pages/Code.js.map +1 -1
- package/login/pages/DeleteAccountConfirm.d.ts +1 -2
- package/login/pages/DeleteAccountConfirm.js +7 -7
- package/login/pages/DeleteAccountConfirm.js.map +1 -1
- package/login/pages/DeleteCredential.d.ts +1 -2
- package/login/pages/DeleteCredential.js +6 -6
- package/login/pages/DeleteCredential.js.map +1 -1
- package/login/pages/Error.d.ts +1 -2
- package/login/pages/Error.js +4 -3
- package/login/pages/Error.js.map +1 -1
- package/login/pages/FrontchannelLogout.d.ts +1 -2
- package/login/pages/FrontchannelLogout.js +4 -3
- package/login/pages/FrontchannelLogout.js.map +1 -1
- package/login/pages/IdpReviewUserProfile.d.ts +1 -2
- package/login/pages/IdpReviewUserProfile.js +6 -6
- package/login/pages/IdpReviewUserProfile.js.map +1 -1
- package/login/pages/Info.d.ts +1 -2
- package/login/pages/Info.js +4 -3
- package/login/pages/Info.js.map +1 -1
- package/login/pages/Login.d.ts +1 -2
- package/login/pages/Login.js +10 -8
- package/login/pages/Login.js.map +1 -1
- package/login/pages/LoginConfigTotp.d.ts +1 -2
- package/login/pages/LoginConfigTotp.js +8 -7
- package/login/pages/LoginConfigTotp.js.map +1 -1
- package/login/pages/LoginIdpLinkConfirm.d.ts +1 -2
- package/login/pages/LoginIdpLinkConfirm.js +6 -6
- package/login/pages/LoginIdpLinkConfirm.js.map +1 -1
- package/login/pages/LoginIdpLinkEmail.d.ts +1 -2
- package/login/pages/LoginIdpLinkEmail.js +4 -3
- package/login/pages/LoginIdpLinkEmail.js.map +1 -1
- package/login/pages/LoginOauth2DeviceVerifyUserCode.d.ts +1 -2
- package/login/pages/LoginOauth2DeviceVerifyUserCode.js +6 -6
- package/login/pages/LoginOauth2DeviceVerifyUserCode.js.map +1 -1
- package/login/pages/LoginOauthGrant.d.ts +1 -2
- package/login/pages/LoginOauthGrant.js +7 -7
- package/login/pages/LoginOauthGrant.js.map +1 -1
- package/login/pages/LoginOtp.d.ts +1 -2
- package/login/pages/LoginOtp.js +6 -6
- package/login/pages/LoginOtp.js.map +1 -1
- package/login/pages/LoginPageExpired.d.ts +1 -2
- package/login/pages/LoginPageExpired.js +4 -3
- package/login/pages/LoginPageExpired.js.map +1 -1
- package/login/pages/LoginPassword.d.ts +1 -2
- package/login/pages/LoginPassword.js +9 -7
- package/login/pages/LoginPassword.js.map +1 -1
- package/login/pages/LoginRecoveryAuthnCodeConfig.d.ts +1 -2
- package/login/pages/LoginRecoveryAuthnCodeConfig.js +9 -7
- package/login/pages/LoginRecoveryAuthnCodeConfig.js.map +1 -1
- package/login/pages/LoginRecoveryAuthnCodeInput.d.ts +1 -2
- package/login/pages/LoginRecoveryAuthnCodeInput.js +6 -6
- package/login/pages/LoginRecoveryAuthnCodeInput.js.map +1 -1
- package/login/pages/LoginResetOtp.d.ts +1 -2
- package/login/pages/LoginResetOtp.js +6 -6
- package/login/pages/LoginResetOtp.js.map +1 -1
- package/login/pages/LoginResetPassword.d.ts +1 -2
- package/login/pages/LoginResetPassword.js +7 -7
- package/login/pages/LoginResetPassword.js.map +1 -1
- package/login/pages/LoginUpdatePassword.d.ts +1 -2
- package/login/pages/LoginUpdatePassword.js +10 -9
- package/login/pages/LoginUpdatePassword.js.map +1 -1
- package/login/pages/LoginUpdateProfile.d.ts +1 -2
- package/login/pages/LoginUpdateProfile.js +7 -12
- package/login/pages/LoginUpdateProfile.js.map +1 -1
- package/login/pages/LoginUsername.d.ts +1 -2
- package/login/pages/LoginUsername.js +8 -7
- package/login/pages/LoginUsername.js.map +1 -1
- package/login/pages/LoginVerifyEmail.d.ts +1 -2
- package/login/pages/LoginVerifyEmail.js +4 -3
- package/login/pages/LoginVerifyEmail.js.map +1 -1
- package/login/pages/LoginX509Info.d.ts +1 -2
- package/login/pages/LoginX509Info.js +6 -6
- package/login/pages/LoginX509Info.js.map +1 -1
- package/login/pages/LogoutConfirm.d.ts +1 -2
- package/login/pages/LogoutConfirm.js +6 -6
- package/login/pages/LogoutConfirm.js.map +1 -1
- package/login/pages/PageProps.d.ts +2 -4
- package/login/pages/Register.d.ts +1 -2
- package/login/pages/Register.js +8 -16
- package/login/pages/Register.js.map +1 -1
- package/login/pages/SamlPostForm.d.ts +1 -2
- package/login/pages/SamlPostForm.js +4 -3
- package/login/pages/SamlPostForm.js.map +1 -1
- package/login/pages/SelectAuthenticator.d.ts +1 -2
- package/login/pages/SelectAuthenticator.js +6 -9
- package/login/pages/SelectAuthenticator.js.map +1 -1
- package/login/pages/Terms.d.ts +1 -2
- package/login/pages/Terms.js +6 -6
- package/login/pages/Terms.js.map +1 -1
- package/login/pages/UpdateEmail.d.ts +1 -2
- package/login/pages/UpdateEmail.js +8 -12
- package/login/pages/UpdateEmail.js.map +1 -1
- package/login/pages/WebauthnAuthenticate.d.ts +1 -2
- package/login/pages/WebauthnAuthenticate.js +13 -12
- package/login/pages/WebauthnAuthenticate.js.map +1 -1
- package/login/pages/WebauthnError.d.ts +1 -2
- package/login/pages/WebauthnError.js +7 -7
- package/login/pages/WebauthnError.js.map +1 -1
- package/login/pages/WebauthnRegister.d.ts +1 -2
- package/login/pages/WebauthnRegister.js +9 -8
- package/login/pages/WebauthnRegister.js.map +1 -1
- package/package.json +24 -16
- package/src/account/Fallback.tsx +1 -2
- package/src/account/KcContext/KcContext.ts +7 -7
- package/src/account/KcContext/getKcContextMock.ts +13 -24
- package/src/account/Template.tsx +8 -8
- package/src/account/TemplateProps.ts +1 -6
- package/src/account/i18n/i18n.tsx +204 -125
- package/src/account/i18n/index.ts +10 -2
- package/src/account/lib/{useGetClassName.ts → kcClsx.ts} +6 -2
- package/src/account/pages/Account.tsx +15 -21
- package/src/account/pages/Applications.tsx +8 -9
- package/src/account/pages/FederatedIdentity.tsx +5 -5
- package/src/account/pages/Log.tsx +8 -8
- package/src/account/pages/PageProps.ts +2 -4
- package/src/account/pages/Password.tsx +13 -16
- package/src/account/pages/Sessions.tsx +9 -10
- package/src/account/pages/Totp.tsx +19 -28
- package/src/bin/keycloakify/generateSrcMainResources/generateMessageProperties.ts +2 -66
- package/src/bin/keycloakify/generateSrcMainResources/generateSrcMainResourcesForMainTheme.ts +7 -1
- package/src/bin/main.ts +15 -0
- package/src/bin/shared/buildOptions.ts +5 -2
- package/src/bin/shared/generateKcGenTs.ts +61 -0
- package/src/bin/tools/escapeStringForPropertiesFile.ts +64 -0
- package/src/bin/update-kc-gen.ts +13 -0
- package/src/lib/getKcClsx.ts +75 -0
- package/src/login/Fallback.tsx +1 -2
- package/src/login/KcContext/KcContext.ts +7 -7
- package/src/login/KcContext/getKcContextMock.ts +13 -24
- package/src/login/Template.tsx +36 -37
- package/src/login/TemplateProps.ts +1 -6
- package/src/login/UserProfileFormFields.tsx +66 -81
- package/src/login/i18n/i18n.tsx +208 -129
- package/src/login/i18n/index.ts +10 -2
- package/src/login/lib/{useGetClassName.ts → kcClsx.ts} +6 -2
- package/src/login/lib/useUserProfileForm.tsx +29 -21
- package/src/login/pages/Code.tsx +10 -8
- package/src/login/pages/DeleteAccountConfirm.tsx +9 -10
- package/src/login/pages/DeleteCredential.tsx +11 -10
- package/src/login/pages/Error.tsx +5 -5
- package/src/login/pages/FrontchannelLogout.tsx +7 -5
- package/src/login/pages/IdpReviewUserProfile.tsx +16 -25
- package/src/login/pages/Info.tsx +7 -5
- package/src/login/pages/Login.tsx +34 -53
- package/src/login/pages/LoginConfigTotp.tsx +30 -38
- package/src/login/pages/LoginIdpLinkConfirm.tsx +10 -21
- package/src/login/pages/LoginIdpLinkEmail.tsx +5 -5
- package/src/login/pages/LoginOauth2DeviceVerifyUserCode.tsx +19 -24
- package/src/login/pages/LoginOauthGrant.tsx +14 -21
- package/src/login/pages/LoginOtp.tsx +29 -33
- package/src/login/pages/LoginPageExpired.tsx +5 -5
- package/src/login/pages/LoginPassword.tsx +23 -33
- package/src/login/pages/LoginRecoveryAuthnCodeConfig.tsx +21 -25
- package/src/login/pages/LoginRecoveryAuthnCodeInput.tsx +21 -25
- package/src/login/pages/LoginResetOtp.tsx +21 -25
- package/src/login/pages/LoginResetPassword.tsx +21 -25
- package/src/login/pages/LoginUpdatePassword.tsx +42 -52
- package/src/login/pages/LoginUpdateProfile.tsx +26 -33
- package/src/login/pages/LoginUsername.tsx +23 -35
- package/src/login/pages/LoginVerifyEmail.tsx +7 -5
- package/src/login/pages/LoginX509Info.tsx +27 -36
- package/src/login/pages/LogoutConfirm.tsx +11 -17
- package/src/login/pages/PageProps.ts +2 -4
- package/src/login/pages/Register.tsx +24 -49
- package/src/login/pages/SamlPostForm.tsx +5 -5
- package/src/login/pages/SelectAuthenticator.tsx +24 -26
- package/src/login/pages/Terms.tsx +9 -16
- package/src/login/pages/UpdateEmail.tsx +26 -36
- package/src/login/pages/WebauthnAuthenticate.tsx +26 -32
- package/src/login/pages/WebauthnError.tsx +11 -22
- package/src/login/pages/WebauthnRegister.tsx +20 -28
- package/src/tools/clsx.ts +6 -48
- package/src/tools/clsx_withTransform.ts +55 -0
- package/src/vite-plugin/vite-plugin.ts +14 -6
- package/tools/clsx.d.ts +3 -2
- package/tools/clsx.js +5 -41
- package/tools/clsx.js.map +1 -1
- package/tools/clsx_withTransform.d.ts +5 -0
- package/tools/clsx_withTransform.js +43 -0
- package/tools/clsx_withTransform.js.map +1 -0
- package/vite-plugin/index.js +167 -37
- package/account/lib/useGetClassName.d.ts +0 -7
- package/account/lib/useGetClassName.js.map +0 -1
- package/lib/useGetClassName.d.ts +0 -10
- package/lib/useGetClassName.js +0 -14
- package/lib/useGetClassName.js.map +0 -1
- package/login/lib/useGetClassName.d.ts +0 -7
- package/login/lib/useGetClassName.js.map +0 -1
- package/src/lib/useGetClassName.ts +0 -27
@@ -1,8 +1,8 @@
|
|
1
1
|
import "keycloakify/tools/Object.fromEntries";
|
2
|
-
import { useEffect, useState
|
3
|
-
import fallbackMessages from "./baseMessages/en";
|
4
|
-
import { getMessages } from "./baseMessages";
|
2
|
+
import { useEffect, useState } from "react";
|
5
3
|
import { assert } from "tsafe/assert";
|
4
|
+
import messages_fallbackLanguage from "./baseMessages/en";
|
5
|
+
import { getMessages } from "./baseMessages";
|
6
6
|
import type { KcContext } from "../KcContext";
|
7
7
|
import { Reflect } from "tsafe/Reflect";
|
8
8
|
|
@@ -17,7 +17,7 @@ export type KcContextLike = {
|
|
17
17
|
|
18
18
|
assert<KcContext extends KcContextLike ? true : false>();
|
19
19
|
|
20
|
-
export type MessageKey = keyof typeof
|
20
|
+
export type MessageKey = keyof typeof messages_fallbackLanguage;
|
21
21
|
|
22
22
|
export type GenericI18n<MessageKey extends string> = {
|
23
23
|
/**
|
@@ -79,166 +79,245 @@ export type GenericI18n<MessageKey extends string> = {
|
|
79
79
|
* See advancedMsg() but instead of returning a JSX.Element it returns a string.
|
80
80
|
*/
|
81
81
|
advancedMsgStr: (key: string, ...args: (string | undefined)[]) => string;
|
82
|
+
|
83
|
+
/**
|
84
|
+
* Initially the messages are in english (fallback language).
|
85
|
+
* The translations in the current language are being fetched dynamically.
|
86
|
+
* This property is true while the translations are being fetched.
|
87
|
+
*/
|
88
|
+
isFetchingTranslations: boolean;
|
82
89
|
};
|
83
90
|
|
84
|
-
|
91
|
+
function createGetI18n<ExtraMessageKey extends string = never>(extraMessages: { [languageTag: string]: { [key in ExtraMessageKey]: string } }) {
|
92
|
+
type I18n = GenericI18n<MessageKey | ExtraMessageKey>;
|
93
|
+
|
94
|
+
type Result = { i18n: I18n; prI18n_currentLanguage: Promise<I18n> | undefined };
|
95
|
+
|
96
|
+
const cachedResultByKcContext = new WeakMap<KcContextLike, Result>();
|
97
|
+
|
98
|
+
function getI18n(params: { kcContext: KcContextLike }): Result {
|
99
|
+
const { kcContext } = params;
|
100
|
+
|
101
|
+
use_cache: {
|
102
|
+
const cachedResult = cachedResultByKcContext.get(kcContext);
|
103
|
+
|
104
|
+
if (cachedResult === undefined) {
|
105
|
+
break use_cache;
|
106
|
+
}
|
107
|
+
|
108
|
+
return cachedResult;
|
109
|
+
}
|
110
|
+
|
111
|
+
const partialI18n: Pick<I18n, "currentLanguageTag" | "getChangeLocalUrl" | "labelBySupportedLanguageTag"> = {
|
112
|
+
currentLanguageTag: kcContext.locale?.currentLanguageTag ?? fallbackLanguageTag,
|
113
|
+
getChangeLocalUrl: newLanguageTag => {
|
114
|
+
const { locale } = kcContext;
|
115
|
+
|
116
|
+
assert(locale !== undefined, "Internationalization not enabled");
|
117
|
+
|
118
|
+
const targetSupportedLocale = locale.supported.find(({ languageTag }) => languageTag === newLanguageTag);
|
119
|
+
|
120
|
+
assert(targetSupportedLocale !== undefined, `${newLanguageTag} need to be enabled in Keycloak admin`);
|
121
|
+
|
122
|
+
return targetSupportedLocale.url;
|
123
|
+
},
|
124
|
+
labelBySupportedLanguageTag: Object.fromEntries((kcContext.locale?.supported ?? []).map(({ languageTag, label }) => [languageTag, label]))
|
125
|
+
};
|
126
|
+
|
127
|
+
const { createI18nTranslationFunctions } = createI18nTranslationFunctionsFactory<MessageKey, ExtraMessageKey>({
|
128
|
+
messages_fallbackLanguage,
|
129
|
+
extraMessages_fallbackLanguage: extraMessages[fallbackLanguageTag],
|
130
|
+
extraMessages: extraMessages[partialI18n.currentLanguageTag]
|
131
|
+
});
|
132
|
+
|
133
|
+
const isCurrentLanguageFallbackLanguage = partialI18n.currentLanguageTag !== fallbackLanguageTag;
|
134
|
+
|
135
|
+
const result: Result = {
|
136
|
+
i18n: {
|
137
|
+
...partialI18n,
|
138
|
+
...createI18nTranslationFunctions({ messages: undefined }),
|
139
|
+
isFetchingTranslations: !isCurrentLanguageFallbackLanguage
|
140
|
+
},
|
141
|
+
prI18n_currentLanguage: isCurrentLanguageFallbackLanguage
|
142
|
+
? undefined
|
143
|
+
: (async () => {
|
144
|
+
const messages = await getMessages(partialI18n.currentLanguageTag);
|
145
|
+
|
146
|
+
const i18n_currentLanguage: I18n = {
|
147
|
+
...partialI18n,
|
148
|
+
...createI18nTranslationFunctions({ messages }),
|
149
|
+
isFetchingTranslations: false
|
150
|
+
};
|
151
|
+
|
152
|
+
// NOTE: This promise.resolve is just because without it we TypeScript
|
153
|
+
// gives a Variable 'result' is used before being assigned. error
|
154
|
+
await Promise.resolve().then(() => {
|
155
|
+
result.i18n = i18n_currentLanguage;
|
156
|
+
result.prI18n_currentLanguage = undefined;
|
157
|
+
});
|
158
|
+
|
159
|
+
return i18n_currentLanguage;
|
160
|
+
})()
|
161
|
+
};
|
162
|
+
|
163
|
+
cachedResultByKcContext.set(kcContext, result);
|
164
|
+
|
165
|
+
return result;
|
166
|
+
}
|
167
|
+
|
168
|
+
return { getI18n };
|
169
|
+
}
|
85
170
|
|
86
171
|
export function createUseI18n<ExtraMessageKey extends string = never>(extraMessages: {
|
87
172
|
[languageTag: string]: { [key in ExtraMessageKey]: string };
|
88
173
|
}) {
|
89
|
-
|
174
|
+
type I18n = GenericI18n<MessageKey | ExtraMessageKey>;
|
175
|
+
|
176
|
+
const { getI18n } = createGetI18n(extraMessages);
|
177
|
+
|
178
|
+
function useI18n(params: { kcContext: KcContextLike }): I18n {
|
90
179
|
const { kcContext } = params;
|
91
180
|
|
92
|
-
const
|
181
|
+
const { i18n, prI18n_currentLanguage } = getI18n({ kcContext });
|
93
182
|
|
94
|
-
const
|
183
|
+
const [i18n_toReturn, setI18n_toReturn] = useState<I18n>(i18n);
|
95
184
|
|
96
185
|
useEffect(() => {
|
97
|
-
|
98
|
-
return;
|
99
|
-
}
|
186
|
+
let isActive = true;
|
100
187
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
messages: {
|
113
|
-
...(await getMessages(currentLanguageTag)),
|
114
|
-
...(extraMessages[currentLanguageTag] ?? {})
|
115
|
-
} as any
|
116
|
-
}),
|
117
|
-
currentLanguageTag,
|
118
|
-
getChangeLocalUrl: newLanguageTag => {
|
119
|
-
const { locale } = kcContext;
|
120
|
-
|
121
|
-
assert(locale !== undefined, "Internationalization not enabled");
|
122
|
-
|
123
|
-
const targetSupportedLocale = locale.supported.find(({ languageTag }) => languageTag === newLanguageTag);
|
124
|
-
|
125
|
-
assert(targetSupportedLocale !== undefined, `${newLanguageTag} need to be enabled in Keycloak admin`);
|
126
|
-
|
127
|
-
return targetSupportedLocale.url;
|
128
|
-
},
|
129
|
-
labelBySupportedLanguageTag: Object.fromEntries(
|
130
|
-
(kcContext.locale?.supported ?? []).map(({ languageTag, label }) => [languageTag, label])
|
131
|
-
)
|
132
|
-
});
|
133
|
-
})();
|
188
|
+
prI18n_currentLanguage?.then(i18n => {
|
189
|
+
if (!isActive) {
|
190
|
+
return;
|
191
|
+
}
|
192
|
+
|
193
|
+
setI18n_toReturn(i18n);
|
194
|
+
});
|
195
|
+
|
196
|
+
return () => {
|
197
|
+
isActive = false;
|
198
|
+
};
|
134
199
|
}, []);
|
135
200
|
|
136
|
-
return
|
201
|
+
return i18n_toReturn;
|
137
202
|
}
|
138
203
|
|
139
|
-
return {
|
140
|
-
useI18n,
|
141
|
-
ofTypeI18n: Reflect<GenericI18n<MessageKey | ExtraMessageKey>>()
|
142
|
-
};
|
204
|
+
return { useI18n, ofTypeI18n: Reflect<I18n>() };
|
143
205
|
}
|
144
206
|
|
145
|
-
function
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
function resolveMsg(props: { key: string; args: (string | undefined)[]; doRenderAsHtml: boolean }): string | JSX.Element | undefined {
|
152
|
-
const { key, args, doRenderAsHtml } = props;
|
207
|
+
function createI18nTranslationFunctionsFactory<MessageKey extends string, ExtraMessageKey extends string>(params: {
|
208
|
+
messages_fallbackLanguage: Record<MessageKey, string>;
|
209
|
+
extraMessages_fallbackLanguage: Record<ExtraMessageKey, string> | undefined;
|
210
|
+
extraMessages: Partial<Record<ExtraMessageKey, string>> | undefined;
|
211
|
+
}) {
|
212
|
+
const { extraMessages } = params;
|
153
213
|
|
154
|
-
|
214
|
+
const messages_fallbackLanguage = {
|
215
|
+
...params.messages_fallbackLanguage,
|
216
|
+
...params.extraMessages_fallbackLanguage
|
217
|
+
};
|
155
218
|
|
156
|
-
|
157
|
-
|
158
|
-
|
219
|
+
function createI18nTranslationFunctions(params: {
|
220
|
+
messages: Partial<Record<MessageKey, string>> | undefined;
|
221
|
+
}): Pick<GenericI18n<MessageKey | ExtraMessageKey>, "msg" | "msgStr" | "advancedMsg" | "advancedMsgStr"> {
|
222
|
+
const messages = {
|
223
|
+
...params.messages,
|
224
|
+
...extraMessages
|
225
|
+
};
|
159
226
|
|
160
|
-
|
227
|
+
function resolveMsg(props: { key: string; args: (string | undefined)[]; doRenderAsHtml: boolean }): string | JSX.Element | undefined {
|
228
|
+
const { key, args, doRenderAsHtml } = props;
|
161
229
|
|
162
|
-
|
163
|
-
const startIndex = message
|
164
|
-
.match(/{[0-9]+}/g)
|
165
|
-
?.map(g => g.match(/{([0-9]+)}/)![1])
|
166
|
-
.map(indexStr => parseInt(indexStr))
|
167
|
-
.sort((a, b) => a - b)[0];
|
230
|
+
const messageOrUndefined: string | undefined = (messages as any)[key] ?? (messages_fallbackLanguage as any)[key];
|
168
231
|
|
169
|
-
if (
|
170
|
-
|
171
|
-
return message;
|
232
|
+
if (messageOrUndefined === undefined) {
|
233
|
+
return undefined;
|
172
234
|
}
|
173
235
|
|
174
|
-
|
236
|
+
const message = messageOrUndefined;
|
175
237
|
|
176
|
-
|
177
|
-
|
178
|
-
|
238
|
+
const messageWithArgsInjectedIfAny = (() => {
|
239
|
+
const startIndex = message
|
240
|
+
.match(/{[0-9]+}/g)
|
241
|
+
?.map(g => g.match(/{([0-9]+)}/)![1])
|
242
|
+
.map(indexStr => parseInt(indexStr))
|
243
|
+
.sort((a, b) => a - b)[0];
|
244
|
+
|
245
|
+
if (startIndex === undefined) {
|
246
|
+
// No {0} in message (no arguments expected)
|
247
|
+
return message;
|
179
248
|
}
|
180
249
|
|
181
|
-
messageWithArgsInjected =
|
182
|
-
new RegExp(`\\{${i + startIndex}\\}`, "g"),
|
183
|
-
arg.replace(/</g, "<").replace(/>/g, ">")
|
184
|
-
);
|
185
|
-
});
|
250
|
+
let messageWithArgsInjected = message;
|
186
251
|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
252
|
+
args.forEach((arg, i) => {
|
253
|
+
if (arg === undefined) {
|
254
|
+
return;
|
255
|
+
}
|
256
|
+
|
257
|
+
messageWithArgsInjected = messageWithArgsInjected.replace(
|
258
|
+
new RegExp(`\\{${i + startIndex}\\}`, "g"),
|
259
|
+
arg.replace(/</g, "<").replace(/>/g, ">")
|
260
|
+
);
|
261
|
+
});
|
262
|
+
|
263
|
+
return messageWithArgsInjected;
|
264
|
+
})();
|
265
|
+
|
266
|
+
return doRenderAsHtml ? (
|
267
|
+
<span
|
268
|
+
// NOTE: The message is trusted. The arguments are not but are escaped.
|
269
|
+
dangerouslySetInnerHTML={{
|
270
|
+
__html: messageWithArgsInjectedIfAny
|
271
|
+
}}
|
272
|
+
/>
|
273
|
+
) : (
|
274
|
+
messageWithArgsInjectedIfAny
|
275
|
+
);
|
276
|
+
}
|
201
277
|
|
202
|
-
|
203
|
-
|
278
|
+
function resolveMsgAdvanced(props: { key: string; args: (string | undefined)[]; doRenderAsHtml: boolean }): JSX.Element | string {
|
279
|
+
const { key, args, doRenderAsHtml } = props;
|
204
280
|
|
205
|
-
|
206
|
-
|
281
|
+
if (!/\$\{[^}]+\}/.test(key)) {
|
282
|
+
const resolvedMessage = resolveMsg({ key, args, doRenderAsHtml });
|
207
283
|
|
208
|
-
|
209
|
-
|
284
|
+
if (resolvedMessage === undefined) {
|
285
|
+
return doRenderAsHtml ? <span dangerouslySetInnerHTML={{ __html: key }} /> : key;
|
286
|
+
}
|
287
|
+
|
288
|
+
return resolvedMessage;
|
210
289
|
}
|
211
290
|
|
212
|
-
|
213
|
-
}
|
291
|
+
let isFirstMatch = true;
|
214
292
|
|
215
|
-
|
293
|
+
const resolvedComplexMessage = key.replace(/\$\{([^}]+)\}/g, (...[, key_i]) => {
|
294
|
+
const replaceBy = resolveMsg({ key: key_i, args: isFirstMatch ? args : [], doRenderAsHtml: false }) ?? key_i;
|
216
295
|
|
217
|
-
|
218
|
-
const replaceBy = resolveMsg({ key: key_i, args: isFirstMatch ? args : [], doRenderAsHtml: false }) ?? key_i;
|
296
|
+
isFirstMatch = false;
|
219
297
|
|
220
|
-
|
298
|
+
return replaceBy;
|
299
|
+
});
|
221
300
|
|
222
|
-
return
|
223
|
-
}
|
301
|
+
return doRenderAsHtml ? <span dangerouslySetInnerHTML={{ __html: resolvedComplexMessage }} /> : resolvedComplexMessage;
|
302
|
+
}
|
224
303
|
|
225
|
-
return
|
304
|
+
return {
|
305
|
+
msgStr: (key, ...args) => resolveMsg({ key, args, doRenderAsHtml: false }) as string,
|
306
|
+
msg: (key, ...args) => resolveMsg({ key, args, doRenderAsHtml: true }) as JSX.Element,
|
307
|
+
advancedMsg: (key, ...args) =>
|
308
|
+
resolveMsgAdvanced({
|
309
|
+
key,
|
310
|
+
args,
|
311
|
+
doRenderAsHtml: true
|
312
|
+
}) as JSX.Element,
|
313
|
+
advancedMsgStr: (key, ...args) =>
|
314
|
+
resolveMsgAdvanced({
|
315
|
+
key,
|
316
|
+
args,
|
317
|
+
doRenderAsHtml: false
|
318
|
+
}) as string
|
319
|
+
};
|
226
320
|
}
|
227
321
|
|
228
|
-
return {
|
229
|
-
msgStr: (key, ...args) => resolveMsg({ key, args, doRenderAsHtml: false }) as string,
|
230
|
-
msg: (key, ...args) => resolveMsg({ key, args, doRenderAsHtml: true }) as JSX.Element,
|
231
|
-
advancedMsg: (key, ...args) =>
|
232
|
-
resolveMsgAdvanced({
|
233
|
-
key,
|
234
|
-
args,
|
235
|
-
doRenderAsHtml: true
|
236
|
-
}) as JSX.Element,
|
237
|
-
advancedMsgStr: (key, ...args) =>
|
238
|
-
resolveMsgAdvanced({
|
239
|
-
key,
|
240
|
-
args,
|
241
|
-
doRenderAsHtml: false
|
242
|
-
}) as string
|
243
|
-
};
|
322
|
+
return { createI18nTranslationFunctions };
|
244
323
|
}
|
@@ -1,2 +1,10 @@
|
|
1
|
-
export type {
|
2
|
-
|
1
|
+
export type { MessageKey } from "./i18n";
|
2
|
+
import { createUseI18n } from "./i18n";
|
3
|
+
export { createUseI18n };
|
4
|
+
export { fallbackLanguageTag } from "./i18n";
|
5
|
+
|
6
|
+
const { useI18n, ofTypeI18n } = createUseI18n({});
|
7
|
+
|
8
|
+
export type I18n = typeof ofTypeI18n;
|
9
|
+
|
10
|
+
export { useI18n };
|
@@ -1,7 +1,7 @@
|
|
1
|
-
import {
|
1
|
+
import { createGetKcClsx } from "keycloakify/lib/getKcClsx";
|
2
2
|
import type { ClassKey } from "keycloakify/account/TemplateProps";
|
3
3
|
|
4
|
-
export const {
|
4
|
+
export const { getKcClsx } = createGetKcClsx<ClassKey>({
|
5
5
|
defaultClasses: {
|
6
6
|
kcHtmlClass: undefined,
|
7
7
|
kcBodyClass: undefined,
|
@@ -19,3 +19,7 @@ export const { useGetClassName } = createUseClassName<ClassKey>({
|
|
19
19
|
"pf-c-form__helper-text pf-m-error required kc-feedback-text"
|
20
20
|
}
|
21
21
|
});
|
22
|
+
|
23
|
+
export type { ClassKey };
|
24
|
+
|
25
|
+
export type KcClsx = ReturnType<typeof getKcClsx>["kcClsx"];
|
@@ -1,26 +1,28 @@
|
|
1
1
|
import { clsx } from "keycloakify/tools/clsx";
|
2
2
|
import type { PageProps } from "keycloakify/account/pages/PageProps";
|
3
|
-
import {
|
3
|
+
import { getKcClsx } from "keycloakify/account/lib/kcClsx";
|
4
4
|
import type { KcContext } from "../KcContext";
|
5
|
-
import
|
5
|
+
import { useI18n } from "../i18n";
|
6
6
|
|
7
|
-
export default function Account(props: PageProps<Extract<KcContext, { pageId: "account.ftl" }
|
8
|
-
const { kcContext,
|
7
|
+
export default function Account(props: PageProps<Extract<KcContext, { pageId: "account.ftl" }>>) {
|
8
|
+
const { kcContext, doUseDefaultCss, Template } = props;
|
9
9
|
|
10
|
-
const
|
10
|
+
const classes = {
|
11
|
+
...props.classes,
|
12
|
+
kcBodyClass: clsx(props.classes?.kcBodyClass, "user")
|
13
|
+
};
|
14
|
+
|
15
|
+
const { kcClsx } = getKcClsx({
|
11
16
|
doUseDefaultCss,
|
12
|
-
classes
|
13
|
-
...classes,
|
14
|
-
kcBodyClass: clsx(classes?.kcBodyClass, "user")
|
15
|
-
}
|
17
|
+
classes
|
16
18
|
});
|
17
19
|
|
18
20
|
const { url, realm, messagesPerField, stateChecker, account, referrer } = kcContext;
|
19
21
|
|
20
|
-
const { msg } =
|
22
|
+
const { msg } = useI18n({ kcContext });
|
21
23
|
|
22
24
|
return (
|
23
|
-
<Template {...{ kcContext,
|
25
|
+
<Template {...{ kcContext, doUseDefaultCss, classes }} active="account">
|
24
26
|
<div className="row">
|
25
27
|
<div className="col-md-10">
|
26
28
|
<h2>{msg("editAccountHtmlTitle")}</h2>
|
@@ -102,11 +104,7 @@ export default function Account(props: PageProps<Extract<KcContext, { pageId: "a
|
|
102
104
|
{referrer !== undefined && <a href={referrer?.url}>{msg("backToApplication")}</a>}
|
103
105
|
<button
|
104
106
|
type="submit"
|
105
|
-
className={
|
106
|
-
getClassName("kcButtonClass"),
|
107
|
-
getClassName("kcButtonPrimaryClass"),
|
108
|
-
getClassName("kcButtonLargeClass")
|
109
|
-
)}
|
107
|
+
className={kcClsx("kcButtonClass", "kcButtonPrimaryClass", "kcButtonLargeClass")}
|
110
108
|
name="submitAction"
|
111
109
|
value="Save"
|
112
110
|
>
|
@@ -114,11 +112,7 @@ export default function Account(props: PageProps<Extract<KcContext, { pageId: "a
|
|
114
112
|
</button>
|
115
113
|
<button
|
116
114
|
type="submit"
|
117
|
-
className={
|
118
|
-
getClassName("kcButtonClass"),
|
119
|
-
getClassName("kcButtonDefaultClass"),
|
120
|
-
getClassName("kcButtonLargeClass")
|
121
|
-
)}
|
115
|
+
className={kcClsx("kcButtonClass", "kcButtonDefaultClass", "kcButtonLargeClass")}
|
122
116
|
name="submitAction"
|
123
117
|
value="Cancel"
|
124
118
|
>
|
@@ -1,13 +1,12 @@
|
|
1
|
-
import {
|
2
|
-
import { useGetClassName } from "keycloakify/account/lib/useGetClassName";
|
1
|
+
import { getKcClsx } from "keycloakify/account/lib/kcClsx";
|
3
2
|
import type { PageProps } from "keycloakify/account/pages/PageProps";
|
4
3
|
import type { KcContext } from "../KcContext";
|
5
|
-
import
|
4
|
+
import { useI18n } from "../i18n";
|
6
5
|
|
7
|
-
export default function Applications(props: PageProps<Extract<KcContext, { pageId: "applications.ftl" }
|
8
|
-
const { kcContext,
|
6
|
+
export default function Applications(props: PageProps<Extract<KcContext, { pageId: "applications.ftl" }>>) {
|
7
|
+
const { kcContext, doUseDefaultCss, classes, Template } = props;
|
9
8
|
|
10
|
-
const {
|
9
|
+
const { kcClsx } = getKcClsx({
|
11
10
|
doUseDefaultCss,
|
12
11
|
classes
|
13
12
|
});
|
@@ -18,10 +17,10 @@ export default function Applications(props: PageProps<Extract<KcContext, { pageI
|
|
18
17
|
stateChecker
|
19
18
|
} = kcContext;
|
20
19
|
|
21
|
-
const { msg, advancedMsg } =
|
20
|
+
const { msg, advancedMsg } = useI18n({ kcContext });
|
22
21
|
|
23
22
|
return (
|
24
|
-
<Template {...{ kcContext,
|
23
|
+
<Template {...{ kcContext, doUseDefaultCss, classes }} active="applications">
|
25
24
|
<div className="row">
|
26
25
|
<div className="col-md-10">
|
27
26
|
<h2>{msg("applicationsHtmlTitle")}</h2>
|
@@ -114,7 +113,7 @@ export default function Applications(props: PageProps<Extract<KcContext, { pageI
|
|
114
113
|
application.additionalGrants.length > 0 ? (
|
115
114
|
<button
|
116
115
|
type="submit"
|
117
|
-
className={
|
116
|
+
className={kcClsx("kcButtonPrimaryClass", "kcButtonClass")}
|
118
117
|
id={`revoke-${application.client.clientId}`}
|
119
118
|
name="clientId"
|
120
119
|
value={application.client.id}
|
@@ -1,14 +1,14 @@
|
|
1
1
|
import type { PageProps } from "keycloakify/account/pages/PageProps";
|
2
2
|
import type { KcContext } from "../KcContext";
|
3
|
-
import
|
3
|
+
import { useI18n } from "../i18n";
|
4
4
|
|
5
|
-
export default function FederatedIdentity(props: PageProps<Extract<KcContext, { pageId: "federatedIdentity.ftl" }
|
6
|
-
const { kcContext,
|
5
|
+
export default function FederatedIdentity(props: PageProps<Extract<KcContext, { pageId: "federatedIdentity.ftl" }>>) {
|
6
|
+
const { kcContext, doUseDefaultCss, classes, Template } = props;
|
7
7
|
|
8
8
|
const { url, federatedIdentity, stateChecker } = kcContext;
|
9
|
-
const { msg } =
|
9
|
+
const { msg } = useI18n({ kcContext });
|
10
10
|
return (
|
11
|
-
<Template {...{ kcContext,
|
11
|
+
<Template {...{ kcContext, doUseDefaultCss, classes }} active="federatedIdentity">
|
12
12
|
<div className="main-layout social">
|
13
13
|
<div className="row">
|
14
14
|
<div className="col-md-10">
|
@@ -1,24 +1,24 @@
|
|
1
1
|
import type { Key } from "react";
|
2
|
-
import {
|
2
|
+
import { getKcClsx } from "keycloakify/account/lib/kcClsx";
|
3
3
|
import type { PageProps } from "keycloakify/account/pages/PageProps";
|
4
|
-
import type { I18n } from "../i18n";
|
5
4
|
import type { KcContext } from "../KcContext";
|
5
|
+
import { useI18n } from "../i18n";
|
6
6
|
|
7
|
-
export default function Log(props: PageProps<Extract<KcContext, { pageId: "log.ftl" }
|
8
|
-
const { kcContext,
|
7
|
+
export default function Log(props: PageProps<Extract<KcContext, { pageId: "log.ftl" }>>) {
|
8
|
+
const { kcContext, doUseDefaultCss, classes, Template } = props;
|
9
9
|
|
10
|
-
const {
|
10
|
+
const { kcClsx } = getKcClsx({
|
11
11
|
doUseDefaultCss,
|
12
12
|
classes
|
13
13
|
});
|
14
14
|
|
15
15
|
const { log } = kcContext;
|
16
16
|
|
17
|
-
const { msg } =
|
17
|
+
const { msg } = useI18n({ kcContext });
|
18
18
|
|
19
19
|
return (
|
20
|
-
<Template {...{ kcContext,
|
21
|
-
<div className={
|
20
|
+
<Template {...{ kcContext, doUseDefaultCss, classes }} active="log">
|
21
|
+
<div className={kcClsx("kcContentWrapperClass")}>
|
22
22
|
<div className="col-md-10">
|
23
23
|
<h2>{msg("accountLogHtmlTitle")}</h2>
|
24
24
|
</div>
|
@@ -1,12 +1,10 @@
|
|
1
1
|
import type { TemplateProps, ClassKey } from "keycloakify/account/TemplateProps";
|
2
2
|
import type { LazyOrNot } from "keycloakify/tools/LazyOrNot";
|
3
|
-
import type { I18n } from "../i18n";
|
4
3
|
import type { KcContext } from "../KcContext";
|
5
4
|
|
6
|
-
export type PageProps<NarrowedKcContext = KcContext
|
7
|
-
Template: LazyOrNot<(props: TemplateProps<any
|
5
|
+
export type PageProps<NarrowedKcContext = KcContext> = {
|
6
|
+
Template: LazyOrNot<(props: TemplateProps<any>) => JSX.Element | null>;
|
8
7
|
kcContext: NarrowedKcContext;
|
9
|
-
i18n: I18nExtended;
|
10
8
|
doUseDefaultCss: boolean;
|
11
9
|
classes?: Partial<Record<ClassKey, string>>;
|
12
10
|
};
|
@@ -1,24 +1,26 @@
|
|
1
1
|
import { useState } from "react";
|
2
2
|
import { clsx } from "keycloakify/tools/clsx";
|
3
|
-
import {
|
3
|
+
import { getKcClsx } from "keycloakify/account/lib/kcClsx";
|
4
4
|
import type { PageProps } from "keycloakify/account/pages/PageProps";
|
5
5
|
import type { KcContext } from "../KcContext";
|
6
|
-
import
|
6
|
+
import { useI18n } from "../i18n";
|
7
7
|
|
8
|
-
export default function Password(props: PageProps<Extract<KcContext, { pageId: "password.ftl" }
|
9
|
-
const { kcContext,
|
8
|
+
export default function Password(props: PageProps<Extract<KcContext, { pageId: "password.ftl" }>>) {
|
9
|
+
const { kcContext, doUseDefaultCss, Template } = props;
|
10
10
|
|
11
|
-
const
|
11
|
+
const classes = {
|
12
|
+
...props.classes,
|
13
|
+
kcBodyClass: clsx(props.classes?.kcBodyClass, "password")
|
14
|
+
};
|
15
|
+
|
16
|
+
const { kcClsx } = getKcClsx({
|
12
17
|
doUseDefaultCss,
|
13
|
-
classes
|
14
|
-
...classes,
|
15
|
-
kcBodyClass: clsx(classes?.kcBodyClass, "password")
|
16
|
-
}
|
18
|
+
classes
|
17
19
|
});
|
18
20
|
|
19
21
|
const { url, password, account, stateChecker } = kcContext;
|
20
22
|
|
21
|
-
const { msgStr, msg } =
|
23
|
+
const { msgStr, msg } = useI18n({ kcContext });
|
22
24
|
|
23
25
|
const [currentPassword, setCurrentPassword] = useState("");
|
24
26
|
const [newPassword, setNewPassword] = useState("");
|
@@ -75,7 +77,6 @@ export default function Password(props: PageProps<Extract<KcContext, { pageId: "
|
|
75
77
|
return kcContext.message;
|
76
78
|
})()
|
77
79
|
},
|
78
|
-
i18n,
|
79
80
|
doUseDefaultCss,
|
80
81
|
classes
|
81
82
|
}}
|
@@ -192,11 +193,7 @@ export default function Password(props: PageProps<Extract<KcContext, { pageId: "
|
|
192
193
|
<button
|
193
194
|
disabled={newPasswordError !== "" || newPasswordConfirmError !== ""}
|
194
195
|
type="submit"
|
195
|
-
className={
|
196
|
-
getClassName("kcButtonClass"),
|
197
|
-
getClassName("kcButtonPrimaryClass"),
|
198
|
-
getClassName("kcButtonLargeClass")
|
199
|
-
)}
|
196
|
+
className={kcClsx("kcButtonClass", "kcButtonPrimaryClass", "kcButtonLargeClass")}
|
200
197
|
name="submitAction"
|
201
198
|
value="Save"
|
202
199
|
>
|