From b44b43a53bc2ade34f20a4b02dc1ce5594c11341 Mon Sep 17 00:00:00 2001 From: Thomas Dax Date: Thu, 11 Jul 2024 16:00:17 +0200 Subject: [PATCH] Join site configs for languages, add language to URL --- admin/src/App.tsx | 5 ++- admin/src/documents/pages/EditPage.tsx | 2 +- site-configs.ts | 32 +++++++++++++------ site-configs/main-en.ts | 12 ------- site-configs/{main-de.ts => main.ts} | 4 +-- site-configs/secondary-en.ts | 12 ------- .../{secondary-de.ts => secondary.ts} | 4 +-- .../app/{ => [lang]}/[[...path]]/layout.tsx | 0 .../src/app/{ => [lang]}/[[...path]]/page.tsx | 0 site/src/config.ts | 5 +-- site/src/middleware.ts | 16 +++++++--- 11 files changed, 46 insertions(+), 46 deletions(-) delete mode 100644 site-configs/main-en.ts rename site-configs/{main-de.ts => main.ts} (75%) delete mode 100644 site-configs/secondary-en.ts rename site-configs/{secondary-de.ts => secondary.ts} (75%) rename site/src/app/{ => [lang]}/[[...path]]/layout.tsx (100%) rename site/src/app/{ => [lang]}/[[...path]]/page.tsx (100%) diff --git a/admin/src/App.tsx b/admin/src/App.tsx index 07c732dd..3d2971bf 100644 --- a/admin/src/App.tsx +++ b/admin/src/App.tsx @@ -58,7 +58,10 @@ export function App() { value={{ configs: config.sitesConfig, resolveSiteConfigForScope: (configs, scope: ContentScope) => { - const siteConfig = configs.find((config) => config.contentScope.domain === scope.domain); + const siteConfig = configs.find((config) => { + return config.contentScope.domain === scope.domain && config.contentScope.language === scope.language; + }); + if (!siteConfig) throw new Error(`siteConfig not found for domain ${scope.domain}`); return { url: siteConfig.url, diff --git a/admin/src/documents/pages/EditPage.tsx b/admin/src/documents/pages/EditPage.tsx index 16c3f48c..5b114505 100644 --- a/admin/src/documents/pages/EditPage.tsx +++ b/admin/src/documents/pages/EditPage.tsx @@ -129,7 +129,7 @@ export const EditPage: React.FC = ({ id, category }) => { startIcon={} disabled={!pageState} onClick={() => { - openSitePreviewWindow(pageState.path, contentScopeMatch.url); + openSitePreviewWindow(`/${scope.language}${pageState.path}`, contentScopeMatch.url); }} color="info" > diff --git a/site-configs.ts b/site-configs.ts index 232719b4..fde20252 100644 --- a/site-configs.ts +++ b/site-configs.ts @@ -3,7 +3,11 @@ import { SiteConfig } from "./site-configs.d"; // Types for files in site-configs/ type Environment = "local" | "dev" | "test" | "staging" | "prod"; -export type Config = Omit & { +export type Config = Omit & { + contentScope: { + domain: string; + languages: string[]; + } domains: { preliminary?: string; } & { @@ -17,17 +21,25 @@ const getSiteConfigs = async (env: Environment): Promise => { const files = (await fs.readdir(path)).filter((file) => !file.startsWith("_")); const imports = (await Promise.all(files.map((file) => import(`${path}/${file}`)))) as { default: Config }[]; - return imports.map((imprt, index) => { + return imports.flatMap((imprt, index) => { const { domains, ...site } = imprt.default; + const languages = site.contentScope.languages - const ret: SiteConfig = { - ...site, - domains: { - main: domains[env] ?? "", - preliminary: env === "prod" ? domains["preliminary"] : undefined, - }, - preloginEnabled: env === "prod" ? site.preloginEnabled : true, - }; + const ret = languages.map((language):SiteConfig => { + return { + ...site, + name: `${site.name} ${language.toUpperCase()}`, + contentScope: { + domain: site.contentScope.domain, + language + }, + domains: { + main: `${domains[env]}/${language}` ?? "", + preliminary: env === "prod" ? `${domains["preliminary"]}/${language}` : undefined, + }, + preloginEnabled: env === "prod" ? site.preloginEnabled : true, + } + }) return ret; }); diff --git a/site-configs/main-en.ts b/site-configs/main-en.ts deleted file mode 100644 index 75cf1eb5..00000000 --- a/site-configs/main-en.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Config } from "../site-configs"; - -export default { - name: "Starter Main EN", - contentScope: { - domain: "main", - language: "en", - }, - domains: { - local: "en.localhost:3000", - }, -} satisfies Config; diff --git a/site-configs/main-de.ts b/site-configs/main.ts similarity index 75% rename from site-configs/main-de.ts rename to site-configs/main.ts index 7c3fe9fe..f9e30503 100644 --- a/site-configs/main-de.ts +++ b/site-configs/main.ts @@ -1,10 +1,10 @@ import { Config } from "../site-configs"; export default { - name: "Starter Main DE", + name: "Starter Main", contentScope: { domain: "main", - language: "de", + languages: ["en", "de"], }, domains: { local: "localhost:3000", diff --git a/site-configs/secondary-en.ts b/site-configs/secondary-en.ts deleted file mode 100644 index 2fe96bfb..00000000 --- a/site-configs/secondary-en.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Config } from "../site-configs"; - -export default { - name: "Starter Secondary EN", - contentScope: { - domain: "secondary", - language: "en", - }, - domains: { - local: "secondary-en.localhost:3000", - }, -} satisfies Config; diff --git a/site-configs/secondary-de.ts b/site-configs/secondary.ts similarity index 75% rename from site-configs/secondary-de.ts rename to site-configs/secondary.ts index 90910436..b35c8e5a 100644 --- a/site-configs/secondary-de.ts +++ b/site-configs/secondary.ts @@ -1,10 +1,10 @@ import { Config } from "../site-configs"; export default { - name: "Starter Secondary DE", + name: "Starter Secondary", contentScope: { domain: "secondary", - language: "de", + languages: ["en", "de"], }, domains: { local: "secondary.localhost:3000", diff --git a/site/src/app/[[...path]]/layout.tsx b/site/src/app/[lang]/[[...path]]/layout.tsx similarity index 100% rename from site/src/app/[[...path]]/layout.tsx rename to site/src/app/[lang]/[[...path]]/layout.tsx diff --git a/site/src/app/[[...path]]/page.tsx b/site/src/app/[lang]/[[...path]]/page.tsx similarity index 100% rename from site/src/app/[[...path]]/page.tsx rename to site/src/app/[lang]/[[...path]]/page.tsx diff --git a/site/src/config.ts b/site/src/config.ts index e52c2b0d..6f9b8f1e 100644 --- a/site/src/config.ts +++ b/site/src/config.ts @@ -10,9 +10,10 @@ export type { SiteConfig }; export async function getSiteConfig() { const host = getHost(headers()); + const language = headers().get("x-current-language"); + const domain = `${host}/${language}`; - let siteConfig = getSiteConfigs().find((siteConfig) => siteConfig.domains.main === host || siteConfig.domains.preliminary === host); - + let siteConfig = getSiteConfigs().find((siteConfig) => siteConfig.domains.main === domain || siteConfig.domains.preliminary === domain); if (!siteConfig) { const preview = await previewParams(); if (preview && preview.scope) { diff --git a/site/src/middleware.ts b/site/src/middleware.ts index 10a15f8c..06e50a2b 100644 --- a/site/src/middleware.ts +++ b/site/src/middleware.ts @@ -9,15 +9,25 @@ import { getSiteConfigs } from "./siteConfigs"; export async function middleware(request: NextRequest) { const headers = request.headers; const host = getHost(headers); + const { pathname } = new URL(request.url); + const language = pathname.split("/")?.[1] ?? ""; + + if (!language) { + return NextResponse.redirect(new URL("/en", request.url)); + } + headers.set("x-current-language", language); + + const domain = `${host}/${language}`; // Site-Preview is handled in getSiteConfigs since draftMode() is not set yet in middleware (https://github.com/vercel/next.js/issues/52080) // Redirect to Main Host - const siteConfig = getSiteConfigs().find((siteConfig) => siteConfig.domains.main === host || siteConfig.domains.preliminary === host); + const siteConfig = getSiteConfigs().find((siteConfig) => siteConfig.domains.main === domain || siteConfig.domains.preliminary === domain); if (!siteConfig) { const redirectSiteConfig = getSiteConfigs().find( (siteConfig) => - siteConfig.domains.additional?.includes(host) || (siteConfig.domains.pattern && host.match(new RegExp(siteConfig.domains.pattern))), + siteConfig.domains.additional?.includes(domain) || + (siteConfig.domains.pattern && domain.match(new RegExp(siteConfig.domains.pattern))), ); if (redirectSiteConfig) { return NextResponse.redirect(redirectSiteConfig.url); @@ -25,8 +35,6 @@ export async function middleware(request: NextRequest) { return; // Fallback for Site-Preview } - const { pathname } = new URL(request.url); - const redirects = await createRedirects(); const redirect = redirects.get(pathname);