fix: localize 404 and ensure header when no lang
This commit is contained in:
11
app/[lang]/(live)/middleware-error/404/page.tsx
Normal file
11
app/[lang]/(live)/middleware-error/404/page.tsx
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { Lang } from "@/constants/languages"
|
||||||
|
|
||||||
|
import NotFound from "@/components/Current/NotFound"
|
||||||
|
|
||||||
|
import { LangParams, PageArgs } from "@/types/params"
|
||||||
|
|
||||||
|
export default function NotFoundPage({ params }: PageArgs<LangParams>) {
|
||||||
|
const lang = params.lang || Lang.en
|
||||||
|
|
||||||
|
return <NotFound lang={lang} />
|
||||||
|
}
|
||||||
@@ -1,11 +1,12 @@
|
|||||||
import { getIntl } from "@/i18n"
|
import { headers } from "next/headers"
|
||||||
|
|
||||||
export default async function NotFound() {
|
import { Lang } from "@/constants/languages"
|
||||||
const { formatMessage } = await getIntl()
|
|
||||||
return (
|
import NotFound from "@/components/Current/NotFound"
|
||||||
<main>
|
|
||||||
<h1>{formatMessage({ id: "Not found" })}</h1>
|
export default function NotFoundPage() {
|
||||||
<p>{formatMessage({ id: "Could not find requested resource" })}</p>
|
const headersList = headers()
|
||||||
</main>
|
const lang = headersList.get("x-sh-language") as Lang
|
||||||
)
|
|
||||||
|
return <NotFound lang={lang} />
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,9 @@ export default async function Header({
|
|||||||
lang,
|
lang,
|
||||||
languageSwitcher,
|
languageSwitcher,
|
||||||
}: LangParams & { languageSwitcher: React.ReactNode }) {
|
}: LangParams & { languageSwitcher: React.ReactNode }) {
|
||||||
const data = await serverClient().contentstack.base.header()
|
const data = await serverClient().contentstack.base.header({
|
||||||
|
lang,
|
||||||
|
})
|
||||||
const session = await auth()
|
const session = await auth()
|
||||||
|
|
||||||
const homeHref = homeHrefs[env.NODE_ENV][lang]
|
const homeHref = homeHrefs[env.NODE_ENV][lang]
|
||||||
|
|||||||
131
components/Current/NotFound/Texts.ts
Normal file
131
components/Current/NotFound/Texts.ts
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
import { Lang } from "@/constants/languages"
|
||||||
|
|
||||||
|
type Texts = {
|
||||||
|
title: string
|
||||||
|
goToStartPage: {
|
||||||
|
question: string
|
||||||
|
link: string
|
||||||
|
linkText: string
|
||||||
|
}
|
||||||
|
goToDestinations: {
|
||||||
|
question: string
|
||||||
|
link: string
|
||||||
|
linkText: string
|
||||||
|
}
|
||||||
|
goToOffers: {
|
||||||
|
question: string
|
||||||
|
link: string
|
||||||
|
linkText: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const texts: Record<Lang, Texts> = {
|
||||||
|
en: {
|
||||||
|
title: "Sorry, page not found.",
|
||||||
|
goToStartPage: {
|
||||||
|
question: "Would you like to go back to the ",
|
||||||
|
link: "https://www.scandichotels.com/",
|
||||||
|
linkText: "startpage",
|
||||||
|
},
|
||||||
|
goToDestinations: {
|
||||||
|
question: "Or take a trip to our ",
|
||||||
|
link: "https://www.scandichotels.com/hotels",
|
||||||
|
linkText: "destinations",
|
||||||
|
},
|
||||||
|
goToOffers: {
|
||||||
|
question: " or latest ",
|
||||||
|
link: "https://www.scandichotels.com/weekend-packages-and-offers",
|
||||||
|
linkText: "offers",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
sv: {
|
||||||
|
title: "Oj då, vi kunde inte hitta sidan du söker.",
|
||||||
|
goToStartPage: {
|
||||||
|
question: "Vill du gå tillbaka till ",
|
||||||
|
link: "https://www.scandichotels.se/",
|
||||||
|
linkText: "startsidan",
|
||||||
|
},
|
||||||
|
goToDestinations: {
|
||||||
|
question: "Eller resa till våra ",
|
||||||
|
link: "https://www.scandichotels.se/hotell",
|
||||||
|
linkText: "destinationer",
|
||||||
|
},
|
||||||
|
goToOffers: {
|
||||||
|
question: " eller se våra senaste ",
|
||||||
|
link: "https://www.scandichotels.se/erbjudanden-och-weekendpaket",
|
||||||
|
linkText: "erbjudanden",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
de: {
|
||||||
|
title: "Tut uns leid, Seite nicht gefunden.",
|
||||||
|
goToStartPage: {
|
||||||
|
question: "Möchten Sie zurück zur ",
|
||||||
|
link: "https://www.scandichotels.de/",
|
||||||
|
linkText: "Startseite",
|
||||||
|
},
|
||||||
|
goToDestinations: {
|
||||||
|
question: "Oder machen Sie einen Ausflug zu unseren ",
|
||||||
|
link: "https://www.scandichotels.de/hotelsuche",
|
||||||
|
linkText: "Reisezielen",
|
||||||
|
},
|
||||||
|
goToOffers: {
|
||||||
|
question: " und aktuellen ",
|
||||||
|
link: "https://www.scandichotels.de/angebote-arrangements",
|
||||||
|
linkText: "Angeboten",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fi: {
|
||||||
|
title: "TValitettavasti sivua ei löydy.",
|
||||||
|
goToStartPage: {
|
||||||
|
question: "Haluaisitko mennä takaisin ",
|
||||||
|
link: "https://www.scandichotels.fi/",
|
||||||
|
linkText: "etusivulle",
|
||||||
|
},
|
||||||
|
goToDestinations: {
|
||||||
|
question: "Voit myös tutustu ",
|
||||||
|
link: "https://www.scandichotels.fi/hotellit",
|
||||||
|
linkText: "kohteisiimme",
|
||||||
|
},
|
||||||
|
goToOffers: {
|
||||||
|
question: " tai ajankohtaisiin ",
|
||||||
|
link: "https://www.scandichotels.fi/tarjoukset",
|
||||||
|
linkText: "tarjouksiimme",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
no: {
|
||||||
|
title: "Oi da, vi fant ikke siden du lette etter...",
|
||||||
|
goToStartPage: {
|
||||||
|
question: "Vil du gå tilbake til ",
|
||||||
|
link: "https://www.scandichotels.no/",
|
||||||
|
linkText: "startsiden",
|
||||||
|
},
|
||||||
|
goToDestinations: {
|
||||||
|
question: "Eller ta en tur til våre ",
|
||||||
|
link: "https://www.scandichotels.no/hotell",
|
||||||
|
linkText: "destinasjoner",
|
||||||
|
},
|
||||||
|
goToOffers: {
|
||||||
|
question: " eller siste ",
|
||||||
|
link: "https://www.scandichotels.no/hotelltilbud",
|
||||||
|
linkText: "tilbud",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
da: {
|
||||||
|
title: "Hov - siden kan ikke findes!",
|
||||||
|
goToStartPage: {
|
||||||
|
question: "Vil du gå tilbage til ",
|
||||||
|
link: "https://www.scandichotels.dk/",
|
||||||
|
linkText: "startsiden",
|
||||||
|
},
|
||||||
|
goToDestinations: {
|
||||||
|
question: "Eller tag en tur til vores ",
|
||||||
|
link: "https://www.scandichotels.dk/hoteller",
|
||||||
|
linkText: "destinationer",
|
||||||
|
},
|
||||||
|
goToOffers: {
|
||||||
|
question: " eller seneste ",
|
||||||
|
link: "https://www.scandichotels.dk/tilbud-og-hotelpakker",
|
||||||
|
linkText: "tilbud",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
48
components/Current/NotFound/index.tsx
Normal file
48
components/Current/NotFound/index.tsx
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import { texts } from "./Texts"
|
||||||
|
|
||||||
|
import styles from "./notFound.module.css"
|
||||||
|
|
||||||
|
import { LangParams } from "@/types/params"
|
||||||
|
|
||||||
|
export default function NotFound({ lang }: LangParams) {
|
||||||
|
const infoTexts = texts[lang]
|
||||||
|
return (
|
||||||
|
<div className={styles.container}>
|
||||||
|
<div className={styles.content}>
|
||||||
|
<h1 className={styles.header}>{infoTexts.title}</h1>
|
||||||
|
<div className={styles.pitch}>
|
||||||
|
<p className={styles.text}>
|
||||||
|
{infoTexts.goToStartPage.question}
|
||||||
|
<a
|
||||||
|
className={styles.link}
|
||||||
|
title={infoTexts.goToStartPage.linkText}
|
||||||
|
href={infoTexts.goToStartPage.link}
|
||||||
|
>
|
||||||
|
{infoTexts.goToStartPage.linkText}
|
||||||
|
</a>
|
||||||
|
?
|
||||||
|
</p>
|
||||||
|
<p className={styles.text}>
|
||||||
|
{infoTexts.goToDestinations.question}
|
||||||
|
<a
|
||||||
|
className={styles.link}
|
||||||
|
title={infoTexts.goToDestinations.linkText}
|
||||||
|
href={infoTexts.goToDestinations.link}
|
||||||
|
>
|
||||||
|
{infoTexts.goToDestinations.linkText}
|
||||||
|
</a>
|
||||||
|
{infoTexts.goToOffers.question}
|
||||||
|
<a
|
||||||
|
className={styles.link}
|
||||||
|
title={infoTexts.goToOffers.linkText}
|
||||||
|
href={infoTexts.goToOffers.link}
|
||||||
|
>
|
||||||
|
{infoTexts.goToOffers.linkText}
|
||||||
|
</a>
|
||||||
|
.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
70
components/Current/NotFound/notFound.module.css
Normal file
70
components/Current/NotFound/notFound.module.css
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
.container {
|
||||||
|
margin-top: 0;
|
||||||
|
background: var(--Main-Grey-White);
|
||||||
|
position: relative;
|
||||||
|
border-top: 50px solid var(--Main-Grey-White);
|
||||||
|
background-clip: content-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
position: relative;
|
||||||
|
text-align: center;
|
||||||
|
box-sizing: content-box;
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 70px 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
font-family:
|
||||||
|
brandon text,
|
||||||
|
Arial,
|
||||||
|
Helvetica,
|
||||||
|
sans-serif;
|
||||||
|
font-size: 32px;
|
||||||
|
line-height: 1;
|
||||||
|
margin: 0;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #483729;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pitch {
|
||||||
|
margin-top: 32px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
font-family:
|
||||||
|
Helvetica Neue,
|
||||||
|
Roboto,
|
||||||
|
Helvetica,
|
||||||
|
Arial,
|
||||||
|
sans-serif;
|
||||||
|
font-weight: 300;
|
||||||
|
line-height: normal;
|
||||||
|
text-transform: none;
|
||||||
|
font-size: 20px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link {
|
||||||
|
color: #00838e;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 740px) {
|
||||||
|
.content {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 950px) {
|
||||||
|
.header {
|
||||||
|
font-size: 46px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { NextMiddleware, NextResponse } from "next/server"
|
import { NextMiddleware, NextResponse } from "next/server"
|
||||||
|
|
||||||
import { findLang } from "./constants/languages"
|
import { findLang, Lang } from "./constants/languages"
|
||||||
import * as authRequired from "./middlewares/authRequired"
|
import * as authRequired from "./middlewares/authRequired"
|
||||||
import * as cmsContent from "./middlewares/cmsContent"
|
import * as cmsContent from "./middlewares/cmsContent"
|
||||||
import * as currentWebLogin from "./middlewares/currentWebLogin"
|
import * as currentWebLogin from "./middlewares/currentWebLogin"
|
||||||
@@ -16,8 +16,10 @@ export const middleware: NextMiddleware = async (request, event) => {
|
|||||||
// Without it we shortcircuit early.
|
// Without it we shortcircuit early.
|
||||||
// We use middleware-error route because notFound() requires a root layout
|
// We use middleware-error route because notFound() requires a root layout
|
||||||
// which we do not want. We can move to that once all Current stuff is gone.
|
// which we do not want. We can move to that once all Current stuff is gone.
|
||||||
|
|
||||||
|
// Default to English if no lang is found.
|
||||||
return NextResponse.rewrite(
|
return NextResponse.rewrite(
|
||||||
new URL(`/${lang}/middleware-error/404`, request.nextUrl),
|
new URL(`/${Lang.en}/middleware-error/404`, request.nextUrl),
|
||||||
{
|
{
|
||||||
status: 404,
|
status: 404,
|
||||||
statusText: "Not found",
|
statusText: "Not found",
|
||||||
|
|||||||
5
server/routers/contentstack/base/input.ts
Normal file
5
server/routers/contentstack/base/input.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import { z } from "zod"
|
||||||
|
|
||||||
|
import { Lang } from "@/constants/languages"
|
||||||
|
|
||||||
|
export const headerInput = z.object({ lang: z.nativeEnum(Lang) })
|
||||||
Reference in New Issue
Block a user