mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-05 07:26:36 +08:00
feat(frontend): add next-intl bilingual i18n for core paths
Wire next-intl without locale routes, add zh-CN/en catalogs, language switcher, and migrate layout/auth/settings UI copy. Document i18n rules in AGENTS.md and keep static export builds working.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import Link from 'next/link';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
@@ -9,39 +10,40 @@ import {
|
||||
} from '@/components/ui/card';
|
||||
import { Bell, Key, Palette, UserRound } from 'lucide-react';
|
||||
|
||||
/* 设置项 */
|
||||
const settingsItems = [
|
||||
{
|
||||
title: '个人资料',
|
||||
description: '查看您的账户信息',
|
||||
icon: UserRound,
|
||||
href: '/settings/profile',
|
||||
category: '个人设置',
|
||||
},
|
||||
{
|
||||
title: '访问令牌 (AccessToken)',
|
||||
description: '管理用于 API 访问的个人 Token',
|
||||
icon: Key,
|
||||
href: '/settings/access-token',
|
||||
category: '个人设置',
|
||||
},
|
||||
{
|
||||
title: '通知设置',
|
||||
description: '设置您的通知偏好',
|
||||
icon: Bell,
|
||||
href: '/settings/notifications',
|
||||
category: '账户设置',
|
||||
},
|
||||
{
|
||||
title: '外观设置',
|
||||
description: '自定义界面主题 and 显示',
|
||||
icon: Palette,
|
||||
href: '/settings/appearance',
|
||||
category: '个人设置',
|
||||
},
|
||||
];
|
||||
|
||||
export default function SettingsPage() {
|
||||
const t = useTranslations('settings');
|
||||
|
||||
const settingsItems = [
|
||||
{
|
||||
title: t('items.profile'),
|
||||
description: t('items.profileDesc'),
|
||||
icon: UserRound,
|
||||
href: '/settings/profile',
|
||||
category: t('categories.personal'),
|
||||
},
|
||||
{
|
||||
title: t('items.accessToken'),
|
||||
description: t('items.accessTokenDesc'),
|
||||
icon: Key,
|
||||
href: '/settings/access-token',
|
||||
category: t('categories.personal'),
|
||||
},
|
||||
{
|
||||
title: t('items.notifications'),
|
||||
description: t('items.notificationsDesc'),
|
||||
icon: Bell,
|
||||
href: '/settings/notifications',
|
||||
category: t('categories.account'),
|
||||
},
|
||||
{
|
||||
title: t('items.appearance'),
|
||||
description: t('items.appearanceDesc'),
|
||||
icon: Palette,
|
||||
href: '/settings/appearance',
|
||||
category: t('categories.personal'),
|
||||
},
|
||||
];
|
||||
|
||||
const groupedSettings = settingsItems.reduce(
|
||||
(acc, item) => {
|
||||
if (!acc[item.category]) {
|
||||
@@ -55,7 +57,7 @@ export default function SettingsPage() {
|
||||
|
||||
return (
|
||||
<div className='space-y-6 py-6'>
|
||||
<div className='font-semibold text-lg'>设置</div>
|
||||
<div className='font-semibold text-lg'>{t('title')}</div>
|
||||
|
||||
{Object.entries(groupedSettings).map(([category, items]) => (
|
||||
<div key={category} className='space-y-4'>
|
||||
|
||||
+27
-16
@@ -1,5 +1,6 @@
|
||||
import type { Metadata } from 'next';
|
||||
import { Inter } from 'next/font/google';
|
||||
import { getLocale, getMessages, getTranslations } from 'next-intl/server';
|
||||
import { Toaster } from '@/components/ui/sonner';
|
||||
import { ThemeProvider } from '@/components/layout/theme-provider';
|
||||
import { CustomThemeProvider } from '@/lib/theme';
|
||||
@@ -7,8 +8,10 @@ import { BellRingProvider } from '@/contexts/bell-ring-context';
|
||||
import { NotificationSettingsProvider } from '@/contexts/notification-settings-context';
|
||||
import { UserProvider } from '@/contexts/user-context';
|
||||
import { AppQueryProvider } from '@/components/providers/query-provider';
|
||||
import { AppIntlProvider } from '@/components/providers/intl-provider';
|
||||
import { SiteTitleUpdater } from '@/components/providers/title-updater';
|
||||
import { RobotsMeta } from '@/components/layout/robots-meta';
|
||||
import type { AppLocale } from '@/i18n/config';
|
||||
import './globals.css';
|
||||
|
||||
const inter = Inter({
|
||||
@@ -17,19 +20,25 @@ const inter = Inter({
|
||||
display: 'swap',
|
||||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Wavelet Platform',
|
||||
description: '通用二次开发标准范式平台',
|
||||
};
|
||||
export async function generateMetadata(): Promise<Metadata> {
|
||||
const t = await getTranslations('metadata');
|
||||
return {
|
||||
title: t('title'),
|
||||
description: t('description'),
|
||||
};
|
||||
}
|
||||
|
||||
export default function RootLayout({
|
||||
export default async function RootLayout({
|
||||
children,
|
||||
}: Readonly<{
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
const locale = (await getLocale()) as AppLocale;
|
||||
const messages = await getMessages();
|
||||
|
||||
return (
|
||||
<html
|
||||
lang='zh-CN'
|
||||
lang={locale}
|
||||
className={`hide-scrollbar font-sans ${inter.variable}`}
|
||||
suppressHydrationWarning
|
||||
>
|
||||
@@ -42,16 +51,18 @@ export default function RootLayout({
|
||||
>
|
||||
<CustomThemeProvider>
|
||||
<AppQueryProvider>
|
||||
<SiteTitleUpdater />
|
||||
<RobotsMeta />
|
||||
<UserProvider>
|
||||
<NotificationSettingsProvider>
|
||||
<BellRingProvider>
|
||||
{children}
|
||||
<Toaster position='top-center' />
|
||||
</BellRingProvider>
|
||||
</NotificationSettingsProvider>
|
||||
</UserProvider>
|
||||
<AppIntlProvider locale={locale} messages={messages}>
|
||||
<SiteTitleUpdater />
|
||||
<RobotsMeta />
|
||||
<UserProvider>
|
||||
<NotificationSettingsProvider>
|
||||
<BellRingProvider>
|
||||
{children}
|
||||
<Toaster position='top-center' />
|
||||
</BellRingProvider>
|
||||
</NotificationSettingsProvider>
|
||||
</UserProvider>
|
||||
</AppIntlProvider>
|
||||
</AppQueryProvider>
|
||||
</CustomThemeProvider>
|
||||
</ThemeProvider>
|
||||
|
||||
Reference in New Issue
Block a user