mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-27 01:11:40 +00:00
feat: add internationalization (i18n) to web dashboard — English + Chinese (#9453)
Add a lightweight i18n system to the web dashboard with English (default) and Chinese language support. A language switcher with flag icons is placed in the header bar, allowing users to toggle between languages. The choice persists to localStorage. Implementation: - src/i18n/ — types, translation files (en.ts, zh.ts), React context + hook - LanguageSwitcher component shows the *other* language's flag as the toggle - I18nProvider wraps the app in main.tsx - All 8 pages + OAuth components updated to use t() translation calls - Zero new dependencies — pure React context + localStorage
This commit is contained in:
parent
19199cd38d
commit
a2ea237db2
19 changed files with 1715 additions and 977 deletions
275
web/src/i18n/en.ts
Normal file
275
web/src/i18n/en.ts
Normal file
|
|
@ -0,0 +1,275 @@
|
|||
import type { Translations } from "./types";
|
||||
|
||||
export const en: Translations = {
|
||||
common: {
|
||||
save: "Save",
|
||||
saving: "Saving...",
|
||||
cancel: "Cancel",
|
||||
close: "Close",
|
||||
delete: "Delete",
|
||||
refresh: "Refresh",
|
||||
retry: "Retry",
|
||||
search: "Search...",
|
||||
loading: "Loading...",
|
||||
create: "Create",
|
||||
creating: "Creating...",
|
||||
set: "Set",
|
||||
replace: "Replace",
|
||||
clear: "Clear",
|
||||
live: "Live",
|
||||
off: "Off",
|
||||
enabled: "enabled",
|
||||
disabled: "disabled",
|
||||
active: "active",
|
||||
inactive: "inactive",
|
||||
unknown: "unknown",
|
||||
untitled: "Untitled",
|
||||
none: "None",
|
||||
form: "Form",
|
||||
noResults: "No results",
|
||||
of: "of",
|
||||
page: "Page",
|
||||
msgs: "msgs",
|
||||
tools: "tools",
|
||||
match: "match",
|
||||
other: "Other",
|
||||
configured: "configured",
|
||||
removed: "removed",
|
||||
failedToToggle: "Failed to toggle",
|
||||
failedToRemove: "Failed to remove",
|
||||
failedToReveal: "Failed to reveal",
|
||||
collapse: "Collapse",
|
||||
expand: "Expand",
|
||||
general: "General",
|
||||
messaging: "Messaging",
|
||||
},
|
||||
|
||||
app: {
|
||||
brand: "Hermes Agent",
|
||||
brandShort: "HA",
|
||||
webUi: "Web UI",
|
||||
footer: {
|
||||
name: "Hermes Agent",
|
||||
org: "Nous Research",
|
||||
},
|
||||
nav: {
|
||||
status: "Status",
|
||||
sessions: "Sessions",
|
||||
analytics: "Analytics",
|
||||
logs: "Logs",
|
||||
cron: "Cron",
|
||||
skills: "Skills",
|
||||
config: "Config",
|
||||
keys: "Keys",
|
||||
},
|
||||
},
|
||||
|
||||
status: {
|
||||
agent: "Agent",
|
||||
gateway: "Gateway",
|
||||
activeSessions: "Active Sessions",
|
||||
recentSessions: "Recent Sessions",
|
||||
connectedPlatforms: "Connected Platforms",
|
||||
running: "Running",
|
||||
starting: "Starting",
|
||||
failed: "Failed",
|
||||
stopped: "Stopped",
|
||||
connected: "Connected",
|
||||
disconnected: "Disconnected",
|
||||
error: "Error",
|
||||
notRunning: "Not running",
|
||||
startFailed: "Start failed",
|
||||
pid: "PID",
|
||||
noneRunning: "None",
|
||||
gatewayFailedToStart: "Gateway failed to start",
|
||||
lastUpdate: "Last update",
|
||||
platformError: "error",
|
||||
platformDisconnected: "disconnected",
|
||||
},
|
||||
|
||||
sessions: {
|
||||
title: "Sessions",
|
||||
searchPlaceholder: "Search message content...",
|
||||
noSessions: "No sessions yet",
|
||||
noMatch: "No sessions match your search",
|
||||
startConversation: "Start a conversation to see it here",
|
||||
noMessages: "No messages",
|
||||
untitledSession: "Untitled session",
|
||||
deleteSession: "Delete session",
|
||||
previousPage: "Previous page",
|
||||
nextPage: "Next page",
|
||||
roles: {
|
||||
user: "User",
|
||||
assistant: "Assistant",
|
||||
system: "System",
|
||||
tool: "Tool",
|
||||
},
|
||||
},
|
||||
|
||||
analytics: {
|
||||
period: "Period:",
|
||||
totalTokens: "Total Tokens",
|
||||
totalSessions: "Total Sessions",
|
||||
apiCalls: "API Calls",
|
||||
dailyTokenUsage: "Daily Token Usage",
|
||||
dailyBreakdown: "Daily Breakdown",
|
||||
perModelBreakdown: "Per-Model Breakdown",
|
||||
input: "Input",
|
||||
output: "Output",
|
||||
total: "Total",
|
||||
noUsageData: "No usage data for this period",
|
||||
startSession: "Start a session to see analytics here",
|
||||
date: "Date",
|
||||
model: "Model",
|
||||
tokens: "Tokens",
|
||||
perDayAvg: "/day avg",
|
||||
acrossModels: "across {count} models",
|
||||
inOut: "{input} in / {output} out",
|
||||
},
|
||||
|
||||
logs: {
|
||||
title: "Logs",
|
||||
autoRefresh: "Auto-refresh",
|
||||
file: "File",
|
||||
level: "Level",
|
||||
component: "Component",
|
||||
lines: "Lines",
|
||||
noLogLines: "No log lines found",
|
||||
},
|
||||
|
||||
cron: {
|
||||
newJob: "New Cron Job",
|
||||
nameOptional: "Name (optional)",
|
||||
namePlaceholder: "e.g. Daily summary",
|
||||
prompt: "Prompt",
|
||||
promptPlaceholder: "What should the agent do on each run?",
|
||||
schedule: "Schedule (cron expression)",
|
||||
schedulePlaceholder: "0 9 * * *",
|
||||
deliverTo: "Deliver to",
|
||||
scheduledJobs: "Scheduled Jobs",
|
||||
noJobs: "No cron jobs configured. Create one above.",
|
||||
last: "Last",
|
||||
next: "Next",
|
||||
pause: "Pause",
|
||||
resume: "Resume",
|
||||
triggerNow: "Trigger now",
|
||||
delivery: {
|
||||
local: "Local",
|
||||
telegram: "Telegram",
|
||||
discord: "Discord",
|
||||
slack: "Slack",
|
||||
email: "Email",
|
||||
},
|
||||
},
|
||||
|
||||
skills: {
|
||||
title: "Skills",
|
||||
searchPlaceholder: "Search skills and toolsets...",
|
||||
enabledOf: "{enabled}/{total} enabled",
|
||||
all: "All",
|
||||
noSkills: "No skills found. Skills are loaded from ~/.hermes/skills/",
|
||||
noSkillsMatch: "No skills match your search or filter.",
|
||||
skillCount: "{count} skill{s}",
|
||||
noDescription: "No description available.",
|
||||
toolsets: "Toolsets",
|
||||
noToolsetsMatch: "No toolsets match the search.",
|
||||
setupNeeded: "Setup needed",
|
||||
disabledForCli: "Disabled for CLI",
|
||||
more: "+{count} more",
|
||||
},
|
||||
|
||||
config: {
|
||||
configPath: "~/.hermes/config.yaml",
|
||||
exportConfig: "Export config as JSON",
|
||||
importConfig: "Import config from JSON",
|
||||
resetDefaults: "Reset to defaults",
|
||||
rawYaml: "Raw YAML Configuration",
|
||||
searchResults: "Search Results",
|
||||
fields: "field{s}",
|
||||
noFieldsMatch: 'No fields match "{query}"',
|
||||
configSaved: "Configuration saved",
|
||||
yamlConfigSaved: "YAML config saved",
|
||||
failedToSave: "Failed to save",
|
||||
failedToSaveYaml: "Failed to save YAML",
|
||||
failedToLoadRaw: "Failed to load raw config",
|
||||
configImported: "Config imported — review and save",
|
||||
invalidJson: "Invalid JSON file",
|
||||
categories: {
|
||||
general: "General",
|
||||
agent: "Agent",
|
||||
terminal: "Terminal",
|
||||
display: "Display",
|
||||
delegation: "Delegation",
|
||||
memory: "Memory",
|
||||
compression: "Compression",
|
||||
security: "Security",
|
||||
browser: "Browser",
|
||||
voice: "Voice",
|
||||
tts: "Text-to-Speech",
|
||||
stt: "Speech-to-Text",
|
||||
logging: "Logging",
|
||||
discord: "Discord",
|
||||
auxiliary: "Auxiliary",
|
||||
},
|
||||
},
|
||||
|
||||
env: {
|
||||
description: "Manage API keys and secrets stored in",
|
||||
changesNote: "Changes are saved to disk immediately. Active sessions pick up new keys automatically.",
|
||||
hideAdvanced: "Hide Advanced",
|
||||
showAdvanced: "Show Advanced",
|
||||
llmProviders: "LLM Providers",
|
||||
providersConfigured: "{configured} of {total} providers configured",
|
||||
getKey: "Get key",
|
||||
notConfigured: "{count} not configured",
|
||||
notSet: "Not set",
|
||||
keysCount: "{count} key{s}",
|
||||
enterValue: "Enter value...",
|
||||
replaceCurrentValue: "Replace current value ({preview})",
|
||||
showValue: "Show real value",
|
||||
hideValue: "Hide value",
|
||||
},
|
||||
|
||||
oauth: {
|
||||
title: "Provider Logins (OAuth)",
|
||||
providerLogins: "Provider Logins (OAuth)",
|
||||
description: "{connected} of {total} OAuth providers connected. Login flows currently run via the CLI; click Copy command and paste into a terminal to set up.",
|
||||
connected: "Connected",
|
||||
expired: "Expired",
|
||||
notConnected: "Not connected. Run {command} in a terminal.",
|
||||
runInTerminal: "in a terminal.",
|
||||
noProviders: "No OAuth-capable providers detected.",
|
||||
login: "Login",
|
||||
disconnect: "Disconnect",
|
||||
managedExternally: "Managed externally",
|
||||
copied: "Copied ✓",
|
||||
cli: "CLI",
|
||||
copyCliCommand: "Copy CLI command (for external / fallback)",
|
||||
connect: "Connect",
|
||||
sessionExpires: "Session expires in {time}",
|
||||
initiatingLogin: "Initiating login flow…",
|
||||
exchangingCode: "Exchanging code for tokens…",
|
||||
connectedClosing: "Connected! Closing…",
|
||||
loginFailed: "Login failed.",
|
||||
sessionExpired: "Session expired. Click Retry to start a new login.",
|
||||
reOpenAuth: "Re-open auth page",
|
||||
reOpenVerification: "Re-open verification page",
|
||||
submitCode: "Submit code",
|
||||
pasteCode: "Paste authorization code (with #state suffix is fine)",
|
||||
waitingAuth: "Waiting for you to authorize in the browser…",
|
||||
enterCodePrompt: "A new tab opened. Enter this code if prompted:",
|
||||
pkceStep1: "A new tab opened to claude.ai. Sign in and click Authorize.",
|
||||
pkceStep2: "Copy the authorization code shown after authorizing.",
|
||||
pkceStep3: "Paste it below and submit.",
|
||||
flowLabels: {
|
||||
pkce: "Browser login (PKCE)",
|
||||
device_code: "Device code",
|
||||
external: "External CLI",
|
||||
},
|
||||
expiresIn: "expires in {time}",
|
||||
},
|
||||
|
||||
language: {
|
||||
switchTo: "Switch to Chinese",
|
||||
},
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue