i18n rebuild from the ground up

This commit is contained in:
garronej
2022-04-27 21:02:10 +02:00
parent cc8b2e72c1
commit 7e7071305f
26 changed files with 288 additions and 361 deletions

View File

@ -2,10 +2,10 @@ import { memo } from "react";
import { Template } from "./Template";
import type { KcProps } from "./KcProps";
import type { KcContextBase } from "../getKcContext/KcContextBase";
import { useKcMessage } from "../i18n/useKcMessage";
import { getMsg } from "../i18n";
export const Error = memo(({ kcContext, ...props }: { kcContext: KcContextBase.Error } & KcProps) => {
const { msg } = useKcMessage();
const { msg } = getMsg(kcContext);
const { message, client } = kcContext;

View File

@ -3,10 +3,10 @@ import { Template } from "./Template";
import type { KcProps } from "./KcProps";
import { assert } from "../tools/assert";
import type { KcContextBase } from "../getKcContext/KcContextBase";
import { useKcMessage } from "../i18n/useKcMessage";
import { getMsg } from "../i18n";
export const Info = memo(({ kcContext, ...props }: { kcContext: KcContextBase.Info } & KcProps) => {
const { msg } = useKcMessage();
const { msg } = getMsg(kcContext);
assert(kcContext.message !== undefined);

View File

@ -2,7 +2,7 @@ import { useState, memo } from "react";
import { Template } from "./Template";
import type { KcProps } from "./KcProps";
import type { KcContextBase } from "../getKcContext/KcContextBase";
import { useKcMessage } from "../i18n/useKcMessage";
import { getMsg } from "../i18n";
import { useCssAndCx } from "tss-react";
import { useConstCallback } from "powerhooks/useConstCallback";
import type { FormEventHandler } from "react";
@ -10,7 +10,7 @@ import type { FormEventHandler } from "react";
export const Login = memo(({ kcContext, ...props }: { kcContext: KcContextBase.Login } & KcProps) => {
const { social, realm, url, usernameEditDisabled, login, auth, registrationDisabled } = kcContext;
const { msg, msgStr } = useKcMessage();
const { msg, msgStr } = getMsg(kcContext);
const { cx } = useCssAndCx();

View File

@ -2,13 +2,13 @@ import { memo } from "react";
import { Template } from "./Template";
import type { KcProps } from "./KcProps";
import type { KcContextBase } from "../getKcContext/KcContextBase";
import { useKcMessage } from "../i18n/useKcMessage";
import { getMsg } from "../i18n";
import { useCssAndCx } from "tss-react";
export const LoginIdpLinkConfirm = memo(({ kcContext, ...props }: { kcContext: KcContextBase.LoginIdpLinkConfirm } & KcProps) => {
const { url, idpAlias } = kcContext;
const { msg } = useKcMessage();
const { msg } = getMsg(kcContext);
const { cx } = useCssAndCx();

View File

@ -2,12 +2,12 @@ import { memo } from "react";
import { Template } from "./Template";
import type { KcProps } from "./KcProps";
import type { KcContextBase } from "../getKcContext/KcContextBase";
import { useKcMessage } from "../i18n/useKcMessage";
import { getMsg } from "../i18n";
export const LoginIdpLinkEmail = memo(({ kcContext, ...props }: { kcContext: KcContextBase.LoginIdpLinkEmail } & KcProps) => {
const { url, realm, brokerContext, idpAlias } = kcContext;
const { msg } = useKcMessage();
const { msg } = getMsg(kcContext);
return (
<Template

View File

@ -2,7 +2,7 @@ import { useEffect, memo } from "react";
import { Template } from "./Template";
import type { KcProps } from "./KcProps";
import type { KcContextBase } from "../getKcContext/KcContextBase";
import { useKcMessage } from "../i18n/useKcMessage";
import { getMsg } from "../i18n";
import { headInsert } from "../tools/headInsert";
import { pathJoin } from "../tools/pathJoin";
import { useCssAndCx } from "tss-react";
@ -12,7 +12,7 @@ export const LoginOtp = memo(({ kcContext, ...props }: { kcContext: KcContextBas
const { cx } = useCssAndCx();
const { msg, msgStr } = useKcMessage();
const { msg, msgStr } = getMsg(kcContext);
useEffect(() => {
let isCleanedUp = false;

View File

@ -2,12 +2,12 @@ import { memo } from "react";
import { Template } from "./Template";
import type { KcProps } from "./KcProps";
import type { KcContextBase } from "../getKcContext/KcContextBase";
import { useKcMessage } from "../i18n/useKcMessage";
import { getMsg } from "../i18n";
export const LoginPageExpired = memo(({ kcContext, ...props }: { kcContext: KcContextBase.LoginPageExpired } & KcProps) => {
const { url } = kcContext;
const { msg } = useKcMessage();
const { msg } = getMsg(kcContext);
return (
<Template

View File

@ -2,13 +2,13 @@ import { memo } from "react";
import { Template } from "./Template";
import type { KcProps } from "./KcProps";
import type { KcContextBase } from "../getKcContext/KcContextBase";
import { useKcMessage } from "../i18n/useKcMessage";
import { getMsg } from "../i18n";
import { useCssAndCx } from "tss-react";
export const LoginResetPassword = memo(({ kcContext, ...props }: { kcContext: KcContextBase.LoginResetPassword } & KcProps) => {
const { url, realm, auth } = kcContext;
const { msg, msgStr } = useKcMessage();
const { msg, msgStr } = getMsg(kcContext);
const { cx } = useCssAndCx();

View File

@ -2,13 +2,13 @@ import { memo } from "react";
import { Template } from "./Template";
import type { KcProps } from "./KcProps";
import type { KcContextBase } from "../getKcContext/KcContextBase";
import { useKcMessage } from "../i18n/useKcMessage";
import { getMsg } from "../i18n";
import { useCssAndCx } from "tss-react";
export const LoginUpdatePassword = memo(({ kcContext, ...props }: { kcContext: KcContextBase.LoginUpdatePassword } & KcProps) => {
const { cx } = useCssAndCx();
const { msg, msgStr } = useKcMessage();
const { msg, msgStr } = getMsg(kcContext);
const { url, messagesPerField, isAppInitiatedAction, username } = kcContext;

View File

@ -2,13 +2,13 @@ import { memo } from "react";
import { Template } from "./Template";
import type { KcProps } from "./KcProps";
import type { KcContextBase } from "../getKcContext/KcContextBase";
import { useKcMessage } from "../i18n/useKcMessage";
import { getMsg } from "../i18n";
import { useCssAndCx } from "tss-react";
export const LoginUpdateProfile = memo(({ kcContext, ...props }: { kcContext: KcContextBase.LoginUpdateProfile } & KcProps) => {
const { cx } = useCssAndCx();
const { msg, msgStr } = useKcMessage();
const { msg, msgStr } = getMsg(kcContext);
const { url, user, messagesPerField, isAppInitiatedAction } = kcContext;

View File

@ -2,10 +2,10 @@ import { memo } from "react";
import { Template } from "./Template";
import type { KcProps } from "./KcProps";
import type { KcContextBase } from "../getKcContext/KcContextBase";
import { useKcMessage } from "../i18n/useKcMessage";
import { getMsg } from "../i18n";
export const LoginVerifyEmail = memo(({ kcContext, ...props }: { kcContext: KcContextBase.LoginVerifyEmail } & KcProps) => {
const { msg } = useKcMessage();
const { msg } = getMsg(kcContext);
const { url } = kcContext;

View File

@ -2,13 +2,13 @@ import { memo } from "react";
import { Template } from "./Template";
import type { KcProps } from "./KcProps";
import type { KcContextBase } from "../getKcContext/KcContextBase";
import { useKcMessage } from "../i18n/useKcMessage";
import { getMsg } from "../i18n";
import { useCssAndCx } from "tss-react";
export const Register = memo(({ kcContext, ...props }: { kcContext: KcContextBase.Register } & KcProps) => {
const { url, messagesPerField, register, realm, passwordRequired, recaptchaRequired, recaptchaSiteKey } = kcContext;
const { msg, msgStr } = useKcMessage();
const { msg, msgStr } = getMsg(kcContext);
const { cx } = useCssAndCx();

View File

@ -2,7 +2,7 @@ import { useMemo, memo, useEffect, useState, Fragment } from "react";
import { Template } from "./Template";
import type { KcProps } from "./KcProps";
import type { KcContextBase, Attribute } from "../getKcContext/KcContextBase";
import { useKcMessage } from "../i18n/useKcMessage";
import { getMsg } from "../i18n";
import { useCssAndCx } from "tss-react";
import type { ReactComponent } from "../tools/ReactComponent";
import { useCallbackFactory } from "powerhooks/useCallbackFactory";
@ -11,7 +11,7 @@ import { useFormValidationSlice } from "../useFormValidationSlice";
export const RegisterUserProfile = memo(({ kcContext, ...props_ }: { kcContext: KcContextBase.RegisterUserProfile } & KcProps) => {
const { url, messagesPerField, recaptchaRequired, recaptchaSiteKey } = kcContext;
const { msg, msgStr } = useKcMessage();
const { msg, msgStr } = getMsg(kcContext);
const { cx, css } = useCssAndCx();
@ -74,7 +74,7 @@ type UserProfileFormFieldsProps = { kcContext: KcContextBase.RegisterUserProfile
const UserProfileFormFields = memo(({ kcContext, onIsFormSubmittableValueChange, ...props }: UserProfileFormFieldsProps) => {
const { cx, css } = useCssAndCx();
const { advancedMsg } = useKcMessage();
const { advancedMsg } = getMsg(kcContext);
const {
formValidationState: { fieldStateByAttributeName, isFormSubmittable },

View File

@ -1,12 +1,9 @@
import { useReducer, useEffect, memo } from "react";
import type { ReactNode } from "react";
import { useKcMessage } from "../i18n/useKcMessage";
import { useKcLanguageTag } from "../i18n/useKcLanguageTag";
import { getMsg, getCurrentKcLanguageTag, changeLocale, getTagLabel } from "../i18n";
import type { KcLanguageTag } from "../i18n";
import type { KcContextBase } from "../getKcContext/KcContextBase";
import { assert } from "../tools/assert";
import type { KcLanguageTag } from "../i18n/KcLanguageTag";
import { getBestMatchAmongKcLanguageTag } from "../i18n/KcLanguageTag";
import { getKcLanguageTagLabel } from "../i18n/KcLanguageTag";
import { useCallbackFactory } from "powerhooks/useCallbackFactory";
import { headInsert } from "../tools/headInsert";
import { pathJoin } from "../tools/pathJoin";
@ -51,36 +48,19 @@ export const Template = memo((props: TemplateProps) => {
console.log("Rendering this page with react using keycloakify");
}, []);
const { msg } = useKcMessage();
const { msg } = getMsg(kcContext);
const { kcLanguageTag, setKcLanguageTag } = useKcLanguageTag();
const onChangeLanguageClickFactory = useCallbackFactory(([languageTag]: [KcLanguageTag]) => setKcLanguageTag(languageTag));
const onChangeLanguageClickFactory = useCallbackFactory(([kcLanguageTag]: [KcLanguageTag]) =>
changeLocale({
kcContext,
kcLanguageTag,
}),
);
const onTryAnotherWayClick = useConstCallback(() => (document.forms["kc-select-try-another-way-form" as never].submit(), false));
const { realm, locale, auth, url, message, isAppInitiatedAction } = kcContext;
useEffect(() => {
if (!realm.internationalizationEnabled) {
return;
}
assert(locale !== undefined);
const kcContext_kcLanguageTag = getBestMatchAmongKcLanguageTag(locale.current);
if (["error.ftl", "info.ftl", "login-page-expired.ftl"].indexOf(kcContext.pageId) >= 0) {
setKcLanguageTag(kcContext_kcLanguageTag);
return;
}
if (kcLanguageTag !== kcContext_kcLanguageTag) {
window.location.href = locale.supported.find(({ languageTag }) => languageTag === kcLanguageTag)!.url;
}
}, [kcLanguageTag]);
const [isExtraCssLoaded, setExtraCssLoaded] = useReducer(() => true, false);
useEffect(() => {
@ -158,13 +138,13 @@ export const Template = memo((props: TemplateProps) => {
<div id="kc-locale-wrapper" className={cx(props.kcLocaleWrapperClass)}>
<div className="kc-dropdown" id="kc-locale-dropdown">
<a href="#" id="kc-current-locale-link">
{getKcLanguageTagLabel(kcLanguageTag)}
{getTagLabel({ "kcLanguageTag": getCurrentKcLanguageTag(kcContext), kcContext })}
</a>
<ul>
{locale.supported.map(({ languageTag }) => (
<li key={languageTag} className="kc-dropdown-item">
<a href="#" onClick={onChangeLanguageClickFactory(languageTag)}>
{getKcLanguageTagLabel(languageTag)}
{getTagLabel({ "kcLanguageTag": languageTag, kcContext })}
</a>
</li>
))}

View File

@ -1,12 +1,33 @@
import { memo } from "react";
import { useReducer, useEffect, memo } from "react";
import { Template } from "./Template";
import type { KcProps } from "./KcProps";
import type { KcContextBase } from "../getKcContext/KcContextBase";
import { useKcMessage } from "../i18n/useKcMessage";
import { getMsg } from "../i18n";
import { useCssAndCx } from "tss-react";
import { kcMessages, getCurrentKcLanguageTag } from "../i18n";
import type { KcLanguageTag } from "../i18n";
/** Allow to avoid bundling the terms and download it on demand*/
export function useDownloadTerms(params: {
kcContext: KcContextBase;
downloadTermMarkdown: (params: { currentKcLanguageTag: KcLanguageTag }) => Promise<string>;
}) {
const { kcContext, downloadTermMarkdown } = params;
const [, forceUpdate] = useReducer(x => x + 1, 0);
useEffect(() => {
const currentKcLanguageTag = getCurrentKcLanguageTag(kcContext);
downloadTermMarkdown({ currentKcLanguageTag }).then(thermMarkdown => {
kcMessages[currentKcLanguageTag].termsText = thermMarkdown;
forceUpdate();
});
}, []);
}
export const Terms = memo(({ kcContext, ...props }: { kcContext: KcContextBase.Terms } & KcProps) => {
const { msg, msgStr } = useKcMessage();
const { msg, msgStr } = getMsg(kcContext);
const { cx } = useCssAndCx();