fix: 语言切换全面修复 —— 品牌层/主题首页/详情区块/404 全量 i18n(zh 矩阵 13/13)

- 站点品牌双语:每站 brandZh(品牌名/标语/hero/导航/页脚/搜索占位)由生成器写入
  站点 messages 的 zh 覆盖;SiteChrome 改为 async getTranslations 按语言渲染
- 五套主题首页接线 siteHome/hero 命名空间(新增 wire-theme-i18n.py 一次性接线脚本,
  仅处理组件函数体、hook 自动插入、hero 用 th 命名空间)
- 详情页 Use cases/Good for/FAQ/reviewCta、用例与合集索引与详情、提交页、
  对比页、Alternatives 表头与 FAQ 全部走 next-intl
- 404 双语言:locale 内走 next-intl,根级按 Accept-Language
- 修复 zh.json 中 84 处 zhXxx 旁挂键归位 + en.json 残留清理(i18n 694 键一致)
- 回归:/zh 下 13 页全中文无英文残留、无横向溢出;五站 /zh lang=zh 全部正确
This commit is contained in:
AI Directory Platform
2026-09-09 16:59:52 +00:00
parent f4f48f7293
commit 5cc4195d68
50 changed files with 4141 additions and 235 deletions
+84 -4
View File
@@ -23,6 +23,15 @@ const SITES_ROOT = path.join(REPO_ROOT, "sites");
// ====================================================================
const SITES = {
"ai-stack": {
brandZh: {
name: "AI Stack",
tagline: "由真实用户排名的专业 AI 工具目录。",
headline: "找到最好的 AI 工具,由真实用户排名",
subheadline: "14 个分类、1000+ AI 工具。对比投票、评论与定价,选出最适合你的。",
nav: ["发现", "用例", "最佳清单", "排行榜", "博客", "提交工具"],
footer: ["发现", "社区", "法律"],
searchPlaceholder: "搜索 1000+ AI 工具...",
},
accent: "222 47% 11%", // 近黑(专业)
port: 3001,
theme: "classic",
@@ -82,6 +91,15 @@ const SITES = {
},
},
launchai: {
brandZh: {
name: "LaunchAI",
tagline: "发现并投票今日的 AI 新品。",
headline: "今日 AI 产品发布",
subheadline: "每天上新。为最好的产品投票,冲上排行榜。",
nav: ["今日", "排行榜", "分类", "合集", "博客", "提交产品"],
footer: ["社区", "探索", "关于"],
searchPlaceholder: "搜索 AI 产品...",
},
accent: "16 85% 55%", // 橙红(产品社区)
port: 3002,
theme: "product",
@@ -139,6 +157,15 @@ const SITES = {
},
},
"the-ai-ledger": {
brandZh: {
name: "The AI Ledger",
tagline: "独立 AI 报道,附社区排名目录。",
headline: "AI 工具,评测与排名",
subheadline: "指南、对比,以及由社区驱动的最佳 AI 工具目录。",
nav: ["文章", "指南", "最佳推荐", "目录", "排行榜", "提交"],
footer: ["阅读", "目录", "公司"],
searchPlaceholder: "搜索目录...",
},
accent: "36 70% 40%", // 纸墨棕(编辑部)
port: 3003,
theme: "editorial",
@@ -197,6 +224,15 @@ const SITES = {
},
},
"devai-tools": {
brandZh: {
name: "DevAI.tools",
tagline: "面向开发者的 AI 工具——精选、实测、社区排名。",
headline: "开发者的 AI 工具",
subheadline: "代码助手、运维自动化、测试副驾驶,你上手的一切。",
nav: ["工具", "工作流", "用例", "排行榜", "提交"],
footer: ["目录", "构建", "法律"],
searchPlaceholder: "搜索开发者工具...",
},
accent: "150 60% 30%", // 终端绿(开发者)
port: 3004,
theme: "niche",
@@ -253,6 +289,15 @@ const SITES = {
},
},
findai: {
brandZh: {
name: "findai",
tagline: "极简 AI 工具搜索引擎。",
headline: "你想完成什么?",
subheadline: "",
nav: ["搜索", "用例", "排行榜", "提交"],
footer: ["搜索", "关于"],
searchPlaceholder: "你需要什么?",
},
accent: "260 70% 52%", // 紫(极简搜索)
port: 3005,
theme: "minimal",
@@ -501,13 +546,25 @@ import { locales, defaultLocale, type Locale } from "${corePkg}/i18n.config";
const brandMessages = {
en: {
seo: { home: ${JSON.stringify({ title: site.seo.en.title, description: site.seo.en.description, ogImage: "/og-image.png" })} },
hero: { title: ${JSON.stringify(site.seo.en.title)}, description: ${JSON.stringify(site.seo.en.description)} },
hero: { title: ${JSON.stringify(site.brand.headline)}, description: ${JSON.stringify(site.brand.subheadline || site.seo.en.description)} },
common: { brand: { name: ${JSON.stringify(site.brand.name)}, tagline: ${JSON.stringify(site.brand.tagline)} } },
navigation: {
main: { tools: ${JSON.stringify(site.navItems[0]?.label ?? "Discover")}, blog: ${JSON.stringify(site.navItems.find((n) => n.href === "/blog")?.label ?? "Blog")} },
site: { items: ${JSON.stringify(site.navItems.map((n) => n.label))}, hrefs: ${JSON.stringify(site.navItems.map((n) => n.href))} },
},
siteFooter: { groups: ${JSON.stringify(site.footerGroups)} },
siteHeader: { searchPlaceholder: ${JSON.stringify(site.searchPlaceholder)} },
},
zh: {
seo: { home: ${JSON.stringify({ title: site.seo.zh.title, description: site.seo.zh.description, ogImage: "/og-image.png" })} },
hero: { title: ${JSON.stringify(site.seo.zh.title)}, description: ${JSON.stringify(site.seo.zh.description)} },
common: { brand: { name: ${JSON.stringify(site.brand.name)}, tagline: ${JSON.stringify(site.brand.tagline)} } },
hero: { title: ${JSON.stringify(site.brandZh?.headline ?? site.seo.zh.title)}, description: ${JSON.stringify(site.brandZh?.subheadline || site.seo.zh.description)} },
common: { brand: { name: ${JSON.stringify(site.brandZh?.name ?? site.brand.name)}, tagline: ${JSON.stringify(site.brandZh?.tagline ?? site.brand.tagline)} } },
navigation: {
main: { tools: ${JSON.stringify(site.brandZh?.nav?.[0] ?? site.navItems[0]?.label ?? "发现")}, blog: ${JSON.stringify(site.brandZh?.nav?.[site.navItems.findIndex((n) => n.href === "/blog")] ?? "博客")} },
site: { items: ${JSON.stringify(site.brandZh?.nav ?? site.navItems.map((n) => n.label))}, hrefs: ${JSON.stringify(site.navItems.map((n) => n.href))} },
},
siteFooter: { groups: ${JSON.stringify(site.footerGroups.map((g, gi) => ({ ...g, title: (site.brandZh?.footer ?? [])[gi] ?? g.title })))} },
siteHeader: { searchPlaceholder: ${JSON.stringify(site.brandZh?.searchPlaceholder ?? site.searchPlaceholder)} },
},
} as const;
@@ -649,7 +706,30 @@ export default getRequestConfig(async ({ requestLocale }) => {
base.common.brand = { ...(base.common.brand ?? {}), name: site.brand.name, tagline: site.brand.tagline };
base.seo = base.seo ?? {};
base.seo.home = { ...(base.seo.home ?? {}), ...site.seo[locale] };
base.hero = { ...(base.hero ?? {}), title: site.seo[locale].title, description: site.seo[locale].description };
base.hero = {
...(base.hero ?? {}),
title: locale === "zh" ? (site.brandZh?.headline ?? site.seo.zh.title) : site.brand.headline,
description: locale === "zh" ? (site.brandZh?.subheadline || site.seo.zh.description) : (site.brand.subheadline || site.seo.en.description),
badge: locale === "zh" ? "" : base.hero?.badge ?? "",
};
if (locale === "zh") delete base.hero.badge;
// 站点导航/页脚/搜索文案(供 ThemeChrome 消费)
base.navigation = {
...(base.navigation ?? {}),
site: {
items: locale === "zh" ? (site.brandZh?.nav ?? site.navItems.map((n) => n.label)) : site.navItems.map((n) => n.label),
hrefs: site.navItems.map((n) => n.href),
},
};
base.siteFooter = {
groups: site.footerGroups.map((g, gi) => ({
...g,
title: locale === "zh" ? ((site.brandZh?.footer ?? [])[gi] ?? g.title) : g.title,
})),
};
base.siteHeader = {
searchPlaceholder: locale === "zh" ? (site.brandZh?.searchPlaceholder ?? site.searchPlaceholder) : site.searchPlaceholder,
};
fs.mkdirSync(path.join(siteRoot, "messages"), { recursive: true });
fs.writeFileSync(
path.join(siteRoot, "messages", `${locale}.json`),