mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-12 07:20:45 +00:00
feat(i18n): add German (de) locale (#28495)
Merged via /review-pr -> /prepare-pr -> /merge-pr.
Prepared head SHA: e418326aaf
Co-authored-by: dsantoreis <220753637+dsantoreis@users.noreply.github.com>
Co-authored-by: Evizero <10854026+Evizero@users.noreply.github.com>
Reviewed-by: @Evizero
This commit is contained in:
@@ -18,6 +18,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Android/Nodes: add `camera.list`, `device.permissions`, `device.health`, and `notifications.actions` (`open`/`dismiss`/`reply`) on Android nodes, plus first-class node-tool actions for the new device/notification commands. (#28260) Thanks @obviyus.
|
||||
- Android/Gateway capability refresh: add live Android capability integration coverage and node canvas capability refresh wiring, plus runtime hardening for A2UI readiness retries, scoped canvas URL normalization, debug diagnostics JSON, and JavaScript MIME delivery. (#28388) Thanks @obviyus.
|
||||
- Docs/Contributing: add Nimrod Gutman to the maintainer roster in `CONTRIBUTING.md`. (#27840) Thanks @ngutman.
|
||||
- Web UI/i18n: add German (`de`) locale support and auto-render language options from supported locale constants in Overview settings. (#28495) thanks @dsantoreis.
|
||||
|
||||
### Fixes
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { Locale, TranslationMap } from "./types.ts";
|
||||
|
||||
type Subscriber = (locale: Locale) => void;
|
||||
|
||||
export const SUPPORTED_LOCALES: ReadonlyArray<Locale> = ["en", "zh-CN", "zh-TW", "pt-BR"];
|
||||
export const SUPPORTED_LOCALES: ReadonlyArray<Locale> = ["en", "zh-CN", "zh-TW", "pt-BR", "de"];
|
||||
|
||||
export function isSupportedLocale(value: string | null | undefined): value is Locale {
|
||||
return value !== null && value !== undefined && SUPPORTED_LOCALES.includes(value as Locale);
|
||||
@@ -30,6 +30,9 @@ class I18nManager {
|
||||
if (navLang.startsWith("pt")) {
|
||||
return "pt-BR";
|
||||
}
|
||||
if (navLang.startsWith("de")) {
|
||||
return "de";
|
||||
}
|
||||
return "en";
|
||||
}
|
||||
|
||||
@@ -64,6 +67,8 @@ class I18nManager {
|
||||
module = await import("../locales/zh-TW.ts");
|
||||
} else if (locale === "pt-BR") {
|
||||
module = await import("../locales/pt-BR.ts");
|
||||
} else if (locale === "de") {
|
||||
module = await import("../locales/de.ts");
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
export type TranslationMap = { [key: string]: string | TranslationMap };
|
||||
|
||||
export type Locale = "en" | "zh-CN" | "zh-TW" | "pt-BR";
|
||||
export type Locale = "en" | "zh-CN" | "zh-TW" | "pt-BR" | "de";
|
||||
|
||||
export interface I18nConfig {
|
||||
locale: Locale;
|
||||
|
||||
126
ui/src/i18n/locales/de.ts
Normal file
126
ui/src/i18n/locales/de.ts
Normal file
@@ -0,0 +1,126 @@
|
||||
import type { TranslationMap } from "../lib/types.ts";
|
||||
|
||||
export const de: TranslationMap = {
|
||||
common: {
|
||||
version: "Version",
|
||||
health: "Status",
|
||||
ok: "OK",
|
||||
offline: "Offline",
|
||||
connect: "Verbinden",
|
||||
refresh: "Aktualisieren",
|
||||
enabled: "Aktiviert",
|
||||
disabled: "Deaktiviert",
|
||||
na: "k. A.",
|
||||
docs: "Dokumentation",
|
||||
resources: "Ressourcen",
|
||||
},
|
||||
nav: {
|
||||
chat: "Chat",
|
||||
control: "Steuerung",
|
||||
agent: "Agent",
|
||||
settings: "Einstellungen",
|
||||
expand: "Seitenleiste ausklappen",
|
||||
collapse: "Seitenleiste einklappen",
|
||||
},
|
||||
tabs: {
|
||||
agents: "Agenten",
|
||||
overview: "Übersicht",
|
||||
channels: "Kanäle",
|
||||
instances: "Instanzen",
|
||||
sessions: "Sitzungen",
|
||||
usage: "Nutzung",
|
||||
cron: "Cron-Aufgaben",
|
||||
skills: "Fähigkeiten",
|
||||
nodes: "Geräte",
|
||||
chat: "Chat",
|
||||
config: "Konfiguration",
|
||||
debug: "Debug",
|
||||
logs: "Protokolle",
|
||||
},
|
||||
subtitles: {
|
||||
agents: "Agent-Arbeitsbereiche, Tools und Identitäten verwalten.",
|
||||
overview: "Gateway-Status, Einstiegspunkte und eine schnelle Zustandsprüfung.",
|
||||
channels: "Kanäle und Einstellungen verwalten.",
|
||||
instances: "Präsenzsignale von verbundenen Clients und Geräten.",
|
||||
sessions: "Aktive Sitzungen inspizieren und Standardeinstellungen pro Sitzung anpassen.",
|
||||
usage: "API-Nutzung und Kosten überwachen.",
|
||||
cron: "Aufweckzeiten und wiederkehrende Agent-Läufe planen.",
|
||||
skills: "Skill-Verfügbarkeit und API-Schlüsselinjektion verwalten.",
|
||||
nodes: "Gekoppelte Geräte, Fähigkeiten und Befehlsfreigabe.",
|
||||
chat: "Direkte Gateway-Chat-Sitzung für schnelle Eingriffe.",
|
||||
config: "~/.openclaw/openclaw.json sicher bearbeiten.",
|
||||
debug: "Gateway-Snapshots, Ereignisse und manuelle RPC-Aufrufe.",
|
||||
logs: "Live-Verfolgung der Gateway-Protokolldateien.",
|
||||
},
|
||||
overview: {
|
||||
access: {
|
||||
title: "Gateway-Zugang",
|
||||
subtitle: "Wo sich das Dashboard verbindet und wie es sich authentifiziert.",
|
||||
wsUrl: "WebSocket-URL",
|
||||
token: "Gateway-Token",
|
||||
password: "Passwort (nicht gespeichert)",
|
||||
sessionKey: "Standard-Sitzungsschlüssel",
|
||||
language: "Sprache",
|
||||
connectHint: "Klicken Sie auf Verbinden, um Verbindungsänderungen anzuwenden.",
|
||||
trustedProxy: "Authentifiziert über vertrauenswürdigen Proxy.",
|
||||
},
|
||||
snapshot: {
|
||||
title: "Snapshot",
|
||||
subtitle: "Neueste Gateway-Handshake-Informationen.",
|
||||
status: "Status",
|
||||
uptime: "Betriebszeit",
|
||||
tickInterval: "Tick-Intervall",
|
||||
lastChannelsRefresh: "Letzte Kanalaktualisierung",
|
||||
channelsHint:
|
||||
"Verwenden Sie Kanäle, um WhatsApp, Telegram, Discord, Signal oder iMessage zu verknüpfen.",
|
||||
},
|
||||
stats: {
|
||||
instances: "Instanzen",
|
||||
instancesHint: "Präsenzsignale in den letzten 5 Minuten.",
|
||||
sessions: "Sitzungen",
|
||||
sessionsHint: "Letzte vom Gateway verfolgte Sitzungsschlüssel.",
|
||||
cron: "Cron",
|
||||
cronNext: "Nächste Ausführung {time}",
|
||||
},
|
||||
notes: {
|
||||
title: "Notizen",
|
||||
subtitle: "Kurze Hinweise für Remote-Steuerung.",
|
||||
tailscaleTitle: "Tailscale Serve",
|
||||
tailscaleText:
|
||||
"Bevorzugen Sie den Serve-Modus, um das Gateway auf Loopback mit Tailnet-Auth zu halten.",
|
||||
sessionTitle: "Sitzungshygiene",
|
||||
sessionText: "Verwenden Sie /new oder sessions.patch, um den Kontext zurückzusetzen.",
|
||||
cronTitle: "Cron-Erinnerungen",
|
||||
cronText: "Verwenden Sie isolierte Sitzungen für wiederkehrende Läufe.",
|
||||
},
|
||||
auth: {
|
||||
required:
|
||||
"Dieses Gateway erfordert Authentifizierung. Fügen Sie ein Token oder Passwort hinzu und klicken Sie auf Verbinden.",
|
||||
failed:
|
||||
"Authentifizierung fehlgeschlagen. Kopieren Sie erneut eine URL mit Token über {command}, oder aktualisieren Sie das Token und klicken Sie auf Verbinden.",
|
||||
},
|
||||
pairing: {
|
||||
hint: "Dieses Gerät benötigt eine Pairing-Freigabe vom Gateway-Host.",
|
||||
mobileHint:
|
||||
"Auf dem Mobilgerät? Kopieren Sie die vollständige URL (einschließlich #token=...) von openclaw dashboard --no-open auf Ihrem Desktop.",
|
||||
},
|
||||
insecure: {
|
||||
hint: "Diese Seite ist HTTP, daher blockiert der Browser die Geräteidentifikation. Verwenden Sie HTTPS (Tailscale Serve) oder öffnen Sie {url} auf dem Gateway-Host.",
|
||||
stayHttp: "Wenn Sie bei HTTP bleiben müssen, setzen Sie {config} (nur Token).",
|
||||
},
|
||||
},
|
||||
chat: {
|
||||
disconnected: "Verbindung zum Gateway getrennt.",
|
||||
refreshTitle: "Chat-Daten aktualisieren",
|
||||
thinkingToggle: "Ausgabe des Assistenten ein-/ausblenden",
|
||||
focusToggle: "Fokusmodus ein-/ausschalten (Seitenleiste + Kopfzeile ausblenden)",
|
||||
onboardingDisabled: "Während der Einrichtung deaktiviert",
|
||||
},
|
||||
languages: {
|
||||
en: "English",
|
||||
zhCN: "简体中文 (Vereinfachtes Chinesisch)",
|
||||
zhTW: "繁體中文 (Traditionelles Chinesisch)",
|
||||
ptBR: "Português (Brasilianisches Portugiesisch)",
|
||||
de: "Deutsch",
|
||||
},
|
||||
};
|
||||
@@ -118,5 +118,6 @@ export const en: TranslationMap = {
|
||||
zhCN: "简体中文 (Simplified Chinese)",
|
||||
zhTW: "繁體中文 (Traditional Chinese)",
|
||||
ptBR: "Português (Brazilian Portuguese)",
|
||||
de: "Deutsch (German)",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -120,5 +120,6 @@ export const pt_BR: TranslationMap = {
|
||||
zhCN: "简体中文 (Chinês Simplificado)",
|
||||
zhTW: "繁體中文 (Chinês Tradicional)",
|
||||
ptBR: "Português (Português Brasileiro)",
|
||||
de: "Deutsch (Alemão)",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -117,5 +117,6 @@ export const zh_CN: TranslationMap = {
|
||||
zhCN: "简体中文 (简体中文)",
|
||||
zhTW: "繁體中文 (繁体中文)",
|
||||
ptBR: "Português (巴西葡萄牙语)",
|
||||
de: "Deutsch (德语)",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -117,5 +117,6 @@ export const zh_TW: TranslationMap = {
|
||||
zhCN: "简体中文 (簡體中文)",
|
||||
zhTW: "繁體中文 (繁體中文)",
|
||||
ptBR: "Português (巴西葡萄牙語)",
|
||||
de: "Deutsch (德語)",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { html } from "lit";
|
||||
import { ConnectErrorDetailCodes } from "../../../../src/gateway/protocol/connect-error-details.js";
|
||||
import { t, i18n, type Locale } from "../../i18n/index.ts";
|
||||
import { t, i18n, SUPPORTED_LOCALES, type Locale } from "../../i18n/index.ts";
|
||||
import { buildExternalLinkRel, EXTERNAL_LINK_TARGET } from "../external-link.ts";
|
||||
import { formatRelativeTimestamp, formatDurationHuman } from "../format.ts";
|
||||
import type { GatewayHelloOk } from "../gateway.ts";
|
||||
@@ -259,10 +259,10 @@ export function renderOverview(props: OverviewProps) {
|
||||
props.onSettingsChange({ ...props.settings, locale: v });
|
||||
}}
|
||||
>
|
||||
<option value="en">${t("languages.en")}</option>
|
||||
<option value="zh-CN">${t("languages.zhCN")}</option>
|
||||
<option value="zh-TW">${t("languages.zhTW")}</option>
|
||||
<option value="pt-BR">${t("languages.ptBR")}</option>
|
||||
${SUPPORTED_LOCALES.map((loc) => {
|
||||
const key = loc.replace(/-([a-zA-Z])/g, (_, c) => c.toUpperCase());
|
||||
return html`<option value=${loc}>${t(`languages.${key}`)}</option>`;
|
||||
})}
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user