Translate login and notfound

This commit is contained in:
Paul Bienkowski 2022-07-24 18:19:37 +02:00
parent 2cff606092
commit a977e2d1c3
5 changed files with 89 additions and 59 deletions

View file

@ -1,56 +1,69 @@
import React from 'react' import React from "react";
import {connect} from 'react-redux' import { connect } from "react-redux";
import {Redirect, useLocation, useHistory} from 'react-router-dom' import { Redirect, useLocation, useHistory } from "react-router-dom";
import {Icon, Message} from 'semantic-ui-react' import { Icon, Message } from "semantic-ui-react";
import {useObservable} from 'rxjs-hooks' import { useObservable } from "rxjs-hooks";
import {switchMap, pluck, distinctUntilChanged} from 'rxjs/operators' import { switchMap, pluck, distinctUntilChanged } from "rxjs/operators";
import { useTranslation } from "react-i18next";
import {Page} from 'components' import { Page } from "components";
import api from 'api' import api from "api";
const LoginRedirectPage = connect((state) => ({loggedIn: Boolean(state.login)}))(function LoginRedirectPage({ const LoginRedirectPage = connect((state) => ({
loggedIn, loggedIn: Boolean(state.login),
}) { }))(function LoginRedirectPage({ loggedIn }) {
const location = useLocation() const location = useLocation();
const history = useHistory() const history = useHistory();
const {search} = location const { search } = location;
const { t } = useTranslation();
/* eslint-disable react-hooks/exhaustive-deps */ /* eslint-disable react-hooks/exhaustive-deps */
// Hook dependency arrays in this block are intentionally left blank, we want // Hook dependency arrays in this block are intentionally left blank, we want
// to keep the initial state, but reset the url once, ASAP, to not leak the // to keep the initial state, but reset the url once, ASAP, to not leak the
// query parameters. This is considered good practice by OAuth. // query parameters. This is considered good practice by OAuth.
const searchParams = React.useMemo(() => Object.fromEntries(new URLSearchParams(search).entries()), []) const searchParams = React.useMemo(
() => Object.fromEntries(new URLSearchParams(search).entries()),
[]
);
React.useEffect(() => { React.useEffect(() => {
history.replace({...location, search: ''}) history.replace({ ...location, search: "" });
}, []) }, []);
/* eslint-enable react-hooks/exhaustive-deps */ /* eslint-enable react-hooks/exhaustive-deps */
if (loggedIn) { if (loggedIn) {
return <Redirect to="/" /> return <Redirect to="/" />;
} }
const {error, error_description: errorDescription, code} = searchParams const { error, error_description: errorDescription, code } = searchParams;
if (error) { if (error) {
return ( return (
<Page small title="Login error"> <Page small title={t("LoginRedirectPage.loginError")}>
<LoginError errorText={errorDescription || error} />
</Page>
);
}
return <ExchangeAuthCode code={code} />;
});
function LoginError({ errorText }: { errorText: string }) {
const { t } = useTranslation();
return (
<Message icon error> <Message icon error>
<Icon name="warning sign" /> <Icon name="warning sign" />
<Message.Content> <Message.Content>
<Message.Header>Login error</Message.Header> <Message.Header>{t("LoginRedirectPage.loginError")}</Message.Header>
The login server reported: {errorDescription || error}. {t("LoginRedirectPage.loginErrorText", { error: errorText })}
</Message.Content> </Message.Content>
</Message> </Message>
</Page> );
) }
}
return <ExchangeAuthCode code={code} /> function ExchangeAuthCode({ code }) {
}) const { t } = useTranslation();
function ExchangeAuthCode({code}) {
const result = useObservable( const result = useObservable(
(_$, args$) => (_$, args$) =>
args$.pipe( args$.pipe(
@ -60,38 +73,31 @@ function ExchangeAuthCode({code}) {
), ),
null, null,
[code] [code]
) );
let content let content;
if (result === null) { if (result === null) {
content = ( content = (
<Message icon info> <Message icon info>
<Icon name="circle notched" loading /> <Icon name="circle notched" loading />
<Message.Content> <Message.Content>
<Message.Header>Logging you in</Message.Header> <Message.Header>{t("LoginRedirectPage.loggingIn")}</Message.Header>
Hang tight... {t("LoginRedirectPage.hangTight")}
</Message.Content> </Message.Content>
</Message> </Message>
) );
} else if (result === true) { } else if (result === true) {
content = <Redirect to="/" /> content = <Redirect to="/" />;
} else { } else {
const {error, error_description: errorDescription} = result const { error, error_description: errorDescription } = result;
content = ( content = <LoginError errorText={errorDescription || error} />;
<>
<Message icon error>
<Icon name="warning sign" />
<Message.Content>
<Message.Header>Login error</Message.Header>
The login server reported: {errorDescription || error}.
</Message.Content>
</Message>
<pre>{JSON.stringify(result, null, 2)}</pre>
</>
)
} }
return <Page small title="Login">{content}</Page> return (
<Page small title="Login">
{content}
</Page>
);
} }
export default LoginRedirectPage export default LoginRedirectPage;

View file

@ -1,16 +1,18 @@
import React from 'react' import React from 'react'
import {Button, Header} from 'semantic-ui-react' import {Button, Header} from 'semantic-ui-react'
import {useHistory} from 'react-router-dom' import {useHistory} from 'react-router-dom'
import { useTranslation } from "react-i18next";
import {Page} from '../components' import {Page} from '../components'
export default function NotFoundPage() { export default function NotFoundPage() {
const { t } = useTranslation();
const history = useHistory() const history = useHistory()
return ( return (
<Page title="Page not found"> <Page title={t('NotFoundPage.title')}>
<Header as="h2">Page not found</Header> <Header as="h2">{t('NotFoundPage.title')}</Header>
<p>You know what that means...</p> <p>{t('NotFoundPage.description')}</p>
<Button onClick={history.goBack.bind(history)}>Go back</Button> <Button onClick={history.goBack.bind(history)}>{t('NotFoundPage.goBack')}</Button>
</Page> </Page>
) )
} }

View file

@ -99,9 +99,20 @@ UploadPage:
size: Größe size: Größe
statusTitle: Status / Titel statusTitle: Status / Titel
FileUploadField: FileUploadField:
dropOrClick: Datei hierher ziehen oder klicken, um eine zum Hochladen auszuwählen dropOrClick: Datei hierher ziehen oder klicken, um eine zum Hochladen auszuwählen
dropOrClickMultiple: Dateien hierher ziehen oder klicken, um Dateien zum Hochladen auszuwählen dropOrClickMultiple: Dateien hierher ziehen oder klicken, um Dateien zum Hochladen auszuwählen
uploadFile: Datei hochladen uploadFile: Datei hochladen
uploadFiles: Dateien hochladen uploadFiles: Dateien hochladen
LoginRedirectPage:
loginError: Login error
loginErrorText: "The login server reported: {error}"
loggingIn: Logging you in
hangTight: Hang tight...
NotFoundPage:
title: Seite nicht gefunden
description: Den Fehler kennst du sicher...
goBack: Zurückgehen

View file

@ -104,9 +104,20 @@ UploadPage:
size: Size size: Size
statusTitle: Status / Title statusTitle: Status / Title
FileUploadField: FileUploadField:
dropOrClick: Drop file here or click to select one for upload dropOrClick: Drop file here or click to select one for upload
dropOrClickMultiple: Drop files here or click to select them for upload dropOrClickMultiple: Drop files here or click to select them for upload
uploadFile: Upload file uploadFile: Upload file
uploadFiles: Upload files uploadFiles: Upload files
LoginRedirectPage:
loginError: Loginfehler
loginErrorText: "Der Login-Server meldet: {error}"
loggingIn: Du wirst eingeloggt
hangTight: Bitte warten...
NotFoundPage:
title: Page not found
description: You know what that means...
goBack: Go back