Show Chinese locale only when Chinese language signals are detected.

Hide the language switcher for English-only browsers; gate /zh via Accept-Language and a client cookie.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-19 19:50:37 +08:00
parent a59aaf1c8d
commit e2fa28e501
6 changed files with 169 additions and 7 deletions

View File

@@ -1,8 +1,13 @@
"use client";
import { useEffect, useMemo, useState } from "react";
import { useLocale, useTranslations } from "next-intl";
import { usePathname, useRouter } from "@/i18n/navigation";
import { routing, type AppLocale } from "@/i18n/routing";
import type { AppLocale } from "@/i18n/routing";
import {
detectChineseClient,
markChineseLocaleAllowed,
} from "@/lib/chinese-locale";
import { cn } from "@/lib/utils";
export function LanguageSwitcher() {
@@ -10,6 +15,31 @@ export function LanguageSwitcher() {
const locale = useLocale() as AppLocale;
const router = useRouter();
const pathname = usePathname();
const [ready, setReady] = useState(false);
const [zhAvailable, setZhAvailable] = useState(false);
useEffect(() => {
const { likely } = detectChineseClient();
setZhAvailable(likely);
setReady(true);
if (likely) {
markChineseLocaleAllowed();
} else if (locale === "zh") {
router.replace(pathname, { locale: "en" });
}
}, [locale, pathname, router]);
const locales = useMemo(() => {
const list: AppLocale[] = ["en"];
if (zhAvailable) list.push("zh");
return list;
}, [zhAvailable]);
// English-only environments: no language control
if (!ready || locales.length < 2) {
return null;
}
return (
<div
@@ -17,7 +47,7 @@ export function LanguageSwitcher() {
role="group"
aria-label={t("label")}
>
{routing.locales.map((loc) => (
{locales.map((loc) => (
<button
key={loc}
type="button"
@@ -28,7 +58,10 @@ export function LanguageSwitcher() {
: "text-[var(--muted)] hover:text-[var(--ink)]"
)}
aria-pressed={loc === locale}
onClick={() => router.replace(pathname, { locale: loc })}
onClick={() => {
if (loc === "zh") markChineseLocaleAllowed();
router.replace(pathname, { locale: loc });
}}
>
{t(loc)}
</button>