feat: add German translation and make UI elements translatable (#190)
Co-authored-by: David Work <davidwork@MBP-von-David.fritz.box>
This commit is contained in:
236
static/i18n.js
236
static/i18n.js
@@ -136,6 +136,232 @@ const LOCALES = {
|
||||
login_btn: 'Sign in',
|
||||
login_invalid_pw: 'Invalid password',
|
||||
login_conn_failed: 'Connection failed',
|
||||
// Sidebar & Tabs
|
||||
tab_chat: 'Chat',
|
||||
tab_tasks: 'Tasks',
|
||||
tab_skills: 'Skills',
|
||||
tab_memory: 'Memory',
|
||||
tab_workspaces: 'Spaces',
|
||||
tab_profiles: 'Profiles',
|
||||
tab_todos: 'Todos',
|
||||
new_conversation: 'New conversation',
|
||||
filter_conversations: 'Filter conversations...',
|
||||
scheduled_jobs: 'Scheduled jobs',
|
||||
new_job: 'New job',
|
||||
loading: 'Loading...',
|
||||
search_skills: 'Search skills...',
|
||||
new_skill: 'New skill',
|
||||
personal_memory: 'Personal memory',
|
||||
current_task_list: 'Current task list',
|
||||
workspace_desc: 'Add and switch workspaces for your sessions.',
|
||||
new_profile: 'New profile',
|
||||
transcript: 'Transcript',
|
||||
download_transcript: 'Download as Markdown',
|
||||
import: 'Import',
|
||||
// Settings detail
|
||||
settings_label_sound: 'Notification sound',
|
||||
settings_desc_sound: 'Play a sound when the assistant finishes a response.',
|
||||
settings_label_notifications: 'Browser notifications',
|
||||
settings_desc_notifications: 'Show a system notification when a response completes while the tab is in the background.',
|
||||
settings_desc_token_usage: 'Displays input/output token count below each assistant reply. Also toggled with /usage.',
|
||||
settings_desc_cli_sessions: 'Merges sessions from the Hermes CLI (state.db) into the session list. Click a CLI session to import it and continue the conversation.',
|
||||
settings_desc_sync_insights: 'Mirrors WebUI token usage to state.db so hermes /insights includes browser session data. Off by default.',
|
||||
settings_desc_check_updates: 'Show a banner when newer versions of the WebUI or Agent are available. Runs a background git fetch periodically.',
|
||||
settings_desc_bot_name: 'Display name for the assistant throughout the UI. Defaults to Hermes.',
|
||||
settings_desc_password: 'Enter a new password to set or change it. Leave blank to keep current setting.',
|
||||
password_placeholder: 'Enter new password…',
|
||||
disable_auth: 'Disable Auth',
|
||||
sign_out: 'Sign Out',
|
||||
cancel: 'Cancel',
|
||||
create_job: 'Create job',
|
||||
save_skill: 'Save skill',
|
||||
editing: 'Editing',
|
||||
// Empty state
|
||||
empty_title: 'What can I help with?',
|
||||
empty_subtitle: 'Ask anything, run commands, explore files, or manage your scheduled tasks.',
|
||||
suggest_files: 'What files are in this workspace?',
|
||||
suggest_schedule: "What's on my schedule today?",
|
||||
suggest_plan: 'Help me plan a small project.',
|
||||
},
|
||||
|
||||
de: {
|
||||
_lang: 'de',
|
||||
_label: 'Deutsch',
|
||||
_speech: 'de-DE',
|
||||
// boot.js
|
||||
cancelling: 'Abbrechen\u2026',
|
||||
cancel_failed: 'Abbrechen fehlgeschlagen: ',
|
||||
mic_denied: 'Mikrofonzugriff verweigert. Überprüfen Sie die Browserberechtigungen.',
|
||||
mic_no_speech: 'Keine Sprache erkannt. Versuchen Sie es erneut.',
|
||||
mic_network: 'Spracherkennung nicht verfügbar.',
|
||||
mic_error: 'Spracheingabefehler: ',
|
||||
session_imported: 'Sitzung importiert',
|
||||
import_failed: 'Import fehlgeschlagen: ',
|
||||
import_invalid_json: 'Ungültiges JSON',
|
||||
image_pasted: 'Bild eingefügt: ',
|
||||
// messages.js
|
||||
edit_message: 'Nachricht bearbeiten',
|
||||
regenerate: 'Antwort regenerieren',
|
||||
copy: 'Kopieren',
|
||||
copied: 'Kopiert!',
|
||||
you: 'Du',
|
||||
thinking: 'Nachdenken',
|
||||
expand_all: 'Alle ausklappen',
|
||||
collapse_all: 'Alle einklappen',
|
||||
edit_failed: 'Bearbeiten fehlgeschlagen: ',
|
||||
regen_failed: 'Regeneration fehlgeschlagen: ',
|
||||
reconnect_active: 'Eine Antwort wird noch generiert. Neu laden, wenn bereit?',
|
||||
reconnect_finished: 'Eine Antwort war in Arbeit, als Sie zuletzt gegangen sind. Nachrichten könnten aktualisiert worden sein.',
|
||||
// approval card
|
||||
approval_heading: 'Genehmigung erforderlich',
|
||||
approval_desc_prefix: 'Gefährlicher Befehl erkannt',
|
||||
approval_btn_once: 'Einmal zulassen',
|
||||
approval_btn_once_title: 'Diesen einen Befehl zulassen (Enter)',
|
||||
approval_btn_session: 'Sitzung zulassen',
|
||||
approval_btn_session_title: 'Für diese Konversationssitzung zulassen',
|
||||
approval_btn_always: 'Immer zulassen',
|
||||
approval_btn_always_title: 'Dieses Befehlsmuster immer zulassen',
|
||||
approval_btn_deny: 'Ablehnen',
|
||||
approval_btn_deny_title: 'Ablehnen \u2014 diesen Befehl nicht ausführen',
|
||||
approval_responding: 'Antwortet\u2026',
|
||||
untitled: 'Unbenannt',
|
||||
n_messages: (n) => `${n} Nachrichten`,
|
||||
model_unavailable: ' (nicht verfügbar)',
|
||||
model_unavailable_title: 'Dieses Modell ist nicht mehr in Ihrer aktuellen Provider-Liste',
|
||||
// commands.js
|
||||
cmd_help: 'Verfügbare Befehle auflisten',
|
||||
cmd_clear: 'Konversationsverlauf löschen',
|
||||
cmd_compact: 'Kontext komprimieren',
|
||||
cmd_model: 'Modell wechseln (z.B. /model gpt-4o)',
|
||||
cmd_workspace: 'Workspace nach Namen wechseln',
|
||||
cmd_new: 'Neue Chat-Sitzung starten',
|
||||
cmd_usage: 'Token-Verbrauchsanzeige umschalten',
|
||||
cmd_theme: 'Theme wechseln (dark/light/slate/solarized/monokai/nord/oled)',
|
||||
cmd_personality: 'Agenten-Persönlichkeit wechseln',
|
||||
available_commands: 'Verfügbare Befehle:',
|
||||
type_slash: 'Tippe / für Befehle',
|
||||
conversation_cleared: 'Konversation gelöscht',
|
||||
model_usage: 'Nutzung: /model <name>',
|
||||
no_model_match: 'Kein Modell gefunden für "',
|
||||
switched_to: 'Gewechselt zu ',
|
||||
workspace_usage: 'Nutzung: /workspace <name>',
|
||||
no_workspace_match: 'Kein Workspace gefunden für "',
|
||||
switched_workspace: 'Gewechselt zu Workspace: ',
|
||||
workspace_switch_failed: 'Workspace-Wechsel fehlgeschlagen: ',
|
||||
new_session: 'Neue Sitzung erstellt',
|
||||
compressing: 'Kontext-Komprimierung wird angefordert...',
|
||||
token_usage_on: 'Token-Verbrauch an',
|
||||
token_usage_off: 'Token-Verbrauch aus',
|
||||
theme_usage: 'Nutzung: /theme ',
|
||||
theme_set: 'Theme: ',
|
||||
no_active_session: 'Keine aktive Sitzung',
|
||||
no_personalities: 'Keine Persönlichkeiten gefunden (füge sie in ~/.hermes/personalities/ hinzu)',
|
||||
available_personalities: 'Verfügbare Persönlichkeiten:',
|
||||
personality_switch_hint: '\n\nNutze `/personality <name>` zum Wechseln, oder `/personality none` zum Löschen.',
|
||||
personalities_load_failed: 'Fehler beim Laden der Persönlichkeiten',
|
||||
personality_cleared: 'Persönlichkeit gelöscht',
|
||||
personality_set: 'Persönlichkeit: ',
|
||||
failed_colon: 'Fehlgeschlagen: ',
|
||||
// ui.js
|
||||
no_workspace: 'Kein Workspace',
|
||||
// workspace.js
|
||||
unsaved_confirm: 'Sie haben ungespeicherte Änderungen in der Vorschau. Verwerfen und fortfahren?',
|
||||
save: 'Speichern',
|
||||
edit: 'Bearbeiten',
|
||||
save_title: 'Änderungen speichern',
|
||||
edit_title: 'Diese Datei bearbeiten',
|
||||
saved: 'Gespeichert',
|
||||
save_failed: 'Speichern fehlgeschlagen: ',
|
||||
image_load_failed: 'Bild konnte nicht geladen werden',
|
||||
file_open_failed: 'Datei konnte nicht geöffnet werden',
|
||||
downloading: (name) => `Lade ${name} herunter\u2026`,
|
||||
double_click_rename: 'Doppelklick zum Umbenennen',
|
||||
renamed_to: 'Umbenannt in ',
|
||||
rename_failed: 'Umbenennen fehlgeschlagen: ',
|
||||
delete_title: 'Löschen',
|
||||
delete_confirm: (name) => `${name} löschen?`,
|
||||
deleted: 'Gelöscht ',
|
||||
delete_failed: 'Löschen fehlgeschlagen: ',
|
||||
new_file_prompt: 'Neuer Dateiname (z.B. notes.md):',
|
||||
created: 'Erstellt ',
|
||||
create_failed: 'Erstellen fehlgeschlagen: ',
|
||||
new_folder_prompt: 'Neuer Ordnername:',
|
||||
folder_created: 'Ordner erstellt ',
|
||||
folder_create_failed: 'Ordner erstellen fehlgeschlagen: ',
|
||||
remove_title: 'Entfernen',
|
||||
empty_dir: '(leer)',
|
||||
upload_failed: 'Upload fehlgeschlagen: ',
|
||||
all_uploads_failed: (n) => `Alle ${n} Upload(s) fehlgeschlagen`,
|
||||
// settings panel
|
||||
settings_title: 'Einstellungen',
|
||||
settings_save_btn: 'Einstellungen speichern',
|
||||
settings_label_model: 'Standard-Modell',
|
||||
settings_label_send_key: 'Sende-Taste',
|
||||
settings_label_theme: 'Theme',
|
||||
settings_label_language: 'Sprache',
|
||||
settings_label_token_usage: 'Token-Verbrauch anzeigen',
|
||||
settings_label_cli_sessions: 'CLI-Sitzungen anzeigen',
|
||||
settings_label_sync_insights: 'Mit Insights synchronisieren',
|
||||
settings_label_check_updates: 'Nach Updates suchen',
|
||||
settings_label_bot_name: 'Assistenten-Name',
|
||||
settings_label_password: 'Zugangspasswort',
|
||||
settings_saved: 'Einstellungen gespeichert',
|
||||
settings_save_failed: 'Speichern fehlgeschlagen: ',
|
||||
settings_load_failed: 'Laden der Einstellungen fehlgeschlagen: ',
|
||||
settings_saved_pw: 'Einstellungen gespeichert (Passwort gesetzt \u2014 Login jetzt erforderlich)',
|
||||
// login page
|
||||
login_title: 'Anmelden',
|
||||
login_subtitle: 'Geben Sie Ihr Passwort ein, um fortzufahren',
|
||||
login_placeholder: 'Passwort',
|
||||
login_btn: 'Anmelden',
|
||||
login_invalid_pw: 'Ungültiges Passwort',
|
||||
login_conn_failed: 'Verbindung fehlgeschlagen',
|
||||
// Sidebar & Tabs
|
||||
tab_chat: 'Chat',
|
||||
tab_tasks: 'Aufgaben',
|
||||
tab_skills: 'Skills',
|
||||
tab_memory: 'Gedächtnis',
|
||||
tab_workspaces: 'Spaces',
|
||||
tab_profiles: 'Profile',
|
||||
tab_todos: 'Todos',
|
||||
new_conversation: 'Neuer Chat',
|
||||
filter_conversations: 'Chats filtern...',
|
||||
scheduled_jobs: 'Geplante Aufgaben',
|
||||
new_job: 'Neuer Job',
|
||||
loading: 'Lädt...',
|
||||
search_skills: 'Skills suchen...',
|
||||
new_skill: 'Neuer Skill',
|
||||
personal_memory: 'Persönliches Gedächtnis',
|
||||
current_task_list: 'Aktuelle Aufgabenliste',
|
||||
workspace_desc: 'Workspaces hinzufügen und wechseln.',
|
||||
new_profile: 'Neues Profil',
|
||||
transcript: 'Protokoll',
|
||||
download_transcript: 'Als Markdown herunterladen',
|
||||
import: 'Importieren',
|
||||
// Settings detail
|
||||
settings_label_sound: 'Benachrichtigungston',
|
||||
settings_desc_sound: 'Spielt einen Ton ab, wenn der Assistent eine Antwort beendet.',
|
||||
settings_label_notifications: 'Browser-Benachrichtigungen',
|
||||
settings_desc_notifications: 'Zeigt eine Systembenachrichtigung an, wenn eine Antwort fertiggestellt wird, während der Tab im Hintergrund ist.',
|
||||
settings_desc_token_usage: 'Zeigt die Anzahl der Input/Output-Token unter jeder Antwort des Assistenten an. Auch umschaltbar mit /usage.',
|
||||
settings_desc_cli_sessions: 'Fügt Sitzungen aus der Hermes CLI (state.db) in die Sitzungsliste ein. Klicken Sie auf eine CLI-Sitzung, um sie zu importieren.',
|
||||
settings_desc_sync_insights: 'Spiegelt den WebUI-Token-Verbrauch in die state.db, sodass hermes /insights Browser-Sitzungsdaten enthält. Standardmäßig aus.',
|
||||
settings_desc_check_updates: 'Zeigt ein Banner an, wenn neuere Versionen der WebUI oder des Agenten verfügbar sind.',
|
||||
settings_desc_bot_name: 'Anzeigename für den Assistenten in der UI. Standardmäßig Hermes.',
|
||||
settings_desc_password: 'Geben Sie ein neues Passwort ein, um es zu setzen oder zu ändern. Leer lassen, um die aktuelle Einstellung beizubehalten.',
|
||||
password_placeholder: 'Neues Passwort eingeben…',
|
||||
disable_auth: 'Authentifizierung deaktivieren',
|
||||
sign_out: 'Abmelden',
|
||||
cancel: 'Abbrechen',
|
||||
create_job: 'Job erstellen',
|
||||
save_skill: 'Skill speichern',
|
||||
editing: 'Bearbeite',
|
||||
// Empty state
|
||||
empty_title: 'Wie kann ich helfen?',
|
||||
empty_subtitle: 'Frage mich alles, führe Befehle aus oder verwalte deine Aufgaben.',
|
||||
suggest_files: 'Welche Dateien sind in diesem Workspace?',
|
||||
suggest_schedule: 'Was steht heute auf meinem Plan?',
|
||||
suggest_plan: 'Hilf mir, ein kleines Projekt zu planen.',
|
||||
},
|
||||
|
||||
zh: {
|
||||
@@ -321,6 +547,16 @@ function applyLocaleToDOM() {
|
||||
const val = t(key);
|
||||
if (val && val !== key) el.textContent = val;
|
||||
});
|
||||
document.querySelectorAll('[data-i18n-title]').forEach(el => {
|
||||
const key = el.getAttribute('data-i18n-title');
|
||||
const val = t(key);
|
||||
if (val && val !== key) el.title = val;
|
||||
});
|
||||
document.querySelectorAll('[data-i18n-placeholder]').forEach(el => {
|
||||
const key = el.getAttribute('data-i18n-placeholder');
|
||||
const val = t(key);
|
||||
if (val && val !== key) el.placeholder = val;
|
||||
});
|
||||
}
|
||||
|
||||
// Apply saved locale immediately so there's no flash of English on reload.
|
||||
|
||||
Reference in New Issue
Block a user