feat(i18n): add German (de) locale

Add German locale to the OpenClaw Control UI.

- New locale file: de.ts — complete translation of all 122 UI strings
- Updated Locale type, SUPPORTED_LOCALES, lazy import, browser detection
- Updated language labels in all existing locales
- Dynamic language selector using SUPPORTED_LOCALES

Contributes to #3460
This commit is contained in:
Daniel dos Santos Reis
2026-02-27 09:22:00 +01:00
committed by Christof Salis
parent 6b317b1f17
commit d551d460ad
14 changed files with 918 additions and 7 deletions

View File

@@ -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;
}

View File

@@ -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;

129
ui/src/i18n/locales/de.ts Normal file
View File

@@ -0,0 +1,129 @@
import type { TranslationMap } from "../lib/types.ts";
export const de: TranslationMap = {
common: {
version: "Version",
health: "Zustand",
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: "Agents",
overview: "Übersicht",
channels: "Kanäle",
instances: "Instanzen",
sessions: "Sitzungen",
usage: "Nutzung",
cron: "Cron-Aufgaben",
skills: "Skills",
nodes: "Knoten",
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 Knoten.",
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 Aktivierung {time}",
},
notes: {
title: "Notizen",
subtitle: "Kurze Erinnerungen für Fernsteuerungskonfigurationen.",
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 die Kopplungsgenehmigung 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: "Denk-/Arbeitsausgabe des Assistenten ein-/ausschalten",
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)",
nl: "Nederlands (Niederländisch)",
fr: "Français (Französisch)",
de: "Deutsch",
it: "Italiano (Italienisch)",
},
};

View File

@@ -118,5 +118,6 @@ export const en: TranslationMap = {
zhCN: "简体中文 (Simplified Chinese)",
zhTW: "繁體中文 (Traditional Chinese)",
ptBR: "Português (Brazilian Portuguese)",
de: "Deutsch (German)",
},
};

View File

@@ -0,0 +1,126 @@
import type { TranslationMap } from "../lib/types.ts";
export const es_AR: TranslationMap = {
common: {
version: "Versión",
health: "Estado",
ok: "OK",
offline: "Sin conexión",
connect: "Conectar",
refresh: "Actualizar",
enabled: "Activado",
disabled: "Desactivado",
na: "n/d",
docs: "Documentación",
resources: "Recursos",
},
nav: {
chat: "Chat",
control: "Control",
agent: "Agente",
settings: "Configuración",
expand: "Expandir barra lateral",
collapse: "Contraer barra lateral",
},
tabs: {
agents: "Agentes",
overview: "Vista General",
channels: "Canales",
instances: "Instancias",
sessions: "Sesiones",
usage: "Consumo",
cron: "Tareas Cron",
skills: "Habilidades",
nodes: "Nodos",
chat: "Chat",
config: "Configuración",
debug: "Depuración",
logs: "Registros",
},
subtitles: {
agents: "Gestionar espacios de trabajo, herramientas e identidades de agentes.",
overview: "Estado del gateway, puntos de entrada y lectura rápida de salud.",
channels: "Gestionar canales y configuraciones.",
instances: "Beacons de presencia de clientes y nodos conectados.",
sessions: "Inspeccionar sesiones activas y ajustar valores predeterminados por sesión.",
usage: "Monitorear el consumo y costos de la API.",
cron: "Programar despertares y ejecuciones recurrentes de agentes.",
skills: "Gestionar disponibilidad de habilidades e inyección de claves de API.",
nodes: "Dispositivos emparejados, capacidades y exposición de comandos.",
chat: "Sesión de chat directa con el gateway para intervenciones rápidas.",
config: "Editar ~/.openclaw/openclaw.json de forma segura.",
debug: "Snapshots del gateway, eventos y llamadas RPC manuales.",
logs: "Seguimiento en vivo de los registros del gateway.",
},
overview: {
access: {
title: "Acceso al Gateway",
subtitle: "Dónde se conecta el panel y cómo se autentica.",
wsUrl: "URL WebSocket",
token: "Token del Gateway",
password: "Contraseña (no almacenada)",
sessionKey: "Clave de Sesión Predeterminada",
language: "Idioma",
connectHint: "Hacé clic en Conectar para aplicar los cambios de conexión.",
trustedProxy: "Autenticado mediante proxy de confianza.",
},
snapshot: {
title: "Snapshot",
subtitle: "Información más reciente del handshake del gateway.",
status: "Estado",
uptime: "Tiempo Activo",
tickInterval: "Intervalo de Tick",
lastChannelsRefresh: "Última Actualización de Canales",
channelsHint: "Usá Canales para vincular WhatsApp, Telegram, Discord, Signal o iMessage.",
},
stats: {
instances: "Instancias",
instancesHint: "Beacons de presencia en los últimos 5 minutos.",
sessions: "Sesiones",
sessionsHint: "Claves de sesión recientes registradas por el gateway.",
cron: "Cron",
cronNext: "Próximo despertar {time}",
},
notes: {
title: "Notas",
subtitle: "Recordatorios rápidos para configuraciones de control remoto.",
tailscaleTitle: "Tailscale serve",
tailscaleText:
"Preferí el modo serve para mantener el gateway en loopback con autenticación tailnet.",
sessionTitle: "Higiene de sesión",
sessionText: "Usá /new o sessions.patch para resetear el contexto.",
cronTitle: "Recordatorios de Cron",
cronText: "Usá sesiones aisladas para ejecuciones recurrentes.",
},
auth: {
required:
"Este gateway requiere autenticación. Agregá un token o contraseña y hacé clic en Conectar.",
failed:
"Falló la autenticación. Volvé a copiar una URL con token usando {command}, o actualizá el token y hacé clic en Conectar.",
},
pairing: {
hint: "Este dispositivo necesita aprobación de emparejamiento del host del gateway.",
mobileHint:
"¿Estás en el celular? Copiá la URL completa (incluyendo #token=...) ejecutando openclaw dashboard --no-open en la computadora.",
},
insecure: {
hint: "Esta página es HTTP, así que el navegador bloquea la identidad del dispositivo. Usá HTTPS (Tailscale Serve) o abrí {url} en el host del gateway.",
stayHttp: "Si necesitás quedarte en HTTP, configurá {config} (solo token).",
},
},
chat: {
disconnected: "Desconectado del gateway.",
refreshTitle: "Actualizar datos del chat",
thinkingToggle: "Alternar salida de pensamiento/trabajo del asistente",
focusToggle: "Alternar modo foco (ocultar barra lateral + encabezado de página)",
onboardingDisabled: "Desactivado durante la configuración inicial",
},
languages: {
en: "English",
zhCN: "简体中文 (Chino Simplificado)",
zhTW: "繁體中文 (Chino Tradicional)",
ptBR: "Português (Portugués Brasileño)",
ptPT: "Português (Portugués Europeo)",
esAR: "Español (Español Argentino)",
},
};

131
ui/src/i18n/locales/es.ts Normal file
View File

@@ -0,0 +1,131 @@
import type { TranslationMap } from "../lib/types.ts";
export const es: TranslationMap = {
common: {
version: "Versión",
health: "Estado",
ok: "OK",
offline: "Sin conexión",
connect: "Conectar",
refresh: "Actualizar",
enabled: "Activado",
disabled: "Desactivado",
na: "n/d",
docs: "Docs",
resources: "Recursos",
},
nav: {
chat: "Chat",
control: "Control",
agent: "Agente",
settings: "Ajustes",
expand: "Expandir barra lateral",
collapse: "Contraer barra lateral",
},
tabs: {
agents: "Agentes",
overview: "Vista General",
channels: "Canales",
instances: "Instancias",
sessions: "Sesiones",
usage: "Uso",
cron: "Tareas Cron",
skills: "Habilidades",
nodes: "Nodos",
chat: "Chat",
config: "Config",
debug: "Debug",
logs: "Logs",
},
subtitles: {
agents: "Gestionar espacios de trabajo, herramientas e identidades de agentes.",
overview: "Estado del gateway, puntos de entrada y lectura rápida de salud.",
channels: "Gestionar canales y configuraciones.",
instances: "Señales de presencia de clientes y nodos conectados.",
sessions: "Inspeccionar sesiones activas y ajustar valores por sesión.",
usage: "Monitorizar uso y costes de API.",
cron: "Programar despertares y ejecuciones recurrentes de agentes.",
skills: "Gestionar disponibilidad de habilidades e inyección de claves API.",
nodes: "Dispositivos emparejados, capacidades y exposición de comandos.",
chat: "Sesión de chat directa con el gateway para intervenciones rápidas.",
config: "Editar ~/.openclaw/openclaw.json de forma segura.",
debug: "Snapshots del gateway, eventos y llamadas RPC manuales.",
logs: "Seguimiento en vivo de los archivos de log del gateway.",
},
overview: {
access: {
title: "Acceso al Gateway",
subtitle: "Dónde se conecta el dashboard y cómo se autentica.",
wsUrl: "URL WebSocket",
token: "Token del Gateway",
password: "Contraseña (no almacenada)",
sessionKey: "Clave de Sesión Predeterminada",
language: "Idioma",
connectHint: "Haz clic en Conectar para aplicar los cambios de conexión.",
trustedProxy: "Autenticado por proxy de confianza.",
},
snapshot: {
title: "Snapshot",
subtitle: "Información más reciente del handshake del gateway.",
status: "Estado",
uptime: "Tiempo de Actividad",
tickInterval: "Intervalo de Tick",
lastChannelsRefresh: "Última Actualización de Canales",
channelsHint: "Usa Canales para vincular WhatsApp, Telegram, Discord, Signal o iMessage.",
},
stats: {
instances: "Instancias",
instancesHint: "Señales de presencia en los últimos 5 minutos.",
sessions: "Sesiones",
sessionsHint: "Claves de sesión recientes rastreadas por el gateway.",
cron: "Cron",
cronNext: "Próximo despertar {time}",
},
notes: {
title: "Notas",
subtitle: "Recordatorios rápidos para configuraciones de control remoto.",
tailscaleTitle: "Tailscale serve",
tailscaleText:
"Prefiere el modo serve para mantener el gateway en loopback con autenticación tailnet.",
sessionTitle: "Higiene de sesión",
sessionText: "Usa /new o sessions.patch para restablecer el contexto.",
cronTitle: "Recordatorios de Cron",
cronText: "Usa sesiones aisladas para ejecuciones recurrentes.",
},
auth: {
required:
"Este gateway requiere autenticación. Añade un token o contraseña y haz clic en Conectar.",
failed:
"Autenticación fallida. Recopia una URL con token usando {command}, o actualiza el token y haz clic en Conectar.",
},
pairing: {
hint: "Este dispositivo necesita aprobación de emparejamiento del host del gateway.",
mobileHint:
"¿En el móvil? Copia la URL completa (incluyendo #token=...) ejecutando openclaw dashboard --no-open en el escritorio.",
},
insecure: {
hint: "Esta página es HTTP, por lo que el navegador bloquea la identidad del dispositivo. Usa HTTPS (Tailscale Serve) o abre {url} en el host del gateway.",
stayHttp: "Si necesitas permanecer en HTTP, establece {config} (solo token).",
},
},
chat: {
disconnected: "Desconectado del gateway.",
refreshTitle: "Actualizar datos del chat",
thinkingToggle: "Alternar salida de pensamiento/trabajo del asistente",
focusToggle: "Alternar modo de enfoque (ocultar barra lateral + encabezado de página)",
onboardingDisabled: "Desactivado durante la integración",
},
languages: {
en: "English",
zhCN: "简体中文 (Chino Simplificado)",
zhTW: "繁體中文 (Chino Tradicional)",
ptBR: "Português (Portugués Brasileño)",
nl: "Nederlands (Neerlandés)",
fr: "Français (Francés)",
de: "Deutsch (Alemán)",
it: "Italiano",
es: "Español",
ja: "日本語 (Japonés)",
ko: "한국어 (Coreano)",
},
};

128
ui/src/i18n/locales/it.ts Normal file
View File

@@ -0,0 +1,128 @@
import type { TranslationMap } from "../lib/types.ts";
export const it: TranslationMap = {
common: {
version: "Versione",
health: "Stato",
ok: "OK",
offline: "Offline",
connect: "Connetti",
refresh: "Aggiorna",
enabled: "Abilitato",
disabled: "Disabilitato",
na: "n/d",
docs: "Documentazione",
resources: "Risorse",
},
nav: {
chat: "Chat",
control: "Controllo",
agent: "Agente",
settings: "Impostazioni",
expand: "Espandi barra laterale",
collapse: "Comprimi barra laterale",
},
tabs: {
agents: "Agenti",
overview: "Panoramica",
channels: "Canali",
instances: "Istanze",
sessions: "Sessioni",
usage: "Utilizzo",
cron: "Attività Cron",
skills: "Skills",
nodes: "Nodi",
chat: "Chat",
config: "Configurazione",
debug: "Debug",
logs: "Registri",
},
subtitles: {
agents: "Gestisci spazi di lavoro, strumenti e identità degli agenti.",
overview: "Stato del gateway, punti di accesso e controllo rapido.",
channels: "Gestisci canali e impostazioni.",
instances: "Segnali di presenza da client e nodi connessi.",
sessions: "Ispeziona le sessioni attive e regola le impostazioni predefinite per sessione.",
usage: "Monitora l'utilizzo dell'API e i costi.",
cron: "Pianifica risvegli ed esecuzioni ricorrenti degli agenti.",
skills: "Gestisci la disponibilità delle skill e l'iniezione di chiavi API.",
nodes: "Dispositivi accoppiati, capacità ed esposizione dei comandi.",
chat: "Sessione chat diretta con il gateway per interventi rapidi.",
config: "Modifica ~/.openclaw/openclaw.json in modo sicuro.",
debug: "Snapshot del gateway, eventi e chiamate RPC manuali.",
logs: "Monitoraggio in tempo reale dei file di registro del gateway.",
},
overview: {
access: {
title: "Accesso al Gateway",
subtitle: "Dove si connette la dashboard e come si autentica.",
wsUrl: "URL WebSocket",
token: "Token del Gateway",
password: "Password (non memorizzata)",
sessionKey: "Chiave di sessione predefinita",
language: "Lingua",
connectHint: "Clicca su Connetti per applicare le modifiche alla connessione.",
trustedProxy: "Autenticato tramite proxy attendibile.",
},
snapshot: {
title: "Istantanea",
subtitle: "Ultime informazioni di handshake del gateway.",
status: "Stato",
uptime: "Tempo di attività",
tickInterval: "Intervallo tick",
lastChannelsRefresh: "Ultimo aggiornamento canali",
channelsHint: "Usa Canali per collegare WhatsApp, Telegram, Discord, Signal o iMessage.",
},
stats: {
instances: "Istanze",
instancesHint: "Segnali di presenza negli ultimi 5 minuti.",
sessions: "Sessioni",
sessionsHint: "Chiavi di sessione recenti tracciate dal gateway.",
cron: "Cron",
cronNext: "Prossimo risveglio {time}",
},
notes: {
title: "Note",
subtitle: "Promemoria rapidi per configurazioni di controllo remoto.",
tailscaleTitle: "Tailscale Serve",
tailscaleText:
"Preferisci la modalità serve per mantenere il gateway in loopback con l'auth tailnet.",
sessionTitle: "Igiene della sessione",
sessionText: "Usa /new o sessions.patch per reimpostare il contesto.",
cronTitle: "Promemoria Cron",
cronText: "Usa sessioni isolate per le esecuzioni ricorrenti.",
},
auth: {
required:
"Questo gateway richiede l'autenticazione. Aggiungi un token o una password, quindi clicca su Connetti.",
failed:
"Autenticazione fallita. Ricopia un URL con token tramite {command}, o aggiorna il token, quindi clicca su Connetti.",
},
pairing: {
hint: "Questo dispositivo necessita dell'approvazione di accoppiamento dall'host del gateway.",
mobileHint:
"Su mobile? Copia l'URL completo (incluso #token=...) da openclaw dashboard --no-open sul tuo desktop.",
},
insecure: {
hint: "Questa pagina è HTTP, quindi il browser blocca l'identità del dispositivo. Usa HTTPS (Tailscale Serve) o apri {url} sull'host del gateway.",
stayHttp: "Se devi restare su HTTP, imposta {config} (solo token).",
},
},
chat: {
disconnected: "Disconnesso dal gateway.",
refreshTitle: "Aggiorna i dati della chat",
thinkingToggle: "Attiva/disattiva l'output di pensiero dell'assistente",
focusToggle: "Attiva/disattiva la modalità focus (nascondi barra laterale + intestazione)",
onboardingDisabled: "Disabilitato durante la configurazione iniziale",
},
languages: {
en: "English",
zhCN: "简体中文 (Cinese semplificato)",
zhTW: "繁體中文 (Cinese tradizionale)",
ptBR: "Português (Portoghese brasiliano)",
nl: "Nederlands (Olandese)",
fr: "Français (Francese)",
de: "Deutsch (Tedesco)",
it: "Italiano",
},
};

131
ui/src/i18n/locales/ja.ts Normal file
View File

@@ -0,0 +1,131 @@
import type { TranslationMap } from "../lib/types.ts";
export const ja: TranslationMap = {
common: {
version: "バージョン",
health: "ヘルス",
ok: "OK",
offline: "オフライン",
connect: "接続",
refresh: "更新",
enabled: "有効",
disabled: "無効",
na: "n/a",
docs: "ドキュメント",
resources: "リソース",
},
nav: {
chat: "チャット",
control: "コントロール",
agent: "エージェント",
settings: "設定",
expand: "サイドバーを展開",
collapse: "サイドバーを折りたたむ",
},
tabs: {
agents: "エージェント",
overview: "概要",
channels: "チャンネル",
instances: "インスタンス",
sessions: "セッション",
usage: "使用状況",
cron: "Cronジョブ",
skills: "スキル",
nodes: "ノード",
chat: "チャット",
config: "設定",
debug: "デバッグ",
logs: "ログ",
},
subtitles: {
agents: "エージェントのワークスペース、ツール、アイデンティティを管理します。",
overview: "ゲートウェイの状態、エントリーポイント、簡易ヘルスチェック。",
channels: "チャンネルと設定を管理します。",
instances: "接続されたクライアントとノードのプレゼンスビーコン。",
sessions: "アクティブなセッションを確認し、セッションごとの設定を調整します。",
usage: "APIの使用状況とコストを監視します。",
cron: "エージェントの定期実行とウェイクアップをスケジュールします。",
skills: "スキルの利用可否とAPIキーの注入を管理します。",
nodes: "ペアリング済みデバイス、機能、コマンドの公開設定。",
chat: "迅速な介入のためのゲートウェイ直接チャットセッション。",
config: "~/.openclaw/openclaw.json を安全に編集します。",
debug: "ゲートウェイのスナップショット、イベント、手動RPCコール。",
logs: "ゲートウェイのファイルログのライブテール。",
},
overview: {
access: {
title: "ゲートウェイアクセス",
subtitle: "ダッシュボードの接続先と認証方法。",
wsUrl: "WebSocket URL",
token: "ゲートウェイトークン",
password: "パスワード(保存されません)",
sessionKey: "デフォルトセッションキー",
language: "言語",
connectHint: "接続をクリックして接続の変更を適用します。",
trustedProxy: "信頼済みプロキシで認証済み。",
},
snapshot: {
title: "スナップショット",
subtitle: "最新のゲートウェイハンドシェイク情報。",
status: "ステータス",
uptime: "稼働時間",
tickInterval: "ティック間隔",
lastChannelsRefresh: "最終チャンネル更新",
channelsHint:
"チャンネルを使用してWhatsApp、Telegram、Discord、Signal、またはiMessageをリンクします。",
},
stats: {
instances: "インスタンス",
instancesHint: "過去5分間のプレゼンスビーコン。",
sessions: "セッション",
sessionsHint: "ゲートウェイが追跡している最近のセッションキー。",
cron: "Cron",
cronNext: "次回のウェイクアップ {time}",
},
notes: {
title: "ノート",
subtitle: "リモートコントロール設定の簡易メモ。",
tailscaleTitle: "Tailscale serve",
tailscaleText: "tailnet認証でゲートウェイをループバックに保つため、serveモードを推奨します。",
sessionTitle: "セッション管理",
sessionText: "コンテキストをリセットするには /new または sessions.patch を使用します。",
cronTitle: "Cronリマインダー",
cronText: "定期実行には分離セッションを使用します。",
},
auth: {
required:
"このゲートウェイには認証が必要です。トークンまたはパスワードを追加し、接続をクリックしてください。",
failed:
"認証に失敗しました。{command} でトークン付きURLを再コピーするか、トークンを更新して接続をクリックしてください。",
},
pairing: {
hint: "このデバイスはゲートウェイホストからのペアリング承認が必要です。",
mobileHint:
"モバイルですか?デスクトップで openclaw dashboard --no-open を実行し、完全なURL#token=... を含む)をコピーしてください。",
},
insecure: {
hint: "このページはHTTPのため、ブラウザがデバイスIDをブロックします。HTTPSTailscale Serveを使用するか、ゲートウェイホストで {url} を開いてください。",
stayHttp: "HTTPのままにする必要がある場合は、{config}(トークンのみ)を設定してください。",
},
},
chat: {
disconnected: "ゲートウェイから切断されました。",
refreshTitle: "チャットデータを更新",
thinkingToggle: "アシスタントの思考/作業出力を切り替え",
focusToggle: "フォーカスモードを切り替え(サイドバー + ページヘッダーを非表示)",
onboardingDisabled: "オンボーディング中は無効",
},
languages: {
en: "English",
zhCN: "简体中文(簡体字中国語)",
zhTW: "繁體中文(繁体字中国語)",
ptBR: "Portuguêsブラジルポルトガル語",
nl: "Nederlandsオランダ語",
fr: "Françaisフランス語",
de: "Deutschドイツ語",
it: "Italianoイタリア語",
es: "Españolスペイン語",
ja: "日本語",
ko: "한국어(韓国語)",
},
};

131
ui/src/i18n/locales/ko.ts Normal file
View File

@@ -0,0 +1,131 @@
import type { TranslationMap } from "../lib/types.ts";
export const ko: TranslationMap = {
common: {
version: "버전",
health: "상태",
ok: "OK",
offline: "오프라인",
connect: "연결",
refresh: "새로고침",
enabled: "활성화",
disabled: "비활성화",
na: "해당 없음",
docs: "문서",
resources: "리소스",
},
nav: {
chat: "채팅",
control: "제어",
agent: "에이전트",
settings: "설정",
expand: "사이드바 펼치기",
collapse: "사이드바 접기",
},
tabs: {
agents: "에이전트",
overview: "개요",
channels: "채널",
instances: "인스턴스",
sessions: "세션",
usage: "사용량",
cron: "Cron 작업",
skills: "스킬",
nodes: "노드",
chat: "채팅",
config: "설정",
debug: "디버그",
logs: "로그",
},
subtitles: {
agents: "에이전트 워크스페이스, 도구 및 아이덴티티를 관리합니다.",
overview: "게이트웨이 상태, 진입점 및 빠른 상태 확인.",
channels: "채널 및 설정을 관리합니다.",
instances: "연결된 클라이언트와 노드의 프레즌스 비콘.",
sessions: "활성 세션을 검사하고 세션별 기본값을 조정합니다.",
usage: "API 사용량과 비용을 모니터링합니다.",
cron: "에이전트 웨이크업과 반복 실행을 예약합니다.",
skills: "스킬 가용성과 API 키 주입을 관리합니다.",
nodes: "페어링된 디바이스, 기능 및 명령 노출.",
chat: "빠른 개입을 위한 게이트웨이 직접 채팅 세션.",
config: "~/.openclaw/openclaw.json을 안전하게 편집합니다.",
debug: "게이트웨이 스냅샷, 이벤트 및 수동 RPC 호출.",
logs: "게이트웨이 파일 로그의 실시간 추적.",
},
overview: {
access: {
title: "게이트웨이 접근",
subtitle: "대시보드의 연결 대상과 인증 방법.",
wsUrl: "WebSocket URL",
token: "게이트웨이 토큰",
password: "비밀번호 (저장되지 않음)",
sessionKey: "기본 세션 키",
language: "언어",
connectHint: "연결을 클릭하여 연결 변경 사항을 적용합니다.",
trustedProxy: "신뢰할 수 있는 프록시로 인증됨.",
},
snapshot: {
title: "스냅샷",
subtitle: "최신 게이트웨이 핸드셰이크 정보.",
status: "상태",
uptime: "가동 시간",
tickInterval: "틱 간격",
lastChannelsRefresh: "마지막 채널 새로고침",
channelsHint:
"채널을 사용하여 WhatsApp, Telegram, Discord, Signal 또는 iMessage를 연결합니다.",
},
stats: {
instances: "인스턴스",
instancesHint: "최근 5분간의 프레즌스 비콘.",
sessions: "세션",
sessionsHint: "게이트웨이가 추적 중인 최근 세션 키.",
cron: "Cron",
cronNext: "다음 웨이크업 {time}",
},
notes: {
title: "노트",
subtitle: "원격 제어 설정을 위한 간단한 메모.",
tailscaleTitle: "Tailscale serve",
tailscaleText: "tailnet 인증으로 게이트웨이를 루프백에 유지하려면 serve 모드를 권장합니다.",
sessionTitle: "세션 관리",
sessionText: "컨텍스트를 초기화하려면 /new 또는 sessions.patch를 사용하세요.",
cronTitle: "Cron 알림",
cronText: "반복 실행에는 격리 세션을 사용하세요.",
},
auth: {
required:
"이 게이트웨이는 인증이 필요합니다. 토큰 또는 비밀번호를 추가하고 연결을 클릭하세요.",
failed:
"인증에 실패했습니다. {command}로 토큰 URL을 다시 복사하거나, 토큰을 업데이트하고 연결을 클릭하세요.",
},
pairing: {
hint: "이 디바이스는 게이트웨이 호스트의 페어링 승인이 필요합니다.",
mobileHint:
"모바일인가요? 데스크톱에서 openclaw dashboard --no-open을 실행하고 전체 URL(#token=... 포함)을 복사하세요.",
},
insecure: {
hint: "이 페이지는 HTTP이므로 브라우저가 디바이스 ID를 차단합니다. HTTPS(Tailscale Serve)를 사용하거나 게이트웨이 호스트에서 {url}을 여세요.",
stayHttp: "HTTP를 유지해야 하는 경우 {config}(토큰 전용)을 설정하세요.",
},
},
chat: {
disconnected: "게이트웨이와의 연결이 끊어졌습니다.",
refreshTitle: "채팅 데이터 새로고침",
thinkingToggle: "어시스턴트 사고/작업 출력 전환",
focusToggle: "포커스 모드 전환 (사이드바 + 페이지 헤더 숨기기)",
onboardingDisabled: "온보딩 중에는 비활성화",
},
languages: {
en: "English",
zhCN: "简体中文 (중국어 간체)",
zhTW: "繁體中文 (중국어 번체)",
ptBR: "Português (브라질 포르투갈어)",
nl: "Nederlands (네덜란드어)",
fr: "Français (프랑스어)",
de: "Deutsch (독일어)",
it: "Italiano (이탈리아어)",
es: "Español (스페인어)",
ja: "日本語 (일본어)",
ko: "한국어",
},
};

View File

@@ -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)",
},
};

View File

@@ -0,0 +1,126 @@
import type { TranslationMap } from "../lib/types.ts";
export const pt_PT: TranslationMap = {
common: {
version: "Versão",
health: "Estado",
ok: "OK",
offline: "Offline",
connect: "Ligar",
refresh: "Atualizar",
enabled: "Ativado",
disabled: "Desativado",
na: "n/d",
docs: "Documentação",
resources: "Recursos",
},
nav: {
chat: "Chat",
control: "Controlo",
agent: "Agente",
settings: "Definições",
expand: "Expandir barra lateral",
collapse: "Recolher barra lateral",
},
tabs: {
agents: "Agentes",
overview: "Visão Geral",
channels: "Canais",
instances: "Instâncias",
sessions: "Sessões",
usage: "Utilização",
cron: "Tarefas Cron",
skills: "Competências",
nodes: "Nós",
chat: "Chat",
config: "Configuração",
debug: "Depuração",
logs: "Registos",
},
subtitles: {
agents: "Gerir espaços de trabalho, ferramentas e identidades de agentes.",
overview: "Estado do gateway, pontos de entrada e leitura rápida de saúde.",
channels: "Gerir canais e configurações.",
instances: "Beacons de presença de clientes e nós ligados.",
sessions: "Inspecionar sessões ativas e ajustar predefinições por sessão.",
usage: "Monitorizar utilização e custos da API.",
cron: "Agendar despertares e execuções recorrentes de agentes.",
skills: "Gerir disponibilidade de competências e injeção de chaves de API.",
nodes: "Dispositivos emparelhados, capacidades e exposição de comandos.",
chat: "Sessão de chat direta com o gateway para intervenções rápidas.",
config: "Editar ~/.openclaw/openclaw.json com segurança.",
debug: "Snapshots do gateway, eventos e chamadas RPC manuais.",
logs: "Acompanhamento em tempo real dos registos do gateway.",
},
overview: {
access: {
title: "Acesso ao Gateway",
subtitle: "Onde o painel de controlo se liga e como se autentica.",
wsUrl: "URL WebSocket",
token: "Token do Gateway",
password: "Palavra-passe (não armazenada)",
sessionKey: "Chave de Sessão Predefinida",
language: "Idioma",
connectHint: "Clique em Ligar para aplicar as alterações de ligação.",
trustedProxy: "Autenticado por proxy de confiança.",
},
snapshot: {
title: "Snapshot",
subtitle: "Informações mais recentes do handshake do gateway.",
status: "Estado",
uptime: "Tempo de Atividade",
tickInterval: "Intervalo de Tick",
lastChannelsRefresh: "Última Atualização de Canais",
channelsHint: "Utilize Canais para vincular WhatsApp, Telegram, Discord, Signal ou iMessage.",
},
stats: {
instances: "Instâncias",
instancesHint: "Beacons de presença nos últimos 5 minutos.",
sessions: "Sessões",
sessionsHint: "Chaves de sessão recentes monitorizadas pelo gateway.",
cron: "Cron",
cronNext: "Próximo despertar {time}",
},
notes: {
title: "Notas",
subtitle: "Lembretes rápidos para configurações de controlo remoto.",
tailscaleTitle: "Tailscale serve",
tailscaleText:
"Prefira o modo serve para manter o gateway em loopback com autenticação tailnet.",
sessionTitle: "Higiene de sessão",
sessionText: "Utilize /new ou sessions.patch para repor o contexto.",
cronTitle: "Lembretes de Cron",
cronText: "Utilize sessões isoladas para execuções recorrentes.",
},
auth: {
required:
"Este gateway requer autenticação. Adicione um token ou palavra-passe e clique em Ligar.",
failed:
"Falha na autenticação. Copie novamente um URL com token utilizando {command}, ou atualize o token e clique em Ligar.",
},
pairing: {
hint: "Este dispositivo necessita de aprovação de emparelhamento do anfitrião do gateway.",
mobileHint:
"No telemóvel? Copie o URL completo (incluindo #token=...) executando openclaw dashboard --no-open no computador.",
},
insecure: {
hint: "Esta página é HTTP, pelo que o navegador bloqueia a identidade do dispositivo. Utilize HTTPS (Tailscale Serve) ou abra {url} no anfitrião do gateway.",
stayHttp: "Se precisar de permanecer em HTTP, defina {config} (apenas token).",
},
},
chat: {
disconnected: "Desligado do gateway.",
refreshTitle: "Atualizar dados do chat",
thinkingToggle: "Alternar saída de pensamento/trabalho do assistente",
focusToggle: "Alternar modo de foco (ocultar barra lateral + cabeçalho da página)",
onboardingDisabled: "Desativado durante a integração",
},
languages: {
en: "English",
zhCN: "简体中文 (Chinês Simplificado)",
zhTW: "繁體中文 (Chinês Tradicional)",
ptBR: "Português (Português do Brasil)",
ptPT: "Português (Português Europeu)",
esAR: "Español (Espanhol Argentino)",
},
};

View File

@@ -117,5 +117,6 @@ export const zh_CN: TranslationMap = {
zhCN: "简体中文 (简体中文)",
zhTW: "繁體中文 (繁体中文)",
ptBR: "Português (巴西葡萄牙语)",
de: "Deutsch (德语)",
},
};

View File

@@ -117,5 +117,6 @@ export const zh_TW: TranslationMap = {
zhCN: "简体中文 (簡體中文)",
zhTW: "繁體中文 (繁體中文)",
ptBR: "Português (巴西葡萄牙語)",
de: "Deutsch (德語)",
},
};

View File

@@ -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>