mirror of
https://github.com/zen-browser/www.git
synced 2025-07-08 09:20:00 +02:00
refactor: Remove unnecessary output property in next.config.js
This commit is contained in:
parent
9fab23d159
commit
406ff44bb4
10 changed files with 21 additions and 171 deletions
|
@ -45,4 +45,4 @@ const nextConfig = (phase, { defaultConfig }) => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {...withNextIntl(nextConfig)};
|
module.exports = withNextIntl(nextConfig);
|
||||||
|
|
|
@ -4,11 +4,9 @@ import "./globals.css";
|
||||||
import { ThemeProvider } from "@/components/theme-provider";
|
import { ThemeProvider } from "@/components/theme-provider";
|
||||||
import StyledComponentsRegistry from "@/lib/styled-components-registry";
|
import StyledComponentsRegistry from "@/lib/styled-components-registry";
|
||||||
import {NextIntlClientProvider} from 'next-intl';
|
import {NextIntlClientProvider} from 'next-intl';
|
||||||
import {unstable_setRequestLocale} from 'next-intl/server';
|
|
||||||
import Footer from "@/components/footer";
|
import Footer from "@/components/footer";
|
||||||
import { Navigation } from "@/components/navigation";
|
import { Navigation } from "@/components/navigation";
|
||||||
import { notFound } from "next/navigation";
|
import { getMessages } from "next-intl/server";
|
||||||
import {routing} from '@/i18n/routing';
|
|
||||||
|
|
||||||
const inter = Inter({ subsets: ["latin"] });
|
const inter = Inter({ subsets: ["latin"] });
|
||||||
|
|
||||||
|
@ -18,29 +16,14 @@ export const metadata: Metadata = {
|
||||||
keywords: ["Zen", "Browser", "Zen Browser", "Web", "Internet", "Fast"],
|
keywords: ["Zen", "Browser", "Zen Browser", "Web", "Internet", "Fast"],
|
||||||
};
|
};
|
||||||
|
|
||||||
const SUPPORTED_LANGUAGES = ["en", "de"];
|
|
||||||
|
|
||||||
async function getMessages(locale: string) {
|
|
||||||
try {
|
|
||||||
return (await import(`../../../messages/${locale}.json`)).default
|
|
||||||
} catch (error) {
|
|
||||||
notFound()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function generateStaticParams() {
|
|
||||||
return routing.locales.map((locale) => ({locale}));
|
|
||||||
}
|
|
||||||
|
|
||||||
export default async function RootLayout({
|
export default async function RootLayout({
|
||||||
children,
|
children,
|
||||||
params: {locale},
|
params: {locale}
|
||||||
}: Readonly<{
|
}: Readonly<{
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
params: {locale: string};
|
params: {locale: string};
|
||||||
}>) {
|
}>) {
|
||||||
unstable_setRequestLocale(locale);
|
const messages = await getMessages();
|
||||||
const messages = await getMessages(locale);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<html lang={locale} suppressHydrationWarning>
|
<html lang={locale} suppressHydrationWarning>
|
||||||
|
|
|
@ -1,8 +1,3 @@
|
||||||
import { BrandingAssets } from "@/components/branding-assets";
|
|
||||||
import Footer from "@/components/footer";
|
|
||||||
import { Navigation } from "@/components/navigation";
|
|
||||||
|
|
||||||
export const runtime = 'edge'
|
|
||||||
|
|
||||||
export default function NotFoundPage() {
|
export default function NotFoundPage() {
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -1,110 +0,0 @@
|
||||||
import { Feed } from "feed";
|
|
||||||
import { releaseNotes } from "@/lib/release-notes";
|
|
||||||
import type { ReleaseNote } from "@/lib/release-notes";
|
|
||||||
|
|
||||||
// Force feed.xml to be cached as static and remain constant for the lifetime of the current site build.
|
|
||||||
// The supplied releaseNotes array is constant per build, so this will always be the latest release notes.
|
|
||||||
export const dynamic = "force-static";
|
|
||||||
|
|
||||||
/** The default number of entries to include in the RSS feed. */
|
|
||||||
const RSS_ENTRY_LIMIT = 20;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles the GET request for the `feed.xml` endpoint.
|
|
||||||
* @returns The RSS feed for the Zen Browser release notes.
|
|
||||||
*/
|
|
||||||
export async function GET() {
|
|
||||||
// Just in case the release notes array is empty for whatever reason.
|
|
||||||
const latestDate = releaseNotes.length > 0
|
|
||||||
? formatRssDate(releaseNotes[0].date)
|
|
||||||
: new Date();
|
|
||||||
|
|
||||||
const feed = new Feed({
|
|
||||||
id: "https://www.zen-browser.app/release-notes",
|
|
||||||
link: "https://www.zen-browser.app/release-notes",
|
|
||||||
title: "Zen Browser Release Notes",
|
|
||||||
description: "Release Notes for the Zen Browser",
|
|
||||||
language: "en",
|
|
||||||
favicon: "https://www.zen-browser.app/favicon.ico",
|
|
||||||
copyright: `Zen Browser © ${new Date().getFullYear()} - Made with ❤️ by the Zen team.`,
|
|
||||||
updated: latestDate,
|
|
||||||
});
|
|
||||||
|
|
||||||
for (const releaseNote of releaseNotes.slice(0, RSS_ENTRY_LIMIT)) {
|
|
||||||
feed.addItem({
|
|
||||||
title: `Release notes for version ${releaseNote.version}`,
|
|
||||||
id: `https://www.zen-browser.app/release-notes/${releaseNote.version}`,
|
|
||||||
link: `https://www.zen-browser.app/release-notes/${releaseNote.version}`,
|
|
||||||
date: formatRssDate(releaseNote.date),
|
|
||||||
description: releaseNote.extra,
|
|
||||||
content: formatReleaseNote(releaseNote),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Response(feed.rss2(), {
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/xml; charset=utf-8',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Formats a date string in the format day/month/year.
|
|
||||||
*
|
|
||||||
* Note: If release notes change to ISO format, this will need to be updated.
|
|
||||||
* @param dateStr The date string to format.
|
|
||||||
* @returns The passed in date string as a Date object.
|
|
||||||
*/
|
|
||||||
function formatRssDate(dateStr: string) {
|
|
||||||
const splitDate = dateStr.split("/");
|
|
||||||
if (splitDate.length !== 3) {
|
|
||||||
throw new Error("Invalid date format");
|
|
||||||
}
|
|
||||||
|
|
||||||
const day = Number(splitDate[0]);
|
|
||||||
const month = Number(splitDate[1]) - 1;
|
|
||||||
const year = Number(splitDate[2]);
|
|
||||||
return new Date(year, month, day);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Formats the release note entry for use as the content of the RSS feed.
|
|
||||||
* @param releaseNote The release note to format.
|
|
||||||
* @returns The formatted release note as a HTML string.
|
|
||||||
*/
|
|
||||||
function formatReleaseNote(releaseNote: ReleaseNote) {
|
|
||||||
let content = "<p>If you encounter any issues, please report them on <a href=\"https://github.com/zen-browser/desktop/issues/\">the issues page</a>. Thanks everyone for your feedback! ❤️</p>";
|
|
||||||
|
|
||||||
if (releaseNote.extra) {
|
|
||||||
content += `<p>${releaseNote.extra.replace(/(\n)/g, "<br />")}</p>`
|
|
||||||
}
|
|
||||||
|
|
||||||
if (releaseNote.breakingChanges) {
|
|
||||||
content += `<h2>⚠️ Breaking changes</h2>`
|
|
||||||
content += `<ul>`
|
|
||||||
for (const breakingChange of releaseNote.breakingChanges) {
|
|
||||||
content += `<li>${breakingChange}</li>`
|
|
||||||
}
|
|
||||||
content += `</ul>`
|
|
||||||
}
|
|
||||||
|
|
||||||
if (releaseNote.features) {
|
|
||||||
content += `<h2>⭐ Features</h2>`
|
|
||||||
content += `<ul>`
|
|
||||||
for (const feature of releaseNote.features) {
|
|
||||||
content += `<li>${feature}</li>`
|
|
||||||
}
|
|
||||||
content += `</ul>`
|
|
||||||
}
|
|
||||||
|
|
||||||
if (releaseNote.fixes) {
|
|
||||||
content += `<h2>✓ Fixes</h2>`
|
|
||||||
content += `<ul>`
|
|
||||||
for (const fix of releaseNote.fixes) {
|
|
||||||
content += `<li>${fix.description}</li>`
|
|
||||||
}
|
|
||||||
content += `</ul>`
|
|
||||||
}
|
|
||||||
|
|
||||||
return content;
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
|
|
||||||
import {ReactNode} from 'react';
|
|
||||||
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
children: ReactNode;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Since we have a `not-found.tsx` page on the root, a layout file
|
|
||||||
// is required, even if it's just passing children through.
|
|
||||||
export default function RootLayout({children}: Props) {
|
|
||||||
return children;
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
|
|
||||||
import {redirect} from 'next/navigation';
|
|
||||||
|
|
||||||
|
|
||||||
export default function RootPage() {
|
|
||||||
redirect('/en');
|
|
||||||
}
|
|
|
@ -1,7 +1,6 @@
|
||||||
"use client";
|
"use client";
|
||||||
import { usePathname, useRouter } from '@/i18n/routing';
|
import { SUPPORTED_LANGUAGES, usePathname, useRouter } from '@/i18n/routing';
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './ui/select';
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './ui/select';
|
||||||
import { SUPPORTED_LANGUAGES } from '@/i18n';
|
|
||||||
|
|
||||||
export default function LocaleSwitcher() {
|
export default function LocaleSwitcher() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
19
src/i18n.ts
19
src/i18n.ts
|
@ -1,9 +1,12 @@
|
||||||
import { getRequestConfig } from "next-intl/server";
|
import {notFound} from 'next/navigation';
|
||||||
|
import {getRequestConfig} from 'next-intl/server';
|
||||||
export const SUPPORTED_LANGUAGES = ['en', 'de'];
|
import {routing} from './i18n/routing';
|
||||||
|
|
||||||
export default getRequestConfig(async ({locale}) => {
|
export default getRequestConfig(async ({locale}) => {
|
||||||
const lang = SUPPORTED_LANGUAGES.includes(locale) ? locale : 'en';
|
// Validate that the incoming `locale` parameter is valid
|
||||||
const messages = await import(`../messages/${lang}.json`);
|
if (!routing.locales.includes(locale as any)) notFound();
|
||||||
return {messages};
|
|
||||||
});
|
return {
|
||||||
|
messages: (await import(`../messages/${locale}.json`)).default
|
||||||
|
};
|
||||||
|
});
|
|
@ -1,13 +1,14 @@
|
||||||
import {defineRouting} from 'next-intl/routing';
|
import {defineRouting} from 'next-intl/routing';
|
||||||
import {createSharedPathnamesNavigation} from 'next-intl/navigation';
|
import {createSharedPathnamesNavigation} from 'next-intl/navigation';
|
||||||
import { SUPPORTED_LANGUAGES } from '@/i18n';
|
export const SUPPORTED_LANGUAGES = ['en', 'de'];
|
||||||
|
|
||||||
export const routing = defineRouting({
|
export const routing = defineRouting({
|
||||||
// A list of all locales that are supported
|
// A list of all locales that are supported
|
||||||
locales: SUPPORTED_LANGUAGES,
|
locales: SUPPORTED_LANGUAGES,
|
||||||
|
|
||||||
// Used when no locale matches
|
// Used when no locale matches
|
||||||
defaultLocale: 'en'
|
defaultLocale: 'en',
|
||||||
|
localePrefix: "always",
|
||||||
});
|
});
|
||||||
|
|
||||||
// Lightweight wrappers around Next.js' navigation APIs
|
// Lightweight wrappers around Next.js' navigation APIs
|
||||||
|
|
|
@ -4,6 +4,6 @@ import {routing} from './i18n/routing';
|
||||||
export default createMiddleware(routing);
|
export default createMiddleware(routing);
|
||||||
|
|
||||||
export const config = {
|
export const config = {
|
||||||
// Match only internationalized pathnames
|
// Match only internationalized pathnames and all paths that dont start with static
|
||||||
matcher: ['/', '/(de|en)/:path*']
|
matcher: ['/', '/:path((?!_next|next|static).*)*'],
|
||||||
};
|
};
|
Loading…
Add table
Add a link
Reference in a new issue