feat(frontend): 控制台 next-intl 中英双语

接入无 URL 前缀的 zh-CN/en,顶栏与外观设置可切换语言;选择写入 cookie 后刷新生效。
This commit is contained in:
ryan
2026-08-16 16:49:16 +08:00
parent 64fbaa7ef1
commit 5a8722ff07
219 changed files with 21437 additions and 5212 deletions
@@ -1,5 +1,7 @@
'use client';
import { useTranslations } from 'next-intl';
import {
Dialog,
DialogContent,
@@ -24,29 +26,33 @@ export function IPGroupTestDialog({
result,
onOpenChange,
}: IPGroupTestDialogProps) {
const t = useTranslations('ipGroups.testDialog');
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className='max-w-2xl'>
<DialogHeader>
<DialogTitle>自动规则测试结果</DialogTitle>
<DialogDescription>
基于当前自动配置 JSON 对请求日志进行回看测试。
</DialogDescription>
<DialogTitle>{t('title')}</DialogTitle>
<DialogDescription>{t('description')}</DialogDescription>
</DialogHeader>
{loading ? (
<p className='text-sm text-muted-foreground py-6 text-center'>
测试中...
{t('testing')}
</p>
) : result ? (
<div className='space-y-4'>
<div className='rounded-lg border border-dashed p-4 text-sm'>
<p>
回看 {result.lookback} · 规则 {result.rule_count} 条 · 命中{' '}
{result.matched_count} 个 IP
{t('summary', {
lookback: result.lookback,
rules: result.rule_count,
matched: result.matched_count,
})}
</p>
<p className='text-xs text-muted-foreground mt-1'>
测试时间:{new Date(result.tested_at).toLocaleString()}
{t('testedAt', {
time: new Date(result.tested_at).toLocaleString(),
})}
</p>
</div>
{result.matched_count > 0 ? (
@@ -54,20 +60,18 @@ export function IPGroupTestDialog({
{result.matched_ips.join('\n')}
</pre>
) : (
<p className='text-sm text-muted-foreground'>
当前没有匹配到任何 IP。
</p>
<p className='text-sm text-muted-foreground'>{t('noMatch')}</p>
)}
</div>
) : (
<p className='text-sm text-muted-foreground py-6 text-center'>
暂无测试结果。
{t('empty')}
</p>
)}
<DialogFooter>
<Button type='button' onClick={() => onOpenChange(false)}>
关闭
{t('close')}
</Button>
</DialogFooter>
</DialogContent>