mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-11-14 03:27:21 +00:00
Added the choice between formal and informal address to the whole app (#1200)
This commit is contained in:
1 parent
382db4b8d0
commit
c9a376f742
342 files changed
+14378
-1893
No files matched your search
+12
-10
@@ -8,6 +8,8 @@ public static class PluginAssistantSecurityResolver
|
||||
{
|
||||
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(PluginAssistantSecurityResolver).Namespace, nameof(PluginAssistantSecurityResolver));
|
||||
|
||||
private static string TA(string fallbackEN) => I18N.I.TA(fallbackEN, typeof(PluginAssistantSecurityResolver).Namespace, nameof(PluginAssistantSecurityResolver));
|
||||
|
||||
private static string NormalizeHash(string hash) => string.IsNullOrWhiteSpace(hash) ? string.Empty : hash.Trim().ToUpperInvariant();
|
||||
|
||||
private static string GetAvailabilityLabel(bool requiresAudit, bool hasAudit, bool hasHashMismatch, bool isBlocked, bool canOverride)
|
||||
@@ -88,8 +90,8 @@ public static class PluginAssistantSecurityResolver
|
||||
if (enterpriseApproval is not null)
|
||||
{
|
||||
var enterpriseHeadline = string.IsNullOrWhiteSpace(enterpriseApproval.DisplayName)
|
||||
? TB("This assistant was approved by your organization.")
|
||||
: string.Format(TB("This assistant was approved by your organization as '{0}'."), enterpriseApproval.DisplayName);
|
||||
? TA("This assistant was approved by your organization.")
|
||||
: string.Format(TA("This assistant was approved by your organization as '{0}'."), enterpriseApproval.DisplayName);
|
||||
|
||||
return new PluginAssistantSecurityState
|
||||
{
|
||||
@@ -115,7 +117,7 @@ public static class PluginAssistantSecurityResolver
|
||||
AvailabilityColor = GetAvailabilityColor(requiresAudit: false, hasAudit: true, hasHashMismatch: false, isBlocked: false, canOverride: false),
|
||||
AvailabilityIcon = GetAvailabilityIcon(requiresAudit: false, hasAudit: true, hasHashMismatch: false, isBlocked: false, canOverride: false),
|
||||
StatusLabel = TB("Unlocked"),
|
||||
SourceLabel = TB("Approved by your organization"),
|
||||
SourceLabel = TA("Approved by your organization"),
|
||||
SourceColor = Color.Success,
|
||||
SourceIcon = AppIcons.ORGANIZATION,
|
||||
BadgeIcon = AppIcons.ORGANIZATION,
|
||||
@@ -169,8 +171,8 @@ public static class PluginAssistantSecurityResolver
|
||||
BadgeIcon = GetSecurityBadgeIcon(requiresAudit, hasAudit, hasHashMismatch, isBlocked, canOverride: false),
|
||||
Headline = requiresAudit ? TB("This assistant is currently locked.") : TB("This assistant currently has no stored audit."),
|
||||
Description = requiresAudit
|
||||
? TB("No security audit exists yet, and your current security settings require one before this assistant plugin may be enabled or used.")
|
||||
: TB("No security audit exists yet. Your current security settings do not require an audit before this assistant plugin may be used."),
|
||||
? TA("No security audit exists yet, and your current security settings require one before this assistant plugin may be enabled or used.")
|
||||
: TA("No security audit exists yet. Your current security settings do not require an audit before this assistant plugin may be used."),
|
||||
StatusColor = GetAvailabilityColor(requiresAudit, hasAudit, hasHashMismatch, isBlocked, canOverride: false),
|
||||
StatusIcon = GetAvailabilityIcon(requiresAudit, hasAudit, hasHashMismatch, isBlocked, canOverride: false),
|
||||
ActionLabel = TB("Start Security Check"),
|
||||
@@ -252,12 +254,12 @@ public static class PluginAssistantSecurityResolver
|
||||
? TB("This assistant is currently locked.")
|
||||
: isEnforcementDisabled
|
||||
? TB("This assistant can still be used because audit enforcement is disabled.")
|
||||
: TB("This assistant can still be used because your settings allow it."),
|
||||
: TA("This assistant can still be used because your settings allow it."),
|
||||
Description = isBlockedByMinimum
|
||||
? string.Format(TB("The current audit result '{0}' is below your required minimum level '{1}'. Your security settings therefore block this assistant plugin."), auditLevel.Name, auditSettings.MinimumLevel.Name)
|
||||
? string.Format(TA("The current audit result '{0}' is below your required minimum level '{1}'. Your security settings therefore block this assistant plugin."), auditLevel.Name, auditSettings.MinimumLevel.Name)
|
||||
: isEnforcementDisabled
|
||||
? string.Format(TB("The current audit result is '{0}', which is below your required minimum level '{1}'. Audit enforcement is currently disabled, so this assistant plugin can still be enabled or used."), auditLevel.Name, auditSettings.MinimumLevel.Name)
|
||||
: string.Format(TB("The current audit result is '{0}', which is below your required minimum level '{1}'. Your settings still allow manual activation, but the assistant keeps this security status and should be reviewed carefully."), auditLevel.Name, auditSettings.MinimumLevel.Name),
|
||||
? string.Format(TA("The current audit result is '{0}', which is below your required minimum level '{1}'. Audit enforcement is currently disabled, so this assistant plugin can still be enabled or used."), auditLevel.Name, auditSettings.MinimumLevel.Name)
|
||||
: string.Format(TA("The current audit result is '{0}', which is below your required minimum level '{1}'. Your settings still allow manual activation, but the assistant keeps this security status and should be reviewed carefully."), auditLevel.Name, auditSettings.MinimumLevel.Name),
|
||||
StatusColor = GetAvailabilityColor(requiresAudit: false, hasAudit, hasHashMismatch: false, isBlockedByMinimum, canOverride),
|
||||
StatusIcon = GetAvailabilityIcon(requiresAudit: false, hasAudit, hasHashMismatch: false, isBlockedByMinimum, canOverride),
|
||||
ActionLabel = TB("Open Security Check"),
|
||||
@@ -294,7 +296,7 @@ public static class PluginAssistantSecurityResolver
|
||||
SourceIcon = AppIcons.SECURITY_AUDIT_PASSED,
|
||||
BadgeIcon = GetSecurityBadgeIcon(requiresAudit: false, hasAudit, hasHashMismatch: false, isBlocked: false, canOverride: false),
|
||||
Headline = TB("This assistant is currently unlocked."),
|
||||
Description = string.Format(TB("The stored audit matches the current plugin code and meets your required minimum level '{0}'."), auditSettings.MinimumLevel.Name),
|
||||
Description = string.Format(TA("The stored audit matches the current plugin code and meets your required minimum level '{0}'."), auditSettings.MinimumLevel.Name),
|
||||
StatusColor = GetAvailabilityColor(requiresAudit: false, hasAudit, hasHashMismatch: false, isBlocked: false, canOverride: false),
|
||||
StatusIcon = GetAvailabilityIcon(requiresAudit: false, hasAudit, hasHashMismatch: false, isBlocked: false, canOverride: false),
|
||||
ActionLabel = TB("Open Security Check"),
|
||||
|
||||
@@ -29,6 +29,8 @@ public static class ConfigurationSnippetImport
|
||||
|
||||
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(ConfigurationSnippetImport).Namespace, nameof(ConfigurationSnippetImport));
|
||||
|
||||
private static string TA(string fallbackEN) => I18N.I.TA(fallbackEN, typeof(ConfigurationSnippetImport).Namespace, nameof(ConfigurationSnippetImport));
|
||||
|
||||
/// <summary>
|
||||
/// Reads a pasted configuration snippet and makes its configuration object one of the user's own.
|
||||
/// </summary>
|
||||
@@ -66,7 +68,7 @@ public static class ConfigurationSnippetImport
|
||||
case DataSourceERI_V1 dataSource:
|
||||
if (dataSource.AuthMethod is AuthMethod.KERBEROS)
|
||||
{
|
||||
issue = TB("Data sources which sign in with Kerberos cannot be imported yet. Please add them yourself.");
|
||||
issue = TA("Data sources which sign in with Kerberos cannot be imported yet. Please add them yourself.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -99,7 +101,7 @@ public static class ConfigurationSnippetImport
|
||||
case ChatTemplate template:
|
||||
var localPaths = attachmentPaths.Where(IsLocalFile).ToList();
|
||||
if (localPaths.Count > 0)
|
||||
hints.Add(string.Format(TB("The chat template attaches these files from this computer to every chat started with it: {0}. Please check that you want to share them."), string.Join(", ", localPaths)));
|
||||
hints.Add(string.Format(TA("The chat template attaches these files from this computer to every chat started with it: {0}. Please check that you want to share them."), string.Join(", ", localPaths)));
|
||||
|
||||
result = new(MakeLocal(template) with { FileAttachments = localPaths.Select(FileAttachment.FromPath).ToList() }, string.Empty, hints, attachmentPaths.Except(localPaths).ToList());
|
||||
return true;
|
||||
@@ -152,15 +154,15 @@ public static class ConfigurationSnippetImport
|
||||
{
|
||||
var templateProvider = settingsManager.GetProviderById(template.ProviderId);
|
||||
if (templateProvider == Settings.Provider.NONE)
|
||||
hints.Add(string.Format(TB("The chat template preselects a provider which does not exist on this computer: {0}. Chats started with it use your usual provider instead."), template.ProviderId));
|
||||
hints.Add(string.Format(TA("The chat template preselects a provider which does not exist on this computer: {0}. Chats started with it use your usual provider instead."), template.ProviderId));
|
||||
else if (settingsManager.GetChatTemplateProvider(template.ProviderId) == Settings.Provider.NONE)
|
||||
hints.Add(string.Format(TB("The chat template preselects the provider '{0}', which does not meet the confidence level required for chats. Chats started with it use your usual provider instead."), templateProvider.InstanceName));
|
||||
hints.Add(string.Format(TA("The chat template preselects the provider '{0}', which does not meet the confidence level required for chats. Chats started with it use your usual provider instead."), templateProvider.InstanceName));
|
||||
}
|
||||
|
||||
if (template.ProfileId is not null && !template.AllowProfileUsage)
|
||||
hints.Add(TB("The chat template preselects a profile but does not allow profiles. Chats started with it ignore that profile."));
|
||||
else if (template.ProfileId is not null && !template.StartsWithoutProfile() && settingsManager.GetProfileById(template.ProfileId) == Profile.NO_PROFILE)
|
||||
hints.Add(string.Format(TB("The chat template preselects a profile which does not exist on this computer: {0}. Chats started with it use your usual profile instead."), template.ProfileId));
|
||||
hints.Add(string.Format(TA("The chat template preselects a profile which does not exist on this computer: {0}. Chats started with it use your usual profile instead."), template.ProfileId));
|
||||
|
||||
return result with { ConfigurationObject = template with { ToolIds = templateToolIds }, Hints = hints };
|
||||
|
||||
@@ -265,14 +267,14 @@ public static class ConfigurationSnippetImport
|
||||
|
||||
if (!EnterpriseEncryption.IsEncrypted(encryptedApiKey))
|
||||
{
|
||||
hints.Add(TB("The pasted configuration contains an API key which is not encrypted, so it was left out. Please enter your API key before you save the provider."));
|
||||
hints.Add(TA("The pasted configuration contains an API key which is not encrypted, so it was left out. Please enter your API key before you save the provider."));
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
if (TryReadSecret(table, API_KEY_FIELD, out var apiKey))
|
||||
return apiKey;
|
||||
|
||||
hints.Add(TB("The API key in the pasted configuration cannot be decrypted on this computer. Please enter your API key before you save the provider."));
|
||||
hints.Add(TA("The API key in the pasted configuration cannot be decrypted on this computer. Please enter your API key before you save the provider."));
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
@@ -303,7 +305,7 @@ public static class ConfigurationSnippetImport
|
||||
{
|
||||
var secretFieldName = DataSourceERI_V1.GetSecretFieldName(authMethod);
|
||||
if (EnterpriseEncryption.IsEncrypted(ReadString(table, secretFieldName)) && !TryReadSecret(table, secretFieldName, out _))
|
||||
return TB("The token or password of the data source cannot be decrypted on this computer. Such data sources can only be imported where the encryption secret of your organization is configured.");
|
||||
return TA("The token or password of the data source cannot be decrypted on this computer. Such data sources can only be imported where the encryption secret of your organization is configured.");
|
||||
}
|
||||
|
||||
return string.Format(TB("The pasted configuration is not a valid configuration of the type '{0}'."), type.Name);
|
||||
|
||||
@@ -25,6 +25,8 @@ public sealed class ConfigurationSnippetParser
|
||||
|
||||
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(ConfigurationSnippetParser).Namespace, nameof(ConfigurationSnippetParser));
|
||||
|
||||
private static string TA(string fallbackEN) => I18N.I.TA(fallbackEN, typeof(ConfigurationSnippetParser).Namespace, nameof(ConfigurationSnippetParser));
|
||||
|
||||
/// <summary>
|
||||
/// Reads a snippet of the form <c>CONFIG["SECTION"][#CONFIG["SECTION"]+1] = { ... }</c>.
|
||||
/// </summary>
|
||||
@@ -39,7 +41,7 @@ public sealed class ConfigurationSnippetParser
|
||||
issue = string.Empty;
|
||||
if (string.IsNullOrWhiteSpace(source) || source.Length > 1_000_000)
|
||||
{
|
||||
issue = TB("Please paste one exported configuration of at most 1 MB.");
|
||||
issue = TA("Please paste one exported configuration of at most 1 MB.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -126,7 +128,7 @@ public sealed class ConfigurationSnippetParser
|
||||
|
||||
// In Lua, nil leaves a field out, and in a list it ends what the parsers read of it:
|
||||
if (this.TakeWord("nil"))
|
||||
throw new FormatException(string.Format(TB("The value nil at character {0} is not supported. Leave the field out instead."), this.position - 2));
|
||||
throw new FormatException(string.Format(TA("The value nil at character {0} is not supported. Leave the field out instead."), this.position - 2));
|
||||
|
||||
var start = this.position;
|
||||
if (this.Peek() == '-')
|
||||
@@ -280,7 +282,7 @@ public sealed class ConfigurationSnippetParser
|
||||
// is refused:
|
||||
//
|
||||
if (this.IsLongBracketAt(this.position + 2))
|
||||
throw new FormatException(string.Format(TB("The block comment at character {0} is not supported. Please use line comments, which start with -- and end at the end of the line."), this.position + 1));
|
||||
throw new FormatException(string.Format(TA("The block comment at character {0} is not supported. Please use line comments, which start with -- and end at the end of the line."), this.position + 1));
|
||||
|
||||
this.position += 2;
|
||||
while (this.position < this.source.Length && this.source[this.position] != '\n')
|
||||
|
||||
@@ -35,6 +35,8 @@ public abstract partial class PluginBase : IPluginMetadata, IDisposable
|
||||
|
||||
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(PluginBase).Namespace, nameof(PluginBase));
|
||||
|
||||
private static string TA(string fallbackEN) => I18N.I.TA(fallbackEN, typeof(PluginBase).Namespace, nameof(PluginBase));
|
||||
|
||||
private readonly IReadOnlyCollection<string> baseIssues;
|
||||
protected readonly LuaState State;
|
||||
|
||||
@@ -509,7 +511,7 @@ public abstract partial class PluginBase : IPluginMetadata, IDisposable
|
||||
if (!this.State.Environment["DEPRECATION_MESSAGE"].TryRead(out deprecationMessage))
|
||||
{
|
||||
deprecationMessage = string.Empty;
|
||||
message = TB("The field DEPRECATION_MESSAGE does not exist, is not a valid string. This message is optional: use an empty string to indicate that the plugin is not deprecated.");
|
||||
message = TA("The field DEPRECATION_MESSAGE does not exist or is not a valid string. This message is optional: use an empty string to indicate that the plugin is not deprecated.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -244,6 +244,9 @@ public sealed class PluginConfiguration(bool isInternal, LuaState state, PluginT
|
||||
// Config: save energy while the AI streams its answers?
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.App, x => x.IsSavingEnergy, this.Id, settingsTable, dryRun);
|
||||
|
||||
// Config: how should the texts address the user?
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.App, x => x.AddressForm, this.Id, settingsTable, dryRun);
|
||||
|
||||
// Config: show prompt-injection alert dialogs?
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.App, x => x.ShowPromptInjectionAlert, this.Id, settingsTable, dryRun);
|
||||
|
||||
@@ -519,7 +522,6 @@ public sealed class PluginConfiguration(bool isInternal, LuaState state, PluginT
|
||||
// Config: BeyondFacts Lab defaults?
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.BeyondFactsLab, x => x.PreselectedProvider, Guid.Empty, this.Id, settingsTable, dryRun);
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.BeyondFactsLab, x => x.MinimumProviderConfidence, this.Id, settingsTable, dryRun);
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.BeyondFactsLab, x => x.AddressForm, this.Id, settingsTable, dryRun);
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.BeyondFactsLab, x => x.AllowPromptOverrides, this.Id, settingsTable, dryRun);
|
||||
|
||||
// Config: Assistant Builder defaults?
|
||||
|
||||
@@ -5,6 +5,8 @@ namespace AIStudio.Tools.PluginSystem;
|
||||
public sealed class PluginLanguage : PluginBase, ILanguagePlugin
|
||||
{
|
||||
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(PluginLanguage).Namespace, nameof(PluginLanguage));
|
||||
|
||||
private static string TA(string fallbackEN) => I18N.I.TA(fallbackEN, typeof(PluginLanguage).Namespace, nameof(PluginLanguage));
|
||||
private static readonly ILogger<PluginLanguage> LOGGER = Program.LOGGER_FACTORY.CreateLogger<PluginLanguage>();
|
||||
|
||||
private readonly Dictionary<string, string> content = [];
|
||||
@@ -61,21 +63,21 @@ public sealed class PluginLanguage : PluginBase, ILanguagePlugin
|
||||
|
||||
if (string.IsNullOrWhiteSpace(readLangCultureTag))
|
||||
{
|
||||
message = TB("The field IETF_TAG is empty. Use a valid IETF tag like 'en-US'. The first part is the language, the second part is the country code.");
|
||||
message = TA("The field IETF_TAG is empty. Use a valid IETF tag like 'en-US'. The first part is the language, the second part is the country code.");
|
||||
readLangCultureTag = string.Empty;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (readLangCultureTag.Length != 5)
|
||||
{
|
||||
message = TB("The field IETF_TAG is not a valid IETF tag. Use a valid IETF tag like 'en-US'. The first part is the language, the second part is the country code.");
|
||||
message = TA("The field IETF_TAG is not a valid IETF tag. Use a valid IETF tag like 'en-US'. The first part is the language, the second part is the country code.");
|
||||
readLangCultureTag = string.Empty;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (readLangCultureTag[2] != '-')
|
||||
{
|
||||
message = TB("The field IETF_TAG is not a valid IETF tag. Use a valid IETF tag like 'en-US'. The first part is the language, the second part is the country code.");
|
||||
message = TA("The field IETF_TAG is not a valid IETF tag. Use a valid IETF tag like 'en-US'. The first part is the language, the second part is the country code.");
|
||||
readLangCultureTag = string.Empty;
|
||||
return false;
|
||||
}
|
||||
@@ -84,7 +86,7 @@ public sealed class PluginLanguage : PluginBase, ILanguagePlugin
|
||||
for (var i = 0; i < 2; i++)
|
||||
if (!char.IsLower(readLangCultureTag[i]))
|
||||
{
|
||||
message = TB("The field IETF_TAG is not a valid IETF tag. Use a valid IETF tag like 'en-US'. The first part is the language, the second part is the country code.");
|
||||
message = TA("The field IETF_TAG is not a valid IETF tag. Use a valid IETF tag like 'en-US'. The first part is the language, the second part is the country code.");
|
||||
readLangCultureTag = string.Empty;
|
||||
return false;
|
||||
}
|
||||
@@ -93,7 +95,7 @@ public sealed class PluginLanguage : PluginBase, ILanguagePlugin
|
||||
for (var i = 3; i < 5; i++)
|
||||
if (!char.IsUpper(readLangCultureTag[i]))
|
||||
{
|
||||
message = TB("The field IETF_TAG is not a valid IETF tag. Use a valid IETF tag like 'en-US'. The first part is the language, the second part is the country code.");
|
||||
message = TA("The field IETF_TAG is not a valid IETF tag. Use a valid IETF tag like 'en-US'. The first part is the language, the second part is the country code.");
|
||||
readLangCultureTag = string.Empty;
|
||||
return false;
|
||||
}
|
||||
@@ -113,7 +115,7 @@ public sealed class PluginLanguage : PluginBase, ILanguagePlugin
|
||||
|
||||
if (string.IsNullOrWhiteSpace(readLangName))
|
||||
{
|
||||
message = TB("The field LANG_NAME is empty. Use a valid language name.");
|
||||
message = TA("The field LANG_NAME is empty. Use a valid language name.");
|
||||
readLangName = string.Empty;
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user