Fix landing locale toggle cache path

This commit is contained in:
2569718930@qq.com
2026-06-14 05:11:37 +08:00
parent b4a23578f2
commit 0084235b57
5 changed files with 38 additions and 12 deletions
+4 -1
View File
@@ -1,6 +1,7 @@
import type { Metadata } from "next";
import { redirect } from "next/navigation";
import { InstitutionalLandingPage } from "@/components/landing/InstitutionalLandingPage";
import { LANDING_LOCALE_QUERY_PARAM } from "@/components/landing/landingLocale";
export const metadata: Metadata = {
title: "PolyWeather | Institutional Weather Signal Intelligence",
@@ -32,6 +33,8 @@ export default async function HomePage({
const qs = usp.toString();
redirect(`/auth/callback${qs ? `?${qs}` : ""}`);
}
const rawLandingLocale = params[LANDING_LOCALE_QUERY_PARAM];
const landingLocale = Array.isArray(rawLandingLocale) ? rawLandingLocale[0] : rawLandingLocale;
const jsonLd = {
"@context": "https://schema.org",
"@type": "WebApplication",
@@ -68,7 +71,7 @@ export default async function HomePage({
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
<InstitutionalLandingPage />
<InstitutionalLandingPage queryLocale={landingLocale} />
</>
);
}
@@ -227,9 +227,10 @@ function WeatherWorkflowIllustration() {
);
}
async function resolveLandingLocale(): Promise<LandingLocale> {
async function resolveLandingLocale(queryLocale?: string | null): Promise<LandingLocale> {
const [cookieStore, headerStore] = await Promise.all([cookies(), headers()]);
return pickLandingLocale(
queryLocale,
cookieStore.get(LANDING_LOCALE_COOKIE)?.value,
headerStore.get("accept-language"),
);
@@ -829,7 +830,11 @@ function InstitutionalLandingScreen({ locale }: { locale: LandingLocale }) {
);
}
export async function InstitutionalLandingPage() {
const locale = await resolveLandingLocale();
export async function InstitutionalLandingPage({
queryLocale,
}: {
queryLocale?: string | null;
} = {}) {
const locale = await resolveLandingLocale(queryLocale);
return <InstitutionalLandingScreen locale={locale} />;
}
@@ -1,9 +1,8 @@
"use client";
import { useTransition } from "react";
import { useRouter } from "next/navigation";
import {
LANDING_LOCALE_COOKIE,
LANDING_LOCALE_QUERY_PARAM,
nextLandingLocale,
type LandingLocale,
} from "@/components/landing/landingLocale";
@@ -11,8 +10,6 @@ import {
const ONE_YEAR_SECONDS = 60 * 60 * 24 * 365;
export function LandingLocaleToggle({ locale }: { locale: LandingLocale }) {
const router = useRouter();
const [isPending, startTransition] = useTransition();
const isEn = locale === "en-US";
const toggleLocale = () => {
@@ -24,16 +21,16 @@ export function LandingLocaleToggle({ locale }: { locale: LandingLocale }) {
} catch {
// Locale persistence is best-effort; the cookie is enough for SSR.
}
startTransition(() => {
router.refresh();
});
const url = new URL(window.location.href);
url.searchParams.set(LANDING_LOCALE_QUERY_PARAM, nextLocale);
window.location.assign(url.toString());
};
return (
<button
type="button"
onClick={toggleLocale}
disabled={isPending}
className="inline-flex h-9 cursor-pointer items-center gap-1 rounded-md border border-slate-200 bg-white px-1 text-xs font-semibold text-slate-500 shadow-sm hover:border-slate-300 disabled:cursor-wait disabled:opacity-70"
aria-label={isEn ? "Switch language" : "切换语言"}
>
@@ -23,6 +23,10 @@ export function runTests() {
path.join(root, "components", "landing", "LandingLocaleToggle.tsx"),
"utf8",
);
const localeHelperSource = fs.readFileSync(
path.join(root, "components", "landing", "landingLocale.ts"),
"utf8",
);
const staticCitiesSource = fs.readFileSync(
path.join(root, "lib", "static-cities.ts"),
"utf8",
@@ -48,6 +52,18 @@ export function runTests() {
assert(!authActionsSource.includes("lucide-react"), "auth island must avoid shipping lucide-react");
assert(!localeToggleSource.includes("lucide-react"), "locale island must avoid shipping lucide-react");
assert(!analyticsSource.includes("lucide-react"), "analytics island must avoid shipping lucide-react");
assert(
localeToggleSource.includes("new URL(window.location.href)") &&
localeToggleSource.includes("LANDING_LOCALE_QUERY_PARAM") &&
localeToggleSource.includes("window.location.assign(url.toString())"),
"landing locale toggle must navigate with an explicit locale query so CDN-cached HTML cannot ignore cookie-only changes",
);
assert(
localeHelperSource.includes("queryLocale") &&
source.includes("resolveLandingLocale(queryLocale") &&
appPageSource.includes("<InstitutionalLandingPage queryLocale={landingLocale} />"),
"landing route must prefer an explicit locale query before cookie or Accept-Language",
);
assert(source.includes("3 天免费试用"), "landing page must advertise the 3-day trial");
assert(source.includes("试用期权益和 Pro 一致,除了不显示付费 Telegram 群链接"), "landing page must state trial access matches Pro except the paid group link");
assert(!source.includes("高频刷新与 API 仍为 Pro 权益"), "landing page must not incorrectly exclude high-frequency refresh or API from trial access");
@@ -1,6 +1,7 @@
export type LandingLocale = "zh-CN" | "en-US";
export const LANDING_LOCALE_COOKIE = "polyweather.locale";
export const LANDING_LOCALE_QUERY_PARAM = "locale";
export const DEFAULT_LANDING_LOCALE: LandingLocale = "zh-CN";
export function normalizeLandingLocale(value: string | null | undefined): LandingLocale | null {
@@ -16,9 +17,13 @@ export function normalizeLandingLocale(value: string | null | undefined): Landin
}
export function pickLandingLocale(
queryLocale: string | null | undefined,
cookieLocale: string | null | undefined,
acceptLanguage: string | null | undefined,
): LandingLocale {
const fromQuery = normalizeLandingLocale(queryLocale);
if (fromQuery) return fromQuery;
const fromCookie = normalizeLandingLocale(cookieLocale);
if (fromCookie) return fromCookie;