From 0a17025da0137fbda8123204e0b17593a48cb82c Mon Sep 17 00:00:00 2001 From: Lazaro Alonso Date: Wed, 28 Jan 2026 09:31:21 +0100 Subject: [PATCH 1/7] lang setup --- mdx-components.tsx | 16 +- package.json | 7 +- src/app/{ => [locale]}/biomass/about/page.mdx | 0 .../{ => [locale]}/biomass/disc&data/page.mdx | 0 .../biomass/earthexplorer/page.mdx | 0 src/app/{ => [locale]}/blog/[slug]/page.tsx | 27 +- src/app/[locale]/blog/page.tsx | 23 ++ .../blog/posts/first_images.mdx | 0 .../blog/posts/first_images_de.mdx | 0 src/app/{ => [locale]}/blog/posts/launch.mdx | 0 .../{ => [locale]}/blog/posts/launch_de.mdx | 0 src/app/{ => [locale]}/blog/posts/news1.mdx | 0 src/app/{ => [locale]}/blog/posts/news10.mdx | 0 src/app/{ => [locale]}/blog/posts/news11.mdx | 0 src/app/{ => [locale]}/blog/posts/news12.mdx | 0 src/app/{ => [locale]}/blog/posts/news13.mdx | 0 src/app/{ => [locale]}/blog/posts/news14.mdx | 0 src/app/{ => [locale]}/blog/posts/news15.mdx | 0 src/app/{ => [locale]}/blog/posts/news16.mdx | 0 src/app/{ => [locale]}/blog/posts/news17.mdx | 0 src/app/{ => [locale]}/blog/posts/news18.mdx | 0 src/app/{ => [locale]}/blog/posts/news19.mdx | 0 src/app/{ => [locale]}/blog/posts/news2.mdx | 0 src/app/{ => [locale]}/blog/posts/news20.mdx | 0 src/app/{ => [locale]}/blog/posts/news21.mdx | 0 src/app/{ => [locale]}/blog/posts/news22.mdx | 0 src/app/{ => [locale]}/blog/posts/news23.mdx | 0 src/app/{ => [locale]}/blog/posts/news24.mdx | 0 src/app/{ => [locale]}/blog/posts/news3.mdx | 0 src/app/{ => [locale]}/blog/posts/news4.mdx | 0 src/app/{ => [locale]}/blog/posts/news6.mdx | 0 src/app/{ => [locale]}/blog/posts/news7.mdx | 0 src/app/{ => [locale]}/blog/posts/news8.mdx | 0 src/app/{ => [locale]}/blog/posts/news9.mdx | 0 .../blog/posts/summerschool24.mdx | 0 .../blog/posts/summerschool24_de.mdx | 0 .../blog/posts/summerschool25.mdx | 0 .../blog/posts/summerschool25_de.mdx | 0 .../{ => [locale]}/blog/posts/workshop12.mdx | 0 src/app/{ => [locale]}/contact/page.mdx | 0 .../{ => [locale]}/decalval/about/page.mdx | 0 .../decalval/team/cards/Andreas.mdx | 0 .../decalval/team/cards/Kostas.mdx | 0 .../decalval/team/cards/Martin.mdx | 0 .../decalval/team/cards/Matthias.mdx | 0 .../decalval/team/cards/Mikhail.mdx | 0 .../decalval/team/cards/Nicole.mdx | 0 .../decalval/team/cards/Nuno.mdx | 0 .../decalval/team/cards/Ralph.mdx | 0 src/app/{ => [locale]}/decalval/team/page.mdx | 0 src/app/{ => [locale]}/decalval/wps/page.mdx | 0 .../{ => [locale]}/events/polinsar/page.mdx | 0 .../events/summerschool/2022/page.mdx | 0 .../events/summerschool/2024/page.mdx | 0 .../events/summerschool/2025/page.mdx | 0 .../events/summerschool/page.mdx | 0 .../{ => [locale]}/events/webinar/page.mdx | 0 src/app/[locale]/landing-de.mdx | 121 ++++++++ src/app/{page.mdx => [locale]/landing-en.mdx} | 7 +- src/app/[locale]/layout.tsx | 29 ++ src/app/[locale]/page.tsx | 19 ++ src/app/{ => [locale]}/project/about/page.mdx | 0 .../project/publications/page.mdx | 0 .../project/team/cards/Laura.mdx | 0 .../project/team/cards/Nicole.mdx | 0 src/app/{ => [locale]}/project/team/page.mdx | 0 src/app/{ => [locale]}/project/wps/page.mdx | 0 .../resources/newsletter/page.mdx | 0 .../resources/publications/page.mdx | 0 .../resources/relatedmissions/page.mdx | 0 .../resources/tools-data/page.mdx | 0 src/app/{ => [locale]}/terms/imprint/page.mdx | 0 src/app/{ => [locale]}/terms/privacy/page.mdx | 0 src/app/blog/page.tsx | 16 -- src/app/layout.tsx | 9 +- src/app/not-found.js | 4 +- src/app/page.tsx | 27 ++ src/app/sitemap.ts | 1 + src/components/Footer.tsx | 13 +- src/components/LocaleLink.tsx | 34 +++ src/components/Logo.tsx | 9 +- src/components/Menu.tsx | 12 +- src/components/SetHtmlLang.tsx | 11 + src/components/posts.tsx | 7 +- src/config/i18n.ts | 8 + src/config/nav.ts | 269 +++++++++++------- src/contexts/LocaleContext.tsx | 27 ++ src/utils/sitemap.ts | 30 +- src/utils/utilsBlog.ts | 19 +- 89 files changed, 560 insertions(+), 185 deletions(-) rename src/app/{ => [locale]}/biomass/about/page.mdx (100%) rename src/app/{ => [locale]}/biomass/disc&data/page.mdx (100%) rename src/app/{ => [locale]}/biomass/earthexplorer/page.mdx (100%) rename src/app/{ => [locale]}/blog/[slug]/page.tsx (73%) create mode 100644 src/app/[locale]/blog/page.tsx rename src/app/{ => [locale]}/blog/posts/first_images.mdx (100%) rename src/app/{ => [locale]}/blog/posts/first_images_de.mdx (100%) rename src/app/{ => [locale]}/blog/posts/launch.mdx (100%) rename src/app/{ => [locale]}/blog/posts/launch_de.mdx (100%) rename src/app/{ => [locale]}/blog/posts/news1.mdx (100%) rename src/app/{ => [locale]}/blog/posts/news10.mdx (100%) rename src/app/{ => [locale]}/blog/posts/news11.mdx (100%) rename src/app/{ => [locale]}/blog/posts/news12.mdx (100%) rename src/app/{ => [locale]}/blog/posts/news13.mdx (100%) rename src/app/{ => [locale]}/blog/posts/news14.mdx (100%) rename src/app/{ => [locale]}/blog/posts/news15.mdx (100%) rename src/app/{ => [locale]}/blog/posts/news16.mdx (100%) rename src/app/{ => [locale]}/blog/posts/news17.mdx (100%) rename src/app/{ => [locale]}/blog/posts/news18.mdx (100%) rename src/app/{ => [locale]}/blog/posts/news19.mdx (100%) rename src/app/{ => [locale]}/blog/posts/news2.mdx (100%) rename src/app/{ => [locale]}/blog/posts/news20.mdx (100%) rename src/app/{ => [locale]}/blog/posts/news21.mdx (100%) rename src/app/{ => [locale]}/blog/posts/news22.mdx (100%) rename src/app/{ => [locale]}/blog/posts/news23.mdx (100%) rename src/app/{ => [locale]}/blog/posts/news24.mdx (100%) rename src/app/{ => [locale]}/blog/posts/news3.mdx (100%) rename src/app/{ => [locale]}/blog/posts/news4.mdx (100%) rename src/app/{ => [locale]}/blog/posts/news6.mdx (100%) rename src/app/{ => [locale]}/blog/posts/news7.mdx (100%) rename src/app/{ => [locale]}/blog/posts/news8.mdx (100%) rename src/app/{ => [locale]}/blog/posts/news9.mdx (100%) rename src/app/{ => [locale]}/blog/posts/summerschool24.mdx (100%) rename src/app/{ => [locale]}/blog/posts/summerschool24_de.mdx (100%) rename src/app/{ => [locale]}/blog/posts/summerschool25.mdx (100%) rename src/app/{ => [locale]}/blog/posts/summerschool25_de.mdx (100%) rename src/app/{ => [locale]}/blog/posts/workshop12.mdx (100%) rename src/app/{ => [locale]}/contact/page.mdx (100%) rename src/app/{ => [locale]}/decalval/about/page.mdx (100%) rename src/app/{ => [locale]}/decalval/team/cards/Andreas.mdx (100%) rename src/app/{ => [locale]}/decalval/team/cards/Kostas.mdx (100%) rename src/app/{ => [locale]}/decalval/team/cards/Martin.mdx (100%) rename src/app/{ => [locale]}/decalval/team/cards/Matthias.mdx (100%) rename src/app/{ => [locale]}/decalval/team/cards/Mikhail.mdx (100%) rename src/app/{ => [locale]}/decalval/team/cards/Nicole.mdx (100%) rename src/app/{ => [locale]}/decalval/team/cards/Nuno.mdx (100%) rename src/app/{ => [locale]}/decalval/team/cards/Ralph.mdx (100%) rename src/app/{ => [locale]}/decalval/team/page.mdx (100%) rename src/app/{ => [locale]}/decalval/wps/page.mdx (100%) rename src/app/{ => [locale]}/events/polinsar/page.mdx (100%) rename src/app/{ => [locale]}/events/summerschool/2022/page.mdx (100%) rename src/app/{ => [locale]}/events/summerschool/2024/page.mdx (100%) rename src/app/{ => [locale]}/events/summerschool/2025/page.mdx (100%) rename src/app/{ => [locale]}/events/summerschool/page.mdx (100%) rename src/app/{ => [locale]}/events/webinar/page.mdx (100%) create mode 100644 src/app/[locale]/landing-de.mdx rename src/app/{page.mdx => [locale]/landing-en.mdx} (96%) create mode 100644 src/app/[locale]/layout.tsx create mode 100644 src/app/[locale]/page.tsx rename src/app/{ => [locale]}/project/about/page.mdx (100%) rename src/app/{ => [locale]}/project/publications/page.mdx (100%) rename src/app/{ => [locale]}/project/team/cards/Laura.mdx (100%) rename src/app/{ => [locale]}/project/team/cards/Nicole.mdx (100%) rename src/app/{ => [locale]}/project/team/page.mdx (100%) rename src/app/{ => [locale]}/project/wps/page.mdx (100%) rename src/app/{ => [locale]}/resources/newsletter/page.mdx (100%) rename src/app/{ => [locale]}/resources/publications/page.mdx (100%) rename src/app/{ => [locale]}/resources/relatedmissions/page.mdx (100%) rename src/app/{ => [locale]}/resources/tools-data/page.mdx (100%) rename src/app/{ => [locale]}/terms/imprint/page.mdx (100%) rename src/app/{ => [locale]}/terms/privacy/page.mdx (100%) delete mode 100644 src/app/blog/page.tsx create mode 100644 src/app/page.tsx create mode 100644 src/app/sitemap.ts create mode 100644 src/components/LocaleLink.tsx create mode 100644 src/components/SetHtmlLang.tsx create mode 100644 src/config/i18n.ts create mode 100644 src/contexts/LocaleContext.tsx diff --git a/mdx-components.tsx b/mdx-components.tsx index b13a250..7ddd4f0 100644 --- a/mdx-components.tsx +++ b/mdx-components.tsx @@ -5,6 +5,7 @@ import { MDXRemote, MDXRemoteProps } from 'next-mdx-remote/rsc'; import { highlight } from 'sugar-high'; import { CardProfile } from '@/components/CardProfile'; import { CopyButton } from '@/components/copy-button'; +import { LocaleLink } from '@/components/LocaleLink'; // Type definitions type HeadingProps = ComponentPropsWithoutRef<'h1'>; @@ -72,23 +73,16 @@ function Table({ data }: { data: TableData }) { ); } -// Custom link component with support for internal/external links +// Custom link: internal links get /[locale] prefix via LocaleLink; external stay function CustomLink(props: React.AnchorHTMLAttributes) { const href = props.href; - - if (href && href.startsWith('/')) { - return ( - - {props.children} - - ); + if (href && (href.startsWith('http') || href.startsWith('//'))) { + return ; } - if (href && href.startsWith('#')) { return ; } - - return ; + return ; } // MDX Components for direct usage diff --git a/package.json b/package.json index e3abe32..38c5de5 100644 --- a/package.json +++ b/package.json @@ -15,10 +15,10 @@ "packageManager": "pnpm@10.8.1", "scripts": { "prChecks": "pnpm lint && pnpm buildRepo", - "dev": "next dev", + "dev": "next dev --webpack", "buildRepo": "pnpm rmBuild && pnpm build", "rmBuild": "pnpm -r exec rm -rf out", - "build": "next build", + "build": "next build --webpack", "start": "next start", "lint": "eslint . --max-warnings=100" }, @@ -38,13 +38,16 @@ "@types/three": "^0.176.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", + "i18next": "^25.8.0", "lucide-react": "^0.511.0", "next": ">=15.5.9", + "next-i18next": "^15.4.3", "next-mdx-remote": "^5.0.0", "next-themes": "^0.4.6", "postcss": "^8.5.4", "react": "^19.1.0", "react-dom": "^19.1.0", + "react-i18next": "^16.5.4", "react-icons": "^5.5.0", "sugar-high": "^0.9.3", "tailwind-merge": "^3.3.0", diff --git a/src/app/biomass/about/page.mdx b/src/app/[locale]/biomass/about/page.mdx similarity index 100% rename from src/app/biomass/about/page.mdx rename to src/app/[locale]/biomass/about/page.mdx diff --git a/src/app/biomass/disc&data/page.mdx b/src/app/[locale]/biomass/disc&data/page.mdx similarity index 100% rename from src/app/biomass/disc&data/page.mdx rename to src/app/[locale]/biomass/disc&data/page.mdx diff --git a/src/app/biomass/earthexplorer/page.mdx b/src/app/[locale]/biomass/earthexplorer/page.mdx similarity index 100% rename from src/app/biomass/earthexplorer/page.mdx rename to src/app/[locale]/biomass/earthexplorer/page.mdx diff --git a/src/app/blog/[slug]/page.tsx b/src/app/[locale]/blog/[slug]/page.tsx similarity index 73% rename from src/app/blog/[slug]/page.tsx rename to src/app/[locale]/blog/[slug]/page.tsx index 1b7570e..12fd9d3 100644 --- a/src/app/blog/[slug]/page.tsx +++ b/src/app/[locale]/blog/[slug]/page.tsx @@ -1,26 +1,29 @@ // Adapted from https://github.com/vercel/examples/tree/main/solutions/blog MIT License import { notFound } from 'next/navigation' import { CustomMDX } from '@/../mdx-components' -import { formatDate, getBlogPosts } from '@/utils/utilsBlog' +import { formatDate, getBlogPosts, getAllBlogPosts } from '@/utils/utilsBlog' import { baseUrl } from '@/utils/sitemap' import Link from 'next/link' -import Image from "next/image"; +import Image from "next/image" +import { isValidLocale, defaultLocale, type Locale } from '@/config/i18n' export async function generateStaticParams() { - const posts = getBlogPosts() - return posts.map((post) => ({ - slug: post.slug, - })) + const all = getAllBlogPosts() + return all.map((post) => { + const locale: Locale = post.slug.endsWith('_de') ? 'de' : 'en' + return { locale, slug: post.slug } + }) } interface BlogParams { - params: Promise<{ slug: string }>; + params: Promise<{ locale: string; slug: string }>; } export default async function Blog({ params }: BlogParams) { - const { slug } = await params; - const posts = getBlogPosts(); - const post = posts.find((post) => post.slug === slug); + const { slug, locale: raw } = await params + const locale: Locale = isValidLocale(raw) ? raw : defaultLocale + const posts = getBlogPosts(locale) + const post = posts.find((p) => p.slug === slug) if (!post) { notFound() @@ -42,7 +45,7 @@ export default async function Blog({ params }: BlogParams) { image: post.metadata.image2 ? `${baseUrl}${post.metadata.image2}` : `/og?title=${encodeURIComponent(post.metadata.title)}`, - url: `${baseUrl}/blog/${post.slug}`, + url: `${baseUrl}/${locale}/blog/${post.slug}`, author: { '@type': 'Person', name: 'My Portfolio', @@ -51,7 +54,7 @@ export default async function Blog({ params }: BlogParams) { }} />
- + ← Back to Posts
diff --git a/src/app/[locale]/blog/page.tsx b/src/app/[locale]/blog/page.tsx new file mode 100644 index 0000000..3f4336f --- /dev/null +++ b/src/app/[locale]/blog/page.tsx @@ -0,0 +1,23 @@ +import { BlogPosts } from '@/components/posts' +import { isValidLocale, defaultLocale, type Locale } from '@/config/i18n' + +export const metadata = { + title: 'Posts', + description: 'Read my posts.', +} + +interface PageProps { + params: Promise<{ locale?: string }> +} + +export default async function Page({ params }: PageProps) { + const { locale: raw } = await params + const locale: Locale = isValidLocale(raw) ? raw : defaultLocale + return ( +
+

+

NEWS

+ +
+ ) +} diff --git a/src/app/blog/posts/first_images.mdx b/src/app/[locale]/blog/posts/first_images.mdx similarity index 100% rename from src/app/blog/posts/first_images.mdx rename to src/app/[locale]/blog/posts/first_images.mdx diff --git a/src/app/blog/posts/first_images_de.mdx b/src/app/[locale]/blog/posts/first_images_de.mdx similarity index 100% rename from src/app/blog/posts/first_images_de.mdx rename to src/app/[locale]/blog/posts/first_images_de.mdx diff --git a/src/app/blog/posts/launch.mdx b/src/app/[locale]/blog/posts/launch.mdx similarity index 100% rename from src/app/blog/posts/launch.mdx rename to src/app/[locale]/blog/posts/launch.mdx diff --git a/src/app/blog/posts/launch_de.mdx b/src/app/[locale]/blog/posts/launch_de.mdx similarity index 100% rename from src/app/blog/posts/launch_de.mdx rename to src/app/[locale]/blog/posts/launch_de.mdx diff --git a/src/app/blog/posts/news1.mdx b/src/app/[locale]/blog/posts/news1.mdx similarity index 100% rename from src/app/blog/posts/news1.mdx rename to src/app/[locale]/blog/posts/news1.mdx diff --git a/src/app/blog/posts/news10.mdx b/src/app/[locale]/blog/posts/news10.mdx similarity index 100% rename from src/app/blog/posts/news10.mdx rename to src/app/[locale]/blog/posts/news10.mdx diff --git a/src/app/blog/posts/news11.mdx b/src/app/[locale]/blog/posts/news11.mdx similarity index 100% rename from src/app/blog/posts/news11.mdx rename to src/app/[locale]/blog/posts/news11.mdx diff --git a/src/app/blog/posts/news12.mdx b/src/app/[locale]/blog/posts/news12.mdx similarity index 100% rename from src/app/blog/posts/news12.mdx rename to src/app/[locale]/blog/posts/news12.mdx diff --git a/src/app/blog/posts/news13.mdx b/src/app/[locale]/blog/posts/news13.mdx similarity index 100% rename from src/app/blog/posts/news13.mdx rename to src/app/[locale]/blog/posts/news13.mdx diff --git a/src/app/blog/posts/news14.mdx b/src/app/[locale]/blog/posts/news14.mdx similarity index 100% rename from src/app/blog/posts/news14.mdx rename to src/app/[locale]/blog/posts/news14.mdx diff --git a/src/app/blog/posts/news15.mdx b/src/app/[locale]/blog/posts/news15.mdx similarity index 100% rename from src/app/blog/posts/news15.mdx rename to src/app/[locale]/blog/posts/news15.mdx diff --git a/src/app/blog/posts/news16.mdx b/src/app/[locale]/blog/posts/news16.mdx similarity index 100% rename from src/app/blog/posts/news16.mdx rename to src/app/[locale]/blog/posts/news16.mdx diff --git a/src/app/blog/posts/news17.mdx b/src/app/[locale]/blog/posts/news17.mdx similarity index 100% rename from src/app/blog/posts/news17.mdx rename to src/app/[locale]/blog/posts/news17.mdx diff --git a/src/app/blog/posts/news18.mdx b/src/app/[locale]/blog/posts/news18.mdx similarity index 100% rename from src/app/blog/posts/news18.mdx rename to src/app/[locale]/blog/posts/news18.mdx diff --git a/src/app/blog/posts/news19.mdx b/src/app/[locale]/blog/posts/news19.mdx similarity index 100% rename from src/app/blog/posts/news19.mdx rename to src/app/[locale]/blog/posts/news19.mdx diff --git a/src/app/blog/posts/news2.mdx b/src/app/[locale]/blog/posts/news2.mdx similarity index 100% rename from src/app/blog/posts/news2.mdx rename to src/app/[locale]/blog/posts/news2.mdx diff --git a/src/app/blog/posts/news20.mdx b/src/app/[locale]/blog/posts/news20.mdx similarity index 100% rename from src/app/blog/posts/news20.mdx rename to src/app/[locale]/blog/posts/news20.mdx diff --git a/src/app/blog/posts/news21.mdx b/src/app/[locale]/blog/posts/news21.mdx similarity index 100% rename from src/app/blog/posts/news21.mdx rename to src/app/[locale]/blog/posts/news21.mdx diff --git a/src/app/blog/posts/news22.mdx b/src/app/[locale]/blog/posts/news22.mdx similarity index 100% rename from src/app/blog/posts/news22.mdx rename to src/app/[locale]/blog/posts/news22.mdx diff --git a/src/app/blog/posts/news23.mdx b/src/app/[locale]/blog/posts/news23.mdx similarity index 100% rename from src/app/blog/posts/news23.mdx rename to src/app/[locale]/blog/posts/news23.mdx diff --git a/src/app/blog/posts/news24.mdx b/src/app/[locale]/blog/posts/news24.mdx similarity index 100% rename from src/app/blog/posts/news24.mdx rename to src/app/[locale]/blog/posts/news24.mdx diff --git a/src/app/blog/posts/news3.mdx b/src/app/[locale]/blog/posts/news3.mdx similarity index 100% rename from src/app/blog/posts/news3.mdx rename to src/app/[locale]/blog/posts/news3.mdx diff --git a/src/app/blog/posts/news4.mdx b/src/app/[locale]/blog/posts/news4.mdx similarity index 100% rename from src/app/blog/posts/news4.mdx rename to src/app/[locale]/blog/posts/news4.mdx diff --git a/src/app/blog/posts/news6.mdx b/src/app/[locale]/blog/posts/news6.mdx similarity index 100% rename from src/app/blog/posts/news6.mdx rename to src/app/[locale]/blog/posts/news6.mdx diff --git a/src/app/blog/posts/news7.mdx b/src/app/[locale]/blog/posts/news7.mdx similarity index 100% rename from src/app/blog/posts/news7.mdx rename to src/app/[locale]/blog/posts/news7.mdx diff --git a/src/app/blog/posts/news8.mdx b/src/app/[locale]/blog/posts/news8.mdx similarity index 100% rename from src/app/blog/posts/news8.mdx rename to src/app/[locale]/blog/posts/news8.mdx diff --git a/src/app/blog/posts/news9.mdx b/src/app/[locale]/blog/posts/news9.mdx similarity index 100% rename from src/app/blog/posts/news9.mdx rename to src/app/[locale]/blog/posts/news9.mdx diff --git a/src/app/blog/posts/summerschool24.mdx b/src/app/[locale]/blog/posts/summerschool24.mdx similarity index 100% rename from src/app/blog/posts/summerschool24.mdx rename to src/app/[locale]/blog/posts/summerschool24.mdx diff --git a/src/app/blog/posts/summerschool24_de.mdx b/src/app/[locale]/blog/posts/summerschool24_de.mdx similarity index 100% rename from src/app/blog/posts/summerschool24_de.mdx rename to src/app/[locale]/blog/posts/summerschool24_de.mdx diff --git a/src/app/blog/posts/summerschool25.mdx b/src/app/[locale]/blog/posts/summerschool25.mdx similarity index 100% rename from src/app/blog/posts/summerschool25.mdx rename to src/app/[locale]/blog/posts/summerschool25.mdx diff --git a/src/app/blog/posts/summerschool25_de.mdx b/src/app/[locale]/blog/posts/summerschool25_de.mdx similarity index 100% rename from src/app/blog/posts/summerschool25_de.mdx rename to src/app/[locale]/blog/posts/summerschool25_de.mdx diff --git a/src/app/blog/posts/workshop12.mdx b/src/app/[locale]/blog/posts/workshop12.mdx similarity index 100% rename from src/app/blog/posts/workshop12.mdx rename to src/app/[locale]/blog/posts/workshop12.mdx diff --git a/src/app/contact/page.mdx b/src/app/[locale]/contact/page.mdx similarity index 100% rename from src/app/contact/page.mdx rename to src/app/[locale]/contact/page.mdx diff --git a/src/app/decalval/about/page.mdx b/src/app/[locale]/decalval/about/page.mdx similarity index 100% rename from src/app/decalval/about/page.mdx rename to src/app/[locale]/decalval/about/page.mdx diff --git a/src/app/decalval/team/cards/Andreas.mdx b/src/app/[locale]/decalval/team/cards/Andreas.mdx similarity index 100% rename from src/app/decalval/team/cards/Andreas.mdx rename to src/app/[locale]/decalval/team/cards/Andreas.mdx diff --git a/src/app/decalval/team/cards/Kostas.mdx b/src/app/[locale]/decalval/team/cards/Kostas.mdx similarity index 100% rename from src/app/decalval/team/cards/Kostas.mdx rename to src/app/[locale]/decalval/team/cards/Kostas.mdx diff --git a/src/app/decalval/team/cards/Martin.mdx b/src/app/[locale]/decalval/team/cards/Martin.mdx similarity index 100% rename from src/app/decalval/team/cards/Martin.mdx rename to src/app/[locale]/decalval/team/cards/Martin.mdx diff --git a/src/app/decalval/team/cards/Matthias.mdx b/src/app/[locale]/decalval/team/cards/Matthias.mdx similarity index 100% rename from src/app/decalval/team/cards/Matthias.mdx rename to src/app/[locale]/decalval/team/cards/Matthias.mdx diff --git a/src/app/decalval/team/cards/Mikhail.mdx b/src/app/[locale]/decalval/team/cards/Mikhail.mdx similarity index 100% rename from src/app/decalval/team/cards/Mikhail.mdx rename to src/app/[locale]/decalval/team/cards/Mikhail.mdx diff --git a/src/app/decalval/team/cards/Nicole.mdx b/src/app/[locale]/decalval/team/cards/Nicole.mdx similarity index 100% rename from src/app/decalval/team/cards/Nicole.mdx rename to src/app/[locale]/decalval/team/cards/Nicole.mdx diff --git a/src/app/decalval/team/cards/Nuno.mdx b/src/app/[locale]/decalval/team/cards/Nuno.mdx similarity index 100% rename from src/app/decalval/team/cards/Nuno.mdx rename to src/app/[locale]/decalval/team/cards/Nuno.mdx diff --git a/src/app/decalval/team/cards/Ralph.mdx b/src/app/[locale]/decalval/team/cards/Ralph.mdx similarity index 100% rename from src/app/decalval/team/cards/Ralph.mdx rename to src/app/[locale]/decalval/team/cards/Ralph.mdx diff --git a/src/app/decalval/team/page.mdx b/src/app/[locale]/decalval/team/page.mdx similarity index 100% rename from src/app/decalval/team/page.mdx rename to src/app/[locale]/decalval/team/page.mdx diff --git a/src/app/decalval/wps/page.mdx b/src/app/[locale]/decalval/wps/page.mdx similarity index 100% rename from src/app/decalval/wps/page.mdx rename to src/app/[locale]/decalval/wps/page.mdx diff --git a/src/app/events/polinsar/page.mdx b/src/app/[locale]/events/polinsar/page.mdx similarity index 100% rename from src/app/events/polinsar/page.mdx rename to src/app/[locale]/events/polinsar/page.mdx diff --git a/src/app/events/summerschool/2022/page.mdx b/src/app/[locale]/events/summerschool/2022/page.mdx similarity index 100% rename from src/app/events/summerschool/2022/page.mdx rename to src/app/[locale]/events/summerschool/2022/page.mdx diff --git a/src/app/events/summerschool/2024/page.mdx b/src/app/[locale]/events/summerschool/2024/page.mdx similarity index 100% rename from src/app/events/summerschool/2024/page.mdx rename to src/app/[locale]/events/summerschool/2024/page.mdx diff --git a/src/app/events/summerschool/2025/page.mdx b/src/app/[locale]/events/summerschool/2025/page.mdx similarity index 100% rename from src/app/events/summerschool/2025/page.mdx rename to src/app/[locale]/events/summerschool/2025/page.mdx diff --git a/src/app/events/summerschool/page.mdx b/src/app/[locale]/events/summerschool/page.mdx similarity index 100% rename from src/app/events/summerschool/page.mdx rename to src/app/[locale]/events/summerschool/page.mdx diff --git a/src/app/events/webinar/page.mdx b/src/app/[locale]/events/webinar/page.mdx similarity index 100% rename from src/app/events/webinar/page.mdx rename to src/app/[locale]/events/webinar/page.mdx diff --git a/src/app/[locale]/landing-de.mdx b/src/app/[locale]/landing-de.mdx new file mode 100644 index 0000000..344efc4 --- /dev/null +++ b/src/app/[locale]/landing-de.mdx @@ -0,0 +1,121 @@ +import ContentSplitSection from '@/components/ContentSplitSection'; +import Image from 'next/image'; +import { Button } from "@/components/ui/button" +import { + Card, + CardDescription, + CardHeader, + CardTitle, +} from "@/components/ui/card" + + +
+ + + + + Projektbüro BIOMASS

+
+ eebiomass +
+ +
+
+
+ + + + + Deutsche BIOMASS Cal/Val-Aktivitäten

+
+ eebiomass +
+
+
+
+
+----------------------- +

+#### Aktuelles + + +
+ + + + + Erste BIOMASS-Produkte verfügbar! + + +
+ + LPS2025 + +
+ +
+
+ + + + Erste BIOMASS-Bilder! +
+ + Erste BIOMASS-Bilder + +
+
+ +
+ + + + BIOMASS Cal/Val-Aktivitäten +
+ + eebiomass + +
+
+
+ +
+ +
+ +
+ +------------------ + +

+ +Im April 2025 startete die ESA den Earth Explorer BIOMASS. Die Mission verbessert unser Verständnis der Rolle der Landbiosphäre im globalen Kohlenstoffkreislauf, mit klaren Implikationen im Kontext des Klimawandels. Mit Hilfe der Fernerkundung ist BIOMASS die erste Mission mit einem operationellen P-Band-SAR im Weltraum und erfasst den Zustand vor allem tropischer Wälder. + +Das Projektbüro BIOMASS ist eine Kooperation des Max-Planck-Instituts für Biogeochemie, der Friedrich-Schiller-Universität Jena, des Deutschen Zentrums für Luft- und Raumfahrt (DLR) und des Helmholtz-Zentrums für Umweltforschung (UFZ). Wir wollen + + +Der Koordinierte Deutsche Beitrag zu den BIOMASS Cal/Val-Aktivitäten ist eine Kooperation des Max-Planck-Instituts für Biogeochemie, des GFZ Helmholtz-Zentrums für Geowissenschaften, des DLR, des UFZ und der Technischen Universität Dresden (TUD), unterstützt von der University of Maryland und Wilderness International. Wir wollen + + +Für unsere Community bieten wir + +

+ +
+ Bundesministerium für Wirtschaft und Klimaschutz +
diff --git a/src/app/page.mdx b/src/app/[locale]/landing-en.mdx similarity index 96% rename from src/app/page.mdx rename to src/app/[locale]/landing-en.mdx index fa7ba46..ec4f9fb 100644 --- a/src/app/page.mdx +++ b/src/app/[locale]/landing-en.mdx @@ -1,4 +1,3 @@ - import ContentSplitSection from '@/components/ContentSplitSection'; import Image from 'next/image'; import { Button } from "@/components/ui/button" @@ -125,12 +124,12 @@ The Coordinated German Contribution to the BIOMASS Cal/Val Act For our community, we host
    - Regular webinars on topics related to BIOMASS science and applications -- Summer schools on the upcoming BIOMASS mission and its context in current research goals +- Summer schools on the upcoming BIOMASS mission and its context in current research goals - Tutorials and background information on the BIOMASS mission via the eo-college -- Support for the DLR’s PolInSAR courses +- Support for the DLR's PolInSAR courses

Ministry for Economics and Climate -
\ No newline at end of file + diff --git a/src/app/[locale]/layout.tsx b/src/app/[locale]/layout.tsx new file mode 100644 index 0000000..a8e2510 --- /dev/null +++ b/src/app/[locale]/layout.tsx @@ -0,0 +1,29 @@ +import { LocaleProvider } from '@/contexts/LocaleContext' +import { SetHtmlLang } from '@/components/SetHtmlLang' +import Menu from '@/components/Menu' +import Footer from '@/components/Footer' +import { locales, isValidLocale, defaultLocale, type Locale } from '@/config/i18n' + +export function generateStaticParams() { + return locales.map((locale) => ({ locale })) +} + +export default async function LocaleLayout({ + children, + params, +}: { + children: React.ReactNode + params: Promise<{ locale: string }> +}) { + const { locale: raw } = await params + const locale: Locale = isValidLocale(raw) ? raw : defaultLocale + + return ( + + + + {children} +