refactor: 主题系统 → monorepo 五个独立网站
- packages/core: @aidir/core 底座库(src/pages 页面组件体 1:1 镜像路由树 / kit 站点外壳工厂 / content/blog / scripts) - sites/: 5 个独立 Next.js 网站(ai-stack / launchai / the-ai-ledger / devai-tools / findai) - 每站独立 package.json / next.config / tailwind / messages / .env / 构建 - src/app 约 56 个薄路由文件(re-export 底座页面 + 内联路由段配置 revalidate/dynamic) - src/site/brand.tsx 站点配置 + src/site/home.tsx 站点首页(createMarketingLayout / createHomePage 工厂) - generate-site.mjs: 站点生成器(新增网站 = SITES 加条目,零 Core 修改) - start-all-sites.sh: 一键启动 3001-3005 - next-config.mjs: 底座统一 Next 配置工厂(next-intl + MDX + standalone) - 五站共享同一套 PostgreSQL / Better Auth / Admin(设计文档 §42) - 验证: 5 站 build OK / typecheck OK / 55 路由冒烟 200 / 品牌-内容-截图 差异确认 / 登录-投票-重复检测 e2e PASS
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
import { getRequestConfig } from "next-intl/server";
|
||||
import { notFound } from "next/navigation";
|
||||
import { locales, defaultLocale, type Locale } from "@aidir/core/i18n.config";
|
||||
|
||||
/** 站点品牌 SEO 文案覆盖(每个网站不同) */
|
||||
const brandMessages = {
|
||||
en: {
|
||||
seo: { home: {"title":"AI Stack — Find the Best AI Tools, Ranked by Real Users","description":"The professional AI tools directory. 1,000+ AI tools across 14 categories ranked by community votes, reviews and engagement.","ogImage":"/og-image.png"} },
|
||||
hero: { title: "AI Stack — Find the Best AI Tools, Ranked by Real Users", description: "The professional AI tools directory. 1,000+ AI tools across 14 categories ranked by community votes, reviews and engagement." },
|
||||
common: { brand: { name: "AI Stack", tagline: "The professional AI tools directory — ranked by the community." } },
|
||||
},
|
||||
zh: {
|
||||
seo: { home: {"title":"AI Stack — 由真实用户排名的 AI 工具目录","description":"专业 AI 工具导航:14 个分类、1000+ 工具,由社区投票、评论与互动数据实时排名。","ogImage":"/og-image.png"} },
|
||||
hero: { title: "AI Stack — 由真实用户排名的 AI 工具目录", description: "专业 AI 工具导航:14 个分类、1000+ 工具,由社区投票、评论与互动数据实时排名。" },
|
||||
common: { brand: { name: "AI Stack", tagline: "The professional AI tools directory — ranked by the community." } },
|
||||
},
|
||||
} as const;
|
||||
|
||||
export default getRequestConfig(async ({ requestLocale }) => {
|
||||
let locale = await requestLocale;
|
||||
if (!locale || !locales.includes(locale as Locale)) {
|
||||
locale = defaultLocale;
|
||||
}
|
||||
try {
|
||||
// 底座基础文案 + 站点品牌覆盖(浅合并到顶层命名空间)
|
||||
const base = (await import(`../../messages/${locale}.json`)).default;
|
||||
const override = brandMessages[locale as keyof typeof brandMessages];
|
||||
const messages = { ...base };
|
||||
for (const [ns, value] of Object.entries(override)) {
|
||||
messages[ns] = { ...(messages[ns] ?? {}), ...value };
|
||||
}
|
||||
return { locale, messages };
|
||||
} catch (error) {
|
||||
console.error("Error loading messages for locale:", locale, error);
|
||||
notFound();
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user