i18n settings pages with clear titles

This commit is contained in:
CREDO23 2026-01-13 02:35:00 +02:00
parent 738e23b51a
commit ce62bef322
4 changed files with 78 additions and 50 deletions

View file

@ -13,6 +13,7 @@ import {
} from "lucide-react";
import { AnimatePresence, motion } from "motion/react";
import { useParams, useRouter } from "next/navigation";
import { useTranslations } from "next-intl";
import { useCallback, useEffect, useState } from "react";
import { LLMRoleManager } from "@/components/settings/llm-role-manager";
import { ModelConfigManager } from "@/components/settings/model-config-manager";
@ -23,28 +24,28 @@ import { cn } from "@/lib/utils";
interface SettingsNavItem {
id: string;
label: string;
description: string;
labelKey: string;
descriptionKey: string;
icon: LucideIcon;
}
const settingsNavItems: SettingsNavItem[] = [
{
id: "models",
label: "Agent Configs",
description: "LLM models with prompts & citations",
labelKey: "nav_agent_configs",
descriptionKey: "nav_agent_configs_desc",
icon: Bot,
},
{
id: "roles",
label: "Role Assignments",
description: "Assign configs to agent roles",
labelKey: "nav_role_assignments",
descriptionKey: "nav_role_assignments_desc",
icon: Brain,
},
{
id: "prompts",
label: "System Instructions",
description: "SearchSpace-wide AI instructions",
labelKey: "nav_system_instructions",
descriptionKey: "nav_system_instructions_desc",
icon: MessageSquare,
},
];
@ -62,6 +63,8 @@ function SettingsSidebar({
isOpen: boolean;
onClose: () => void;
}) {
const t = useTranslations("searchSpaceSettings");
const handleNavClick = (sectionId: string) => {
onSectionChange(sectionId);
onClose(); // Close sidebar on mobile after selection
@ -94,22 +97,28 @@ function SettingsSidebar({
isOpen ? "translate-x-0" : "-translate-x-full md:translate-x-0"
)}
>
{/* Header with back button */}
<div className="p-4 flex items-center justify-between">
<Button
variant="ghost"
onClick={onBackToApp}
className="flex-1 justify-start gap-3 h-11 px-3 hover:bg-muted group"
>
<div className="flex items-center justify-center w-8 h-8 rounded-lg bg-primary/10 group-hover:bg-primary/20 transition-colors">
<ArrowLeft className="h-4 w-4 text-primary" />
</div>
<span className="font-medium">Back to app</span>
</Button>
{/* Mobile close button */}
<Button variant="ghost" size="icon" onClick={onClose} className="md:hidden h-9 w-9">
<X className="h-5 w-5" />
</Button>
{/* Header with title */}
<div className="p-4 space-y-3">
<div className="flex items-center justify-between">
<Button
variant="ghost"
onClick={onBackToApp}
className="justify-start gap-3 h-11 px-3 hover:bg-muted group"
>
<div className="flex items-center justify-center w-8 h-8 rounded-lg bg-primary/10 group-hover:bg-primary/20 transition-colors">
<ArrowLeft className="h-4 w-4 text-primary" />
</div>
<span className="font-medium">{t("back_to_app")}</span>
</Button>
{/* Mobile close button */}
<Button variant="ghost" size="icon" onClick={onClose} className="md:hidden h-9 w-9">
<X className="h-5 w-5" />
</Button>
</div>
{/* Settings Title */}
<div className="px-3">
<h2 className="text-lg font-semibold text-foreground">{t("title")}</h2>
</div>
</div>
{/* Navigation Items */}
@ -159,9 +168,9 @@ function SettingsSidebar({
isActive ? "text-foreground" : "text-muted-foreground"
)}
>
{item.label}
{t(item.labelKey)}
</p>
<p className="text-xs text-muted-foreground/70 truncate">{item.description}</p>
<p className="text-xs text-muted-foreground/70 truncate">{t(item.descriptionKey)}</p>
</div>
<ChevronRight
className={cn(
@ -176,10 +185,6 @@ function SettingsSidebar({
})}
</nav>
{/* Footer */}
<div className="p-4">
<p className="text-xs text-muted-foreground text-center">Search Space Settings</p>
</div>
</aside>
</>
);
@ -194,6 +199,7 @@ function SettingsContent({
searchSpaceId: number;
onMenuClick: () => void;
}) {
const t = useTranslations("searchSpaceSettings");
const activeItem = settingsNavItems.find((item) => item.id === activeSection);
const Icon = activeItem?.icon || Settings;
@ -236,7 +242,7 @@ function SettingsContent({
</motion.div>
<div className="min-w-0">
<h1 className="text-lg md:text-2xl font-bold tracking-tight truncate">
{activeItem?.label}
{activeItem ? t(activeItem.labelKey) : ""}
</h1>
</div>
</div>

View file

@ -75,20 +75,27 @@ function UserSettingsSidebar({
isOpen ? "translate-x-0" : "-translate-x-full md:translate-x-0"
)}
>
<div className="flex items-center justify-between p-4">
<Button
variant="ghost"
onClick={onBackToApp}
className="group h-11 flex-1 justify-start gap-3 px-3 hover:bg-muted"
>
<div className="flex h-8 w-8 items-center justify-center rounded-lg bg-primary/10 transition-colors group-hover:bg-primary/20">
<ArrowLeft className="h-4 w-4 text-primary" />
</div>
<span className="font-medium">{t("back_to_app")}</span>
</Button>
<Button variant="ghost" size="icon" onClick={onClose} className="h-9 w-9 md:hidden">
<X className="h-5 w-5" />
</Button>
{/* Header with title */}
<div className="space-y-3 p-4">
<div className="flex items-center justify-between">
<Button
variant="ghost"
onClick={onBackToApp}
className="group h-11 justify-start gap-3 px-3 hover:bg-muted"
>
<div className="flex h-8 w-8 items-center justify-center rounded-lg bg-primary/10 transition-colors group-hover:bg-primary/20">
<ArrowLeft className="h-4 w-4 text-primary" />
</div>
<span className="font-medium">{t("back_to_app")}</span>
</Button>
<Button variant="ghost" size="icon" onClick={onClose} className="h-9 w-9 md:hidden">
<X className="h-5 w-5" />
</Button>
</div>
{/* Settings Title */}
<div className="px-3">
<h2 className="text-lg font-semibold text-foreground">{t("title")}</h2>
</div>
</div>
<nav className="flex-1 space-y-1 overflow-y-auto px-3 py-2">
@ -154,9 +161,6 @@ function UserSettingsSidebar({
})}
</nav>
<div className="p-4">
<p className="text-center text-xs text-muted-foreground">{t("footer")}</p>
</div>
</aside>
</>
);

View file

@ -105,7 +105,6 @@
"title": "User Settings",
"description": "Manage your account settings and API access",
"back_to_app": "Back to app",
"footer": "User Settings",
"api_key_nav_label": "API Key",
"api_key_nav_description": "Manage your API access token",
"api_key_title": "API Key",
@ -684,6 +683,16 @@
"server_error": "Server error",
"network_error": "Network error"
},
"searchSpaceSettings": {
"title": "Search Space Settings",
"back_to_app": "Back to app",
"nav_agent_configs": "Agent Configs",
"nav_agent_configs_desc": "LLM models with prompts & citations",
"nav_role_assignments": "Role Assignments",
"nav_role_assignments_desc": "Assign configs to agent roles",
"nav_system_instructions": "System Instructions",
"nav_system_instructions_desc": "SearchSpace-wide AI instructions"
},
"homepage": {
"hero_title_part1": "The AI Workspace",
"hero_title_part2": "Built for Teams",

View file

@ -105,7 +105,6 @@
"title": "用户设置",
"description": "管理您的账户设置和API访问",
"back_to_app": "返回应用",
"footer": "用户设置",
"api_key_nav_label": "API密钥",
"api_key_nav_description": "管理您的API访问令牌",
"api_key_title": "API密钥",
@ -678,6 +677,16 @@
"server_error": "服务器错误",
"network_error": "网络错误"
},
"searchSpaceSettings": {
"title": "搜索空间设置",
"back_to_app": "返回应用",
"nav_agent_configs": "代理配置",
"nav_agent_configs_desc": "LLM 模型配置提示词和引用",
"nav_role_assignments": "角色分配",
"nav_role_assignments_desc": "为代理角色分配配置",
"nav_system_instructions": "系统指令",
"nav_system_instructions_desc": "搜索空间级别的 AI 指令"
},
"homepage": {
"hero_title_part1": "AI 工作空间",
"hero_title_part2": "为团队而生",