Add German localization (#430)
Build and Release / Read metadata (push) Waiting to run
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-unknown-linux-gnu, linux-arm64, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, appimage deb updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-unknown-linux-gnu, linux-x64, ubuntu-22.04, x86_64-unknown-linux-gnu, appimage deb updater) (push) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions

This commit is contained in:
Thorsten Sommer authored and GitHub committed 2025-04-27 16:13:15 +02:00
1 parent 2494ee2294
commit 47b6a89685
44 files changed
+3394 -262

No files matched your search

@@ -58,19 +58,19 @@
this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is not WorkspaceStorageBehavior.DISABLE_WORKSPACES
&& this.SettingsManager.ConfigurationData.Workspace.DisplayBehavior is WorkspaceDisplayBehavior.TOGGLE_OVERLAY)
{
<MudTooltip Text="Show your workspaces" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
<MudTooltip Text="@T("Show your workspaces")" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
<MudIconButton Icon="@Icons.Material.Filled.SnippetFolder" OnClick="() => this.ToggleWorkspaceOverlay()"/>
</MudTooltip>
}
@if (this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_MANUALLY)
{
<MudTooltip Text="Save chat" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
<MudTooltip Text="@T("Save chat")" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
<MudIconButton Icon="@Icons.Material.Filled.Save" OnClick="() => this.SaveThread()" Disabled="@(!this.CanThreadBeSaved)"/>
</MudTooltip>
}
<MudTooltip Text="Start temporary chat" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
<MudTooltip Text="@T("Start temporary chat")" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
<MudIconButton Icon="@Icons.Material.Filled.AddComment" OnClick="() => this.StartNewChat(useSameWorkspace: false)"/>
</MudTooltip>
@@ -102,7 +102,7 @@
@if (this.isStreaming && this.cancellationTokenSource is not null)
{
<MudTooltip Text="Stop generation" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
<MudTooltip Text="@T("Stop generation")" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
<MudIconButton Icon="@Icons.Material.Filled.Stop" Color="Color.Error" OnClick="() => this.CancelStreaming()"/>
</MudTooltip>
}
@@ -1,9 +1,9 @@
@using AIStudio.Settings
@inherits MSGComponentBase
@if (this.SelectionMode is DataSourceSelectionMode.SELECTION_MODE)
{
<div class="d-flex">
<MudTooltip Text="Select the data you want to use here." Placement="Placement.Top">
<MudTooltip Text="@T("Select the data you want to use here.")" Placement="Placement.Top">
@if (this.PopoverTriggerMode is PopoverTriggerMode.ICON)
{
<MudIconButton Icon="@Icons.Material.Filled.Source" Class="@this.PopoverButtonClasses" OnClick="@(() => this.ToggleDataSourceSelection())"/>
@@ -11,7 +11,7 @@
else
{
<MudButton Variant="Variant.Filled" StartIcon="@Icons.Material.Filled.Source" Class="@this.PopoverButtonClasses" OnClick="@(() => this.ToggleDataSourceSelection())">
Select data
@T("Select data")
</MudButton>
}
</MudTooltip>
@@ -22,9 +22,11 @@
<CardHeaderContent>
<PreviewPrototype/>
<MudStack Row="true" AlignItems="AlignItems.Center">
<MudText Typo="Typo.h5">Data Source Selection</MudText>
<MudText Typo="Typo.h5">
@T("Data Source Selection")
</MudText>
<MudSpacer/>
<MudTooltip Text="Manage your data sources" Placement="Placement.Top">
<MudTooltip Text="@T("Manage your data sources")" Placement="Placement.Top">
<MudIconButton Variant="Variant.Filled" Icon="@Icons.Material.Filled.Settings" OnClick="@this.OpenSettingsDialog"/>
</MudTooltip>
</MudStack>
@@ -40,57 +42,52 @@
else if (this.SettingsManager.ConfigurationData.DataSources.Count == 0)
{
<MudJustifiedText Typo="Typo.body1" Class="mb-3">
You haven't configured any data sources. To grant the AI access to your data, you need to
add such a source. However, if you wish to use data from your device, you first have to set up
a so-called embedding. This embedding is necessary so the AI can effectively search your data,
find and retrieve the correct information required for each task. In addition to local data,
you can also incorporate your company's data. To do so, your company must provide the data through
an ERI (External Retrieval Interface).
@T("You haven't configured any data sources. To grant the AI access to your data, you need to add such a source. However, if you wish to use data from your device, you first have to set up a so-called embedding. This embedding is necessary so the AI can effectively search your data, find and retrieve the correct information required for each task. In addition to local data, you can also incorporate your company's data. To do so, your company must provide the data through an ERI (External Retrieval Interface).")
</MudJustifiedText>
<MudStack StretchItems="StretchItems.None" AlignItems="AlignItems.Start">
<MudButton Variant="Variant.Filled" OnClick="this.OpenSettingsDialog" StartIcon="@Icons.Material.Filled.Settings">
Manage Data Sources
@T("Manage Data Sources")
</MudButton>
<MudButton Variant="Variant.Filled" Href="https://mindworkai.org/#eri---external-retrieval-interface" Target="_blank" StartIcon="@Icons.Material.Filled.Settings">
Read more about ERI
@T("Read more about ERI")
</MudButton>
</MudStack>
}
else if (this.showDataSourceSelection)
{
<MudTextSwitch Label="Are data sources enabled?" Value="@this.areDataSourcesEnabled" LabelOn="Yes, I want to use data sources." LabelOff="No, I don't want to use data sources." ValueChanged="@this.EnabledChanged"/>
<MudTextSwitch Label="Are data sources enabled?" Value="@this.areDataSourcesEnabled" LabelOn="@T("Yes, I want to use data sources.")" LabelOff="@T("No, I don't want to use data sources.")" ValueChanged="@this.EnabledChanged"/>
@if (this.areDataSourcesEnabled)
{
<MudTextSwitch Label="AI-based data source selection" Value="@this.aiBasedSourceSelection" LabelOn="Yes, let the AI decide which data sources are needed." LabelOff="No, I manually decide which data source to use." ValueChanged="@this.AutoModeChanged"/>
<MudTextSwitch Label="@T("AI-based data source selection")" Value="@this.aiBasedSourceSelection" LabelOn="@T("Yes, let the AI decide which data sources are needed.")" LabelOff="@T("No, I manually decide which data source to use.")" ValueChanged="@this.AutoModeChanged"/>
@if (this.SettingsManager.ConfigurationData.AgentRetrievalContextValidation.EnableRetrievalContextValidation)
{
<MudTextSwitch Label="AI-based data validation" Value="@this.aiBasedValidation" LabelOn="Yes, let the AI validate & filter the retrieved data." LabelOff="No, use all data retrieved from the data sources." ValueChanged="@this.ValidationModeChanged"/>
<MudTextSwitch Label="@T("AI-based data validation")" Value="@this.aiBasedValidation" LabelOn="@T("Yes, let the AI validate & filter the retrieved data.")" LabelOff="@T("No, use all data retrieved from the data sources.")" ValueChanged="@this.ValidationModeChanged"/>
}
@switch (this.aiBasedSourceSelection)
{
case true when this.availableDataSources.Count == 0:
<MudText Typo="Typo.body1" Class="mb-3">
Your data sources cannot be used with the LLM provider you selected due to data privacy, or they are currently unavailable.
@T("Your data sources cannot be used with the LLM provider you selected due to data privacy, or they are currently unavailable.")
</MudText>
break;
case true when this.DataSourcesAISelected.Count == 0:
<MudText Typo="Typo.body1" Class="mb-3">
The AI evaluates each of your inputs to determine whether and which data sources are necessary. Currently, the AI has not selected any source.
@T("The AI evaluates each of your inputs to determine whether and which data sources are necessary. Currently, the AI has not selected any source.")
</MudText>
break;
case false when this.availableDataSources.Count == 0:
<MudText Typo="Typo.body1" Class="mb-3">
Your data sources cannot be used with the LLM provider you selected due to data privacy, or they are currently unavailable.
@T("Your data sources cannot be used with the LLM provider you selected due to data privacy, or they are currently unavailable.")
</MudText>
break;
case false:
<MudField Label="Available Data Sources" Variant="Variant.Outlined" Class="mb-3" Disabled="@this.aiBasedSourceSelection">
<MudField Label="@T("Available Data Sources")" Variant="Variant.Outlined" Class="mb-3" Disabled="@this.aiBasedSourceSelection">
<MudList T="IDataSource" SelectionMode="@this.GetListSelectionMode()" @bind-SelectedValues:get="@this.selectedDataSources" @bind-SelectedValues:set="@(x => this.SelectionChanged(x))" Style="max-height: 14em;">
@foreach (var source in this.availableDataSources)
{
@@ -104,7 +101,7 @@
case true:
<MudExpansionPanels MultiExpansion="@false" Class="mt-3" Style="max-height: 14em;">
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.TouchApp" HeaderText="Available Data Sources">
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.TouchApp" HeaderText="@T("Available Data Sources")">
<MudList T="IDataSource" SelectionMode="MudBlazor.SelectionMode.SingleSelection" SelectedValues="@this.selectedDataSources" Style="max-height: 14em;">
@foreach (var source in this.availableDataSources)
{
@@ -114,7 +111,7 @@
}
</MudList>
</ExpansionPanel>
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Filter" HeaderText="AI-Selected Data Sources">
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Filter" HeaderText="@T("AI-Selected Data Sources")">
<MudList T="DataSourceAgentSelected" SelectionMode="MudBlazor.SelectionMode.MultiSelection" ReadOnly="@true" SelectedValues="@this.GetSelectedDataSourcesWithAI()" Style="max-height: 14em;">
@foreach (var source in this.DataSourcesAISelected)
{
@@ -141,7 +138,7 @@
</MudCardContent>
<MudCardActions>
<MudButton Variant="Variant.Filled" OnClick="@(() => this.HideDataSourceSelection())">
Close
@T("Close")
</MudButton>
</MudCardActions>
</MudCard>
@@ -152,7 +149,9 @@ else if (this.SelectionMode is DataSourceSelectionMode.CONFIGURATION_MODE)
{
<MudPaper Class="pa-3 mb-8 mt-3 border-dashed border rounded-lg">
<PreviewPrototype/>
<MudText Typo="Typo.h5">Data Source Selection</MudText>
<MudText Typo="Typo.h5">
@T("Data Source Selection")
</MudText>
@if (!string.IsNullOrWhiteSpace(this.ConfigurationHeaderMessage))
{
@@ -161,12 +160,12 @@ else if (this.SelectionMode is DataSourceSelectionMode.CONFIGURATION_MODE)
</MudText>
}
<MudTextSwitch Label="Are data sources enabled?" Value="@this.areDataSourcesEnabled" LabelOn="Yes, I want to use data sources." LabelOff="No, I don't want to use data sources." ValueChanged="@this.EnabledChanged"/>
<MudTextSwitch Label="@T("Are data sources enabled?")" Value="@this.areDataSourcesEnabled" LabelOn="@T("Yes, I want to use data sources.")" LabelOff="@T("No, I don't want to use data sources.")" ValueChanged="@this.EnabledChanged"/>
@if (this.areDataSourcesEnabled)
{
<MudTextSwitch Label="AI-based data source selection" Value="@this.aiBasedSourceSelection" LabelOn="Yes, let the AI decide which data sources are needed." LabelOff="No, I manually decide which data source to use." ValueChanged="@this.AutoModeChanged"/>
<MudTextSwitch Label="AI-based data validation" Value="@this.aiBasedValidation" LabelOn="Yes, let the AI validate & filter the retrieved data." LabelOff="No, use all data retrieved from the data sources." ValueChanged="@this.ValidationModeChanged"/>
<MudField Label="Available Data Sources" Variant="Variant.Outlined" Class="mb-3" Disabled="@this.aiBasedSourceSelection">
<MudTextSwitch Label="@T("AI-based data source selection")" Value="@this.aiBasedSourceSelection" LabelOn="@T("Yes, let the AI decide which data sources are needed.")" LabelOff="@T("No, I manually decide which data source to use.")" ValueChanged="@this.AutoModeChanged"/>
<MudTextSwitch Label="@T("AI-based data validation")" Value="@this.aiBasedValidation" LabelOn="@T("Yes, let the AI validate & filter the retrieved data.")" LabelOff="@T("No, use all data retrieved from the data sources.")" ValueChanged="@this.ValidationModeChanged"/>
<MudField Label="@T("Available Data Sources")" Variant="Variant.Outlined" Class="mb-3" Disabled="@this.aiBasedSourceSelection">
<MudList T="IDataSource" SelectionMode="@this.GetListSelectionMode()" @bind-SelectedValues:get="@this.selectedDataSources" @bind-SelectedValues:set="@(x => this.SelectionChanged(x))">
@foreach (var source in this.availableDataSources)
{
@@ -9,7 +9,7 @@ using DialogOptions = AIStudio.Dialogs.DialogOptions;
namespace AIStudio.Components;
public partial class DataSourceSelection : ComponentBase, IMessageBusReceiver, IDisposable
public partial class DataSourceSelection : MSGComponentBase
{
[Parameter]
public DataSourceSelectionMode SelectionMode { get; set; } = DataSourceSelectionMode.SELECTION_MODE;
@@ -38,12 +38,6 @@ public partial class DataSourceSelection : ComponentBase, IMessageBusReceiver, I
[Parameter]
public bool AutoSaveAppSettings { get; set; }
[Inject]
private SettingsManager SettingsManager { get; init; } = null!;
[Inject]
private MessageBus MessageBus { get; init; } = null!;
[Inject]
private DataSourceService DataSourceService { get; init; } = null!;
@@ -63,8 +57,7 @@ public partial class DataSourceSelection : ComponentBase, IMessageBusReceiver, I
protected override async Task OnInitializedAsync()
{
this.MessageBus.RegisterComponent(this);
this.MessageBus.ApplyFilters(this, [], [ Event.COLOR_THEME_CHANGED, Event.RAG_AUTO_DATA_SOURCES_SELECTED ]);
this.ApplyFilters([], [ Event.RAG_AUTO_DATA_SOURCES_SELECTED ]);
//
// Load the settings:
@@ -253,19 +246,12 @@ public partial class DataSourceSelection : ComponentBase, IMessageBusReceiver, I
private void HideDataSourceSelection() => this.showDataSourceSelection = false;
#region Implementation of IMessageBusReceiver
#region Overrides of MSGComponentBase
public string ComponentName => nameof(ConfidenceInfo);
public Task ProcessMessage<T>(ComponentBase? sendingComponent, Event triggeredEvent, T? data)
protected override Task ProcessIncomingMessage<T>(ComponentBase? sendingComponent, Event triggeredEvent, T? data) where T : default
{
switch (triggeredEvent)
{
case Event.COLOR_THEME_CHANGED:
this.showDataSourceSelection = false;
this.StateHasChanged();
break;
case Event.RAG_AUTO_DATA_SOURCES_SELECTED:
if(data is IReadOnlyList<DataSourceAgentSelected> aiSelectedDataSources)
this.DataSourcesAISelected = aiSelectedDataSources;
@@ -273,23 +259,9 @@ public partial class DataSourceSelection : ComponentBase, IMessageBusReceiver, I
this.StateHasChanged();
break;
}
return Task.CompletedTask;
}
public Task<TResult?> ProcessMessageWithResult<TPayload, TResult>(ComponentBase? sendingComponent, Event triggeredEvent, TPayload? data)
{
return Task.FromResult<TResult?>(default);
}
#endregion
#region Implementation of IDisposable
public void Dispose()
{
this.MessageBus.Unregister(this);
}
#endregion
}
@@ -35,6 +35,9 @@ public abstract class MSGComponentBase : ComponentBase, IDisposable, IMessageBus
/// <inheritdoc />
public string T(string fallbackEN) => this.GetText(this.Lang, fallbackEN);
/// <inheritdoc />
public string T(string fallbackEN, string? typeNamespace, string? typeName) => this.GetText(this.Lang, fallbackEN, typeNamespace, typeName);
#endregion
@@ -73,20 +76,6 @@ public abstract class MSGComponentBase : ComponentBase, IDisposable, IMessageBus
{
return Task.FromResult<TResult?>(default);
}
protected virtual void DisposeResources()
{
}
#region Implementation of IDisposable
public void Dispose()
{
this.MessageBus.Unregister(this);
this.DisposeResources();
}
#endregion
protected async Task SendMessage<T>(Event triggeredEvent, T? data = default)
{
@@ -114,4 +103,18 @@ public abstract class MSGComponentBase : ComponentBase, IDisposable, IMessageBus
this.MessageBus.ApplyFilters(this, filterComponents, eventsList.ToArray());
}
protected virtual void DisposeResources()
{
}
#region Implementation of IDisposable
public void Dispose()
{
this.MessageBus.Unregister(this);
this.DisposeResources();
}
#endregion
}
@@ -2,7 +2,9 @@
@foreach(var item in this.Items)
{
<MudListItem T="string" Icon="@this.Icon" Style="display: flex; align-items: flex-start;">
<MudText Typo="Typo.body1" Align="Align.Justify" Style="hyphens: auto; word-break: auto-phrase;"><b>@item.Header:</b> @item.Text</MudText>
<MudText Typo="Typo.body1" Align="Align.Justify" Style="hyphens: auto; word-break: auto-phrase;">
<b>@item.Header:</b> @item.Text
</MudText>
</MudListItem>
}
</MudList>
@@ -1,10 +1,20 @@
using Microsoft.AspNetCore.Components;
namespace AIStudio.Components;
public partial class Vision : MSGComponentBase
{
private readonly TextItem[] itemsVision;
private TextItem[] itemsVision = [];
public Vision()
#region Overrides of MSGComponentBase
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
this.InitializeVisionItems();
}
private void InitializeVisionItems()
{
this.itemsVision =
[
@@ -20,4 +30,17 @@ public partial class Vision : MSGComponentBase
new(T("Browser usage"), T("We're working on offering AI Studio features in your browser via a plugin, allowing, e.g., for spell-checking or text rewriting directly in the browser.")),
];
}
protected override async Task ProcessIncomingMessage<T>(ComponentBase? sendingComponent, Event triggeredEvent, T? data) where T : default
{
switch (triggeredEvent)
{
case Event.PLUGINS_RELOADED:
this.InitializeVisionItems();
await this.InvokeAsync(this.StateHasChanged);
break;
}
}
#endregion
}
@@ -39,6 +39,8 @@ public partial class Workspaces : MSGComponentBase
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
//
// Notice: In order to get the server-based loading to work, we need to respect the following rules:
// - We must have initial tree items
@@ -46,7 +48,6 @@ public partial class Workspaces : MSGComponentBase
// - When assigning the tree items to the MudTreeViewItem component, we must set the Value property to the value of the item
//
await this.LoadTreeItems();
await base.OnInitializedAsync();
}
#endregion
@@ -504,4 +505,19 @@ public partial class Workspaces : MSGComponentBase
await this.LoadChat(chatPath, switchToChat: true);
await this.LoadTreeItems();
}
#region Overrides of MSGComponentBase
protected override async Task ProcessIncomingMessage<T>(ComponentBase? sendingComponent, Event triggeredEvent, T? data) where T : default
{
switch (triggeredEvent)
{
case Event.PLUGINS_RELOADED:
await this.LoadTreeItems();
await this.InvokeAsync(this.StateHasChanged);
break;
}
}
#endregion
}