settings framework and section metadata keyed (487 -> 425)

SettingsSection now carries titleKey/descriptionKey instead of title/description, and
the sidebar and content pane resolve them. The section arrays are module-level consts
holding JSX content, so they cannot call a hook — the data holds keys and the renderers
translate. Sidebar search matches the RESOLVED words, so it works in the language on
screen.

Capital K in titleKey is load-bearing: docs-check-settings.ts greps key:\s*'…' for
route segments, and a lowercase title_key would have fed it twenty bogus paths.
Verified 0 bogus, 26 declared, 20 offered, 0 missing.

Section titles now share one key with the Spotlight rows that name the same section,
per 'one key per meaning'. Two casings had to converge, so Settings shows Spotlight's:
'Change Password' now reads 'Change password'.

Settings sidebar search placeholder was 'Search...'; it is now 'Search settings…',
which is what the skeleton catalog already said and what distinguishes it from the
global Spotlight.
This commit is contained in:
2026-08-23 04:46:07 +00:00
parent 926034750f
commit c3c62828e3
8 changed files with 301 additions and 153 deletions
+75 -20
View File
@@ -50,74 +50,129 @@
"sections": {
"profile": {
"label": "Profile",
"hint": "avatar, name, email"
"hint": "avatar, name, email",
"description": "Avatar, name, and email"
},
"changePassword": {
"label": "Change password"
"label": "Change password",
"description": "Update your password"
},
"apiKeys": {
"label": "API keys",
"hint": "keys that sign in as you"
"hint": "keys that sign in as you",
"description": "Keys that sign in as you, revocable one at a time"
},
"languages": {
"label": "Languages",
"hint": "spoken and translation"
"hint": "spoken and translation",
"description": "Spoken, default, and translation"
},
"voice": {
"label": "Voice",
"hint": "text-to-speech"
"hint": "text-to-speech",
"description": "Text-to-speech voice preference"
},
"dock": {
"label": "Dock",
"hint": "choose and reorder"
"hint": "choose and reorder",
"description": "Choose and reorder dock items"
},
"myModels": {
"label": "My Models"
"label": "My Models",
"description": "Show or hide models for yourself"
},
"channelModels": {
"label": "Channel Models"
"label": "Channel Models",
"description": "Models reachable by non-owner accounts"
},
"defaultModels": {
"label": "Default Models"
"label": "Default Models",
"description": "Default models for chat, projects, and tasks"
},
"providers": {
"label": "Providers",
"hint": "harnesses"
"hint": "harnesses",
"description": "Remote and local AI providers"
},
"tts": {
"label": "Text to Speech"
"label": "Text to Speech",
"description": "TTS provider and voice"
},
"stt": {
"label": "Speech to Text"
"label": "Speech to Text",
"description": "Whisper server URL"
},
"ocr": {
"label": "OCR"
"label": "OCR",
"description": "Vision model for text extraction"
},
"maintenance": {
"label": "Rebuild & restart",
"hint": "maintenance"
"hint": "maintenance",
"description": "Load changes without a terminal"
},
"smtp": {
"label": "SMTP",
"hint": "outgoing mail"
"hint": "outgoing mail",
"description": "Email delivery provider"
},
"googleOauth": {
"label": "Google OAuth"
"label": "Google OAuth",
"description": "Client ID and secret for Google APIs"
},
"apify": {
"label": "Apify"
"label": "Apify",
"description": "API token for web scraping actors"
},
"davSync": {
"label": "Calendar & Contacts sync",
"hint": "app passwords"
"hint": "app passwords",
"description": "Per-device passwords for CalDAV/CardDAV clients"
},
"accounts": {
"label": "Accounts",
"hint": "users"
"hint": "users",
"description": "Who has access, and as what"
},
"permissions": {
"label": "Permissions"
"label": "Permissions",
"description": "What each role can reach"
}
},
"searchPlaceholder": "Search settings…",
"selectSection": "Select a section",
"groups": {
"models": "Models",
"defaults": "Defaults",
"providers": "Providers",
"ai": "AI",
"maintenance": "Maintenance",
"email": "Email"
},
"nav": {
"profile": "Profile",
"ai": "AI",
"system": "System",
"integrations": "Integrations",
"users": "Users"
},
"ai": {
"noModels": "No models available. Configure API keys in Providers.",
"dragToShow": "Drag models here to show",
"allVisible": "All models visible",
"dragToEnable": "Drag models here to enable",
"allEnabled": "All models enabled",
"visible": "Visible",
"hidden": "Hidden",
"enabled": "Enabled",
"disabled": "Disabled",
"refresh": "Refresh models from providers",
"refreshed": "Models refreshed",
"refreshFailed": "Failed to refresh models"
},
"integrations": {
"enterprise": "Enterprise",
"personal": "Personal"
}
},
"header": {
+75 -20
View File
@@ -50,74 +50,129 @@
"sections": {
"profile": {
"label": "Perfil",
"hint": "avatar, nome, email"
"hint": "avatar, nome, email",
"description": "Avatar, nome e email"
},
"changePassword": {
"label": "Alterar palavra-passe"
"label": "Alterar palavra-passe",
"description": "Atualize a sua palavra-passe"
},
"apiKeys": {
"label": "Chaves de API",
"hint": "chaves que iniciam sessão como você"
"hint": "chaves que iniciam sessão como você",
"description": "Chaves que iniciam sessão como você, revogáveis uma a uma"
},
"languages": {
"label": "Idiomas",
"hint": "falados e tradução"
"hint": "falados e tradução",
"description": "Falados, predefinido e tradução"
},
"voice": {
"label": "Voz",
"hint": "conversão de texto em fala"
"hint": "conversão de texto em fala",
"description": "Preferência de voz para conversão de texto em fala"
},
"dock": {
"label": "Dock",
"hint": "escolher e reordenar"
"hint": "escolher e reordenar",
"description": "Escolher e reordenar os itens do dock"
},
"myModels": {
"label": "Os meus modelos"
"label": "Os meus modelos",
"description": "Mostrar ou ocultar modelos para si"
},
"channelModels": {
"label": "Modelos do canal"
"label": "Modelos do canal",
"description": "Modelos acessíveis a contas que não são do proprietário"
},
"defaultModels": {
"label": "Modelos predefinidos"
"label": "Modelos predefinidos",
"description": "Modelos predefinidos para chat, projetos e tarefas"
},
"providers": {
"label": "Fornecedores",
"hint": "harnesses"
"hint": "harnesses",
"description": "Fornecedores de IA remotos e locais"
},
"tts": {
"label": "Texto para fala"
"label": "Texto para fala",
"description": "Fornecedor de TTS e voz"
},
"stt": {
"label": "Fala para texto"
"label": "Fala para texto",
"description": "URL do servidor Whisper"
},
"ocr": {
"label": "OCR"
"label": "OCR",
"description": "Modelo de visão para extração de texto"
},
"maintenance": {
"label": "Reconstruir e reiniciar",
"hint": "manutenção"
"hint": "manutenção",
"description": "Carregar alterações sem um terminal"
},
"smtp": {
"label": "SMTP",
"hint": "correio a enviar"
"hint": "correio a enviar",
"description": "Fornecedor de entrega de email"
},
"googleOauth": {
"label": "Google OAuth"
"label": "Google OAuth",
"description": "Client ID e secret para as APIs Google"
},
"apify": {
"label": "Apify"
"label": "Apify",
"description": "Token de API para atores de web scraping"
},
"davSync": {
"label": "Sincronização de Calendário e Contactos",
"hint": "palavras-passe de aplicação"
"hint": "palavras-passe de aplicação",
"description": "Palavras-passe por dispositivo para clientes CalDAV/CardDAV"
},
"accounts": {
"label": "Contas",
"hint": "utilizadores"
"hint": "utilizadores",
"description": "Quem tem acesso, e como"
},
"permissions": {
"label": "Permissões"
"label": "Permissões",
"description": "O que cada função pode alcançar"
}
},
"searchPlaceholder": "Pesquisar definições…",
"selectSection": "Selecione uma secção",
"groups": {
"models": "Modelos",
"defaults": "Predefinições",
"providers": "Fornecedores",
"ai": "IA",
"maintenance": "Manutenção",
"email": "Email"
},
"nav": {
"profile": "Perfil",
"ai": "IA",
"system": "Sistema",
"integrations": "Integrações",
"users": "Utilizadores"
},
"ai": {
"noModels": "Nenhum modelo disponível. Configure as chaves de API em Fornecedores.",
"dragToShow": "Arraste modelos para aqui para os mostrar",
"allVisible": "Todos os modelos visíveis",
"dragToEnable": "Arraste modelos para aqui para os ativar",
"allEnabled": "Todos os modelos ativados",
"visible": "Visíveis",
"hidden": "Ocultos",
"enabled": "Ativados",
"disabled": "Desativados",
"refresh": "Atualizar modelos a partir dos fornecedores",
"refreshed": "Modelos atualizados",
"refreshFailed": "Falha ao atualizar modelos"
},
"integrations": {
"enterprise": "Empresa",
"personal": "Pessoal"
}
},
"header": {