diff --git a/app/MindWork AI Studio/Assistants/I18N/AssistantI18N.razor b/app/MindWork AI Studio/Assistants/I18N/AssistantI18N.razor index 2fe167a9..bd39da42 100644 --- a/app/MindWork AI Studio/Assistants/I18N/AssistantI18N.razor +++ b/app/MindWork AI Studio/Assistants/I18N/AssistantI18N.razor @@ -1,5 +1,81 @@ @attribute [Route(Routes.ASSISTANT_AI_STUDIO_I18N)] +@using AIStudio.Settings @inherits AssistantBaseCore - - \ No newline at end of file + +@if (this.isLoading) +{ + + The data is being loaded, please wait... + +} else if (!this.isLoading && !string.IsNullOrWhiteSpace(this.loadingIssue)) +{ + + While loading the I18N data, an issue occurred: @this.loadingIssue + +} +else if (!this.isLoading && string.IsNullOrWhiteSpace(this.loadingIssue)) +{ + + Added Content (@this.addedKeys.Count entries) + + + + + + + + + + + Key + Text + + + +
+                    @context.Key
+                
+
+ + @context.Value + +
+ + + +
+ + + Removed Content (@this.removedKeys.Count entries) + + + + + + + + + + + Key + Text + + + +
+                    @context.Key
+                
+
+ + @context.Value + +
+ + + +
+ + + +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Assistants/I18N/AssistantI18N.razor.cs b/app/MindWork AI Studio/Assistants/I18N/AssistantI18N.razor.cs index 460a978a..2bb5bcf8 100644 --- a/app/MindWork AI Studio/Assistants/I18N/AssistantI18N.razor.cs +++ b/app/MindWork AI Studio/Assistants/I18N/AssistantI18N.razor.cs @@ -1,4 +1,7 @@ using AIStudio.Dialogs.Settings; +using AIStudio.Tools.PluginSystem; + +using Microsoft.Extensions.FileProviders; namespace AIStudio.Assistants.I18N; @@ -25,11 +28,14 @@ public partial class AssistantI18N : AssistantBaseCore protected override string SubmitText => "Localize AI Studio"; protected override Func SubmitAction => this.LocalizeText; + + protected override bool SubmitDisabled => !this.localizationPossible; protected override void ResetForm() { if (!this.MightPreselectValues()) { + this.selectedLanguagePluginId = InternalPlugin.LANGUAGE_EN_US.MetaData().Id; this.selectedTargetLanguage = CommonLanguages.AS_IS; this.customTargetLanguage = string.Empty; } @@ -39,6 +45,7 @@ public partial class AssistantI18N : AssistantBaseCore { if (this.SettingsManager.ConfigurationData.I18N.PreselectOptions) { + this.selectedLanguagePluginId = this.SettingsManager.ConfigurationData.I18N.PreselectedLanguagePluginId; this.selectedTargetLanguage = this.SettingsManager.ConfigurationData.I18N.PreselectedTargetLanguage; this.customTargetLanguage = this.SettingsManager.ConfigurationData.I18N.PreselectOtherLanguage; return true; @@ -49,6 +56,105 @@ public partial class AssistantI18N : AssistantBaseCore private CommonLanguages selectedTargetLanguage; private string customTargetLanguage = string.Empty; + private bool isLoading = true; + private string loadingIssue = string.Empty; + private bool localizationPossible; + private string searchString = string.Empty; + private Guid selectedLanguagePluginId; + private Dictionary addedKeys = []; + private Dictionary removedKeys = []; + + #region Overrides of AssistantBase + + protected override async Task OnInitializedAsync() + { + await base.OnInitializedAsync(); + await this.LoadData(); + } + + #endregion + + private async Task OnLanguagePluginChanged(Guid pluginId) + { + this.selectedLanguagePluginId = pluginId; + await this.LoadData(); + this.StateHasChanged(); + } + + private async Task LoadData() + { + this.isLoading = true; + this.StateHasChanged(); + + // + // Read the file `Assistants\I18N\allTexts.lua`: + // + + #if DEBUG + var filePath = Path.Join(Environment.CurrentDirectory, "Assistants", "I18N"); + var resourceFileProvider = new PhysicalFileProvider(filePath); + #else + var resourceFileProvider = new ManifestEmbeddedFileProvider(Assembly.GetAssembly(type: typeof(Program))!, "Assistants.I18N"); + #endif + + var file = resourceFileProvider.GetFileInfo("allTexts.lua"); + await using var fileStream = file.CreateReadStream(); + using var reader = new StreamReader(fileStream); + var newI18NDataLuaCode = await reader.ReadToEndAsync(); + + // + // Next, we try to load the text as a language plugin -- without + // actually starting the plugin: + // + var newI18NPlugin = await PluginFactory.Load(null, newI18NDataLuaCode); + switch (newI18NPlugin) + { + case NoPlugin noPlugin when noPlugin.Issues.Any(): + this.loadingIssue = noPlugin.Issues.First(); + break; + + case NoPlugin: + this.loadingIssue = "Was not able to load the I18N plugin. Please check the plugin code."; + break; + + case { IsValid: false } plugin when plugin.Issues.Any(): + this.loadingIssue = plugin.Issues.First(); + break; + + case PluginLanguage pluginLanguage: + this.loadingIssue = string.Empty; + var newI18NContent = pluginLanguage.Content; + + if(PluginFactory.RunningPlugins.FirstOrDefault(n => n is PluginLanguage && n.Id == this.selectedLanguagePluginId) is not PluginLanguage comparisonPlugin) + { + this.loadingIssue = $"Was not able to load the language plugin for comparison ({this.selectedLanguagePluginId}). Please select a valid, loaded & running language plugin."; + break; + } + + var currentI18NContent = comparisonPlugin.Content; + this.addedKeys = newI18NContent.ExceptBy(currentI18NContent.Keys, n => n.Key).ToDictionary(); + this.removedKeys = currentI18NContent.ExceptBy(newI18NContent.Keys, n => n.Key).ToDictionary(); + this.localizationPossible = true; + break; + } + + this.isLoading = false; + this.StateHasChanged(); + } + + private bool FilterFunc(KeyValuePair element) + { + if (string.IsNullOrWhiteSpace(this.searchString)) + return true; + + if (element.Key.Contains(this.searchString, StringComparison.OrdinalIgnoreCase)) + return true; + + if (element.Value.Contains(this.searchString, StringComparison.OrdinalIgnoreCase)) + return true; + + return false; + } private string? ValidatingTargetLanguage(CommonLanguages language) {