Added the choice between formal and informal address to the whole app (#1200)

This commit is contained in:
Thorsten Sommer authored and GitHub committed 2026-11-13 10:16:56 +01:00
1 parent 382db4b8d0
commit c9a376f742
342 files changed
+14378 -1893

No files matched your search

@@ -68,7 +68,7 @@
<MudCopyClipboardButton TooltipMessage="@T("Copy project ID")" StringContent="@this.selectedProject.BriefingId.ToString("D")"/>
</MudStack>
<MudText Typo="Typo.body2">
@T("If you need help, report the problem and include the project ID.")
@TA("If you need help, report the problem and include the project ID.")
<MudLink Href="https://github.com/MindWorkAI/AI-Studio" Target="_blank">@T("Report a problem?")</MudLink>
</MudText>
<MudStack Row="true" Spacing="1" Wrap="Wrap.Wrap">
@@ -81,7 +81,7 @@
else if (this.selectedBriefing is null)
{
<MudPaper Outlined="true" Class="pa-6">
<MudText Typo="Typo.h5">@T("Create or import a visual briefing to begin.")</MudText>
<MudText Typo="Typo.h5">@TA("Create or import a visual briefing to begin.")</MudText>
</MudPaper>
}
else
@@ -248,7 +248,7 @@
</MudTooltip>
<MudTooltip Text="@(this.SelectedVersionSupportsEdits
? T("Recompile this version with the current AI Studio version without AI model calls.")
: T("This version has no compatible semantic artifacts. Rebuild the briefing instead."))">
: TA("This version has no compatible semantic artifacts. Rebuild the briefing instead."))">
<span>
<MudButton Variant="Variant.Filled" StartIcon="@AppIcons.RECOMPILE" OnClick="@(() => this.RecompileAsync())" Disabled="@this.CannotRecompile">@T("Recompile briefing")</MudButton>
</span>
@@ -278,7 +278,7 @@
{
<MudAlert Severity="Severity.Warning" Variant="Variant.Outlined" Class="mb-4">
<MudStack Row="true" AlignItems="AlignItems.Center" Justify="Justify.SpaceBetween" Wrap="Wrap.Wrap">
<MudText>@T("The updated content no longer fits the current presentation. You can continue as a rebuild without another content model call.")</MudText>
<MudText>@TA("The updated content no longer fits the current presentation. You can continue as a rebuild without another content model call.")</MudText>
<MudButton Variant="Variant.Filled"
Color="Color.Warning"
StartIcon="@AppIcons.REGENERATE"
@@ -169,7 +169,7 @@ public partial class VisualBriefingAssistant
parentRevisionId, generationProvider, generationProfile, reusableBuildId, token),
T("A new visual briefing version was created."),
T("The visual briefing generation was canceled."),
T("The visual briefing operation failed unexpectedly. Copy the technical details for support."));
TA("The visual briefing operation failed unexpectedly. Copy the technical details for support."));
}
/// <summary>
@@ -189,7 +189,7 @@ public partial class VisualBriefingAssistant
token => this.BuildOrchestrator.RecompileAsync(recompileBriefing, parentRevisionId, token),
T("The briefing was recompiled with the current AI Studio version."),
T("The visual briefing recompilation was canceled."),
T("The visual briefing recompilation failed unexpectedly. Copy the technical details for support."));
TA("The visual briefing recompilation failed unexpectedly. Copy the technical details for support."));
}
/// <summary>
@@ -100,13 +100,13 @@ public partial class VisualBriefingAssistant
var parameters = new DialogParameters<SingleInputDialog>
{
{ dialog => dialog.Message, T("Enter a new name for this visual briefing.") },
{ dialog => dialog.Message, TA("Enter a new name for this visual briefing.") },
{ dialog => dialog.InputHeaderText, T("Briefing name") },
{ dialog => dialog.UserInput, this.editor.Name },
{ dialog => dialog.ConfirmText, T("Rename") },
{ dialog => dialog.ConfirmColor, Color.Info },
{ dialog => dialog.AllowEmptyInput, false },
{ dialog => dialog.EmptyInputErrorMessage, T("Please enter a briefing name.") },
{ dialog => dialog.EmptyInputErrorMessage, TA("Please enter a briefing name.") },
};
var reference = await this.DialogService.ShowAsync<SingleInputDialog>(T("Rename visual briefing"), parameters, DialogOptions.FULLSCREEN);
@@ -131,7 +131,7 @@ public partial class VisualBriefingAssistant
parameters.Add(dialog => dialog.Message, string.Format(T("Permanently delete the visual briefing '{0}' and all of its versions and transcripts?"), this.selectedProject.Name));
else
{
var reportingWarning = T("This visual briefing cannot currently be opened. Consider reporting the problem in the [MindWork AI Studio issue tracker](https://github.com/MindWorkAI/AI-Studio), because a future update may make the briefing accessible again.");
var reportingWarning = TA("This visual briefing cannot currently be opened. Consider reporting the problem in the [MindWork AI Studio issue tracker](https://github.com/MindWorkAI/AI-Studio), because a future update may make the briefing accessible again.");
var deletionWarning = T("Permanently delete this visual briefing and all of its versions and transcripts?");
parameters.Add(dialog => dialog.MarkdownBody, $"{reportingWarning}\n\n{deletionWarning}");
}
@@ -42,7 +42,7 @@ public partial class VisualBriefingAssistant
List<string> issues = [.. this.formIssues, .. this.FieldIssues, .. this.SourceIssues];
if (this.selectedBriefing is { Versions.Count: > 0 } && !this.SelectedVersionSupportsEdits)
issues.Add(T("This version has no compatible semantic artifacts. Rebuild the briefing instead."));
issues.Add(TA("This version has no compatible semantic artifacts. Rebuild the briefing instead."));
return [.. issues.Where(issue => !string.IsNullOrWhiteSpace(issue)).Distinct(StringComparer.Ordinal)];
}
@@ -80,12 +80,12 @@ public partial class VisualBriefingAssistant
List<string> issues = [];
if (!this.HasSourceMaterial)
issues.Add(T("Please add at least one source material file."));
issues.Add(TA("Please add at least one source material file."));
// A model can be selected long after the images were attached, so the capability that was
// checked while attaching them has to be checked again here:
if (this.HasImageSources && this.editor.Provider != ProviderSettings.NONE && !this.editor.Provider.SupportsImageInput())
issues.Add(T("Images are not supported by the selected provider and model. Select a model with image support, or remove the image sources."));
issues.Add(TA("Images are not supported by the selected provider and model. Select a model with image support, or remove the image sources."));
foreach (var source in this.selectedBriefing.Sources)
{
@@ -93,11 +93,11 @@ public partial class VisualBriefingAssistant
switch (source.Status)
{
case VisualBriefingSourceStatus.UNREACHABLE:
issues.Add(string.Format(T("The source '{0}' is no longer reachable. Restore or relink it."), fileName));
issues.Add(string.Format(TA("The source '{0}' is no longer reachable. Restore or relink it."), fileName));
break;
case VisualBriefingSourceStatus.TRANSCRIPT_OUTDATED:
issues.Add(string.Format(T("The transcript for '{0}' is missing or outdated. Transcribe the media source again."), fileName));
issues.Add(string.Format(TA("The transcript for '{0}' is missing or outdated. Transcribe the media source again."), fileName));
break;
}
}
@@ -107,7 +107,7 @@ public partial class VisualBriefingAssistant
}
/// <summary>Validates the briefing name.</summary>
private string? ValidateProjectName(string name) => string.IsNullOrWhiteSpace(name) ? T("Please provide a briefing name.") : null;
private string? ValidateProjectName(string name) => string.IsNullOrWhiteSpace(name) ? TA("Please provide a briefing name.") : null;
/// <summary>Validates the selected generation provider.</summary>
/// <remarks>
@@ -117,11 +117,11 @@ public partial class VisualBriefingAssistant
private string? ValidateProvider(ProviderSettings value)
{
if (value == ProviderSettings.NONE || value.UsedLLMProvider is LLMProviders.NONE)
return T("Please select a provider.");
return TA("Please select a provider.");
var restrictions = this.selectedBriefing?.Restrictions ?? ChatRestrictions.NONE;
if (!restrictions.IsLLMProviderAllowed(value) && ChatRestrictions.NONE.IsLLMProviderAllowed(value))
return T("This provider may not see the text sent to this briefing, because of where the text came from. Please select another provider.");
return TA("This provider may not see the text sent to this briefing, because of where the text came from. Please select another provider.");
return null;
}
@@ -129,13 +129,13 @@ public partial class VisualBriefingAssistant
/// <summary>Validates the free-form target language when Other is selected.</summary>
private string? ValidateCustomTargetLanguage(string language) =>
this.editor.TargetLanguage is CommonLanguages.OTHER && string.IsNullOrWhiteSpace(language)
? T("Please provide a custom target language.")
? TA("Please provide a custom target language.")
: null;
/// <summary>Validates the free-form protection level when Other is selected.</summary>
private string? ValidateCustomProtectionLevel(string level) =>
this.editor.ProtectionLevel is VisualBriefingProtectionLevel.OTHER && string.IsNullOrWhiteSpace(level)
? T("Please provide a custom protection level.")
? TA("Please provide a custom protection level.")
: null;
/// <summary>Revalidates after a conditional Other field has been added or removed.</summary>
@@ -118,7 +118,7 @@ public partial class VisualBriefingAssistant
if (PathComparer().Equals(Path.GetFullPath(sourcePath), Path.GetFullPath(response.SaveFilePath)))
{
await this.MessageBus.SendError(new(AppIcons.SAVE_FAILED, T("Choose a different export location so the immutable briefing version is not overwritten.")));
await this.MessageBus.SendError(new(AppIcons.SAVE_FAILED, TA("Choose a different export location so the immutable briefing version is not overwritten.")));
return;
}
@@ -176,7 +176,7 @@ public partial class VisualBriefingAssistant
catch (Exception e)
{
this.Logger.LogError(e, "The visual briefing could not be exported, because the file '{FilePath}' cannot be opened for writing.", targetPath);
await this.MessageBus.SendError(new(AppIcons.EXPORT, T("The visual briefing could not be exported. Please check that the target file is not open in another program.")));
await this.MessageBus.SendError(new(AppIcons.EXPORT, TA("The visual briefing could not be exported. Please check that the target file is not open in another program.")));
return false;
}
@@ -13,6 +13,8 @@ internal static class VisualBriefingFailureExtensions
{
private static string TB(string fallbackEN) => Tools.PluginSystem.I18N.I.T(fallbackEN, typeof(VisualBriefingFailureExtensions).Namespace, nameof(VisualBriefingFailureExtensions));
private static string TA(string fallbackEN) => Tools.PluginSystem.I18N.I.TA(fallbackEN, typeof(VisualBriefingFailureExtensions).Namespace, nameof(VisualBriefingFailureExtensions));
/// <param name="failure">The recorded failure.</param>
extension(VisualBriefingFailure failure)
{
@@ -52,30 +54,30 @@ internal static class VisualBriefingFailureExtensions
/// <returns>The localized message.</returns>
private string ToUserMessage() => rule switch
{
VisualBriefingValidationRule.JSON_INVALID => TB("The model did not return valid JSON. Please try again or select another model."),
VisualBriefingValidationRule.VALUE_TYPE_INVALID => TB("The model response contained a value of the wrong type. Please try again or select another model."),
VisualBriefingValidationRule.UNKNOWN_FIELD => TB("The model response contained unexpected fields. Please try again or select another model."),
VisualBriefingValidationRule.CONTRACT_VERSION_UNSUPPORTED => TB("The model response used an unsupported contract version. Please try again or select another model."),
VisualBriefingValidationRule.ID_INVALID => TB("The model response contained an empty, malformed, or duplicated identifier. Please try again or select another model."),
VisualBriefingValidationRule.REFERENCE_INVALID => TB("The model response referenced content that does not exist. Please try again or select another model."),
VisualBriefingValidationRule.SOURCE_COVERAGE_INVALID => TB("The model did not cover every source of this briefing exactly once. Please try again or select another model."),
VisualBriefingValidationRule.ASSET_PLAN_INVALID => TB("The model did not plan every visual asset of this briefing exactly once. Please try again or select another model."),
VisualBriefingValidationRule.SLOT_FULFILLMENT_INVALID => TB("The model did not fill every planned content slot exactly once. Please try again or select another model."),
VisualBriefingValidationRule.SLOT_VALUE_TYPE_INVALID => TB("The model filled a content slot with the wrong kind of value. Please try again or select another model."),
VisualBriefingValidationRule.CHART_SET_INVALID => TB("The charts of the model response did not match the planned briefing elements. Please try again or select another model."),
VisualBriefingValidationRule.CHART_DATA_INVALID => TB("A chart of the model response contained invalid categories or data series. Please try again or select another model."),
VisualBriefingValidationRule.CONTROL_ID_INVALID => TB("An interactive control of the model response used an invalid identifier. Please try again or select another model."),
VisualBriefingValidationRule.CONTROL_TARGET_INVALID => TB("An interactive control of the model response targeted an invalid briefing element. Please try again or select another model."),
VisualBriefingValidationRule.CONTROL_STATE_INVALID => TB("An interactive control of the model response used an invalid initial state. Please try again or select another model."),
VisualBriefingValidationRule.CONTROL_REQUIREMENT_INVALID => TB("A briefing element of the model response was missing its required interactive controls. Please try again or select another model."),
VisualBriefingValidationRule.FORMULA_TARGET_INVALID => TB("A calculation of the model response targeted an invalid briefing element. Please try again or select another model."),
VisualBriefingValidationRule.FORMULA_AST_INVALID => TB("A calculation of the model response used an invalid operation. Please try again or select another model."),
VisualBriefingValidationRule.ACCESSIBILITY_SET_INVALID => TB("The accessibility texts of the model response did not match the briefing elements. Please try again or select another model."),
VisualBriefingValidationRule.ACCESSIBILITY_TEXT_INVALID => TB("An accessibility text of the model response was empty or invalid. Please try again or select another model."),
VisualBriefingValidationRule.LAYOUT_INVALID => TB("The model response used an invalid briefing layout. Please try again or select another model."),
VisualBriefingValidationRule.TEMPLATE_ATTRIBUTE_PROHIBITED => TB("The model response used a prohibited attribute. Please try again or select another model."),
VisualBriefingValidationRule.MODEL_MARKUP_PROHIBITED => TB("The model response contained markup or code, which this briefing does not allow. Please try again or select another model."),
VisualBriefingValidationRule.COMPILER_OUTPUT_INVALID => TB("AI Studio compiled this briefing into an inconsistent result. Please copy the technical details and report this issue."),
VisualBriefingValidationRule.JSON_INVALID => TA("The model did not return valid JSON. Please try again or select another model."),
VisualBriefingValidationRule.VALUE_TYPE_INVALID => TA("The model response contained a value of the wrong type. Please try again or select another model."),
VisualBriefingValidationRule.UNKNOWN_FIELD => TA("The model response contained unexpected fields. Please try again or select another model."),
VisualBriefingValidationRule.CONTRACT_VERSION_UNSUPPORTED => TA("The model response used an unsupported contract version. Please try again or select another model."),
VisualBriefingValidationRule.ID_INVALID => TA("The model response contained an empty, malformed, or duplicated identifier. Please try again or select another model."),
VisualBriefingValidationRule.REFERENCE_INVALID => TA("The model response referenced content that does not exist. Please try again or select another model."),
VisualBriefingValidationRule.SOURCE_COVERAGE_INVALID => TA("The model did not cover every source of this briefing exactly once. Please try again or select another model."),
VisualBriefingValidationRule.ASSET_PLAN_INVALID => TA("The model did not plan every visual asset of this briefing exactly once. Please try again or select another model."),
VisualBriefingValidationRule.SLOT_FULFILLMENT_INVALID => TA("The model did not fill every planned content slot exactly once. Please try again or select another model."),
VisualBriefingValidationRule.SLOT_VALUE_TYPE_INVALID => TA("The model filled a content slot with the wrong kind of value. Please try again or select another model."),
VisualBriefingValidationRule.CHART_SET_INVALID => TA("The charts of the model response did not match the planned briefing elements. Please try again or select another model."),
VisualBriefingValidationRule.CHART_DATA_INVALID => TA("A chart of the model response contained invalid categories or data series. Please try again or select another model."),
VisualBriefingValidationRule.CONTROL_ID_INVALID => TA("An interactive control of the model response used an invalid identifier. Please try again or select another model."),
VisualBriefingValidationRule.CONTROL_TARGET_INVALID => TA("An interactive control of the model response targeted an invalid briefing element. Please try again or select another model."),
VisualBriefingValidationRule.CONTROL_STATE_INVALID => TA("An interactive control of the model response used an invalid initial state. Please try again or select another model."),
VisualBriefingValidationRule.CONTROL_REQUIREMENT_INVALID => TA("A briefing element of the model response was missing its required interactive controls. Please try again or select another model."),
VisualBriefingValidationRule.FORMULA_TARGET_INVALID => TA("A calculation of the model response targeted an invalid briefing element. Please try again or select another model."),
VisualBriefingValidationRule.FORMULA_AST_INVALID => TA("A calculation of the model response used an invalid operation. Please try again or select another model."),
VisualBriefingValidationRule.ACCESSIBILITY_SET_INVALID => TA("The accessibility texts of the model response did not match the briefing elements. Please try again or select another model."),
VisualBriefingValidationRule.ACCESSIBILITY_TEXT_INVALID => TA("An accessibility text of the model response was empty or invalid. Please try again or select another model."),
VisualBriefingValidationRule.LAYOUT_INVALID => TA("The model response used an invalid briefing layout. Please try again or select another model."),
VisualBriefingValidationRule.TEMPLATE_ATTRIBUTE_PROHIBITED => TA("The model response used a prohibited attribute. Please try again or select another model."),
VisualBriefingValidationRule.MODEL_MARKUP_PROHIBITED => TA("The model response contained markup or code, which this briefing does not allow. Please try again or select another model."),
VisualBriefingValidationRule.COMPILER_OUTPUT_INVALID => TA("AI Studio compiled this briefing into an inconsistent result. Please copy the technical details and report this issue."),
_ => string.Empty,
};
@@ -90,27 +92,27 @@ internal static class VisualBriefingFailureExtensions
/// <returns>The localized message.</returns>
private string ToUserMessage() => code switch
{
VisualBriefingFailureCode.PROVIDER_NOT_SELECTED => TB("This briefing has no provider selected. Please select a provider before you generate a briefing."),
VisualBriefingFailureCode.PROVIDER_NOT_ALLOWED => TB("The selected provider may not see the content of this briefing. Please select another provider."),
VisualBriefingFailureCode.MODEL_CAPABILITY_MISSING => TB("The selected model lacks a capability this briefing needs. Please select another model."),
VisualBriefingFailureCode.SOURCE_UNREACHABLE => TB("A source of this briefing can no longer be reached. Please relink or remove the affected source."),
VisualBriefingFailureCode.TRANSCRIPT_UNAVAILABLE => TB("A media transcript of this briefing is missing or outdated. Please transcribe the affected media again."),
VisualBriefingFailureCode.PROVIDER_NOT_SELECTED => TA("This briefing has no provider selected. Please select a provider before you generate a briefing."),
VisualBriefingFailureCode.PROVIDER_NOT_ALLOWED => TA("The selected provider may not see the content of this briefing. Please select another provider."),
VisualBriefingFailureCode.MODEL_CAPABILITY_MISSING => TA("The selected model lacks a capability this briefing needs. Please select another model."),
VisualBriefingFailureCode.SOURCE_UNREACHABLE => TA("A source of this briefing can no longer be reached. Please relink or remove the affected source."),
VisualBriefingFailureCode.TRANSCRIPT_UNAVAILABLE => TA("A media transcript of this briefing is missing or outdated. Please transcribe the affected media again."),
VisualBriefingFailureCode.SOURCE_PREPARATION_FAILED => TB("The sources of this briefing could not be prepared."),
VisualBriefingFailureCode.PROVIDER_CALL_FAILED => TB("The selected provider could not complete this briefing stage."),
VisualBriefingFailureCode.RESPONSE_JSON_INVALID => TB("The model did not return valid JSON. Please try again or select another model."),
VisualBriefingFailureCode.RESPONSE_CONTRACT_INVALID => TB("The model response did not match the required contract. Please try again or select another model."),
VisualBriefingFailureCode.COMPILER_INVARIANT_VIOLATED => TB("AI Studio compiled this briefing into an inconsistent result. Please copy the technical details and report this issue."),
VisualBriefingFailureCode.SOURCE_COVERAGE_INVALID => TB("The model did not cover every source of this briefing exactly once. Please try again or select another model."),
VisualBriefingFailureCode.ASSET_PLAN_INVALID => TB("The model did not plan every visual asset of this briefing exactly once. Please try again or select another model."),
VisualBriefingFailureCode.CONTENT_SIGNATURE_INCOMPATIBLE => TB("The updated content no longer fits the current presentation. You can continue as a rebuild."),
VisualBriefingFailureCode.PRESENTATION_INVALID => TB("The presentation of the model response did not match the briefing contract. Please try again or select another model."),
VisualBriefingFailureCode.RESPONSE_JSON_INVALID => TA("The model did not return valid JSON. Please try again or select another model."),
VisualBriefingFailureCode.RESPONSE_CONTRACT_INVALID => TA("The model response did not match the required contract. Please try again or select another model."),
VisualBriefingFailureCode.COMPILER_INVARIANT_VIOLATED => TA("AI Studio compiled this briefing into an inconsistent result. Please copy the technical details and report this issue."),
VisualBriefingFailureCode.SOURCE_COVERAGE_INVALID => TA("The model did not cover every source of this briefing exactly once. Please try again or select another model."),
VisualBriefingFailureCode.ASSET_PLAN_INVALID => TA("The model did not plan every visual asset of this briefing exactly once. Please try again or select another model."),
VisualBriefingFailureCode.CONTENT_SIGNATURE_INCOMPATIBLE => TA("The updated content no longer fits the current presentation. You can continue as a rebuild."),
VisualBriefingFailureCode.PRESENTATION_INVALID => TA("The presentation of the model response did not match the briefing contract. Please try again or select another model."),
VisualBriefingFailureCode.ASSEMBLY_FAILED => TB("This briefing could not be assembled."),
VisualBriefingFailureCode.ARTIFACT_VALIDATION_FAILED => TB("The assembled briefing did not pass the security validation."),
VisualBriefingFailureCode.STORE_FAILED => TB("The new version of this briefing could not be saved."),
VisualBriefingFailureCode.NO_CHANGES => TB("This operation did not change the briefing, so no new version was created."),
VisualBriefingFailureCode.CANCELED => TB("This visual briefing operation was canceled."),
VisualBriefingFailureCode.BUILD_INTERRUPTED => TB("AI Studio was closed while this briefing was being built. You can resume the build."),
VisualBriefingFailureCode.UNEXPECTED => TB("This visual briefing operation failed because of an unexpected internal error. Please copy the technical details for support."),
VisualBriefingFailureCode.BUILD_INTERRUPTED => TA("AI Studio was closed while this briefing was being built. You can resume the build."),
VisualBriefingFailureCode.UNEXPECTED => TA("This visual briefing operation failed because of an unexpected internal error. Please copy the technical details for support."),
_ => string.Empty,
};