feat(dashboard): add i18n support with zh/en/ja/ko locales
- Add react-i18next + i18next + i18next-browser-languagedetector - Create i18n config (singleton import) with zh/en/ja/ko JSON locale files - Add language switcher Globe dropdown in Header topbar - Replace all hardcoded Chinese strings in: - Layout (Header, Sidebar, NavItem, Layout, constants) - Settings (index, AppearanceTab, SecurityTab, OtherTab, AboutTab) - Auth page (auth.tsx) - Search dialog (searchItems via useMemo + t()) - Restart overlay (getStatusConfig accepts t param) - Error boundary (ErrorFallback, ErrorDetails function components) - HTTP warning banner - localStorage key: maibot-locale - Compatible with Electron
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { Component } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import type { ErrorInfo, ReactNode } from 'react'
|
||||
import { AlertTriangle, RefreshCw, Home, ChevronDown, ChevronUp, Copy, Check, Bug } from 'lucide-react'
|
||||
import { Button } from '@/components/ui/button'
|
||||
@@ -65,6 +66,7 @@ function ErrorDetails({ error, errorInfo }: { error: Error; errorInfo: ErrorInfo
|
||||
const [isStackOpen, setIsStackOpen] = useState(true)
|
||||
const [isComponentStackOpen, setIsComponentStackOpen] = useState(false)
|
||||
const [copied, setCopied] = useState(false)
|
||||
const { t } = useTranslation()
|
||||
|
||||
const stackFrames = error.stack ? parseStackTrace(error.stack) : []
|
||||
|
||||
@@ -183,12 +185,12 @@ Time: ${new Date().toISOString()}
|
||||
{copied ? (
|
||||
<>
|
||||
<Check className="mr-2 h-4 w-4 text-green-500" />
|
||||
已复制到剪贴板
|
||||
{t('errorBoundary.copiedToClipboard')}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Copy className="mr-2 h-4 w-4" />
|
||||
复制错误信息
|
||||
{t('errorBoundary.copyError')}
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
@@ -204,6 +206,7 @@ function ErrorFallback({
|
||||
error: Error
|
||||
errorInfo: ErrorInfo | null
|
||||
}) {
|
||||
const { t } = useTranslation()
|
||||
const handleGoHome = () => {
|
||||
window.location.href = '/'
|
||||
}
|
||||
@@ -219,9 +222,9 @@ function ErrorFallback({
|
||||
<div className="mx-auto flex h-16 w-16 items-center justify-center rounded-full bg-red-100 dark:bg-red-900/30 mb-4">
|
||||
<AlertTriangle className="h-8 w-8 text-red-600 dark:text-red-400" />
|
||||
</div>
|
||||
<CardTitle className="text-2xl font-bold">页面出现了问题</CardTitle>
|
||||
<CardTitle className="text-2xl font-bold">{t('errorBoundary.title')}</CardTitle>
|
||||
<CardDescription className="text-base mt-2">
|
||||
应用程序遇到了意外错误。您可以尝试刷新页面或返回首页。
|
||||
{t('errorBoundary.description')}
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
|
||||
@@ -232,17 +235,17 @@ function ErrorFallback({
|
||||
<div className="flex flex-col sm:flex-row gap-2 pt-2">
|
||||
<Button onClick={handleRefresh} className="flex-1">
|
||||
<RefreshCw className="mr-2 h-4 w-4" />
|
||||
刷新页面
|
||||
{t('errorBoundary.refreshPage')}
|
||||
</Button>
|
||||
<Button onClick={handleGoHome} variant="outline" className="flex-1">
|
||||
<Home className="mr-2 h-4 w-4" />
|
||||
返回首页
|
||||
{t('errorBoundary.goHome')}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* 提示信息 */}
|
||||
<p className="text-xs text-center text-muted-foreground pt-2">
|
||||
如果问题持续存在,请将错误信息复制并反馈给开发者
|
||||
{t('errorBoundary.footer')}
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
Reference in New Issue
Block a user