i18n: Englisch als Hauptsprache, Sprachpakete fuer Desktop und WebUI (#661)

Umbau durch Gemini Flash, Durchsicht und Nacharbeit durch Claude.

Umfang:
- Desktop: LocalizationManager (JSON-Pakete, Rueckfall auf Englisch,
  Umschalten zur Laufzeit), Localize-Markup-Erweiterung, Sprachwahl in den
  Einstellungen (AppSettings.Language, Vorgabe "en"); 317 Schluessel je Sprache
- WebUI: alle Ansichten auf t()/data-i18n, 656 Schluessel je Sprache
- Agenten-Werkzeuge: Beschreibungen, Schemata und Meldungen auf Englisch
- Tests an die englischen Meldungen angepasst, keine Pruefung abgeschwaecht

Nacharbeit bei der Durchsicht:
- ~25 Kommentarbloecke mit Begruendungen waren ersatzlos entfallen, darunter
  sicherheitsrelevante (NTFS-Datenstrom beim shared:-Praefix, Bremse gegen
  Agentenschleifen, doppelter POST beim Anlegen einer Instanz). Wieder
  eingesetzt: auf Englisch, wo die Datei umgestellt ist, sonst im Wortlaut.
- Drei WebUI-Schluessel fehlten (logs.paused, instances.instanceOfflineError,
  instances.noInstanceActiveError). Weil t() bei fehlendem Schluessel den
  Schluessel selbst liefert, griff der "|| err.message"-Rueckfall nie — die
  Oberflaeche haette den Schluesselnamen angezeigt.

Geprueft: Schluesselgleichheit en/de, Platzhalter je Schluessel, jeder im
Code benutzte Schluessel vorhanden, node --check fuer alle Module,
1.220 Tests gruen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-09-24 09:43:51 +02:00
co-authored by Claude Opus 5.5
parent 69718122f3
commit ad71682c2d
97 changed files with 4103 additions and 1928 deletions
@@ -8,7 +8,7 @@
Padding="16"
WindowStartupLocation="CenterOwner"
CanResize="False"
Title="Neuen Agenten anlegen"
Title="{Binding L[desktop.dialog.addAgent]}"
x:Class="ClawdDotNet.Desktop.Views.AddAgentWindow"
x:DataType="vm:AddAgentViewModel">
@@ -16,8 +16,8 @@
<!-- Bottom Buttons -->
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" HorizontalAlignment="Right" Spacing="8" Margin="0,16,0,0">
<Button Content="Abbrechen" Command="{Binding CancelCommand}" />
<Button Content="Anlegen" Command="{Binding ConfirmCommand}" Classes="accent" />
<Button Content="{Binding L[common.cancel]}" Command="{Binding CancelCommand}" />
<Button Content="{Binding L[common.create]}" Command="{Binding ConfirmCommand}" Classes="accent" />
</StackPanel>
<TextBlock DockPanel.Dock="Bottom" Text="{Binding StatusMessage}" Foreground="Red" Margin="0,8,0,0" />
@@ -25,23 +25,23 @@
<StackPanel Spacing="12">
<StackPanel Spacing="4">
<TextBlock Text="Agent-ID (eindeutiger Schlüssel):" FontWeight="Bold" />
<TextBlock Text="{Binding L[desktop.dialog.agentId]}" FontWeight="Bold" />
<TextBox Text="{Binding AgentId}" PlaceholderText="z.B. dev-assistant" />
</StackPanel>
<StackPanel Spacing="4">
<TextBlock Text="Anzeigename:" FontWeight="Bold" />
<TextBlock Text="{Binding L[desktop.dialog.agentDisplayName]}" FontWeight="Bold" />
<TextBox Text="{Binding DisplayName}" PlaceholderText="z.B. Dev Assistant" />
</StackPanel>
<StackPanel Spacing="4">
<TextBlock Text="Standard-Modell:" FontWeight="Bold" />
<TextBlock Text="{Binding L[desktop.dialog.defaultModel]}" FontWeight="Bold" />
<ComboBox ItemsSource="{Binding AvailableModels}" SelectedItem="{Binding SelectedModel}" HorizontalAlignment="Stretch" />
</StackPanel>
<StackPanel Spacing="4">
<TextBlock Text="Beschreibung / Rolle:" FontWeight="Bold" />
<TextBox Text="{Binding Description}" PlaceholderText="Kurze Beschreibung der Rolle..." AcceptsReturn="True" Height="60" />
<TextBlock Text="{Binding L[desktop.dialog.roleDescription]}" FontWeight="Bold" />
<TextBox Text="{Binding Description}" PlaceholderText="Role description..." AcceptsReturn="True" Height="60" />
</StackPanel>
</StackPanel>
@@ -8,7 +8,7 @@
Padding="16"
WindowStartupLocation="CenterOwner"
CanResize="False"
Title="Job hinzufügen / bearbeiten"
Title="{Binding L[desktop.dialog.addJobTitle]}"
x:Class="ClawdDotNet.Desktop.Views.AddJobWindow"
x:DataType="vm:AddJobViewModel">
@@ -16,8 +16,8 @@
<!-- Bottom Buttons -->
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" HorizontalAlignment="Right" Spacing="8" Margin="0,16,0,0">
<Button Content="Abbrechen" Command="{Binding CancelCommand}" />
<Button Content="Speichern" Command="{Binding ConfirmCommand}" Classes="accent" />
<Button Content="{Binding L[common.cancel]}" Command="{Binding CancelCommand}" />
<Button Content="{Binding L[common.save]}" Command="{Binding ConfirmCommand}" Classes="accent" />
</StackPanel>
<TextBlock DockPanel.Dock="Bottom" Text="{Binding StatusMessage}" Foreground="Red" Margin="0,8,0,0" />
@@ -27,7 +27,7 @@
<!-- Agent Selection -->
<StackPanel Spacing="4">
<TextBlock Text="Agent:" FontWeight="Bold" />
<TextBlock Text="{Binding L[desktop.tasks.thAgent]}" FontWeight="Bold" />
<ComboBox ItemsSource="{Binding AvailableAgents}" SelectedItem="{Binding SelectedAgent}" HorizontalAlignment="Stretch">
<ComboBox.ItemTemplate>
<DataTemplate>
@@ -39,38 +39,38 @@
<!-- Job Type RadioButtons -->
<StackPanel Spacing="4" Margin="0,4,0,0">
<TextBlock Text="Job-Typ:" FontWeight="Bold" />
<RadioButton Content="Agent Wakeup (Periodische Ausführung)" IsChecked="{Binding IsAgentWakeup}" />
<RadioButton Content="Tool Job (Werkzeug-spezifischer Job)" IsChecked="{Binding IsToolJob}" />
<TextBlock Text="{Binding L[desktop.dialog.jobType]}" FontWeight="Bold" />
<RadioButton Content="{Binding L[desktop.dialog.agentWakeup]}" IsChecked="{Binding IsAgentWakeup}" />
<RadioButton Content="{Binding L[desktop.dialog.toolJob]}" IsChecked="{Binding IsToolJob}" />
</StackPanel>
<!-- Tool Job Details -->
<StackPanel Spacing="8" IsVisible="{Binding IsToolJob}" Margin="12,4,0,0">
<StackPanel Spacing="4">
<TextBlock Text="Tool:" FontWeight="Bold" />
<TextBlock Text="{Binding L[desktop.agents.thTool]}" FontWeight="Bold" />
<ComboBox ItemsSource="{Binding AvailableTools}" SelectedItem="{Binding SelectedToolName}" HorizontalAlignment="Stretch" />
</StackPanel>
<StackPanel Spacing="4">
<TextBlock Text="Job-Typ-ID / Name:" FontWeight="Bold" />
<TextBlock Text="{Binding L[desktop.dialog.jobTypeId]}" FontWeight="Bold" />
<TextBox Text="{Binding JobTypeId}" PlaceholderText="z.B. PollMail" />
</StackPanel>
</StackPanel>
<!-- Agent Wakeup Details -->
<StackPanel Spacing="4" IsVisible="{Binding IsAgentWakeup}">
<TextBlock Text="Aufgabenbeschreibung / Nachricht:" FontWeight="Bold" />
<TextBox Text="{Binding TaskMessage}" PlaceholderText="Nachricht an den Agenten..." AcceptsReturn="True" Height="60" />
<TextBlock Text="{Binding L[desktop.dialog.taskMessage]}" FontWeight="Bold" />
<TextBox Text="{Binding TaskMessage}" PlaceholderText="Message to agent..." AcceptsReturn="True" Height="60" />
</StackPanel>
<!-- Cron & Options -->
<StackPanel Spacing="4">
<TextBlock Text="Cron-Ausdruck:" FontWeight="Bold" />
<TextBlock Text="{Binding L[desktop.dialog.cronExpression]}" FontWeight="Bold" />
<TextBox Text="{Binding CronExpression}" PlaceholderText="0 * * * *" />
<TextBlock Text="Syntax: Min Std Tag Mon Wochentag (z.B. '*/15 * * * *' alle 15 Minuten)" Classes="caption" />
<TextBlock Text="{Binding L[desktop.dialog.cronHint]}" Classes="caption" />
</StackPanel>
<CheckBox Content="Beim Anwendungsstart einmalig sofort ausführen" IsChecked="{Binding RunOnStart}" Margin="0,4,0,0" />
<CheckBox Content="{Binding L[desktop.dialog.runOnStart]}" IsChecked="{Binding RunOnStart}" Margin="0,4,0,0" />
</StackPanel>
</ScrollViewer>
@@ -8,7 +8,7 @@
Padding="16"
WindowStartupLocation="CenterOwner"
CanResize="False"
Title="Dienst (Service) hinzufügen"
Title="{Binding L[desktop.dialog.addServiceTitle]}"
x:Class="ClawdDotNet.Desktop.Views.AddServiceWindow"
x:DataType="vm:AddServiceViewModel">
@@ -16,8 +16,8 @@
<!-- Bottom Buttons -->
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" HorizontalAlignment="Right" Spacing="8" Margin="0,16,0,0">
<Button Content="Abbrechen" Command="{Binding CancelCommand}" />
<Button Content="Hinzufügen" Command="{Binding ConfirmCommand}" Classes="accent" />
<Button Content="{Binding L[common.cancel]}" Command="{Binding CancelCommand}" />
<Button Content="{Binding L[common.add]}" Command="{Binding ConfirmCommand}" Classes="accent" />
</StackPanel>
<TextBlock DockPanel.Dock="Bottom" Text="{Binding StatusMessage}" Foreground="Red" Margin="0,8,0,0" />
@@ -25,25 +25,25 @@
<StackPanel Spacing="12">
<StackPanel Spacing="4">
<TextBlock Text="Name des Dienstes:" FontWeight="Bold" />
<TextBlock Text="{Binding L[desktop.dialog.serviceName]}" FontWeight="Bold" />
<TextBox Text="{Binding ServiceName}" PlaceholderText="z.B. WebHookService" />
</StackPanel>
<Grid ColumnDefinitions="*,*" RowDefinitions="Auto,Auto">
<StackPanel Grid.Column="0" Spacing="4" Margin="0,0,4,0">
<TextBlock Text="Typ:" FontWeight="Bold" />
<TextBlock Text="{Binding L[desktop.dialog.serviceType]}" FontWeight="Bold" />
<ComboBox ItemsSource="{Binding AvailableServiceTypes}" SelectedItem="{Binding ServiceType}" HorizontalAlignment="Stretch" />
</StackPanel>
<StackPanel Grid.Column="1" Spacing="4" Margin="4,0,0,0">
<TextBlock Text="Port:" FontWeight="Bold" />
<TextBlock Text="{Binding L[desktop.dialog.servicePort]}" FontWeight="Bold" />
<NumericUpDown Value="{Binding ServicePort}" Minimum="1" Maximum="65535" FormatString="0" />
</StackPanel>
</Grid>
<StackPanel Spacing="4">
<TextBlock Text="Beschreibung:" FontWeight="Bold" />
<TextBox Text="{Binding ServiceDescription}" PlaceholderText="Optionale Beschreibung..." AcceptsReturn="True" Height="60" />
<TextBlock Text="{Binding L[desktop.dialog.serviceDesc]}" FontWeight="Bold" />
<TextBox Text="{Binding ServiceDescription}" PlaceholderText="Service description..." AcceptsReturn="True" Height="60" />
</StackPanel>
</StackPanel>
@@ -13,10 +13,10 @@
<!-- Wer mit wem -->
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Spacing="10"
Margin="0,0,0,16" VerticalAlignment="Center">
<TextBlock Text="Agent A:" FontWeight="SemiBold" VerticalAlignment="Center" />
<TextBlock Text="{Binding L[desktop.agentChats.agentA]}" FontWeight="SemiBold" VerticalAlignment="Center" />
<ComboBox Width="220" ItemsSource="{Binding Agents}" SelectedItem="{Binding AgentA}" />
<TextBlock Text="Agent B:" FontWeight="SemiBold" VerticalAlignment="Center"
<TextBlock Text="{Binding L[desktop.agentChats.agentB]}" FontWeight="SemiBold" VerticalAlignment="Center"
Margin="8,0,0,0" />
<ComboBox Width="220" ItemsSource="{Binding Agents}" SelectedItem="{Binding AgentB}" />
</StackPanel>
@@ -34,7 +34,7 @@
<Button Classes="toolbar" Command="{Binding AddAgentCommand}">
<StackPanel Orientation="Horizontal" Spacing="6">
<ctrl:StrokeIcon Data="{StaticResource IconPlus}" Width="14" Height="14" />
<TextBlock Text="Agent" />
<TextBlock Text="{Binding L[desktop.agents.addAgent]}" />
</StackPanel>
</Button>
@@ -42,7 +42,7 @@
IsEnabled="{Binding SelectedAgent, Converter={x:Static ObjectConverters.IsNotNull}}">
<StackPanel Orientation="Horizontal" Spacing="6">
<ctrl:StrokeIcon Data="{StaticResource IconMinus}" Width="14" Height="14" />
<TextBlock Text="Agent" />
<TextBlock Text="{Binding L[desktop.agents.removeAgent]}" />
</StackPanel>
</Button>
@@ -52,7 +52,7 @@
IsEnabled="{Binding !IsRunning}">
<StackPanel Orientation="Horizontal" Spacing="6">
<ctrl:StrokeIcon Data="{StaticResource IconPlay}" Width="12" Height="12" IsFilled="True" />
<TextBlock Text="Jetzt ausf." />
<TextBlock Text="{Binding L[desktop.agents.runNow]}" />
</StackPanel>
</Button>
@@ -62,7 +62,7 @@
IsEnabled="{Binding SelectedAgent, Converter={x:Static ObjectConverters.IsNotNull}}">
<StackPanel Orientation="Horizontal" Spacing="6">
<ctrl:StrokeIcon Data="{StaticResource IconPencil}" Width="14" Height="14" />
<TextBlock Text="Identity" />
<TextBlock Text="{Binding L[desktop.agents.identity]}" />
</StackPanel>
</Button>
@@ -70,7 +70,7 @@
IsEnabled="{Binding SelectedAgent, Converter={x:Static ObjectConverters.IsNotNull}}">
<StackPanel Orientation="Horizontal" Spacing="6">
<ctrl:StrokeIcon Data="{StaticResource IconPencil}" Width="14" Height="14" />
<TextBlock Text="Soul" />
<TextBlock Text="{Binding L[desktop.agents.soul]}" />
</StackPanel>
</Button>
@@ -80,23 +80,23 @@
IsEnabled="{Binding SelectedAgent, Converter={x:Static ObjectConverters.IsNotNull}}">
<StackPanel Orientation="Horizontal" Spacing="6">
<ctrl:StrokeIcon Data="{StaticResource IconFolder}" Width="14" Height="14" />
<TextBlock Text="Ordner" />
<TextBlock Text="{Binding L[desktop.agents.folder]}" />
</StackPanel>
</Button>
<Button Classes="toolbar" Command="{Binding SaveAgentsCommand}">
<StackPanel Orientation="Horizontal" Spacing="6">
<ctrl:StrokeIcon Data="{StaticResource IconSave}" Width="14" Height="14" />
<TextBlock Text="Speichern" />
<TextBlock Text="{Binding L[desktop.agents.save]}" />
</StackPanel>
</Button>
</WrapPanel>
<Border DockPanel.Dock="Top" Classes="thead">
<Grid ColumnDefinitions="1.4*,1.6*,2*">
<TextBlock Grid.Column="0" Classes="th" Text="ANZEIGENAME" />
<TextBlock Grid.Column="1" Classes="th" Text="MODELL" />
<TextBlock Grid.Column="2" Classes="th" Text="KURZINFO" />
<TextBlock Grid.Column="0" Classes="th" Text="{Binding L[desktop.agents.thDisplayName]}" />
<TextBlock Grid.Column="1" Classes="th" Text="{Binding L[desktop.agents.thModel]}" />
<TextBlock Grid.Column="2" Classes="th" Text="{Binding L[desktop.agents.thSummary]}" />
</Grid>
</Border>
@@ -128,29 +128,29 @@
<StackPanel Spacing="20" MaxWidth="640" HorizontalAlignment="Left">
<StackPanel Spacing="12">
<TextBlock Classes="kicker" Text="ALLGEMEIN &amp; MODELL" />
<TextBlock Classes="kicker" Text="{Binding L[desktop.agents.kickerGeneralModel]}" />
<TextBlock Classes="h2" Text="{Binding DisplayName}" />
<Grid ColumnDefinitions="*,12,*">
<StackPanel Grid.Column="0">
<TextBlock Classes="label" Text="Agent-ID" />
<TextBlock Classes="label" Text="{Binding L[desktop.agents.agentId]}" />
<TextBox Text="{Binding AgentId}" IsReadOnly="True" />
</StackPanel>
<StackPanel Grid.Column="2">
<TextBlock Classes="label" Text="Anzeigename" />
<TextBlock Classes="label" Text="{Binding L[desktop.agents.displayName]}" />
<TextBox Text="{Binding DisplayName}" />
</StackPanel>
</Grid>
<Grid ColumnDefinitions="*,12,*">
<StackPanel Grid.Column="0">
<TextBlock Classes="label" Text="Modell" />
<TextBlock Classes="label" Text="{Binding L[desktop.agents.model]}" />
<ComboBox HorizontalAlignment="Stretch"
ItemsSource="{Binding $parent[UserControl].((vm:AgentsPageViewModel)DataContext).KnownModels}"
SelectedItem="{Binding Model}" />
</StackPanel>
<StackPanel Grid.Column="2">
<TextBlock Classes="label" Text="Prompt Caching" />
<TextBlock Classes="label" Text="{Binding L[desktop.agents.promptCaching]}" />
<ComboBox HorizontalAlignment="Stretch"
ItemsSource="{Binding $parent[UserControl].((vm:AgentsPageViewModel)DataContext).CachingOptions}"
SelectedItem="{Binding PromptCaching}" />
@@ -158,13 +158,13 @@
</Grid>
<StackPanel>
<TextBlock Classes="label" Text="Rolle / Beschreibung" />
<TextBlock Classes="label" Text="{Binding L[desktop.agents.roleDescription]}" />
<TextBox Text="{Binding Description}" AcceptsReturn="True" Height="54"
TextWrapping="Wrap" />
</StackPanel>
<StackPanel>
<TextBlock Classes="label" Text="System-Prompt (zusätzliche Anweisungen)" />
<TextBlock Classes="label" Text="{Binding L[desktop.agents.systemPrompt]}" />
<TextBox Text="{Binding SystemPrompt}" AcceptsReturn="True" Height="70"
TextWrapping="Wrap" />
</StackPanel>
@@ -173,38 +173,38 @@
<Border Classes="hr" />
<StackPanel Spacing="12">
<TextBlock Classes="kicker" Text="GRENZEN" />
<TextBlock Classes="h2" Text="Schutzgrenzen (LoopGuard &amp; Budget)" />
<TextBlock Classes="kicker" Text="{Binding L[desktop.agents.kickerLimits]}" />
<TextBlock Classes="h2" Text="{Binding L[desktop.agents.limitsTitle]}" />
<Grid ColumnDefinitions="*,12,*">
<StackPanel Grid.Column="0">
<TextBlock Classes="label" Text="Max. Schritte pro Run" />
<TextBlock Classes="label" Text="{Binding L[desktop.agents.maxSteps]}" />
<TextBox Text="{Binding MaxSteps}" />
</StackPanel>
<StackPanel Grid.Column="2">
<TextBlock Classes="label" Text="Timeout (Sekunden)" />
<TextBlock Classes="label" Text="{Binding L[desktop.agents.timeoutSeconds]}" />
<TextBox Text="{Binding TimeoutSeconds}" />
</StackPanel>
</Grid>
<Grid ColumnDefinitions="*,12,*">
<StackPanel Grid.Column="0">
<TextBlock Classes="label" Text="Max. Kontext-Tokens" />
<TextBlock Classes="label" Text="{Binding L[desktop.agents.maxContextTokens]}" />
<TextBox Text="{Binding MaxContextTokens}" />
</StackPanel>
<StackPanel Grid.Column="2">
<TextBlock Classes="label" Text="Max. Tool-Ergebnis (Zeichen)" />
<TextBlock Classes="label" Text="{Binding L[desktop.agents.maxToolResultChars]}" />
<TextBox Text="{Binding MaxToolResultChars}" />
</StackPanel>
</Grid>
<Grid ColumnDefinitions="*,12,*">
<StackPanel Grid.Column="0">
<TextBlock Classes="label" Text="Tagesbudget ($ USD)" />
<TextBlock Classes="label" Text="{Binding L[desktop.agents.dailyCost]}" />
<TextBox Text="{Binding DailyCostUsd}" />
</StackPanel>
<StackPanel Grid.Column="2">
<TextBlock Classes="label" Text="Tagesbudget (Tokens)" />
<TextBlock Classes="label" Text="{Binding L[desktop.agents.dailyTokens]}" />
<TextBox Text="{Binding DailyTokens}" />
</StackPanel>
</Grid>
@@ -225,13 +225,12 @@
<DockPanel Grid.Column="0" Margin="0,0,14,0">
<TextBlock DockPanel.Dock="Top" Classes="kicker" Margin="0,4,0,8"
Text="{Binding SelectedAgent.DisplayName,
StringFormat='ZUGELASSENE WERKZEUGE FÜR {0}'}" />
Text="{Binding AllowedToolsHeader}" />
<Border DockPanel.Dock="Top" Classes="thead">
<Grid ColumnDefinitions="36,1.4*,2.4*">
<TextBlock Grid.Column="1" Classes="th" Text="WERKZEUG" />
<TextBlock Grid.Column="2" Classes="th" Text="BESCHREIBUNG" />
<TextBlock Grid.Column="1" Classes="th" Text="{Binding L[desktop.agents.thTool]}" />
<TextBlock Grid.Column="2" Classes="th" Text="{Binding L[desktop.agents.thDescription]}" />
</Grid>
</Border>
@@ -258,7 +257,7 @@
<DockPanel Grid.Column="2" Margin="4,0,0,0">
<StackPanel DockPanel.Dock="Top" Spacing="2" Margin="0,4,0,10">
<TextBlock Classes="kicker" Text="WERKZEUG-EINSTELLUNGEN" />
<TextBlock Classes="kicker" Text="{Binding L[desktop.agents.toolSettingsKicker]}" />
<DockPanel>
<TextBlock Classes="h2" VerticalAlignment="Center"
Text="{Binding SelectedTool.Name}" />
@@ -267,7 +266,7 @@
IsEnabled="{Binding ToolSettings, Converter={x:Static ObjectConverters.IsNotNull}}">
<StackPanel Orientation="Horizontal" Spacing="6">
<ctrl:StrokeIcon Data="{StaticResource IconSave}" Width="14" Height="14" />
<TextBlock Text="Übernehmen" />
<TextBlock Text="{Binding L[desktop.agents.apply]}" />
</StackPanel>
</Button>
</DockPanel>
@@ -18,41 +18,41 @@
<!-- ══════════════════ Manuell ══════════════════ -->
<StackPanel Spacing="12">
<TextBlock Classes="kicker" Text="MANUELL" />
<TextBlock Classes="h2" Text="Sicherung erstellen" />
<TextBlock Classes="kicker" Text="{Binding L[desktop.backup.kickerManual]}" />
<TextBlock Classes="h2" Text="{Binding L[desktop.backup.titleCreate]}" />
<Grid ColumnDefinitions="*,Auto" VerticalAlignment="Bottom">
<StackPanel Grid.Column="0">
<TextBlock Classes="label" Text="Zielordner" />
<TextBlock Classes="label" Text="{Binding L[desktop.backup.targetFolder]}" />
<TextBox Text="{Binding TargetFolder}"
PlaceholderText="Zielordner für Sicherungen…" />
PlaceholderText="{Binding L[desktop.backup.targetFolderPlaceholder]}" />
</StackPanel>
<Button Grid.Column="1" Content="Durchsuchen…" Click="OnBrowseTargetFolder"
<Button Grid.Column="1" Content="{Binding L[desktop.backup.browse]}" Click="OnBrowseTargetFolder"
Margin="8,0,0,0" VerticalAlignment="Bottom" />
</Grid>
<StackPanel Spacing="6">
<TextBlock Classes="label" Text="Zugangsdaten" />
<TextBlock Classes="label" Text="{Binding L[desktop.backup.credentials]}" />
<StackPanel Orientation="Horizontal" Spacing="18">
<RadioButton GroupName="secrets" Content="nicht mitsichern"
<RadioButton GroupName="secrets" Content="{Binding L[desktop.backup.credentialsExclude]}"
IsChecked="{Binding SecretsExclude}" />
<RadioButton GroupName="secrets" Content="mit Passphrase schützen"
<RadioButton GroupName="secrets" Content="{Binding L[desktop.backup.credentialsProtect]}"
IsChecked="{Binding SecretsPassphrase}" />
</StackPanel>
</StackPanel>
<StackPanel Spacing="8" Margin="24,0,0,0" IsVisible="{Binding SecretsPassphrase}">
<TextBox Text="{Binding Passphrase}" PasswordChar="•" Width="320"
HorizontalAlignment="Left" PlaceholderText="Passphrase eingeben" />
HorizontalAlignment="Left" PlaceholderText="{Binding L[desktop.backup.passphrase]}" />
<TextBox Text="{Binding PassphraseRepeat}" PasswordChar="•" Width="320"
HorizontalAlignment="Left" PlaceholderText="Passphrase wiederholen" />
HorizontalAlignment="Left" PlaceholderText="{Binding L[desktop.backup.passphraseRepeat]}" />
</StackPanel>
<StackPanel Spacing="6">
<TextBlock Classes="label" Text="Umfang" />
<TextBlock Classes="label" Text="{Binding L[desktop.backup.scope]}" />
<StackPanel Orientation="Horizontal" Spacing="18">
<CheckBox Content="Chatverläufe" IsChecked="{Binding IncludeChatHistory}" />
<CheckBox Content="Protokolle" IsChecked="{Binding IncludeLogs}" />
<CheckBox Content="{Binding L[desktop.backup.scopeChat]}" IsChecked="{Binding IncludeChatHistory}" />
<CheckBox Content="{Binding L[desktop.backup.scopeLogs]}" IsChecked="{Binding IncludeLogs}" />
</StackPanel>
</StackPanel>
@@ -60,7 +60,7 @@
Command="{Binding CreateBackupCommand}" IsEnabled="{Binding !IsBusy}">
<StackPanel Orientation="Horizontal" Spacing="6">
<ctrl:StrokeIcon Data="{StaticResource IconPlay}" Width="12" Height="12" IsFilled="True" />
<TextBlock Text="Sicherung jetzt erstellen" />
<TextBlock Text="{Binding L[desktop.backup.createNow]}" />
</StackPanel>
</Button>
</StackPanel>
@@ -69,36 +69,36 @@
<!-- ══════════════════ Automatik ══════════════════ -->
<StackPanel Spacing="10">
<TextBlock Classes="kicker" Text="AUTOMATIK" />
<TextBlock Classes="h2" Text="Automatische Sicherung" />
<TextBlock Classes="kicker" Text="{Binding L[desktop.backup.kickerAuto]}" />
<TextBlock Classes="h2" Text="{Binding L[desktop.backup.titleAuto]}" />
<CheckBox Content="täglich sichern um" IsChecked="{Binding AutoBackupEnabled}" />
<CheckBox Content="{Binding L[desktop.backup.autoDaily]}" IsChecked="{Binding AutoBackupEnabled}" />
<StackPanel Orientation="Horizontal" Spacing="24" Margin="24,0,0,0"
IsEnabled="{Binding AutoBackupEnabled}">
<StackPanel Width="100">
<TextBlock Classes="label" Text="Uhrzeit" />
<TextBlock Classes="label" Text="{Binding L[desktop.backup.time]}" />
<TextBox Text="{Binding AutoBackupTime}" PlaceholderText="03:00" />
</StackPanel>
<StackPanel Width="160">
<TextBlock Classes="label" Text="Aufbewahren" />
<TextBlock Classes="label" Text="{Binding L[desktop.backup.keep]}" />
<TextBox Text="{Binding KeepCount}" />
</StackPanel>
</StackPanel>
<TextBlock Classes="caption" Margin="24,0,0,0" TextWrapping="Wrap"
Text="Die Automatik sichert ohne Zugangsdaten — eine gespeicherte Passphrase wäre wirkungslos." />
Text="{Binding L[desktop.backup.autoHint]}" />
</StackPanel>
<Border Classes="hr" />
<!-- ══════════════════ Bestand ══════════════════ -->
<StackPanel Spacing="10">
<TextBlock Classes="kicker" Text="BESTAND" />
<TextBlock Classes="kicker" Text="{Binding L[desktop.backup.kickerExisting]}" />
<DockPanel>
<TextBlock Classes="h2" Text="Vorhandene Sicherungen" VerticalAlignment="Center" />
<TextBlock Classes="h2" Text="{Binding L[desktop.backup.titleExisting]}" VerticalAlignment="Center" />
<!-- Mindestabstand zur Ueberschrift links. Vorher stand hier Margin="0" und
der Zwischenraum entstand nur, wenn das Fenster breit genug war; bei
@@ -106,15 +106,15 @@
beruehrte die Schaltflaeche "Aktualisieren". -->
<WrapPanel DockPanel.Dock="Right" HorizontalAlignment="Right" Classes="toolbar"
Margin="16,0,0,0">
<Button Classes="toolbar" Content="Aktualisieren"
<Button Classes="toolbar" Content="{Binding L[desktop.backup.refresh]}"
Command="{Binding RefreshBackupListCommand}" />
<Button Classes="toolbar" Content="Ordner öffnen"
<Button Classes="toolbar" Content="{Binding L[desktop.backup.openFolder]}"
Command="{Binding ShowSelectedInFolderCommand}"
IsEnabled="{Binding SelectedBackup, Converter={x:Static ObjectConverters.IsNotNull}}" />
<Button Classes="toolbar" Content="Löschen"
<Button Classes="toolbar" Content="{Binding L[desktop.backup.delete]}"
Command="{Binding DeleteSelectedCommand}"
IsEnabled="{Binding SelectedBackup, Converter={x:Static ObjectConverters.IsNotNull}}" />
<Button Classes="toolbar primary" Content="Wiederherstellen…"
<Button Classes="toolbar primary" Content="{Binding L[desktop.backup.restore]}"
Command="{Binding RestoreSelectedCommand}"
IsEnabled="{Binding SelectedBackup, Converter={x:Static ObjectConverters.IsNotNull}}" />
</WrapPanel>
@@ -122,11 +122,11 @@
<Border Classes="thead">
<Grid ColumnDefinitions="2.6*,1.5*,1.3*,0.9*,1.3*">
<TextBlock Grid.Column="0" Classes="th" Text="DATEINAME" />
<TextBlock Grid.Column="1" Classes="th" Text="ERSTELLT AM" />
<TextBlock Grid.Column="2" Classes="th" Text="INSTANZ" />
<TextBlock Grid.Column="3" Classes="th" Text="GRÖSSE" />
<TextBlock Grid.Column="4" Classes="th" Text="ZUGANGSDATEN" />
<TextBlock Grid.Column="0" Classes="th" Text="{Binding L[desktop.backup.thFilename]}" />
<TextBlock Grid.Column="1" Classes="th" Text="{Binding L[desktop.backup.thCreatedAt]}" />
<TextBlock Grid.Column="2" Classes="th" Text="{Binding L[desktop.backup.thInstance]}" />
<TextBlock Grid.Column="3" Classes="th" Text="{Binding L[desktop.backup.thSize]}" />
<TextBlock Grid.Column="4" Classes="th" Text="{Binding L[desktop.backup.thSecrets]}" />
</Grid>
</Border>
@@ -13,7 +13,7 @@
<!-- Agentenauswahl und Verlaufsbefehle -->
<StackPanel DockPanel.Dock="Top" Classes="toolbar" Margin="0,0,0,16">
<TextBlock Text="Agent:" FontWeight="SemiBold" VerticalAlignment="Center" />
<TextBlock Text="{Binding L[desktop.chat.agent]}" FontWeight="SemiBold" VerticalAlignment="Center" />
<ComboBox ItemsSource="{Binding AvailableAgents}" SelectedItem="{Binding SelectedAgent}"
Width="220">
<ComboBox.ItemTemplate>
@@ -28,14 +28,14 @@
<Button Classes="toolbar" Command="{Binding ClearHistoryCommand}">
<StackPanel Orientation="Horizontal" Spacing="6">
<ctrl:StrokeIcon Data="{StaticResource IconTrash}" Width="14" Height="14" />
<TextBlock Text="Verlauf leeren" />
<TextBlock Text="{Binding L[desktop.chat.clearHistory]}" />
</StackPanel>
</Button>
<Button Classes="toolbar" Command="{Binding AbortCommand}" IsEnabled="{Binding IsSending}">
<StackPanel Orientation="Horizontal" Spacing="6">
<ctrl:StrokeIcon Data="{StaticResource IconStop}" Width="12" Height="12" IsFilled="True" />
<TextBlock Text="Abbrechen" />
<TextBlock Text="{Binding L[desktop.chat.abort]}" />
</StackPanel>
</Button>
</StackPanel>
@@ -47,11 +47,11 @@
<!-- Eingabe -->
<Grid DockPanel.Dock="Bottom" ColumnDefinitions="*,Auto" Margin="0,12,0,0">
<TextBox Grid.Column="0" Text="{Binding InputPrompt}"
PlaceholderText="Nachricht eingeben… (Strg+Eingabe zum Senden)"
PlaceholderText="{Binding L[desktop.chat.inputPlaceholder]}"
AcceptsReturn="True" Height="60" TextWrapping="Wrap"
KeyDown="OnInputKeyDown" />
<Button Grid.Column="1" Classes="primary" Content="Senden" Width="100"
<Button Grid.Column="1" Classes="primary" Content="{Binding L[desktop.chat.send]}" Width="100"
Command="{Binding SendMessageCommand}" IsEnabled="{Binding !IsSending}"
VerticalAlignment="Stretch" Margin="8,0,0,0" />
</Grid>
@@ -25,14 +25,14 @@
<!-- Anwendung -->
<StackPanel Spacing="10">
<TextBlock Classes="kicker" Text="ANWENDUNG" />
<TextBlock Classes="h2" Text="Build" />
<TextBlock Classes="kicker" Text="{Binding L[desktop.info.kickerApp]}" />
<TextBlock Classes="h2" Text="{Binding L[desktop.info.build]}" />
<Grid ColumnDefinitions="170,*" RowDefinitions="Auto,Auto" >
<TextBlock Grid.Row="0" Grid.Column="0" Classes="label" Text="Version" />
<TextBlock Grid.Row="0" Grid.Column="0" Classes="label" Text="{Binding L[desktop.info.version]}" />
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding AppVersion}" />
<TextBlock Grid.Row="1" Grid.Column="0" Classes="label" Text="Build-Zusammenfassung"
<TextBlock Grid.Row="1" Grid.Column="0" Classes="label" Text="{Binding L[desktop.info.buildSummary]}"
Margin="0,6,0,0" />
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding BuildSummary}"
TextWrapping="Wrap" Margin="0,6,0,0" />
@@ -43,36 +43,36 @@
<!-- Instanz -->
<StackPanel Spacing="10">
<TextBlock Classes="kicker" Text="INSTANZ" />
<TextBlock Classes="kicker" Text="{Binding L[desktop.info.kickerInstance]}" />
<DockPanel>
<TextBlock Classes="h2" Text="Aktuelle Instanz" VerticalAlignment="Center" />
<TextBlock Classes="h2" Text="{Binding L[desktop.info.currentInstance]}" VerticalAlignment="Center" />
<Button DockPanel.Dock="Right" HorizontalAlignment="Right" Classes="toolbar"
Command="{Binding OpenInstanceFolderCommand}">
<StackPanel Orientation="Horizontal" Spacing="6">
<ctrl:StrokeIcon Data="{StaticResource IconFolder}" Width="14" Height="14" />
<TextBlock Text="Instanz-Ordner öffnen" />
<TextBlock Text="{Binding L[desktop.info.openFolder]}" />
</StackPanel>
</Button>
</DockPanel>
<Grid ColumnDefinitions="170,*" RowDefinitions="Auto,Auto,Auto,Auto,Auto">
<TextBlock Grid.Row="0" Grid.Column="0" Classes="label" Text="Name" />
<TextBlock Grid.Row="0" Grid.Column="0" Classes="label" Text="{Binding L[desktop.info.name]}" />
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding InstanceName}" />
<TextBlock Grid.Row="1" Grid.Column="0" Classes="label" Text="ID" Margin="0,6,0,0" />
<TextBlock Grid.Row="1" Grid.Column="0" Classes="label" Text="{Binding L[desktop.info.id]}" Margin="0,6,0,0" />
<TextBlock Grid.Row="1" Grid.Column="1" Classes="mono" Text="{Binding InstanceId}"
Margin="0,6,0,0" />
<TextBlock Grid.Row="2" Grid.Column="0" Classes="label" Text="Pfad" Margin="0,6,0,0" />
<TextBlock Grid.Row="2" Grid.Column="0" Classes="label" Text="{Binding L[desktop.info.path]}" Margin="0,6,0,0" />
<SelectableTextBlock Grid.Row="2" Grid.Column="1" Text="{Binding InstancePath}"
TextWrapping="Wrap" Margin="0,6,0,0" />
<TextBlock Grid.Row="3" Grid.Column="0" Classes="label" Text="Log-Ordner" Margin="0,6,0,0" />
<TextBlock Grid.Row="3" Grid.Column="0" Classes="label" Text="{Binding L[desktop.info.logDir]}" Margin="0,6,0,0" />
<SelectableTextBlock Grid.Row="3" Grid.Column="1" Text="{Binding LogDirectory}"
TextWrapping="Wrap" Margin="0,6,0,0" />
<TextBlock Grid.Row="4" Grid.Column="0" Classes="label" Text="OpenRouter" Margin="0,6,0,0" />
<TextBlock Grid.Row="4" Grid.Column="0" Classes="label" Text="{Binding L[desktop.info.openRouter]}" Margin="0,6,0,0" />
<TextBlock Grid.Row="4" Grid.Column="1" Text="{Binding OpenRouterStatus}" Margin="0,6,0,0" />
</Grid>
</StackPanel>
@@ -81,8 +81,8 @@
<!-- Baugruppen -->
<StackPanel Spacing="10">
<TextBlock Classes="kicker" Text="MODULE" />
<TextBlock Classes="h2" Text="Baugruppen" />
<TextBlock Classes="kicker" Text="{Binding L[desktop.info.kickerModules]}" />
<TextBlock Classes="h2" Text="{Binding L[desktop.info.assemblies]}" />
<!-- Feste Breiten statt Sternanteilen fuer die drei schmalen Spalten.
Sternbreiten teilen den Platz erst auf, NACHDEM die Mindestbreite jedes
@@ -99,10 +99,10 @@
Grenzfall nicht aneinanderstossen. -->
<Border Classes="thead">
<Grid ColumnDefinitions="170,60,150,*" ClipToBounds="True">
<TextBlock Grid.Column="0" Classes="th" Text="MODUL" />
<TextBlock Grid.Column="1" Classes="th" Text="BUILD" />
<TextBlock Grid.Column="2" Classes="th" Text="BUILD-DATUM" />
<TextBlock Grid.Column="3" Classes="th" Text="ÄNDERUNGEN" Margin="10,0,0,0" />
<TextBlock Grid.Column="0" Classes="th" Text="{Binding L[desktop.info.thModule]}" />
<TextBlock Grid.Column="1" Classes="th" Text="{Binding L[desktop.info.thBuild]}" />
<TextBlock Grid.Column="2" Classes="th" Text="{Binding L[desktop.info.thBuildDate]}" />
<TextBlock Grid.Column="3" Classes="th" Text="{Binding L[desktop.info.thChanges]}" Margin="10,0,0,0" />
</Grid>
</Border>
@@ -36,12 +36,12 @@
<Border Classes="hr" />
<Grid ColumnDefinitions="*,Auto">
<TextBox Grid.Column="0" Text="{Binding NewInstanceName}"
PlaceholderText="Name der neuen Instanz" />
PlaceholderText="{Binding L[desktop.instancePicker.newInstancePlaceholder]}" />
<Button Grid.Column="1" Classes="primary" Margin="8,0,0,0"
Command="{Binding CreateCommand}">
<StackPanel Orientation="Horizontal" Spacing="6">
<ctrl:StrokeIcon Data="{StaticResource IconPlus}" Width="14" Height="14" />
<TextBlock Text="Anlegen" />
<TextBlock Text="{Binding L[desktop.instancePicker.create]}" />
</StackPanel>
</Button>
</Grid>
@@ -50,7 +50,7 @@
<!-- Abschluss -->
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" Spacing="8"
HorizontalAlignment="Right" Margin="0,14,0,0">
<Button Content="Abbrechen" Command="{Binding CancelCommand}" IsCancel="True" />
<Button Content="{Binding L[common.cancel]}" Command="{Binding CancelCommand}" IsCancel="True" />
<Button Classes="primary" Content="{Binding ConfirmLabel}" IsDefault="True"
Command="{Binding StartCommand}" />
</StackPanel>
@@ -84,13 +84,13 @@
Stroke="{DynamicResource SurfaceBrush}" StrokeThickness="2"
Fill="{DynamicResource SuccessBrush}"
IsVisible="{Binding IsReady}"
ToolTip.Tip="API-Key hinterlegt" />
ToolTip.Tip="{Binding $parent[ItemsControl].((vm:InstancePickerViewModel)DataContext).L[desktop.instancePicker.tooltipConfigured]}" />
<Ellipse Width="10" Height="10" HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Stroke="{DynamicResource SurfaceBrush}" StrokeThickness="2"
Fill="{DynamicResource Neutral500Brush}"
IsVisible="{Binding !IsReady}"
ToolTip.Tip="Kein API-Key — Agenten bleiben deaktiviert" />
ToolTip.Tip="{Binding $parent[ItemsControl].((vm:InstancePickerViewModel)DataContext).L[desktop.instancePicker.tooltipMissing]}" />
</Panel>
<Button DockPanel.Dock="Right" Classes="toolbar" VerticalAlignment="Center"
@@ -100,7 +100,7 @@
<Border DockPanel.Dock="Right" Classes="tag ok" Margin="0,0,8,0"
IsVisible="{Binding IsCurrent}">
<TextBlock Text="Aktiv" />
<TextBlock Text="{Binding $parent[ItemsControl].((vm:InstancePickerViewModel)DataContext).L[desktop.instancePicker.active]}" />
</Border>
<StackPanel VerticalAlignment="Center">
@@ -7,14 +7,14 @@
x:Class="ClawdDotNet.Desktop.Views.LicenseWindow"
x:DataType="vm:LicenseViewModel"
Icon="/Assets/app.ico"
Title="ClawdDotNet – Lizenz"
Title="{Binding L[desktop.dialog.licenseTitle]}"
Width="520" SizeToContent="Height"
CanResize="False"
WindowStartupLocation="CenterScreen">
<StackPanel Margin="20" Spacing="12">
<TextBlock Classes="heading" Text="Lizenzschlüssel" />
<TextBlock Classes="heading" Text="{Binding L[desktop.dialog.licenseKey]}" />
<!-- Nur sichtbar, wenn es einen Grund gibt -->
<Border Classes="card"
@@ -28,15 +28,15 @@
FontFamily="{DynamicResource ContentControlThemeFontFamily}" />
<StackPanel Spacing="4">
<TextBlock Classes="caption" Text="Hardware-ID (für den Support):" />
<TextBlock Classes="caption" Text="{Binding L[desktop.dialog.hardwareId]}" />
<SelectableTextBlock Classes="caption"
Text="{Binding HardwareId}"
TextWrapping="Wrap" />
</StackPanel>
<StackPanel Orientation="Horizontal" Spacing="8" HorizontalAlignment="Right">
<Button Content="Beenden" Command="{Binding CancelCommand}" />
<Button Content="Prüfen" Classes="accent" IsDefault="True"
<Button Content="{Binding L[common.exit]}" Command="{Binding CancelCommand}" />
<Button Content="{Binding L[desktop.dialog.verify]}" Classes="accent" IsDefault="True"
Command="{Binding ConfirmCommand}" />
</StackPanel>
@@ -15,11 +15,11 @@
<!-- Werkzeugleiste -->
<StackPanel DockPanel.Dock="Top" Classes="toolbar">
<TextBlock Text="Modul:" FontSize="12.5" VerticalAlignment="Center" />
<TextBlock Text="{Binding L[desktop.logs.module]}" FontSize="12.5" VerticalAlignment="Center" />
<ComboBox ItemsSource="{Binding Modules}" SelectedItem="{Binding SelectedModule}"
Width="180" MinHeight="30" Padding="8,3" />
<TextBlock Text="Stufe:" FontSize="12.5" VerticalAlignment="Center" Margin="6,0,0,0" />
<TextBlock Text="{Binding L[desktop.logs.level]}" FontSize="12.5" VerticalAlignment="Center" Margin="6,0,0,0" />
<ComboBox ItemsSource="{Binding Levels}" SelectedItem="{Binding SelectedLevel}"
Width="120" MinHeight="30" Padding="8,3" />
@@ -28,25 +28,25 @@
<Button Classes="toolbar" Command="{Binding RefreshModulesCommand}">
<StackPanel Orientation="Horizontal" Spacing="6">
<ctrl:StrokeIcon Data="{StaticResource IconRefresh}" Width="14" Height="14" />
<TextBlock Text="Aktualisieren" />
<TextBlock Text="{Binding L[desktop.logs.refresh]}" />
</StackPanel>
</Button>
<Button Classes="toolbar" Command="{Binding ClearCommand}">
<StackPanel Orientation="Horizontal" Spacing="6">
<ctrl:StrokeIcon Data="{StaticResource IconTrash}" Width="14" Height="14" />
<TextBlock Text="Leeren" />
<TextBlock Text="{Binding L[desktop.logs.clear]}" />
</StackPanel>
</Button>
<Button Classes="toolbar" Command="{Binding OpenFolderCommand}">
<StackPanel Orientation="Horizontal" Spacing="6">
<ctrl:StrokeIcon Data="{StaticResource IconFolder}" Width="14" Height="14" />
<TextBlock Text="Ordner öffnen" />
<TextBlock Text="{Binding L[desktop.logs.openFolder]}" />
</StackPanel>
</Button>
<CheckBox Content="Mitlaufen" IsChecked="{Binding FollowTail}"
<CheckBox Content="{Binding L[desktop.logs.follow]}" IsChecked="{Binding FollowTail}"
VerticalAlignment="Center" Margin="8,0,0,0" />
</StackPanel>
@@ -33,7 +33,7 @@
<Button DockPanel.Dock="Right" Classes="flat"
Command="{Binding ToggleSidebarCommand}"
ToolTip.Tip="Seitenleiste ein-/ausklappen"
ToolTip.Tip="{Binding L[desktop.mainWindow.sidebarTooltip]}"
Padding="4" VerticalAlignment="Center">
<ctrl:StrokeIcon Width="14" Height="14"
Data="{Binding IsSidebarCollapsed,
@@ -60,7 +60,7 @@
<Button DockPanel.Dock="Top" Classes="instance" Margin="12,12,12,0"
Command="{Binding OpenInstanceManagerCommand}"
IsEnabled="{Binding CanSwitchInstance}"
ToolTip.Tip="Instanz wechseln">
ToolTip.Tip="{Binding L[desktop.mainWindow.switchInstance]}">
<DockPanel>
<ctrl:StrokeIcon Data="{StaticResource IconLogo}" Width="15" Height="15"
DockPanel.Dock="Left" VerticalAlignment="Center" />
@@ -70,7 +70,7 @@
IsVisible="{Binding IsSidebarExpanded}" />
<StackPanel Margin="8,0,0,0" IsVisible="{Binding IsSidebarExpanded}">
<TextBlock Text="INSTANZ" FontSize="9" LetterSpacing="1"
<TextBlock Text="{Binding L[desktop.mainWindow.instance]}" FontSize="9" LetterSpacing="1"
Foreground="{DynamicResource AccentBrush}" />
<TextBlock Classes="h2" FontSize="13" Text="{Binding InstanceName}"
TextTrimming="CharacterEllipsis" />
@@ -142,7 +142,7 @@
HorizontalAlignment="Right" VerticalAlignment="Center">
<TextBlock Classes="caption" Text="{Binding ThemeLabel}" VerticalAlignment="Center" />
<Button Classes="icon" Command="{Binding ToggleThemeCommand}"
ToolTip.Tip="Dunkelmodus umschalten">
ToolTip.Tip="{Binding L[desktop.mainWindow.themeToggle]}">
<ctrl:StrokeIcon Width="16" Height="16"
Data="{Binding ThemeIconKey,
Converter={x:Static conv:IconConverter.Instance}}" />
@@ -172,7 +172,7 @@
Margin="0,0,10,0" />
<Button DockPanel.Dock="Right" Classes="flat" Padding="2"
Command="{Binding DismissCommand}" ToolTip.Tip="Ausblenden"
Command="{Binding DismissCommand}" ToolTip.Tip="{Binding $parent[Window].((vm:MainWindowViewModel)DataContext).L[desktop.mainWindow.dismiss]}"
VerticalAlignment="Center">
<ctrl:StrokeIcon Data="{StaticResource IconClose}" Width="13" Height="13" />
</Button>
@@ -190,7 +190,7 @@
<Border DockPanel.Dock="Bottom" Classes="statusbar">
<DockPanel>
<StackPanel Orientation="Horizontal" Spacing="8">
<TextBlock Classes="caption" Text="{Binding InstanceName, StringFormat='Instanz: {0}'}" />
<TextBlock Classes="caption" Text="{Binding InstanceStatusLabel}" />
<TextBlock Classes="caption" Text="·" />
<StackPanel Orientation="Horizontal" Spacing="5" VerticalAlignment="Center">
@@ -200,7 +200,7 @@
<Ellipse Width="7" Height="7" VerticalAlignment="Center"
Fill="{DynamicResource DangerBrush}"
IsVisible="{Binding !IsApiReachable}" />
<TextBlock Classes="caption" Text="{Binding ApiStatusText, StringFormat='API {0}'}" />
<TextBlock Classes="caption" Text="{Binding ApiStatusDisplay}" />
</StackPanel>
<TextBlock Classes="caption" Text="·"
@@ -8,7 +8,7 @@
Padding="16"
WindowStartupLocation="CenterOwner"
CanResize="False"
Title="Sicherung wiederherstellen"
Title="{Binding L[desktop.dialog.restoreTitle]}"
x:Class="ClawdDotNet.Desktop.Views.RestoreBackupWindow"
x:DataType="vm:RestoreBackupViewModel">
@@ -16,8 +16,8 @@
<!-- Buttons unten -->
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" HorizontalAlignment="Right" Spacing="8" Margin="0,16,0,0">
<Button Content="Abbrechen" Command="{Binding CancelCommand}" />
<Button Content="Wiederherstellen" Command="{Binding ConfirmCommand}" Classes="accent" />
<Button Content="{Binding L[common.cancel]}" Command="{Binding CancelCommand}" />
<Button Content="{Binding L[desktop.backup.restore]}" Command="{Binding ConfirmCommand}" Classes="accent" />
</StackPanel>
<!-- Statusmeldung unten -->
@@ -29,34 +29,34 @@
<!-- Information -->
<Border Classes="card">
<StackPanel Spacing="4">
<TextBlock Text="Sicherungsinformationen" Classes="heading" />
<TextBlock Text="{Binding InstanceName, StringFormat='Instanz: {0}'}" />
<TextBlock Text="{Binding CreatedAt, StringFormat='Erstellt: {0:g}'}" />
<TextBlock Text="{Binding FileCount, StringFormat='Dateien: {0}'}" />
<TextBlock Text="{Binding SecretsDescription, StringFormat='Zugangsdaten: {0}'}" />
<TextBlock Text="{Binding L[desktop.dialog.backupInfo]}" Classes="heading" />
<TextBlock Text="{Binding InstanceInfoText}" />
<TextBlock Text="{Binding CreatedAtText}" />
<TextBlock Text="{Binding FileCountText}" />
<TextBlock Text="{Binding SecretsText}" />
</StackPanel>
</Border>
<!-- Zielordner -->
<StackPanel Spacing="4">
<TextBlock Text="Zielordner:" FontWeight="Bold" />
<TextBlock Text="{Binding L[desktop.dialog.targetDir]}" FontWeight="Bold" />
<Grid ColumnDefinitions="*,Auto">
<TextBox Text="{Binding TargetDirectory}" Grid.Column="0" />
<Button Content="Ordner wählen" Click="OnBrowseFolder" Grid.Column="1" Margin="8,0,0,0" />
<Button Content="{Binding L[desktop.dialog.chooseFolder]}" Click="OnBrowseFolder" Grid.Column="1" Margin="8,0,0,0" />
</Grid>
<TextBlock Text="Hinweis: Es wird empfohlen, in einen neuen Ordner wiederherzustellen, um Konflikte mit laufenden Prozessen zu vermeiden."
<TextBlock Text="{Binding L[desktop.dialog.restoreHint]}"
Classes="caption" TextWrapping="Wrap" />
</StackPanel>
<!-- Passphrase -->
<StackPanel Spacing="4" IsVisible="{Binding NeedsPassphrase}">
<TextBlock Text="Passphrase:" FontWeight="Bold" />
<TextBlock Text="{Binding L[desktop.dialog.passphrase]}" FontWeight="Bold" />
<TextBox Text="{Binding Passphrase}" PasswordChar="*" />
<TextBlock Text="Diese Sicherung enthält geschützte Zugangsdaten." Classes="caption" />
<TextBlock Text="{Binding L[desktop.dialog.passphraseProtected]}" Classes="caption" />
</StackPanel>
<!-- Überschreiben -->
<CheckBox Content="Vorhandene Dateien im Zielordner überschreiben" IsChecked="{Binding Overwrite}" Margin="0,8,0,0" />
<CheckBox Content="{Binding L[desktop.dialog.overwriteExisting]}" IsChecked="{Binding Overwrite}" Margin="0,8,0,0" />
</StackPanel>
</ScrollViewer>
@@ -15,11 +15,11 @@
<Border DockPanel.Dock="Bottom" BorderBrush="{DynamicResource DividerBrush}"
BorderThickness="0,1,0,0" Padding="0,12,0,0" Margin="0,16,0,0">
<StackPanel Orientation="Horizontal" Spacing="8" HorizontalAlignment="Right">
<Button Content="Verwerfen" Command="{Binding LoadFromHostCommand}" />
<Button Content="{Binding L[desktop.settings.discard]}" Command="{Binding LoadFromHostCommand}" />
<Button Classes="primary" Command="{Binding SaveSettingsCommand}">
<StackPanel Orientation="Horizontal" Spacing="6">
<ctrl:StrokeIcon Data="{StaticResource IconSave}" Width="14" Height="14" />
<TextBlock Text="Speichern" />
<TextBlock Text="{Binding L[desktop.settings.save]}" />
</StackPanel>
</Button>
</StackPanel>
@@ -30,39 +30,39 @@
<!-- ══════════════════ Instanz ══════════════════ -->
<StackPanel Spacing="14">
<TextBlock Classes="kicker" Text="INSTANZ" />
<TextBlock Classes="kicker" Text="{Binding L[desktop.settings.instance]}" />
<StackPanel>
<TextBlock Classes="label" Text="Instanz-Name" />
<TextBlock Classes="label" Text="{Binding L[desktop.settings.instanceName]}" />
<TextBox Text="{Binding InstanceName}" />
</StackPanel>
<StackPanel>
<TextBlock Classes="label" Text="OpenRouter API-Key" />
<TextBlock Classes="label" Text="{Binding L[desktop.settings.apiKey]}" />
<TextBox Text="{Binding OpenRouterApiKey}" PasswordChar="•" />
</StackPanel>
<StackPanel>
<CheckBox IsChecked="{Binding AutostartByManager}"
Content="Autostart durch Manager" />
Content="{Binding L[desktop.settings.autostart]}" />
<TextBlock Classes="caption" TextWrapping="Wrap" Margin="0,4,0,0"
Text="Der Instanzmanager startet diese Instanz, wenn er hochkommt, und wieder, wenn sie abstürzt. Nach mehreren Neustarts in kurzer Folge setzt er aus und meldet es." />
Text="{Binding L[desktop.settings.autostartHint]}" />
</StackPanel>
<StackPanel>
<TextBlock Classes="label" Text="Protokoll-Verzeichnis" />
<TextBlock Classes="label" Text="{Binding L[desktop.settings.logDir]}" />
<TextBox Text="{Binding LogDirectory}" />
<TextBlock Classes="caption" TextWrapping="Wrap" Margin="0,4,0,0"
Text="Gilt nur für diese Instanz. Leer heißt: Unterordner Logs im Instanzverzeichnis." />
Text="{Binding L[desktop.settings.logDirHint]}" />
</StackPanel>
<Grid ColumnDefinitions="*,16,*">
<StackPanel Grid.Column="0">
<TextBlock Classes="label" Text="Tagesbudget ($ USD)" />
<TextBlock Classes="label" Text="{Binding L[desktop.settings.dailyCost]}" />
<TextBox Text="{Binding InstanceDailyCostUsd}" />
</StackPanel>
<StackPanel Grid.Column="2">
<TextBlock Classes="label" Text="Tagesbudget (Tokens)" />
<TextBlock Classes="label" Text="{Binding L[desktop.settings.dailyTokens]}" />
<TextBox Text="{Binding InstanceDailyTokens}" />
</StackPanel>
</Grid>
@@ -72,21 +72,33 @@
<!-- ══════════════════ Allgemein ══════════════════ -->
<StackPanel Spacing="14">
<TextBlock Classes="kicker" Text="ALLGEMEIN" />
<TextBlock Classes="kicker" Text="{Binding L[desktop.settings.general]}" />
<StackPanel>
<TextBlock Classes="label" Text="Instanzen-Verzeichnis" />
<TextBlock Classes="label" Text="{Binding L[desktop.settings.language]}" />
<ComboBox ItemsSource="{Binding AvailableLanguages}" SelectedItem="{Binding SelectedLanguageOption}"
HorizontalAlignment="Stretch">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
<StackPanel>
<TextBlock Classes="label" Text="{Binding L[desktop.settings.instancesDir]}" />
<TextBox Text="{Binding InstancesDirectory}" />
</StackPanel>
<Grid ColumnDefinitions="*,16,*">
<StackPanel Grid.Column="0">
<TextBlock Classes="label" Text="Minimaler Log-Level" />
<TextBlock Classes="label" Text="{Binding L[desktop.settings.minLogLevel]}" />
<ComboBox ItemsSource="{Binding LogLevels}" SelectedItem="{Binding MinimumLogLevel}"
HorizontalAlignment="Stretch" />
</StackPanel>
<StackPanel Grid.Column="2">
<TextBlock Classes="label" Text="OpenRouter Base-URL" />
<TextBlock Classes="label" Text="{Binding L[desktop.settings.openRouterUrl]}" />
<TextBox Text="{Binding OpenRouterBaseUrl}" />
</StackPanel>
</Grid>
@@ -96,26 +108,26 @@
<!-- ══════════════════ Deploymentcenter ══════════════════ -->
<StackPanel Spacing="14">
<TextBlock Classes="kicker" Text="DEPLOYMENTCENTER &amp; LIZENZ" />
<TextBlock Classes="kicker" Text="{Binding L[desktop.settings.dcAndLicense]}" />
<StackPanel>
<TextBlock Classes="label" Text="Server-URL" />
<TextBlock Classes="label" Text="{Binding L[desktop.settings.dcUrl]}" />
<TextBox Text="{Binding DeploymentcenterUrl}" />
</StackPanel>
<StackPanel>
<TextBlock Classes="label" Text="Master-Token" />
<TextBlock Classes="label" Text="{Binding L[desktop.settings.dcToken]}" />
<TextBox Text="{Binding DeploymentcenterToken}" PasswordChar="•" />
</StackPanel>
<Grid ColumnDefinitions="*,16,*">
<StackPanel Grid.Column="0">
<TextBlock Classes="label" Text="Update-Kanal" />
<TextBlock Classes="label" Text="{Binding L[desktop.settings.updateChannel]}" />
<ComboBox ItemsSource="{Binding UpdateChannels}" SelectedItem="{Binding UpdateChannel}"
HorizontalAlignment="Stretch" />
</StackPanel>
<StackPanel Grid.Column="2">
<TextBlock Classes="label" Text="Umgebung" />
<TextBlock Classes="label" Text="{Binding L[desktop.settings.dcEnv]}" />
<ComboBox ItemsSource="{Binding Environments}"
SelectedItem="{Binding DeploymentcenterEnvironment}"
HorizontalAlignment="Stretch" />
@@ -123,14 +135,14 @@
</Grid>
<StackPanel>
<TextBlock Classes="label" Text="Lizenzschlüssel" />
<TextBlock Classes="label" Text="{Binding L[desktop.settings.licenseKey]}" />
<TextBox Text="{Binding LicenseKey}" PasswordChar="•" />
</StackPanel>
<StackPanel Spacing="10" Margin="0,4,0,0">
<CheckBox Content="Fehler automatisch an Deploymentcenter melden"
<CheckBox Content="{Binding L[desktop.settings.errorReporting]}"
IsChecked="{Binding ErrorReportingEnabled}" />
<CheckBox Content="Beim Start automatisch auf Updates prüfen"
<CheckBox Content="{Binding L[desktop.settings.updateCheck]}"
IsChecked="{Binding UpdateCheckEnabled}" />
</StackPanel>
</StackPanel>
@@ -16,13 +16,13 @@
Bildpunkt, damit zwischen ihnen nur eine Linie steht und nicht zwei. -->
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal"
HorizontalAlignment="Left" Margin="0,0,0,14">
<ToggleButton Content="Geplante Jobs" Margin="0,0,-1,0"
<ToggleButton Content="{Binding L[desktop.tasks.tabJobs]}" Margin="0,0,-1,0"
IsChecked="{Binding IsJobsTab, Mode=OneWay}"
Command="{Binding SelectTabCommand}" CommandParameter="Jobs" />
<ToggleButton Content="Dienste" Margin="0,0,-1,0"
<ToggleButton Content="{Binding L[desktop.tasks.tabServices]}" Margin="0,0,-1,0"
IsChecked="{Binding IsServicesTab, Mode=OneWay}"
Command="{Binding SelectTabCommand}" CommandParameter="Services" />
<ToggleButton Content="Verlauf"
<ToggleButton Content="{Binding L[desktop.tasks.tabHistory]}"
IsChecked="{Binding IsHistoryTab, Mode=OneWay}"
Command="{Binding SelectTabCommand}" CommandParameter="History" />
</StackPanel>
@@ -40,7 +40,7 @@
<Button Classes="toolbar primary" Command="{Binding AddJobCommand}">
<StackPanel Orientation="Horizontal" Spacing="6">
<ctrl:StrokeIcon Data="{StaticResource IconPlus}" Width="14" Height="14" />
<TextBlock Text="Job hinzufügen" />
<TextBlock Text="{Binding L[desktop.tasks.addJob]}" />
</StackPanel>
</Button>
@@ -48,7 +48,7 @@
IsEnabled="{Binding SelectedJob, Converter={x:Static ObjectConverters.IsNotNull}}">
<StackPanel Orientation="Horizontal" Spacing="6">
<ctrl:StrokeIcon Data="{StaticResource IconPencil}" Width="14" Height="14" />
<TextBlock Text="Bearbeiten" />
<TextBlock Text="{Binding L[desktop.tasks.editJob]}" />
</StackPanel>
</Button>
@@ -56,7 +56,7 @@
IsEnabled="{Binding SelectedJob, Converter={x:Static ObjectConverters.IsNotNull}}">
<StackPanel Orientation="Horizontal" Spacing="6">
<ctrl:StrokeIcon Data="{StaticResource IconTrash}" Width="14" Height="14" />
<TextBlock Text="Entfernen" />
<TextBlock Text="{Binding L[desktop.tasks.removeJob]}" />
</StackPanel>
</Button>
@@ -64,7 +64,7 @@
IsEnabled="{Binding SelectedJob, Converter={x:Static ObjectConverters.IsNotNull}}">
<StackPanel Orientation="Horizontal" Spacing="6">
<ctrl:StrokeIcon Data="{StaticResource IconPower}" Width="14" Height="14" />
<TextBlock Text="Aktivieren/Deaktivieren" />
<TextBlock Text="{Binding L[desktop.tasks.toggleJob]}" />
</StackPanel>
</Button>
@@ -74,27 +74,27 @@
IsEnabled="{Binding SelectedJob, Converter={x:Static ObjectConverters.IsNotNull}}">
<StackPanel Orientation="Horizontal" Spacing="6">
<ctrl:StrokeIcon Data="{StaticResource IconPlay}" Width="12" Height="12" IsFilled="True" />
<TextBlock Text="Jetzt ausführen" />
<TextBlock Text="{Binding L[desktop.tasks.runJobNow]}" />
</StackPanel>
</Button>
<Button Classes="toolbar" Command="{Binding RefreshJobListCommand}">
<StackPanel Orientation="Horizontal" Spacing="6">
<ctrl:StrokeIcon Data="{StaticResource IconRefresh}" Width="14" Height="14" />
<TextBlock Text="Aktualisieren" />
<TextBlock Text="{Binding L[desktop.tasks.refresh]}" />
</StackPanel>
</Button>
</WrapPanel>
<Border DockPanel.Dock="Top" Classes="thead">
<Grid ColumnDefinitions="1.1*,1.3*,2.2*,1.1*,1.3*,1.3*,0.9*">
<TextBlock Grid.Column="0" Classes="th" Text="TYP" />
<TextBlock Grid.Column="1" Classes="th" Text="AGENT" />
<TextBlock Grid.Column="2" Classes="th" Text="TOOL / NACHRICHT" />
<TextBlock Grid.Column="3" Classes="th" Text="CRON" />
<TextBlock Grid.Column="4" Classes="th" Text="NÄCHSTER LAUF" />
<TextBlock Grid.Column="5" Classes="th" Text="LETZTER LAUF" />
<TextBlock Grid.Column="6" Classes="th" Text="STATUS" />
<TextBlock Grid.Column="0" Classes="th" Text="{Binding L[desktop.tasks.thType]}" />
<TextBlock Grid.Column="1" Classes="th" Text="{Binding L[desktop.tasks.thAgent]}" />
<TextBlock Grid.Column="2" Classes="th" Text="{Binding L[desktop.tasks.thTask]}" />
<TextBlock Grid.Column="3" Classes="th" Text="{Binding L[desktop.tasks.thCron]}" />
<TextBlock Grid.Column="4" Classes="th" Text="{Binding L[desktop.tasks.thNextRun]}" />
<TextBlock Grid.Column="5" Classes="th" Text="{Binding L[desktop.tasks.thLastRun]}" />
<TextBlock Grid.Column="6" Classes="th" Text="{Binding L[desktop.tasks.thStatus]}" />
</Grid>
</Border>
@@ -131,7 +131,7 @@
<Button Classes="toolbar primary" Command="{Binding AddServiceCommand}">
<StackPanel Orientation="Horizontal" Spacing="6">
<ctrl:StrokeIcon Data="{StaticResource IconPlus}" Width="14" Height="14" />
<TextBlock Text="Dienst hinzufügen" />
<TextBlock Text="{Binding L[desktop.services.addService]}" />
</StackPanel>
</Button>
@@ -139,7 +139,7 @@
IsEnabled="{Binding SelectedService, Converter={x:Static ObjectConverters.IsNotNull}}">
<StackPanel Orientation="Horizontal" Spacing="6">
<ctrl:StrokeIcon Data="{StaticResource IconTrash}" Width="14" Height="14" />
<TextBlock Text="Entfernen" />
<TextBlock Text="{Binding L[desktop.services.removeService]}" />
</StackPanel>
</Button>
@@ -152,25 +152,25 @@
IsEnabled="{Binding SelectedService, Converter={x:Static ObjectConverters.IsNotNull}}">
<StackPanel Orientation="Horizontal" Spacing="6">
<ctrl:StrokeIcon Data="{StaticResource IconPower}" Width="14" Height="14" />
<TextBlock Text="Aktivieren/Deaktivieren" />
<TextBlock Text="{Binding L[desktop.services.toggleService]}" />
</StackPanel>
</Button>
<Button Classes="toolbar" Command="{Binding RefreshServiceListCommand}">
<StackPanel Orientation="Horizontal" Spacing="6">
<ctrl:StrokeIcon Data="{StaticResource IconRefresh}" Width="14" Height="14" />
<TextBlock Text="Aktualisieren" />
<TextBlock Text="{Binding L[desktop.tasks.refresh]}" />
</StackPanel>
</Button>
</WrapPanel>
<Border DockPanel.Dock="Top" Classes="thead">
<Grid ColumnDefinitions="1.8*,1*,0.7*,1*,3*">
<TextBlock Grid.Column="0" Classes="th" Text="DIENSTNAME" />
<TextBlock Grid.Column="1" Classes="th" Text="TYP" />
<TextBlock Grid.Column="2" Classes="th" Text="PORT" />
<TextBlock Grid.Column="3" Classes="th" Text="STATUS" />
<TextBlock Grid.Column="4" Classes="th" Text="BESCHREIBUNG" />
<TextBlock Grid.Column="0" Classes="th" Text="{Binding L[desktop.services.thName]}" />
<TextBlock Grid.Column="1" Classes="th" Text="{Binding L[desktop.services.thType]}" />
<TextBlock Grid.Column="2" Classes="th" Text="{Binding L[desktop.services.thPort]}" />
<TextBlock Grid.Column="3" Classes="th" Text="{Binding L[desktop.services.thStatus]}" />
<TextBlock Grid.Column="4" Classes="th" Text="{Binding L[desktop.services.thDescription]}" />
</Grid>
</Border>
@@ -206,19 +206,19 @@
<Button Classes="toolbar" Command="{Binding RefreshJobHistoryCommand}">
<StackPanel Orientation="Horizontal" Spacing="6">
<ctrl:StrokeIcon Data="{StaticResource IconRefresh}" Width="14" Height="14" />
<TextBlock Text="Verlauf aktualisieren" />
<TextBlock Text="{Binding L[desktop.history.refresh]}" />
</StackPanel>
</Button>
</StackPanel>
<Border DockPanel.Dock="Top" Classes="thead">
<Grid ColumnDefinitions="1.3*,1.6*,1.4*,2*,0.9*,2.4*">
<TextBlock Grid.Column="0" Classes="th" Text="ZEITPUNKT" />
<TextBlock Grid.Column="1" Classes="th" Text="JOB" />
<TextBlock Grid.Column="2" Classes="th" Text="AGENT" />
<TextBlock Grid.Column="3" Classes="th" Text="BESCHREIBUNG" />
<TextBlock Grid.Column="4" Classes="th" Text="STATUS" />
<TextBlock Grid.Column="5" Classes="th" Text="DETAILS" />
<TextBlock Grid.Column="0" Classes="th" Text="{Binding L[desktop.history.thTime]}" />
<TextBlock Grid.Column="1" Classes="th" Text="{Binding L[desktop.history.thJob]}" />
<TextBlock Grid.Column="2" Classes="th" Text="{Binding L[desktop.history.thAgent]}" />
<TextBlock Grid.Column="3" Classes="th" Text="{Binding L[desktop.history.thDescription]}" />
<TextBlock Grid.Column="4" Classes="th" Text="{Binding L[desktop.history.thStatus]}" />
<TextBlock Grid.Column="5" Classes="th" Text="{Binding L[desktop.history.thDetails]}" />
</Grid>
</Border>
@@ -17,12 +17,12 @@
<DockPanel>
<TextBlock x:Name="TitleText" DockPanel.Dock="Top" Classes="h1"
Text="Text bearbeiten" Margin="0,0,0,12" TextWrapping="Wrap" />
Text="Edit Text" Margin="0,0,0,12" TextWrapping="Wrap" />
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" Spacing="8"
HorizontalAlignment="Right" Margin="0,14,0,0">
<Button Content="Abbrechen" IsCancel="True" Click="OnCancel" />
<Button Classes="primary" Content="Speichern" IsDefault="True" Click="OnSave" />
<Button x:Name="CancelButton" Content="Cancel" IsCancel="True" Click="OnCancel" />
<Button x:Name="SaveButton" Classes="primary" Content="Save" IsDefault="True" Click="OnSave" />
</StackPanel>
<TextBox x:Name="Editor" AcceptsReturn="True" TextWrapping="Wrap"
@@ -17,6 +17,9 @@ public partial class TextEditorWindow : Window
public TextEditorWindow()
{
InitializeComponent();
Title = ClawdDotNet.Desktop.Services.LocalizationManager.Instance["desktop.dialog.textEditorTitle"] ?? "Edit Text";
CancelButton.Content = ClawdDotNet.Desktop.Services.LocalizationManager.Instance["common.cancel"] ?? "Cancel";
SaveButton.Content = ClawdDotNet.Desktop.Services.LocalizationManager.Instance["common.save"] ?? "Save";
}
/// <summary>
@@ -15,19 +15,19 @@
<StackPanel Orientation="Horizontal" Spacing="12">
<Border Classes="card" MinWidth="160">
<StackPanel Spacing="6">
<TextBlock Classes="kicker" Text="TOKENS (7 TAGE)" />
<TextBlock Classes="kicker" Text="{Binding L[desktop.usage.kickerTokens7d]}" />
<TextBlock Classes="h2" Text="{Binding TotalTokens}" />
</StackPanel>
</Border>
<Border Classes="card" MinWidth="160">
<StackPanel Spacing="6">
<TextBlock Classes="kicker" Text="KOSTEN (7 TAGE)" />
<TextBlock Classes="kicker" Text="{Binding L[desktop.usage.kickerCost7d]}" />
<TextBlock Classes="h2" Text="{Binding TotalCost}" />
</StackPanel>
</Border>
<Border Classes="card" MinWidth="160">
<StackPanel Spacing="6">
<TextBlock Classes="kicker" Text="RUNS (7 TAGE)" />
<TextBlock Classes="kicker" Text="{Binding L[desktop.usage.kickerRuns7d]}" />
<TextBlock Classes="h2" Text="{Binding TotalRuns}" />
</StackPanel>
</Border>
@@ -35,7 +35,7 @@
<Button Classes="toolbar" Command="{Binding RefreshCommand}" VerticalAlignment="Bottom">
<StackPanel Orientation="Horizontal" Spacing="6">
<ctrl:StrokeIcon Data="{StaticResource IconRefresh}" Width="14" Height="14" />
<TextBlock Text="Aktualisieren" />
<TextBlock Text="{Binding L[desktop.usage.refresh]}" />
</StackPanel>
</Button>
</StackPanel>
@@ -46,7 +46,7 @@
<!-- Tagesbalken -->
<StackPanel Spacing="12" IsVisible="{Binding !IsEmpty}">
<TextBlock Classes="h2" Text="Tokens pro Tag" />
<TextBlock Classes="h2" Text="{Binding L[desktop.usage.tokensPerDay]}" />
<Border BorderBrush="{DynamicResource DividerBrush}" BorderThickness="0,0,0,1"
Padding="0,0,0,2">
@@ -78,15 +78,15 @@
<!-- Aufschlüsselung -->
<StackPanel Spacing="10" MaxWidth="860" HorizontalAlignment="Left"
IsVisible="{Binding !IsEmpty}">
<TextBlock Classes="h2" Text="Aufschlüsselung nach Agent &amp; Modell" />
<TextBlock Classes="h2" Text="{Binding L[desktop.usage.breakdownTitle]}" />
<Border Classes="thead">
<Grid ColumnDefinitions="2*,2*,1.2*,1.2*,0.8*">
<TextBlock Grid.Column="0" Classes="th" Text="AGENT" />
<TextBlock Grid.Column="1" Classes="th" Text="MODELL" />
<TextBlock Grid.Column="2" Classes="th" Text="TOKENS" />
<TextBlock Grid.Column="3" Classes="th" Text="KOSTEN" />
<TextBlock Grid.Column="4" Classes="th" Text="RUNS" />
<TextBlock Grid.Column="0" Classes="th" Text="{Binding L[desktop.usage.thAgent]}" />
<TextBlock Grid.Column="1" Classes="th" Text="{Binding L[desktop.usage.thModel]}" />
<TextBlock Grid.Column="2" Classes="th" Text="{Binding L[desktop.usage.thTokens]}" />
<TextBlock Grid.Column="3" Classes="th" Text="{Binding L[desktop.usage.thCost]}" />
<TextBlock Grid.Column="4" Classes="th" Text="{Binding L[desktop.usage.thRuns]}" />
</Grid>
</Border>
@@ -23,25 +23,25 @@
<StackPanel Spacing="12" IsVisible="{Binding ToolName,
Converter={x:Static conv:ToolMatchConverter.Instance}, ConverterParameter=FTP}">
<StackPanel>
<TextBlock Classes="label" Text="Host" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.host]}" />
<TextBox Text="{Binding FtpHost}" PlaceholderText="ftp.example.com" />
</StackPanel>
<Grid ColumnDefinitions="*,12,*">
<StackPanel Grid.Column="0">
<TextBlock Classes="label" Text="Port" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.port]}" />
<TextBox Text="{Binding FtpPort}" />
</StackPanel>
<StackPanel Grid.Column="2">
<TextBlock Classes="label" Text="Benutzername" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.username]}" />
<TextBox Text="{Binding FtpUsername}" />
</StackPanel>
</Grid>
<StackPanel>
<TextBlock Classes="label" Text="Passwort" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.password]}" />
<TextBox Text="{Binding FtpPassword}" PasswordChar="•" />
</StackPanel>
<StackPanel>
<TextBlock Classes="label" Text="Root-Pfad" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.rootPath]}" />
<TextBox Text="{Binding FtpRootPath}" />
</StackPanel>
</StackPanel>
@@ -51,36 +51,36 @@
Converter={x:Static conv:ToolMatchConverter.Instance}, ConverterParameter=Mail}">
<Grid ColumnDefinitions="*,12,*">
<StackPanel Grid.Column="0">
<TextBlock Classes="label" Text="Benutzername" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.username]}" />
<TextBox Text="{Binding MailUsername}" />
</StackPanel>
<StackPanel Grid.Column="2">
<TextBlock Classes="label" Text="Passwort" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.password]}" />
<TextBox Text="{Binding MailPassword}" PasswordChar="•" />
</StackPanel>
</Grid>
<Grid ColumnDefinitions="*,12,*">
<StackPanel Grid.Column="0">
<TextBlock Classes="label" Text="IMAP-Host" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.imapHost]}" />
<TextBox Text="{Binding MailImapHost}" />
</StackPanel>
<StackPanel Grid.Column="2">
<TextBlock Classes="label" Text="IMAP-Port" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.imapPort]}" />
<TextBox Text="{Binding MailImapPort}" />
</StackPanel>
</Grid>
<Grid ColumnDefinitions="*,12,*">
<StackPanel Grid.Column="0">
<TextBlock Classes="label" Text="SMTP-Host" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.smtpHost]}" />
<TextBox Text="{Binding MailSmtpHost}" />
</StackPanel>
<StackPanel Grid.Column="2">
<TextBlock Classes="label" Text="SMTP-Port" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.smtpPort]}" />
<TextBox Text="{Binding MailSmtpPort}" />
</StackPanel>
</Grid>
<StackPanel>
<TextBlock Classes="label" Text="Erlaubte Empfänger" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.allowedRecipients]}" />
<TextBox Text="{Binding MailAllowedRecipients}"
PlaceholderText="adresse1@domain.de, adresse2@domain.de" />
</StackPanel>
@@ -90,21 +90,21 @@
<StackPanel Spacing="12" IsVisible="{Binding ToolName,
Converter={x:Static conv:ToolMatchConverter.Instance}, ConverterParameter=Database}">
<StackPanel>
<TextBlock Classes="label" Text="Typ" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.type]}" />
<ComboBox ItemsSource="{Binding DbTypes}" SelectedItem="{Binding DbType}"
HorizontalAlignment="Stretch" />
</StackPanel>
<StackPanel>
<TextBlock Classes="label" Text="Connection-String" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.connectionString]}" />
<TextBox Text="{Binding DbConnectionString}" PasswordChar="•" />
</StackPanel>
<StackPanel>
<TextBlock Classes="label" Text="Zugriffsebene" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.accessLevel]}" />
<ComboBox ItemsSource="{Binding DbAccessLevels}" SelectedItem="{Binding DbAccessLevel}"
HorizontalAlignment="Stretch" />
</StackPanel>
<StackPanel>
<TextBlock Classes="label" Text="Erlaubte Tabellen" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.allowedTables]}" />
<TextBox Text="{Binding DbAllowedTables}" PlaceholderText="tabelle1, tabelle2" />
</StackPanel>
</StackPanel>
@@ -113,15 +113,15 @@
<StackPanel Spacing="12" IsVisible="{Binding ToolName,
Converter={x:Static conv:ToolMatchConverter.Instance}, ConverterParameter=Telegram}">
<StackPanel>
<TextBlock Classes="label" Text="Bot-Token" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.botToken]}" />
<TextBox Text="{Binding TelegramBotToken}" PasswordChar="•" />
</StackPanel>
<StackPanel>
<TextBlock Classes="label" Text="Standard Chat-ID" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.defaultChatId]}" />
<TextBox Text="{Binding TelegramDefaultChatId}" />
</StackPanel>
<StackPanel>
<TextBlock Classes="label" Text="Erlaubte Chat-IDs" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.allowedChatIds]}" />
<TextBox Text="{Binding TelegramAllowedChatIds}" PlaceholderText="id1, id2" />
</StackPanel>
</StackPanel>
@@ -131,20 +131,20 @@
Converter={x:Static conv:ToolMatchConverter.Instance}, ConverterParameter=DirectAPI}">
<Grid ColumnDefinitions="*,12,*">
<StackPanel Grid.Column="0">
<TextBlock Classes="label" Text="Standard-Provider" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.defaultProvider]}" />
<TextBox Text="{Binding DirectApiDefaultProvider}" />
</StackPanel>
<StackPanel Grid.Column="2">
<TextBlock Classes="label" Text="Cache TTL (Sekunden)" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.cacheTtl]}" />
<TextBox Text="{Binding DirectApiCacheTtlSeconds}" />
</StackPanel>
</Grid>
<StackPanel>
<TextBlock Classes="label" Text="Twelve Data Key" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.twelveDataKey]}" />
<TextBox Text="{Binding DirectApiTwelveDataKey}" PasswordChar="•" />
</StackPanel>
<StackPanel>
<TextBlock Classes="label" Text="Alpha Vantage Key" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.alphaVantageKey]}" />
<TextBox Text="{Binding DirectApiAlphaVantageKey}" PasswordChar="•" />
</StackPanel>
</StackPanel>
@@ -153,17 +153,17 @@
<StackPanel Spacing="12" IsVisible="{Binding ToolName,
Converter={x:Static conv:ToolMatchConverter.Instance}, ConverterParameter=WebFetch}">
<StackPanel>
<TextBlock Classes="label" Text="Erlaubte Domains" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.allowedDomains]}" />
<TextBox Text="{Binding WebFetchAllowedDomains}"
PlaceholderText="reuters.com, coindesk.com" />
</StackPanel>
<Grid ColumnDefinitions="*,12,*">
<StackPanel Grid.Column="0">
<TextBlock Classes="label" Text="Max. Antwortgröße (KB)" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.maxResponseKb]}" />
<TextBox Text="{Binding WebFetchMaxResponseKb}" />
</StackPanel>
<StackPanel Grid.Column="2">
<TextBlock Classes="label" Text="User Agent" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.userAgent]}" />
<TextBox Text="{Binding WebFetchUserAgent}" />
</StackPanel>
</Grid>
@@ -173,34 +173,34 @@
<StackPanel Spacing="12" IsVisible="{Binding ToolName,
Converter={x:Static conv:ToolMatchConverter.Instance}, ConverterParameter=SocialMediaManager}">
<StackPanel>
<TextBlock Classes="label" Text="X (Twitter) API-Key" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.xApiKey]}" />
<TextBox Text="{Binding SmmXApiKey}" PasswordChar="•" />
</StackPanel>
<StackPanel>
<TextBlock Classes="label" Text="X Accounts" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.xAccounts]}" />
<TextBox Text="{Binding SmmXWatchAccounts}" PlaceholderText="account1, account2" />
</StackPanel>
<Grid ColumnDefinitions="*,12,*">
<StackPanel Grid.Column="0">
<TextBlock Classes="label" Text="Subreddits" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.subreddits]}" />
<TextBox Text="{Binding SmmRedditWatchSubreddits}" PlaceholderText="stocks, investing" />
</StackPanel>
<StackPanel Grid.Column="2">
<TextBlock Classes="label" Text="Reddit Post Limit" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.redditPostLimit]}" />
<TextBox Text="{Binding SmmRedditPostLimit}" />
</StackPanel>
</Grid>
<StackPanel>
<TextBlock Classes="label" Text="OpenRouter Key" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.openRouterKey]}" />
<TextBox Text="{Binding SmmOpenRouterApiKey}" PasswordChar="•" />
</StackPanel>
<Grid ColumnDefinitions="*,12,*">
<StackPanel Grid.Column="0">
<TextBlock Classes="label" Text="STT-Modell" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.sttModel]}" />
<TextBox Text="{Binding SmmSttModel}" />
</StackPanel>
<StackPanel Grid.Column="2">
<TextBlock Classes="label" Text="YouTube-Kanäle" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.youtubeChannels]}" />
<TextBox Text="{Binding SmmYoutubeChannels}" PlaceholderText="URL1, URL2" />
</StackPanel>
</Grid>
@@ -210,28 +210,28 @@
<StackPanel Spacing="12" IsVisible="{Binding ToolName,
Converter={x:Static conv:ToolMatchConverter.Instance}, ConverterParameter=FileRW}">
<StackPanel>
<TextBlock Classes="label" Text="Erlaubte Dateiendungen (persönlich)" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.fileRwPersonalExt]}" />
<TextBox Text="{Binding FileRwPersonalAllowedExtensions}" />
</StackPanel>
<StackPanel>
<TextBlock Classes="label" Text="Zugriffsebene (geteilt)" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.fileRwSharedAccess]}" />
<ComboBox ItemsSource="{Binding FileRwAccessLevels}"
SelectedItem="{Binding FileRwSharedAccessLevel}"
HorizontalAlignment="Stretch" />
</StackPanel>
<StackPanel>
<TextBlock Classes="label" Text="Erlaubte Dateiendungen (geteilt)" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.fileRwSharedExt]}" />
<TextBox Text="{Binding FileRwSharedAllowedExtensions}" />
</StackPanel>
<StackPanel>
<TextBlock Classes="label" Text="Geschützte Pfade" />
<TextBlock Classes="label" Text="{Binding L[desktop.toolSettings.fileRwProtectedPaths]}" />
<TextBox Text="{Binding FileRwProtectedPaths}" />
</StackPanel>
</StackPanel>
<!-- Werkzeuge ohne weitere Einstellungen -->
<TextBlock Classes="muted" FontStyle="Italic" TextWrapping="Wrap"
Text="Dieses Werkzeug benötigt keine weiteren Einstellungen."
Text="{Binding L[desktop.toolSettings.noSettings]}"
IsVisible="{Binding SettingsObject, Converter={x:Static ObjectConverters.IsNull}}" />
</StackPanel>