Skip to content

feat(i18n): add German (de) locale#28495

Merged
Evizero merged 2 commits intoopenclaw:mainfrom
dsantoreis:feat/i18n-german
Feb 27, 2026
Merged

feat(i18n): add German (de) locale#28495
Evizero merged 2 commits intoopenclaw:mainfrom
dsantoreis:feat/i18n-german

Conversation

@dsantoreis
Copy link
Contributor

Summary

Add German locale to the OpenClaw Control UI.

New Language

  • 🇩🇪 German (de)

Changes

  • New locale file: — complete translation of all 122 UI strings
  • Updated , (SUPPORTED_LOCALES, lazy import, browser detection)
  • Updated language labels in all existing locales
  • Dynamic language selector using

Contributes to #3460

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 27, 2026

Greptile Summary

This PR adds German (de) locale support to the OpenClaw Control UI with proper integration into the i18n system. The German translation is complete and the integration is solid: SUPPORTED_LOCALES updated, Locale type extended, browser detection added, and lazy loading implemented. The language selector was improved to dynamically generate options from SUPPORTED_LOCALES.

Major Issue: The PR includes 6 additional complete locale files (es, es-AR, it, ja, ko, pt-PT) totaling ~750 lines of code that are not enabled in SUPPORTED_LOCALES and won't be loaded or used by the application. This appears to be scope creep, as the PR title and description only mention adding German support.

Key Issues:

  • Unused locale files (es.ts, es-AR.ts, it.ts, ja.ts, ko.ts, pt-PT.ts) should be removed or moved to separate PRs
  • German locale's languages object includes keys for unsupported locales (nl, fr, it), creating inconsistency with existing locale files which only list actually supported languages
  • The enabled German locale integration is correct and follows the existing patterns

Confidence Score: 2/5

  • Safe to merge after addressing unused locale files and language label inconsistencies
  • The German locale integration is technically correct and won't cause runtime errors. However, the PR includes 6 unused locale files (~750 LOC) that don't match the stated scope, and the German locale file has inconsistent language labels. These are organizational and maintenance issues rather than functional bugs, but they should be resolved before merge to maintain code quality and prevent confusion.
  • ui/src/i18n/locales/es.ts, ui/src/i18n/locales/es-AR.ts, ui/src/i18n/locales/it.ts, ui/src/i18n/locales/ja.ts, ui/src/i18n/locales/ko.ts, ui/src/i18n/locales/pt-PT.ts, and ui/src/i18n/locales/de.ts (lines 119-128) require attention

Last reviewed commit: 70c76a5

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

14 files reviewed, 7 comments

Edit Code Review Agent Settings | Greptile

Comment on lines +119 to +128
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)",
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

languages object includes keys for unsupported locales (nl, fr, it). These languages aren't in SUPPORTED_LOCALES and don't match the pattern used in existing locale files (en.ts, pt-BR.ts, zh-CN.ts, zh-TW.ts) which only include keys for the 5 supported locales.

Suggested change
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)",
},
languages: {
en: "English",
zhCN: "简体中文 (Vereinfachtes Chinesisch)",
zhTW: "繁體中文 (Traditionelles Chinesisch)",
ptBR: "Português (Brasilianisches Portugiesisch)",
de: "Deutsch",
},
Prompt To Fix With AI
This is a comment left during a code review.
Path: ui/src/i18n/locales/de.ts
Line: 119-128

Comment:
`languages` object includes keys for unsupported locales (`nl`, `fr`, `it`). These languages aren't in `SUPPORTED_LOCALES` and don't match the pattern used in existing locale files (`en.ts`, `pt-BR.ts`, `zh-CN.ts`, `zh-TW.ts`) which only include keys for the 5 supported locales.

```suggestion
  languages: {
    en: "English",
    zhCN: "简体中文 (Vereinfachtes Chinesisch)",
    zhTW: "繁體中文 (Traditionelles Chinesisch)",
    ptBR: "Português (Brasilianisches Portugiesisch)",
    de: "Deutsch",
  },
```

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +1 to +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)",
},
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spanish locale file added but not enabled in SUPPORTED_LOCALES (ui/src/i18n/lib/translate.ts:6) or Locale type union (ui/src/i18n/lib/types.ts:3). This file won't be loaded or used. If Spanish support is intended for this PR, add "es" to both locations and add the import case in translate.ts. Otherwise, remove from this PR and add in a dedicated Spanish locale PR.

Prompt To Fix With AI
This is a comment left during a code review.
Path: ui/src/i18n/locales/es.ts
Line: 1-131

Comment:
Spanish locale file added but not enabled in `SUPPORTED_LOCALES` (ui/src/i18n/lib/translate.ts:6) or `Locale` type union (ui/src/i18n/lib/types.ts:3). This file won't be loaded or used. If Spanish support is intended for this PR, add `"es"` to both locations and add the import case in `translate.ts`. Otherwise, remove from this PR and add in a dedicated Spanish locale PR.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +1 to +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)",
},
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spanish-Argentina locale file added but not enabled. Not in SUPPORTED_LOCALES or Locale type, so it won't be loaded. Remove from this PR or integrate properly.

Prompt To Fix With AI
This is a comment left during a code review.
Path: ui/src/i18n/locales/es-AR.ts
Line: 1-126

Comment:
Spanish-Argentina locale file added but not enabled. Not in `SUPPORTED_LOCALES` or `Locale` type, so it won't be loaded. Remove from this PR or integrate properly.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +1 to +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",
},
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Italian locale file added but not enabled. Not in SUPPORTED_LOCALES or Locale type, so it won't be loaded. Remove from this PR or integrate properly.

Prompt To Fix With AI
This is a comment left during a code review.
Path: ui/src/i18n/locales/it.ts
Line: 1-128

Comment:
Italian locale file added but not enabled. Not in `SUPPORTED_LOCALES` or `Locale` type, so it won't be loaded. Remove from this PR or integrate properly.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +1 to +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をブロックします。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: "한국어(韓国語)",
},
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Japanese locale file added but not enabled. Not in SUPPORTED_LOCALES or Locale type, so it won't be loaded. Remove from this PR or integrate properly.

Prompt To Fix With AI
This is a comment left during a code review.
Path: ui/src/i18n/locales/ja.ts
Line: 1-131

Comment:
Japanese locale file added but not enabled. Not in `SUPPORTED_LOCALES` or `Locale` type, so it won't be loaded. Remove from this PR or integrate properly.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +1 to +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: "한국어",
},
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Korean locale file added but not enabled. Not in SUPPORTED_LOCALES or Locale type, so it won't be loaded. Remove from this PR or integrate properly.

Prompt To Fix With AI
This is a comment left during a code review.
Path: ui/src/i18n/locales/ko.ts
Line: 1-131

Comment:
Korean locale file added but not enabled. Not in `SUPPORTED_LOCALES` or `Locale` type, so it won't be loaded. Remove from this PR or integrate properly.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +1 to +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)",
},
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Portuguese-Portugal locale file added but not enabled. Not in SUPPORTED_LOCALES or Locale type, so it won't be loaded. Remove from this PR or integrate properly.

Prompt To Fix With AI
This is a comment left during a code review.
Path: ui/src/i18n/locales/pt-PT.ts
Line: 1-126

Comment:
Portuguese-Portugal locale file added but not enabled. Not in `SUPPORTED_LOCALES` or `Locale` type, so it won't be loaded. Remove from this PR or integrate properly.

How can I resolve this? If you propose a fix, please make it concise.

@Evizero Evizero self-assigned this Feb 27, 2026
dsantoreis and others added 2 commits February 27, 2026 11:35
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
@Evizero
Copy link
Member

Evizero commented Feb 27, 2026

I reviewed and prepared this PR for merge readiness.

Kept the PR scoped to German locale support only and removed unrelated non-German locale additions (es, es-AR, it, ja, ko, pt-PT).

German translation updates in ui/src/i18n/locales/de.ts:

Key From To Motivation
common.health Zustand Status Topbar badge context; “Status” is the clearer UI term
tabs.agents Agents Agenten Avoid mixed English/German in navigation
tabs.skills Skills Fähigkeiten Consistent localized navigation terminology
tabs.nodes Knoten Geräte Tab represents paired devices/capabilities; “Geräte” fits meaning better
subtitles.instances Präsenzsignale von verbundenen Clients und Knoten. Präsenzsignale von verbundenen Clients und Geräten. Keep wording consistent with nodes -> Geräte
overview.stats.cronNext Nächste Aktivierung {time} Nächste Ausführung {time} Better scheduled-run wording in German
overview.notes.subtitle Kurze Erinnerungen für Fernsteuerungskonfigurationen. Kurze Hinweise für Remote-Steuerung. More natural, less literal helper text
overview.pairing.hint Dieses Gerät benötigt die Kopplungsgenehmigung vom Gateway-Host. Dieses Gerät benötigt eine Pairing-Freigabe vom Gateway-Host. More natural approval-action phrasing
chat.thinkingToggle Denk-/Arbeitsausgabe des Assistenten ein-/ausschalten Ausgabe des Assistenten ein-/ausblenden Shorter tooltip, same intent
languages.de Deutsch (Deutsch) Deutsch Remove redundant self-label

Validation run after rebase onto latest main:

  • pnpm build
  • pnpm check
  • pnpm test

PR branch is prepared for maintainer merge.

@Evizero Evizero merged commit 84a88b2 into openclaw:main Feb 27, 2026
26 checks passed
@Evizero
Copy link
Member

Evizero commented Feb 27, 2026

Merged via squash.

Thanks @dsantoreis!

@dsantoreis
Copy link
Contributor Author

Thank you @Evizero for the thorough review and translation improvements! The German wording changes are much more natural. Really appreciate you taking the time to scope and prepare the PR for merge.

I've applied the same scoping pattern to the remaining i18n PRs — each one now contains only its own locale. Looking forward to your review on those as well!

github-actions bot pushed a commit to tankerwng2/openclaw that referenced this pull request Feb 27, 2026
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e418326
Co-authored-by: dsantoreis <220753637+dsantoreis@users.noreply.github.com>
Co-authored-by: Evizero <10854026+Evizero@users.noreply.github.com>
Reviewed-by: @Evizero
sunquangang pushed a commit to ottin4ttc/openclaw that referenced this pull request Feb 27, 2026
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e418326
Co-authored-by: dsantoreis <220753637+dsantoreis@users.noreply.github.com>
Co-authored-by: Evizero <10854026+Evizero@users.noreply.github.com>
Reviewed-by: @Evizero
erik55 pushed a commit to erik55/openclaw that referenced this pull request Feb 27, 2026
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e418326
Co-authored-by: dsantoreis <220753637+dsantoreis@users.noreply.github.com>
Co-authored-by: Evizero <10854026+Evizero@users.noreply.github.com>
Reviewed-by: @Evizero
erik55 pushed a commit to erik55/openclaw that referenced this pull request Feb 27, 2026
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e418326
Co-authored-by: dsantoreis <220753637+dsantoreis@users.noreply.github.com>
Co-authored-by: Evizero <10854026+Evizero@users.noreply.github.com>
Reviewed-by: @Evizero
hmemcpy pushed a commit to hmemcpy/openclaw that referenced this pull request Feb 27, 2026
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e418326
Co-authored-by: dsantoreis <220753637+dsantoreis@users.noreply.github.com>
Co-authored-by: Evizero <10854026+Evizero@users.noreply.github.com>
Reviewed-by: @Evizero
KrD-Hub added a commit to KrD-Hub/openclaw that referenced this pull request Feb 27, 2026
* Secrets migrate: share helpers and narrow env scrub scope

* Secrets migrate: ensure unique backup ids per write

* Agents: restore auth.json static scrub during pi auth discovery

* Secrets migrate: split plan/apply/backup modules

* Onboard: persist env-backed API keys as secret refs

* Onboard auth: use shared secret-ref helpers

* Auth choice tests: assert env-backed keyRef persistence

* Auth choice tests: expect env-backed key refs

* Onboard: require explicit mode for env secret refs

* Tests: align auth-choice helper expectations with secret mode

* Tests: update onboard credential expectations for explicit ref mode

* Onboard: store OpenAI auth in profiles instead of .env

* Tests: narrow OpenAI default model assertion typing

* Onboard auth: remove leftover merge marker

* Onboard OpenAI: explicit secret-input-mode behavior

* Onboard: move volcengine/byteplus auth from .env to profiles

* Onboard non-interactive: avoid rewriting profile-backed keys

* Secrets: keep read-only runtime sync in-memory

* Onboard: require explicit mode for env secret refs

* Docs: document secrets refs runtime and migration

* Docs: add secrets and CLI secrets reference pages

* Docs: address review feedback on secrets docs

* feat(secrets): finalize external secrets runtime and migration hardening

* fix(secrets): harden sops migration sops rule matching

* feat(secrets): expand onboarding secret-ref flows and custom-provider parity

* test: sops invocation assertion

Signed-off-by: joshavant <830519+joshavant@users.noreply.github.com>

* feat(security): add provider-based external secrets management

* docs(secrets): align provider model and add exec resolver coverage

* test(secrets): skip strict file-permission resolver tests on windows

* test(secrets): skip windows ACL-sensitive file-provider runtime tests

* test(session): normalize parent fork parentSession path assertion

* fix(secrets): enforce file provider read timeouts

* fix(secrets): align ref contracts and non-interactive ref persistence

* feat(secrets): replace migrate flow with audit/configure/apply

* fix(secrets): make apply idempotent and keep audit read-only

* feat(secrets): finalize mode rename and validated exec docs

* feat(secrets): allow opt-in symlink exec command paths

* docs(secrets): add direct 1password exec example

* fix(secrets): harden apply and audit plan handling

* test(secrets): cover skill migration and symlinked exec command flow

* docs(secrets): clarify partial migration guidance

* fix(test): skip exec-backed audit batching assertion on windows

* fix(secrets): harden plan target paths and ref-only auth profiles

* docs(secrets): add dedicated apply plan contract page

* fix: stabilize secrets land + docs note (openclaw#26155) (thanks @joshavant)

* docs(gateway): clarify remote token local fallback semantics

* docs(changelog): highlight external secrets management (openclaw#26155)

* docs(changelog): reorder unreleased changes by user interest

* docs(changelog): reorder all unreleased entries by user impact

* fix(browser): land PR openclaw#27617 relay reconnect resilience

* fix(ci): sync protocol models and acpx version

* fix: tolerate missing pi-coding-agent backend export

* fix: detect OpenClaw-managed launchd/systemd services in process respawn

restartGatewayProcessWithFreshPid() checks SUPERVISOR_HINT_ENV_VARS to
decide whether to let the supervisor handle the restart (mode=supervised)
or to fork a detached child (mode=spawned). The existing list only had
native launchd vars (LAUNCH_JOB_LABEL, LAUNCH_JOB_NAME) and systemd vars
(INVOCATION_ID, SYSTEMD_EXEC_PID, JOURNAL_STREAM).

macOS launchd does NOT automatically inject LAUNCH_JOB_LABEL into the
child environment. OpenClaw's own plist generator (buildServiceEnvironment
in service-env.ts) sets OPENCLAW_LAUNCHD_LABEL instead. So on stock macOS
LaunchAgent installs, isLikelySupervisedProcess() returned false, causing
the gateway to fork a detached child on SIGUSR1 restart. The original
process then exits, launchd sees its child died, respawns a new instance
which finds the orphan holding the port — infinite crash loop.

Fix: add OPENCLAW_LAUNCHD_LABEL, OPENCLAW_SYSTEMD_UNIT, and
OPENCLAW_SERVICE_MARKER to the supervisor hint list. These are set by
OpenClaw's own service environment builders for both launchd and systemd
and are the reliable supervised-mode signals.

Fixes openclaw#27605

* fix: clean stale gateway PIDs before triggerOpenClawRestart calls launchctl/systemctl

When the /restart command runs inside an embedded agent process (no
SIGUSR1 listener), it falls through to triggerOpenClawRestart() which
calls launchctl kickstart -k directly — bypassing the pre-restart port
cleanup added in openclaw#27013. If the gateway was started via TUI/CLI, the
orphaned process still holds the port and the new launchd instance
crash-loops.

Add synchronous stale-PID detection (lsof) and termination
(SIGTERM→SIGKILL) inside triggerOpenClawRestart() itself, so every
caller — including the embedded agent /restart path — gets port cleanup
before the service manager restart command fires.

Closes openclaw#26736

Made-with: Cursor

* feat(agents): default codex transport to websocket-first

* chore(deps): refresh grammy and @types/node

* fix(gateway): add ThrottleInterval to launchd plist to prevent restart loop

* docs(changelog): unify gateway restart-loop fixes

* fix(security): centralize dm/group allowlist auth composition

* fix(telegram): split stop-created preview finalization path

Refactor lane preview finalization into explicit branches so stop-created
previews never duplicate sends when edit fails.

Add Telegram dispatch regressions for:
- stop-created preview edit failure (no duplicate send)
- existing preview edit failure (fallback send preserved)
- missing message id after stop-created flush (fallback send)

Thanks @obviyus for the original preview-prime direction in openclaw#27449.

Co-authored-by: Ayaan Zaidi <hi@obviy.us>

* fix(security): bind node system.run approvals to env

* fix(pi): stop history image reinjection token blowup

* refactor(restart): extract stale pid cleanup and supervisor markers

* fix(bluebubbles): allow configured host for attachment SSRF guard

Co-authored-by: damaozi <1811866786@qq.com>

* fix(msteams): Send invokeResponse immediately to prevent Teams timeout (openclaw#27632)

Fix file upload 'Something went wrong' error by sending the invoke
acknowledgement before performing the file upload, rather than after.

Changes:
- Move invokeResponse to fire immediately upon receiving fileConsent/invoke
- Handle file upload asynchronously without blocking the response
- Update test to wait for async upload completion using vi.waitFor

This prevents Teams from timing out while waiting for the HTTP 200
acknowledgement during slow file uploads to OneDrive.

Fixes openclaw#27632

* fix(msteams): Fix test timing for async file upload handling

Update tests to properly wait for async file upload operations:
- Use vi.waitFor() to wait for async upload completion in success case
- Use vi.waitFor() to wait for error message in cross-conversation case
- Add setTimeout delay for decline case to ensure async handler completes
- Adjust assertion order to match new execution flow (invokeResponse first)

The tests were failing because the file upload now happens asynchronously
after sending the invokeResponse, so we need to explicitly wait for the
async operations to complete before making assertions.

* fix(msteams): Fix code formatting

Remove trailing whitespace to pass oxfmt format check.

* fix: finalize teams file-consent timeout landing (openclaw#27641) (thanks @scz2011)

* refactor: unify channel/plugin ssrf fetch policy and auth fallback

* refactor(pi): extract history image prune helpers

* docs: add unreleased security note for msteams ssrf hardening

* refactor(pi): simplify image reference detection

* fix: set authHeader: true by default for MiniMax API provider (openclaw#27622)

* Update onboard-auth.config-minimax.ts

fix issue openclaw#27600

* fix(minimax): default authHeader for implicit + onboarding providers (openclaw#27600)

Landed from contributor PR openclaw#27622 by @riccoyuanft and PR openclaw#27631 by @kevinWangSheng.
Includes a small TS nullability guard in lane delivery to keep build green on rebased head.

Co-authored-by: riccoyuanft <riccoyuan@gmail.com>
Co-authored-by: Kevin Shenghui <shenghuikevin@github.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Kevin Shenghui <shenghuikevin@github.com>

* feat(android): add device invoke protocol commands

* feat(android): add device status and info handler

* feat(android): wire device commands into runtime

* refactor(android): remove dead thermal sdk branch

* fix(android): require validated network for device status

* docs: add changelog for android device node commands (openclaw#27664) (thanks @obviyus)

* refactor(exec-approvals): unify system.run binding and generate host env policy

* fix: harden typing lifecycle and cross-channel suppression

* fix: harden plugin route auth path canonicalization

* test(exec-approvals): cover v1 binding precedence and mismatch mapping

* Mattermost: avoid raw fetch in monitor media download

* protocol: regenerate Swift models for exec env field

* refactor: share gateway security path canonicalization

* fix(gateway): preserve turn-origin messageChannel in agent runs

* refactor: unify typing dispatch lifecycle and policy boundaries

* fix(agents): harden compaction and reset safety

Co-authored-by: jaden-clovervnd <91520439+jaden-clovervnd@users.noreply.github.com>
Co-authored-by: Sid <201593046+Sid-Qin@users.noreply.github.com>
Co-authored-by: Marcus Widing <245375637+widingmarcus-cyber@users.noreply.github.com>

* test(agents): add compaction and workspace reset regressions

* refactor: unify dm policy store reads and reason codes

* fix(discord): avoid invalid /acp native option payload

* docs(acp): expand /acp operator playbook

* add me to Maintainers list

Signed-off-by: joshavant <830519+joshavant@users.noreply.github.com>

* docs(security): scope obfuscation parity reports as hardening

* docs(security): clarify Teams fileConsent uploadUrl report scope

* refactor(security): enforce v1 node exec approval binding

* feat(auto-reply): make agent time-aware with message timestamps

Add human-readable timestamp field to the Conversation info JSON block.

Before:
  {
    "conversation_label": "D id:123"
  }

After:
  {
    "conversation_label": "D id:123",
    "timestamp": "Sun 2026-02-15 13:35 GMT+8"
  }

Benefits:
- Better time awareness for time-related questions
- Understand conversation gaps and response delays
- Handle delayed message delivery
- Context for relative time references ("just now", "later")

* test(auto-reply): cover inbound timestamp guard

* docs(changelog): add PR openclaw#17017 entry

* fix: enforce explicit group auth boundaries across channels

* fix: restore dm command and self-chat auth behavior

* style: format auth boundary updates

* fix(cli): gateway status probe with TLS when bind=lan

- Use wss:// scheme when TLS is enabled (specifically for bind=lan)
- Load TLS runtime to get certificate fingerprint
- Pass fingerprint to probeGatewayStatus for self-signed cert trust

* fix(cli): add TLS daemon-status probe regression coverage

* fix(cli): scope daemon status TLS fingerprint to local probes

* test(cli): tighten daemon status TLS mock typings

* fix(cli): list all supported auth modes in gateway run --auth help

Made-with: Cursor

* fix: align gateway run auth modes (openclaw#27469) (thanks @s1korrrr)

* Add contributor Jonathan Taylor to CONTRIBUTING.md

Added Jonathan Taylor's contributions and contact links.

* fix: add nimrod gutman maintainer profile (openclaw#27840) (thanks @ngutman)

* fix: harden dm command authorization in open mode

* fix(windows): normalize namespaced path containment checks

* refactor(cli): dedupe gateway run mode parsing

* fix(config): add openai-codex-responses to ModelApiSchema

The config schema validates provider api fields against ModelApiSchema,
but openai-codex-responses was missing from the allowed values. This
forces users to set api: "openai-responses" for the openai-codex
provider, which routes requests to api.openai.com/v1/responses instead
of chatgpt.com/backend-api/codex/responses, causing HTTP 401 errors
because Codex OAuth tokens lack api.responses.write scope for the
standard OpenAI Responses endpoint.

The runtime already supports openai-codex-responses throughout: model
registry, stream dispatch (streamOpenAICodexResponses), and provider
detection (OPENAI_MODEL_APIS set). Only the config schema was missing
the literal.

* fix: align codex model api schema/type coverage (openclaw#27501) (thanks @AytuncYildizli)

* refactor(config): dedupe model api definitions

* CI: add maintainer ping auto-response

* fix(tui): preserve streamed text during tool call transitions

Fixes openclaw#27674

The TUI was erasing already-streamed assistant text when tool calls
were triggered. This happened because the finalize() method in
TuiStreamAssembler was not using the protectBoundaryDrops option
when updating run state.

Now finalize() applies the same boundary drop protection as
ingestDelta(), ensuring that streamed text before tool calls is
preserved when the final payload drops earlier content blocks.

* fix: narrow finalize boundary-drop guard (openclaw#27711) (thanks @scz2011)

* refactor(tui): simplify stream boundary-drop modes

* Changelog: add entries for PR openclaw#12849 and openclaw#27585 (openclaw#27887)

* fix(browser): stop wrapping application errors with Can't reach message

* fix: pass sessionKey to deliverOutboundPayloads for message:sent hook dispatch

Several call sites of deliverOutboundPayloads() were not passing the
sessionKey parameter, causing the internal message:sent hook to never
fire (the guard `if (!sessionKeyForInternalHooks) return` in deliver.ts
silently skipped the triggerInternalHook call).

Fixed call sites:
- commands/agent/delivery.ts (agent loop replies — main fix)
- infra/heartbeat-runner.ts (heartbeat OK + alert delivery)
- infra/outbound/message.ts (message tool sends)
- cron/isolated-agent/delivery-dispatch.ts (cron job delivery)
- gateway/server-node-events.ts (node event forwarding)

The sessionKey parameter already existed in DeliverOutboundPayloadsCoreParams
and was used by deliver.ts to emit the message:sent internal hook event,
but was simply not being passed from most callers.

* fix: complete sessionKey forwarding for message:sent hook (openclaw#27584) (thanks @qualiobra)

* fix(matrix): preserve sender labels in Matrix BodyForAgent

* refactor(matrix): dedupe sender label resolution for inbound bodies

* refactor: unify outbound session context wiring

* fix(gemini-oauth): align OAuth project discovery metadata and endpoint fallbacks (openclaw#16684)

* fix(gemini-oauth): align loadCodeAssist metadata and endpoint fallback

* test(gemini-oauth): cover endpoint fallback and env project fallback

* fix(gemini-oauth): route timed fetches through ssrf guard

* test(gemini-oauth): mock guarded fetch in oauth tests

* chore(onboarding): add explicit account-risk warning for Gemini CLI OAuth and docs (openclaw#16683)

* docs: add account-risk caution to Google OAuth provider docs

* docs(plugin): add Gemini CLI account safety caution

* CLI: add risk hint for Gemini CLI auth choice

* Onboarding: require confirmation for Gemini CLI OAuth

* Tests: cover Gemini CLI OAuth risk confirmation flow

* fix(voice-call): bind webhook dedupe to verified request identity

* feat(config): add embedded pi project settings policy

* fix(agents): harden embedded pi project settings loading

* fix(security): harden node exec approvals against symlink rebind

* refactor(voice-call): share header and guarded api helpers

* refactor(voice-call): enforce verified webhook key contract

* test(voice-call): cover verification key and header helpers

* docs: enforce repo-relative file refs in AGENTS

* refactor(extensions): use scoped pairing helper

* refactor(security): enforce account-scoped pairing APIs

* refactor(node-host): split system.run plan and allowlist internals

* refactor(gateway): share node command catalog

* refactor(gateway): centralize system.run approval context and errors

* refactor(cli): decompose nodes run approval flow

* fix(nodes): resolve default node when multiple canvas-capable nodes are connected

`pickDefaultNode()` returned null when multiple connected canvas-capable
nodes existed and none matched the local Mac heuristic. This caused
"node required" errors for agents (especially sub-agents) calling the
canvas tool without an explicit node parameter.

In multi-node setups, any canvas-capable node is a valid target — the
receiving node broadcasts A2UI surfaces to all other connected devices.
Fall back to the first connected candidate instead of failing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: add nodes default-node regression test (openclaw#27444) (thanks @carbaj03)

* fix(agent): forward resolved outbound session context for delivery

* fix(browser): accept fill fields without explicit type

Default missing fill field type to 'text' in /act route to avoid spurious 'fields are required' failures from relay/tool callers. Add regression test for fill payloads with ref+value only.

* fix: browser fill default type parity (openclaw#27662) (thanks @Uface11)

* test(gateway): align outbound session assertion shape

* docs(changelog): credit reporter for pairing isolation fix

* refactor(browser): unify fill field normalization

* fix: forward resolved session key in agent delivery (follow-up openclaw#27584 by @qualiobra)

Co-authored-by: Lucas Teixeira Campos Araujo <lucas@MacBook-Pro-de-Lucas.local>

* refactor(nodes): share default selection and tighten node.list fallback

* test: fix pairing/daemon assertion drift

* test: fix TS2783 in nodes-utils helper

* docs: reorder unreleased 2026.2.26 changelog entries

* fix(cli): accept node24 executable names in argv reparse

* fix: preserve assistant usage snapshots during compaction cleanup

* refactor(channels): unify dm pairing policy flows

* fix(models): extend gpt-5.3-codex forward compat to github-copilot

The codex forward-compat fallback only matched openai-codex, leaving
github-copilot users without gpt-5.3-codex despite the model being
available on the Copilot API.

Made-with: Cursor

* fix(delivery-queue): change break to continue to prevent head-of-line blocking

When an entry's backoff exceeds the recovery budget, the code was using
break which blocked all subsequent entries from being processed. This
caused permanent queue blockage for any installation with a delivery entry
at retryCount >= 2.

Fix: Changed break to continue so entries whose backoff exceeds the
remaining budget are skipped individually rather than blocking the
entire loop.

Closes openclaw#27638

* fix: harden delivery recovery backoff eligibility and tests (openclaw#27710) (thanks @Jimmy-xuzimo)

* docs(security): clarify parity-only command-risk reports

* refactor(daemon): unify runtime binary detection

* refactor(outbound): split recovery counters and normalize legacy retry entries

* chore: silence onboard warning noise

* fix(googlechat): keep startAccount pending until abort to prevent restart loop

* fix: add googlechat lifecycle regression test (openclaw#27384) (thanks @junsuwhy)

* fix: harden temp dir perms for umask 0002 (landed from openclaw#27860 by @stakeswky)

Co-authored-by: 不做了睡大觉 <stakeswky@gmail.com>

* fix(nextcloud-talk): keep startAccount pending until abort (openclaw#27897)

* test: align compaction hook usage expectation

* fix(cli): make gateway --force resilient to lsof EACCES

* test: align compaction hook usage expectation

* fix: reject dmPolicy="allowlist" with empty allowFrom across all channels

When dmPolicy is set to "allowlist" but allowFrom is missing or empty,
all DMs are silently dropped because no sender can match the empty
allowlist. This is a common pitfall after upgrades that change how
allowlist files are handled (e.g., external allowlist-dm.json files
being deprecated in favor of inline allowFrom arrays).

Changes:
- Add requireAllowlistAllowFrom schema refinement (zod-schema.core.ts)
- Apply validation to all channel schemas: Telegram, Discord, Slack,
  Signal, IRC, iMessage, BlueBubbles, MS Teams, Google Chat, WhatsApp
- Add detectEmptyAllowlistPolicy to doctor-config-flow.ts so
  "openclaw doctor" surfaces a clear warning with remediation steps
- Add 12 test cases covering reject/accept for multiple channels

Fixes openclaw#27892

* fix: skip allowFrom validation at account level (inherits from parent)

Account configs inherit channel-level fields at runtime (e.g.,
resolveTelegramAccount shallow-merges top-level and account values).
An account can set dmPolicy='allowlist' and rely on the parent's
allowFrom, so validating allowFrom on the account object alone
incorrectly rejects valid multi-account configs.

Removes requireAllowlistAllowFrom and requireOpenAllowFrom from all
account-level schemas (Telegram, Signal, IRC, iMessage, BlueBubbles).
Top-level config schemas still enforce the validation.

Addresses Codex review feedback on openclaw#27936.

* fix: enforce dm allowFrom inheritance across account channels (openclaw#27936) (thanks @widingmarcus-cyber)

* Protocol: regenerate Swift models for systemRunPlanV2

* docs(changelog): reorder docker gateway fix by user impact

* chore(release): cut 2026.2.26-beta.1

* chore(release): point appcast to beta tag

* fix(ios): eliminate Swift warnings and clean build logs

* fix: unblock CI minimatch audit and host policy check

* fix(ci): align sync boundary realpath canonicalization

* Changelog: include Gemini OAuth PRs openclaw#16683 and openclaw#16684 (openclaw#27987)

* fix: repair Telegram allowlist DM migrations (openclaw#27936) (thanks @widingmarcus-cyber)

* docs(cli): improve secrets command guide

* Docs: expand ACP first-use naming and link protocol site

* fix(agents): add forward-compat fallback for google-gemini-cli gemini-3.1-pro/flash-preview (openclaw#26570)

* fix(agents): add "google" provider to isReasoningTagProvider to prevent reasoning leak

The gemini-api-key auth flow creates a profile with provider "google"
(e.g. google/gemini-3-pro-preview), but isReasoningTagProvider only
matched "google-gemini-cli" (OAuth) and "google-generative-ai". As a
result:
- reasoningTagHint was false → system prompt omitted <think>/<final>
  formatting instructions
- enforceFinalTag was false → <final> tag filtering was skipped

Raw <think> reasoning output was delivered to the end user.

Fix: add the bare "google" provider string to the match list and cover
it with two new test cases (exact match + case-insensitive).

Fixes openclaw#26551

* fix(agents): add forward-compat fallback for google-gemini-cli gemini-3.1-pro/flash-preview

gemini-3.1-pro-preview and gemini-3.1-flash-preview are not yet present in
pi-ai's built-in google-gemini-cli model catalog (only gemini-3-pro-preview
and gemini-3-flash-preview are registered). When users configure these models
they get "Unknown model" errors even though Gemini CLI OAuth supports them.

The codebase already has isGemini31Model() in extra-params.ts, which proves
intent to support these models. Add a resolveGoogleGeminiCli31ForwardCompatModel
entry to resolveForwardCompatModel following the same clone-template pattern
used for zai/glm-5 and anthropic 4.6 models.

- gemini-3.1-pro-* clones gemini-3-pro-preview (with reasoning: true)
- gemini-3.1-flash-* clones gemini-3-flash-preview (with reasoning: true)

Also add test helpers and three test cases to model.forward-compat.test.ts.

Fixes openclaw#26524

* Changelog: credit Google Gemini provider fallback fixes

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>

* fix(provider): normalize bare gemini-3 Pro model IDs for google-antigravity (openclaw#24145)

* fix(provider): normalize bare gemini-3 Pro model IDs for google-antigravity

The Antigravity Cloud Code Assist API requires a thinking-tier suffix
(-low or -high) for all Gemini 3 Pro variants.  When a user configures
a bare model ID like `gemini-3.1-pro`, the API returns a 404 because it
only recognises `gemini-3.1-pro-low` or `gemini-3.1-pro-high`.

Add `normalizeAntigravityModelId()` that appends `-low` (the default
tier) to bare Pro model IDs, and apply it during provider normalisation
for `google-antigravity`.  Also refactor the per-provider model
normalisation into a shared `normalizeProviderModels()` helper.

Closes openclaw#24071

Co-authored-by: Cursor <cursoragent@cursor.com>

* Tests: cover antigravity model ID normalization

* Changelog: note antigravity pro tier normalization

* Tests: type antigravity model helper inputs

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>

* chore(release): cut 2026.2.26

* test: stabilize docker live model suites

* ui: remove Google Fonts import blocked by CSP (style-src 'self' 'unsafe-inline'); fonts never loaded; closes openclaw#28038

* docs(telegram): clarify group auth boundary

* docs: consolidate grammy links to telegram

* docs: remove legacy grammy page

* docs(telegram): align channel docs with runtime behavior

* fix(update): fallback to --omit=optional when global npm update fails (openclaw#24896)

* fix(update): fallback to --omit=optional when global npm update fails

* fix(update): add recovery hints and fallback for npm global update failures

* chore(update): align fallback progress step index ordering

* chore(update): label omit-optional retry step in progress output

* chore(update): avoid showing 1/2 when fallback path is not used

* chore(ci): retrigger after unrelated test OOM

* fix(update): scope recovery hints to npm failures

* test(update): cover non-npm hint suppression

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>

* Fix NODE_EXTRA_CA_CERTS missing from LaunchAgent environment on macOS

launchd services do not inherit the shell environment, so Node's undici/fetch
cannot locate the macOS system CA bundle (/etc/ssl/cert.pem). This causes TLS
verification failures for all HTTPS requests (e.g. Telegram, webhooks) when the
gateway runs as a LaunchAgent, while the same gateway works fine in a terminal.

Add NODE_EXTRA_CA_CERTS defaulting to /etc/ssl/cert.pem on macOS in both
buildServiceEnvironment and buildNodeServiceEnvironment. User-supplied
NODE_EXTRA_CA_CERTS is always respected and takes precedence.

Fixes openclaw#22856

Co-authored-by: Clawborn <tianrun.yang103@gmail.com>

* fix: add missing closing brace in proxy env test

* fix: stabilize launchd CA env tests (openclaw#27915) (thanks @Lukavyi)

* Fix npm-spec plugin installs when npm pack output is empty (openclaw#21039)

* fix(plugins): recover npm pack archive when stdout is empty

* test(plugins): create npm pack archive in metadata mock

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>

* fix(plugins): clear error when npm package not found (Closes openclaw#24993) (openclaw#25073)

* Docs: align gateway config key paths with metadata (openclaw#28196)

* Docs: align gateway config key paths in reference

* Docs: expand config reference coverage for channels plugins and providers

* fix(android): parse camera and screen invoke params as JSON

* test(android): cover camera clip upload URL JSON parsing

* refactor(android): make camera clip transport deterministic

* test(android): cover camera clip payload size guard

* fix(android): reject non-positive camera maxWidth

* fix: update changelog for android camera clip (openclaw#28229) (thanks @obviyus)

* Changelog: add missing npm update and plugin fix credits (openclaw#28257)

* feat(android): add camera list and device selection

* feat(nodes): add device status and info actions

* docs(nodes): document android camera list and device actions

* fix(android): scale invoke result ack timeout to invoke budget

* feat(node): add device diagnostics and notification action commands

* feat(android): implement device diagnostics and notification actions

* feat(nodes): expose device diagnostics and notification actions

* fix(nodes): reject facing=both when camera deviceId is set

* fix(android): allow open and reply on non-clearable notifications

* fix(android): rebind listener before notification actions

* refactor(nodes): map read actions to invoke commands

* refactor(android-node): unify notifications snapshot rebind preflight

* refactor(android-node): share battery snapshot parsing across device handlers

* docs(changelog): note android node diagnostics and action updates (openclaw#28260) (thanks @obviyus)

* fix: add npm link to fix CLI permission denied (exit 127) (openclaw#17151)

Co-authored-by: Yutaka Sasaki <sskyu@minio.local>

* CI: smoke test root Dockerfile openclaw CLI (openclaw#28308)

* Docker: replace npm link with root CLI symlink (openclaw#28312)

* Gateway: improve device-auth v2 migration diagnostics (openclaw#28305)

* Gateway: add device-auth detail code resolver

* Gateway: emit specific device-auth detail codes

* Gateway tests: cover nonce and signature detail codes

* Docs: add gateway device-auth migration diagnostics

* Docs: add device-auth v2 troubleshooting signatures

* fix(agents): demote Ollama empty-discovery log from warn to debug (openclaw#26379)

When Ollama responds successfully but returns zero models (e.g. on Linux
with the bundled `ollama-stub.service`), `discoverOllamaModels` was
logging at `warn` level:

  [agents/model-providers] No Ollama models found on local instance

This appeared on every agent invocation even when Ollama was not
intentionally configured, polluting production logs.  An empty model
list is a normal operational state — it warrants at most a debug
note, not a warning.

Fix: change `log.warn` → `log.debug` for the zero-models branch.
The error paths (HTTP failure, fetch exception) remain at `warn`
since those indicate genuine connectivity problems.

Closes openclaw#26354

* test: add android integration test script

* docs: document android capability sweep in testing guide

* feat(android): wire runtime canvas capability refresh

* feat(gateway): add node canvas capability refresh flow

* test(gateway): add live android capability integration suite

* docs(android): add integration test preconditions and pitfalls

* fix(android): retry A2UI after canvas capability refresh

* fix(android): return valid debug.ed25519 diagnostics JSON

* fix(media): serve JavaScript assets with text/javascript

* fix(android): refresh scoped canvas URLs without trailing slash

* fix(android): avoid duplicate A2UI readiness probe on happy path

* fix: update changelog for android capability refresh land (openclaw#28388) (thanks @obviyus)

* fix(android): send object params for canvas capability refresh

* fix: document canvas capability refresh params fix (openclaw#28413) (thanks @obviyus)

* Discord: thread bindings idle + max-age lifecycle (openclaw#27845) (thanks @osolmaz)

* refactor discord thread bindings to idle and max-age lifecycle

* fix: migrate legacy thread binding expiry and reduce hot-path disk writes

* refactor: remove remaining thread-binding ttl legacy paths

* fix: harden thread-binding lifecycle persistence

* Discord: fix thread binding types in message/reply paths

* Infra: handle win32 unknown inode in file identity checks

* Infra: relax win32 guarded-open identity checks

* Config: migrate threadBindings ttlHours to idleHours

* Revert "Infra: relax win32 guarded-open identity checks"

This reverts commit de94126.

* Revert "Infra: handle win32 unknown inode in file identity checks"

This reverts commit 96fc5dd.

* Discord: re-read live binding state before sweep unbind

* fix: add changelog note for thread binding lifecycle update (openclaw#27845) (thanks @osolmaz)

---------

Co-authored-by: Onur Solmaz <onur@textcortex.com>

* fix(telegram): include replied media files in reply context (openclaw#28488)

* fix(telegram): include replied media files in reply context

* fix(telegram): keep reply media fields nullable

* perf(telegram): defer reply-media fetch to debounce flush

* fix(telegram): gate and preserve reply media attachments

* fix(telegram): preserve cached-sticker reply media context

* fix: update changelog for telegram reply-media context fixes (openclaw#28488) (thanks @obviyus)

* fix(agents): normalize whitespace-padded tool call names before dispatch (openclaw#27094)

Fix tool-call lookup failures when models emit whitespace-padded names by normalizing
both transcript history and live streamed embedded-runner tool calls before dispatch.

Co-authored-by: wangchunyue <80630709+openperf@users.noreply.github.com>
Co-authored-by: Sid <sidqin0410@gmail.com>
Co-authored-by: Philipp Spiess <hello@philippspiess.com>

* feat(i18n): add German (de) locale (openclaw#28495)

Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e418326
Co-authored-by: dsantoreis <220753637+dsantoreis@users.noreply.github.com>
Co-authored-by: Evizero <10854026+Evizero@users.noreply.github.com>
Reviewed-by: @Evizero

* chore: add collaboration rules and OpenRouter env passthrough

* docs: add krakra final mapping and production config template

---------

Signed-off-by: joshavant <830519+joshavant@users.noreply.github.com>
Co-authored-by: joshavant <830519+joshavant@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: taw0002 <webmaster@sodsolutions.com>
Co-authored-by: SidQin-cyber <sidqin0410@gmail.com>
Co-authored-by: Kevin Shenghui <shenghuikevin@github.com>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
Co-authored-by: damaozi <1811866786@qq.com>
Co-authored-by: AI Assistant <ai@assistant.local>
Co-authored-by: riccoyuanft <riccoyuan@gmail.com>
Co-authored-by: Ayaan Zaidi <zaidi@uplause.io>
Co-authored-by: Shakker <shakkerdroid@gmail.com>
Co-authored-by: jaden-clovervnd <91520439+jaden-clovervnd@users.noreply.github.com>
Co-authored-by: Sid <201593046+Sid-Qin@users.noreply.github.com>
Co-authored-by: Marcus Widing <245375637+widingmarcus-cyber@users.noreply.github.com>
Co-authored-by: Liu Yuan <namei.unix@gmail.com>
Co-authored-by: Rafal <mrsikorarafal@gmail.com>
Co-authored-by: Viz <visionik@pobox.com>
Co-authored-by: Nimrod Gutman <nimrod.g@singular.net>
Co-authored-by: AytuncYildizli <cryptosquanch@gmail.com>
Co-authored-by: Shadow <hi@shadowing.dev>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
Co-authored-by: Taras Shynkarenko <taras.shinkarenko@gmail.com>
Co-authored-by: Lucas Teixeira Campos Araujo <lucas@MacBook-Pro-de-Lucas.local>
Co-authored-by: ACV <acv@Mac.home>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Rick <agentrick@Mac.localdomain>
Co-authored-by: Xu Zimo <xuzimojimmy@163.com>
Co-authored-by: Chang Shu-Huai <junsuwhy@gmail.com>
Co-authored-by: 不做了睡大觉 <stakeswky@gmail.com>
Co-authored-by: Marcus Widing <widing.marcus@gmail.com>
Co-authored-by: Philipp Spiess <hello@philippspiess.com>
Co-authored-by: Byungsker <72309817+byungsker@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Xinhua Gu <xinhua.gu@gmail.com>
Co-authored-by: Clawborn <tianrun.yang@hotmail.com>
Co-authored-by: Clawborn <tianrun.yang103@gmail.com>
Co-authored-by: clawdbot <lukavyi@me.com>
Co-authored-by: graysurf <10785178+graysurf@users.noreply.github.com>
Co-authored-by: Dale Yarborough <daleyarborough@gmail.com>
Co-authored-by: Yutaka Sasaki <sskyutaka@gmail.com>
Co-authored-by: Yutaka Sasaki <sskyu@minio.local>
Co-authored-by: Onur Solmaz <2453968+osolmaz@users.noreply.github.com>
Co-authored-by: Onur Solmaz <onur@textcortex.com>
Co-authored-by: wangchunyue <80630709+openperf@users.noreply.github.com>
Co-authored-by: Daniel Reis <dsantoreis@gmail.com>
Co-authored-by: dsantoreis <220753637+dsantoreis@users.noreply.github.com>
Co-authored-by: Evizero <10854026+Evizero@users.noreply.github.com>
Co-authored-by: KrD-Hub <93096409+KrD-Hub@users.noreply.github.com>
Co-authored-by: KraKra <krakra@KraKras-MacBook-Pro.local>
wanjizheng pushed a commit to wanjizheng/openclaw that referenced this pull request Feb 27, 2026
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e418326
Co-authored-by: dsantoreis <220753637+dsantoreis@users.noreply.github.com>
Co-authored-by: Evizero <10854026+Evizero@users.noreply.github.com>
Reviewed-by: @Evizero
wanjizheng pushed a commit to wanjizheng/openclaw that referenced this pull request Feb 27, 2026
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e418326
Co-authored-by: dsantoreis <220753637+dsantoreis@users.noreply.github.com>
Co-authored-by: Evizero <10854026+Evizero@users.noreply.github.com>
Reviewed-by: @Evizero

(cherry picked from commit 78afd7c)
execute008 pushed a commit to execute008/openclaw that referenced this pull request Feb 27, 2026
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e418326
Co-authored-by: dsantoreis <220753637+dsantoreis@users.noreply.github.com>
Co-authored-by: Evizero <10854026+Evizero@users.noreply.github.com>
Reviewed-by: @Evizero
r4jiv007 pushed a commit to r4jiv007/openclaw that referenced this pull request Feb 28, 2026
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e418326
Co-authored-by: dsantoreis <220753637+dsantoreis@users.noreply.github.com>
Co-authored-by: Evizero <10854026+Evizero@users.noreply.github.com>
Reviewed-by: @Evizero
xiexikang pushed a commit to cclawd007/cclawd that referenced this pull request Feb 28, 2026
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e418326
Co-authored-by: dsantoreis <220753637+dsantoreis@users.noreply.github.com>
Co-authored-by: Evizero <10854026+Evizero@users.noreply.github.com>
Reviewed-by: @Evizero
mylukin pushed a commit to mylukin/openclaw that referenced this pull request Feb 28, 2026
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e418326
Co-authored-by: dsantoreis <220753637+dsantoreis@users.noreply.github.com>
Co-authored-by: Evizero <10854026+Evizero@users.noreply.github.com>
Reviewed-by: @Evizero
xiexikang pushed a commit to cclawd007/cclawd that referenced this pull request Feb 28, 2026
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e418326
Co-authored-by: dsantoreis <220753637+dsantoreis@users.noreply.github.com>
Co-authored-by: Evizero <10854026+Evizero@users.noreply.github.com>
Reviewed-by: @Evizero
mylukin pushed a commit to mylukin/openclaw that referenced this pull request Feb 28, 2026
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e418326
Co-authored-by: dsantoreis <220753637+dsantoreis@users.noreply.github.com>
Co-authored-by: Evizero <10854026+Evizero@users.noreply.github.com>
Reviewed-by: @Evizero
wanjizheng pushed a commit to wanjizheng/openclaw that referenced this pull request Feb 28, 2026
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e418326
Co-authored-by: dsantoreis <220753637+dsantoreis@users.noreply.github.com>
Co-authored-by: Evizero <10854026+Evizero@users.noreply.github.com>
Reviewed-by: @Evizero

(cherry picked from commit 78afd7c)
wanjizheng pushed a commit to wanjizheng/openclaw that referenced this pull request Feb 28, 2026
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e418326
Co-authored-by: dsantoreis <220753637+dsantoreis@users.noreply.github.com>
Co-authored-by: Evizero <10854026+Evizero@users.noreply.github.com>
Reviewed-by: @Evizero

(cherry picked from commit 78afd7c)
wanjizheng pushed a commit to wanjizheng/openclaw that referenced this pull request Feb 28, 2026
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e418326
Co-authored-by: dsantoreis <220753637+dsantoreis@users.noreply.github.com>
Co-authored-by: Evizero <10854026+Evizero@users.noreply.github.com>
Reviewed-by: @Evizero

(cherry picked from commit 78afd7c)
wanjizheng pushed a commit to wanjizheng/openclaw that referenced this pull request Feb 28, 2026
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e418326
Co-authored-by: dsantoreis <220753637+dsantoreis@users.noreply.github.com>
Co-authored-by: Evizero <10854026+Evizero@users.noreply.github.com>
Reviewed-by: @Evizero

(cherry picked from commit 78afd7c)
vincentkoc pushed a commit to Sid-Qin/openclaw that referenced this pull request Feb 28, 2026
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e418326
Co-authored-by: dsantoreis <220753637+dsantoreis@users.noreply.github.com>
Co-authored-by: Evizero <10854026+Evizero@users.noreply.github.com>
Reviewed-by: @Evizero
vincentkoc pushed a commit to rylena/rylen-openclaw that referenced this pull request Feb 28, 2026
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e418326
Co-authored-by: dsantoreis <220753637+dsantoreis@users.noreply.github.com>
Co-authored-by: Evizero <10854026+Evizero@users.noreply.github.com>
Reviewed-by: @Evizero
newtontech pushed a commit to newtontech/openclaw-fork that referenced this pull request Feb 28, 2026
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e418326
Co-authored-by: dsantoreis <220753637+dsantoreis@users.noreply.github.com>
Co-authored-by: Evizero <10854026+Evizero@users.noreply.github.com>
Reviewed-by: @Evizero
wanjizheng pushed a commit to wanjizheng/openclaw that referenced this pull request Mar 1, 2026
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e418326
Co-authored-by: dsantoreis <220753637+dsantoreis@users.noreply.github.com>
Co-authored-by: Evizero <10854026+Evizero@users.noreply.github.com>
Reviewed-by: @Evizero
wanjizheng pushed a commit to wanjizheng/openclaw that referenced this pull request Mar 1, 2026
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e418326
Co-authored-by: dsantoreis <220753637+dsantoreis@users.noreply.github.com>
Co-authored-by: Evizero <10854026+Evizero@users.noreply.github.com>
Reviewed-by: @Evizero
hughdidit pushed a commit to hughdidit/DAISy-Agency that referenced this pull request Mar 1, 2026
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e418326
Co-authored-by: dsantoreis <220753637+dsantoreis@users.noreply.github.com>
Co-authored-by: Evizero <10854026+Evizero@users.noreply.github.com>
Reviewed-by: @Evizero

(cherry picked from commit 84a88b2)

# Conflicts:
#	ui/src/i18n/lib/translate.ts
#	ui/src/i18n/lib/types.ts
#	ui/src/ui/views/overview.ts
steipete pushed a commit to Sid-Qin/openclaw that referenced this pull request Mar 2, 2026
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e418326
Co-authored-by: dsantoreis <220753637+dsantoreis@users.noreply.github.com>
Co-authored-by: Evizero <10854026+Evizero@users.noreply.github.com>
Reviewed-by: @Evizero
safzanpirani pushed a commit to safzanpirani/clawdbot that referenced this pull request Mar 2, 2026
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e418326
Co-authored-by: dsantoreis <220753637+dsantoreis@users.noreply.github.com>
Co-authored-by: Evizero <10854026+Evizero@users.noreply.github.com>
Reviewed-by: @Evizero
venjiang pushed a commit to venjiang/openclaw that referenced this pull request Mar 2, 2026
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e418326
Co-authored-by: dsantoreis <220753637+dsantoreis@users.noreply.github.com>
Co-authored-by: Evizero <10854026+Evizero@users.noreply.github.com>
Reviewed-by: @Evizero
robertchang-ga pushed a commit to robertchang-ga/openclaw that referenced this pull request Mar 2, 2026
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e418326
Co-authored-by: dsantoreis <220753637+dsantoreis@users.noreply.github.com>
Co-authored-by: Evizero <10854026+Evizero@users.noreply.github.com>
Reviewed-by: @Evizero
hughdidit pushed a commit to hughdidit/DAISy-Agency that referenced this pull request Mar 3, 2026
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e418326
Co-authored-by: dsantoreis <220753637+dsantoreis@users.noreply.github.com>
Co-authored-by: Evizero <10854026+Evizero@users.noreply.github.com>
Reviewed-by: @Evizero

(cherry picked from commit 84a88b2)

# Conflicts:
#	ui/src/i18n/lib/translate.ts
#	ui/src/i18n/lib/types.ts
#	ui/src/ui/views/overview.ts
dorgonman pushed a commit to kanohorizonia/openclaw that referenced this pull request Mar 3, 2026
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e418326
Co-authored-by: dsantoreis <220753637+dsantoreis@users.noreply.github.com>
Co-authored-by: Evizero <10854026+Evizero@users.noreply.github.com>
Reviewed-by: @Evizero
zooqueen pushed a commit to hanzoai/bot that referenced this pull request Mar 6, 2026
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e418326
Co-authored-by: dsantoreis <220753637+dsantoreis@users.noreply.github.com>
Co-authored-by: Evizero <10854026+Evizero@users.noreply.github.com>
Reviewed-by: @Evizero
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants