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

@@ -43,6 +43,8 @@ internal sealed partial class FileSourceIndexer(SettingsManager settingsManager,
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(FileSourceIndexer).Namespace, nameof(FileSourceIndexer));
private static string TA(string fallbackEN) => I18N.I.TA(fallbackEN, typeof(FileSourceIndexer).Namespace, nameof(FileSourceIndexer));
private enum RagFileIndexingDecision
{
INDEXABLE,
@@ -94,7 +96,7 @@ internal sealed partial class FileSourceIndexer(SettingsManager settingsManager,
&& inputFiles.Files.Count == 0 && inputFiles.IgnoredFiles.Count == 0
&& inputFiles.FilePatternExclusionCount == 0 && inputFiles.ExcludedFolderCount == 0
&& inputFiles.FailedFiles == 0 && inputFiles.UnreadableDirectories.Count == 0)
return this.StopWithoutRoot(context, dataSource, string.Format(TB("The folder '{0}' currently appears empty. AI Studio kept the index of this data source, because the folder of a drive that is not connected can look empty. Connect the drive and refresh this data source. If you emptied the folder on purpose, remove this data source."), directory.Path));
return this.StopWithoutRoot(context, dataSource, string.Format(TA("The folder '{0}' currently appears empty. AI Studio kept the index of this data source, because the folder of a drive that is not connected can look empty. Connect the drive and refresh this data source. If you emptied the folder on purpose, remove this data source."), directory.Path));
var indexedFiles = inputFiles.Files;
var totalFiles = indexedFiles.Count + inputFiles.FailedFiles + inputFiles.IgnoredFiles.Count;
@@ -762,7 +764,7 @@ internal sealed partial class FileSourceIndexer(SettingsManager settingsManager,
this.EnumerateAccessibleFiles(localDirectory, manifest, mediaTranscriptionAvailability, result);
if (result.UnreadableDirectories.Any(directory => string.Equals(Path.TrimEndingDirectorySeparator(Path.GetFullPath(directory)),
Path.TrimEndingDirectorySeparator(Path.GetFullPath(localDirectory.Path)), PathTools.COMPARISON)))
result.UnreachableRootReason = string.Format(TB("The folder '{0}' could not be opened. Please check whether you are allowed to read it. Nothing was removed from the index."), localDirectory.Path);
result.UnreachableRootReason = string.Format(TA("The folder '{0}' could not be opened. Please check whether you are allowed to read it. Nothing was removed from the index."), localDirectory.Path);
return result;
}
@@ -773,11 +775,11 @@ internal sealed partial class FileSourceIndexer(SettingsManager settingsManager,
switch (dataSource)
{
case DataSourceLocalFile localFile:
result.UnreachableRootReason = string.Format(TB("The file '{0}' cannot be reached. Perhaps the drive it is on is not connected, or the file was moved or renamed. Nothing was removed from the index. If the file was moved or renamed, edit this data source to select its new location. Once the file is back, refresh this data source. When it is gone for good, remove this data source."), localFile.FilePath);
result.UnreachableRootReason = string.Format(TA("The file '{0}' cannot be reached. Perhaps the drive it is on is not connected, or the file was moved or renamed. Nothing was removed from the index. If the file was moved or renamed, edit this data source to select its new location. Once the file is back, refresh this data source. When it is gone for good, remove this data source."), localFile.FilePath);
break;
case DataSourceLocalDirectory localDirectory:
result.UnreachableRootReason = string.Format(TB("The folder '{0}' cannot be reached. Perhaps the drive it is on is not connected, or the folder was moved or renamed. Nothing was removed from the index. If the folder was moved or renamed, edit this data source to select its new location. Once the folder is back, refresh this data source."), localDirectory.Path);
result.UnreachableRootReason = string.Format(TA("The folder '{0}' cannot be reached. Perhaps the drive it is on is not connected, or the folder was moved or renamed. Nothing was removed from the index. If the folder was moved or renamed, edit this data source to select its new location. Once the folder is back, refresh this data source."), localDirectory.Path);
break;
}
@@ -802,7 +804,7 @@ internal sealed partial class FileSourceIndexer(SettingsManager settingsManager,
reportInaccessibleDirectory: (directoryPath, exception) =>
{
logger.LogWarning(exception, "Cannot access directory '{DirectoryPath}' while indexing.", directoryPath);
result.AddUnreadableDirectory(directoryPath, string.Format(TB("The folder '{0}' could not be opened. Please check whether you are allowed to read it."), directoryPath));
result.AddUnreadableDirectory(directoryPath, string.Format(TA("The folder '{0}' could not be opened. Please check whether you are allowed to read it."), directoryPath));
}))
{
if (!selection.Selects(filePath))
@@ -824,7 +826,7 @@ internal sealed partial class FileSourceIndexer(SettingsManager settingsManager,
catch (Exception exception)
{
logger.LogWarning(exception, "Cannot inspect file '{FilePath}' while indexing.", filePath);
result.AddFailure(filePath, string.Format(TB("The file '{0}' could not be read. Please check whether you are allowed to read it."), filePath));
result.AddFailure(filePath, string.Format(TA("The file '{0}' could not be read. Please check whether you are allowed to read it."), filePath));
continue;
}
@@ -50,6 +50,8 @@ internal sealed class IndexedRunContext(IIndexedDataSource dataSource, Embedding
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(IndexedRunContext).Namespace, nameof(IndexedRunContext));
private static string TA(string fallbackEN) => I18N.I.TA(fallbackEN, typeof(IndexedRunContext).Namespace, nameof(IndexedRunContext));
/// <summary>
/// One chunk on its way to the stores, with the id it is stored under and the hash of its text.
/// </summary>
@@ -743,20 +745,20 @@ internal sealed class IndexedRunContext(IIndexedDataSource dataSource, Embedding
}
if (vectors.Count != texts.Count)
throw new InvalidOperationException(string.Format(TB("The embedding provider answered with {0} vectors for {1} parts of '{2}'. Please select another embedding model or provider."), vectors.Count, texts.Count, document.Key));
throw new InvalidOperationException(string.Format(TA("The embedding provider answered with {0} vectors for {1} parts of '{2}'. Please select another embedding model or provider."), vectors.Count, texts.Count, document.Key));
var vectorSize = vectors.FirstOrDefault()?.Count ?? 0;
if (vectorSize <= 0)
throw new InvalidOperationException(TB("The embedding provider answered with an empty vector. Please select another embedding model or provider."));
throw new InvalidOperationException(TA("The embedding provider answered with an empty vector. Please select another embedding model or provider."));
if (vectors.Any(vector => vector.Count != vectorSize))
throw new InvalidOperationException(TB("The embedding provider answered with vectors of different sizes. Please select another embedding model or provider."));
throw new InvalidOperationException(TA("The embedding provider answered with vectors of different sizes. Please select another embedding model or provider."));
if (vectors.Any(vector => vector.Any(value => !float.IsFinite(value))))
throw new InvalidOperationException(TB("The embedding provider answered with a vector containing an invalid number. Please select another embedding model or provider."));
throw new InvalidOperationException(TA("The embedding provider answered with a vector containing an invalid number. Please select another embedding model or provider."));
if (manifest.VectorSize > 0 && manifest.VectorSize != vectorSize)
throw new InvalidOperationException(string.Format(TB("The size of the embedding vectors changed from {0} to {1}. Please save the data source again to index it from scratch."), manifest.VectorSize, vectorSize));
throw new InvalidOperationException(string.Format(TA("The size of the embedding vectors changed from {0} to {1}. Please save the data source again to index it from scratch."), manifest.VectorSize, vectorSize));
return vectors;
}
@@ -782,7 +784,7 @@ internal sealed class IndexedRunContext(IIndexedDataSource dataSource, Embedding
await vectorStore.DeleteVectorStore(this.CollectionName, token);
ensureResult = await vectorStore.EnsureVectorStoreExists(this.CollectionName, dataSource.Name, vectorSize, token);
if (!ensureResult.Created)
throw new InvalidOperationException(string.Format(TB("The local index '{0}' could not be created again. Please restart AI Studio and try once more."), this.CollectionName));
throw new InvalidOperationException(string.Format(TA("The local index '{0}' could not be created again. Please restart AI Studio and try once more."), this.CollectionName));
}
await indexStore.UpdateVectorSizeAsync(dataSource.Id, vectorSize, token);
@@ -74,6 +74,8 @@ internal sealed partial class MailboxIndexer(SettingsManager settingsManager, Ru
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(MailboxIndexer).Namespace, nameof(MailboxIndexer));
private static string TA(string fallbackEN) => I18N.I.TA(fallbackEN, typeof(MailboxIndexer).Namespace, nameof(MailboxIndexer));
/// <summary>
/// One folder after the first pass of a run.
/// </summary>
@@ -144,7 +146,7 @@ internal sealed partial class MailboxIndexer(SettingsManager settingsManager, Ru
var password = await this.ReadPasswordAsync(mailbox);
if (password is null)
{
(await this.CreateStoredStateProgressAsync(context, token)).PublishRunFailure(TB("The password of the mailbox could not be read from the operating system. Please enter it again in the settings of the mailbox."));
(await this.CreateStoredStateProgressAsync(context, token)).PublishRunFailure(TA("The password of the mailbox could not be read from the operating system. Please enter it again in the settings of the mailbox."));
return IndexedRunOutcome.DONE;
}
@@ -224,7 +226,7 @@ internal sealed partial class MailboxIndexer(SettingsManager settingsManager, Ru
// would remove every mail from the index, and embedding them again costs hours.
//
logger.LogWarning("The server no longer lists the root folder of mailbox '{MailboxId}'. The sync stops, and nothing is removed from the index.", mailbox.Id);
(await this.CreateStoredStateProgressAsync(context, token)).PublishRunFailure(string.Format(TB("The server no longer lists the folder '{0}' to which this mailbox is limited. Perhaps it was renamed or deleted. Nothing was removed from the index. Rename the folder back on the server, or add the mailbox anew."), mailbox.RootFolder));
(await this.CreateStoredStateProgressAsync(context, token)).PublishRunFailure(string.Format(TA("The server no longer lists the folder '{0}' to which this mailbox is limited. Perhaps it was renamed or deleted. Nothing was removed from the index. Rename the folder back on the server, or add the mailbox anew."), mailbox.RootFolder));
return IndexedRunOutcome.DONE;
}
@@ -607,11 +609,11 @@ internal sealed partial class MailboxIndexer(SettingsManager settingsManager, Ru
}
private static string GetAuthFailureMessage(MailboxAuthFailure failure) => string.Format(
TB("Signing in to the mailbox failed on {0}. Presumably your password changed. AI Studio does not try again on its own, so that your account is not locked. Please enter your current password in the settings of the mailbox."),
TA("Signing in to the mailbox failed on {0}. Presumably your password changed. AI Studio does not try again on its own, so that your account is not locked. Please enter your current password in the settings of the mailbox."),
failure.FailedAtUtc.ToLocalTime().ToString("g", I18N.I.Culture));
private static string GetRemovalMessage(int removalCount) => string.Format(
TB("This sync would remove {0} mails from the index of AI Studio at once, so it waits for you to agree. On the server, the mails stay as they are. Should they come back later, e.g. because you choose a larger period again, they have to be embedded anew, which takes time and, with a cloud provider, money."),
TA("This sync would remove {0} mails from the index of AI Studio at once, so it waits for you to agree. On the server, the mails stay as they are. Should they come back later, e.g. because you choose a larger period again, they have to be embedded anew, which takes time and, with a cloud provider, money."),
removalCount.CompactCount());
/// <summary>