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:
@@ -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`),
|
||||
|
||||
Reference in New Issue
Block a user