From cfc2103b436ecd6d969a00eb354259cd8afe054f Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Sat, 3 May 2025 21:47:43 +0200 Subject: [PATCH] Improved I18N system (#445) --- app/Build/Commands/CollectI18NKeysCommand.cs | 12 ++++---- .../Assistants/I18N/allTexts.lua | 9 ++++++ .../Layout/MainLayout.razor.cs | 4 +++ .../plugin.lua | 14 ++++++++- .../plugin.lua | 14 ++++++++- .../DataModel/LangBehaviorExtensions.cs | 16 ++++++++++ .../DataModel/LangBehaviourExtensions.cs | 12 -------- .../Settings/SettingsManager.cs | 18 ++++++++--- .../Tools/PluginSystem/I18N.cs | 30 +++++++++++++++++++ .../Tools/PluginSystem/ILangExtensions.cs | 4 +-- .../wwwroot/changelog/v0.9.42.md | 2 ++ 11 files changed, 109 insertions(+), 26 deletions(-) create mode 100644 app/MindWork AI Studio/Settings/DataModel/LangBehaviorExtensions.cs delete mode 100644 app/MindWork AI Studio/Settings/DataModel/LangBehaviourExtensions.cs create mode 100644 app/MindWork AI Studio/Tools/PluginSystem/I18N.cs diff --git a/app/Build/Commands/CollectI18NKeysCommand.cs b/app/Build/Commands/CollectI18NKeysCommand.cs index 1a09d77a..ec7c291f 100644 --- a/app/Build/Commands/CollectI18NKeysCommand.cs +++ b/app/Build/Commands/CollectI18NKeysCommand.cs @@ -11,16 +11,16 @@ namespace Build.Commands; public sealed partial class CollectI18NKeysCommand { private const string START_TAG1 = """ - T(" - """; + T(" + """; private const string START_TAG2 = """ - TB(" - """; + TB(" + """; private const string START_TAG3 = """ - T(@" - """; + T(@" + """; private const string END_TAG = """ ") diff --git a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua index 3971eaf1..2e67d6d2 100644 --- a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua +++ b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua @@ -2529,3 +2529,12 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::WRITER::T3948127789"] = "Suggestion" -- Your stage directions UI_TEXT_CONTENT["AISTUDIO::PAGES::WRITER::T779923726"] = "Your stage directions" + +-- Unknown option +UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::LANGBEHAVIOREXTENSIONS::T3964902774"] = "Unknown option" + +-- Choose the language manually. +UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::LANGBEHAVIOREXTENSIONS::T3988034966"] = "Choose the language manually." + +-- Choose the language automatically, based on your system language. +UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::LANGBEHAVIOREXTENSIONS::T485389934"] = "Choose the language automatically, based on your system language." diff --git a/app/MindWork AI Studio/Layout/MainLayout.razor.cs b/app/MindWork AI Studio/Layout/MainLayout.razor.cs index 934dc358..9a50cf88 100644 --- a/app/MindWork AI Studio/Layout/MainLayout.razor.cs +++ b/app/MindWork AI Studio/Layout/MainLayout.razor.cs @@ -206,6 +206,10 @@ public partial class MainLayout : LayoutComponentBase, IMessageBusReceiver, ILan break; case Event.PLUGINS_RELOADED: + this.Lang = await this.SettingsManager.GetActiveLanguagePlugin(); + I18N.Init(this.Lang); + this.LoadNavItems(); + await this.InvokeAsync(this.StateHasChanged); break; } diff --git a/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua b/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua index 6b7fa4af..ca902253 100644 --- a/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua +++ b/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua @@ -447,6 +447,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T636393754"] = "Verschiebe -- Show your workspaces UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T733672375"] = "Zeige deine Arbeitsbereiche" +-- Start new chat in workspace "{0}" +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T896906391"] = "Neuen Chat im Arbeitsbereich \"{0}\" starten" + -- Region UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIDENCEINFO::T1227782301"] = "Region" @@ -2059,7 +2062,7 @@ UI_TEXT_CONTENT["AISTUDIO::LAYOUT::MAINLAYOUT::T2864211629"] = "Bitte warten Sie UI_TEXT_CONTENT["AISTUDIO::LAYOUT::MAINLAYOUT::T2929332068"] = "Unterstützer" -- Writer -UI_TEXT_CONTENT["AISTUDIO::LAYOUT::MAINLAYOUT::T2979224202"] = "Schreiber" +UI_TEXT_CONTENT["AISTUDIO::LAYOUT::MAINLAYOUT::T2979224202"] = "Schreiben" -- Show details UI_TEXT_CONTENT["AISTUDIO::LAYOUT::MAINLAYOUT::T3692372066"] = "Details anzeigen" @@ -2528,3 +2531,12 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::WRITER::T3948127789"] = "Vorschlag" -- Your stage directions UI_TEXT_CONTENT["AISTUDIO::PAGES::WRITER::T779923726"] = "Ihre Regieanweisungen" + +-- Unknown option +UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::LANGBEHAVIOREXTENSIONS::T3964902774"] = "Unbekannte Option" + +-- Choose the language manually. +UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::LANGBEHAVIOREXTENSIONS::T3988034966"] = "Sprache manuell auswählen." + +-- Choose the language automatically, based on your system language. +UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::LANGBEHAVIOREXTENSIONS::T485389934"] = "Sprache automatisch anhand Ihrer Systemsprache auswählen." diff --git a/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua b/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua index 12abae43..d20f9b13 100644 --- a/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua +++ b/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua @@ -447,6 +447,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T636393754"] = "Move the c -- Show your workspaces UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T733672375"] = "Show your workspaces" +-- Start new chat in workspace "{0}" +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T896906391"] = "Start new chat in workspace \"{0}\"" + -- Region UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIDENCEINFO::T1227782301"] = "Region" @@ -2059,7 +2062,7 @@ UI_TEXT_CONTENT["AISTUDIO::LAYOUT::MAINLAYOUT::T2864211629"] = "Please wait for UI_TEXT_CONTENT["AISTUDIO::LAYOUT::MAINLAYOUT::T2929332068"] = "Supporters" -- Writer -UI_TEXT_CONTENT["AISTUDIO::LAYOUT::MAINLAYOUT::T2979224202"] = "Writer" +UI_TEXT_CONTENT["AISTUDIO::LAYOUT::MAINLAYOUT::T2979224202"] = "Writing" -- Show details UI_TEXT_CONTENT["AISTUDIO::LAYOUT::MAINLAYOUT::T3692372066"] = "Show details" @@ -2529,3 +2532,12 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::WRITER::T3948127789"] = "Suggestion" -- Your stage directions UI_TEXT_CONTENT["AISTUDIO::PAGES::WRITER::T779923726"] = "Your stage directions" +-- Unknown option +UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::LANGBEHAVIOREXTENSIONS::T3964902774"] = "Unknown option" + +-- Choose the language manually. +UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::LANGBEHAVIOREXTENSIONS::T3988034966"] = "Choose the language manually." + +-- Choose the language automatically, based on your system language. +UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::LANGBEHAVIOREXTENSIONS::T485389934"] = "Choose the language automatically, based on your system language." + diff --git a/app/MindWork AI Studio/Settings/DataModel/LangBehaviorExtensions.cs b/app/MindWork AI Studio/Settings/DataModel/LangBehaviorExtensions.cs new file mode 100644 index 00000000..a480ef36 --- /dev/null +++ b/app/MindWork AI Studio/Settings/DataModel/LangBehaviorExtensions.cs @@ -0,0 +1,16 @@ +using AIStudio.Tools.PluginSystem; + +namespace AIStudio.Settings.DataModel; + +public static class LangBehaviorExtensions +{ + private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(LangBehaviorExtensions).Namespace, nameof(LangBehaviorExtensions)); + + public static string Name(this LangBehavior langBehavior) => langBehavior switch + { + LangBehavior.AUTO => TB("Choose the language automatically, based on your system language."), + LangBehavior.MANUAL => TB("Choose the language manually."), + + _ => TB("Unknown option") + }; +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Settings/DataModel/LangBehaviourExtensions.cs b/app/MindWork AI Studio/Settings/DataModel/LangBehaviourExtensions.cs deleted file mode 100644 index c71caf92..00000000 --- a/app/MindWork AI Studio/Settings/DataModel/LangBehaviourExtensions.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace AIStudio.Settings.DataModel; - -public static class LangBehaviorExtensions -{ - public static string Name(this LangBehavior langBehavior) => langBehavior switch - { - LangBehavior.AUTO => "Choose the language automatically, based on your system language.", - LangBehavior.MANUAL => "Choose the language manually.", - - _ => "Unknown option" - }; -} \ No newline at end of file diff --git a/app/MindWork AI Studio/Settings/SettingsManager.cs b/app/MindWork AI Studio/Settings/SettingsManager.cs index 72d196c5..e34be596 100644 --- a/app/MindWork AI Studio/Settings/SettingsManager.cs +++ b/app/MindWork AI Studio/Settings/SettingsManager.cs @@ -13,7 +13,7 @@ namespace AIStudio.Settings; /// /// The settings manager. /// -public sealed class SettingsManager(ILogger logger, RustService rustService) +public sealed class SettingsManager { private const string SETTINGS_FILENAME = "settings.json"; @@ -23,9 +23,19 @@ public sealed class SettingsManager(ILogger logger, RustService Converters = { new TolerantEnumConverter() }, }; - private readonly ILogger logger = logger; - private readonly RustService rustService = rustService; - + private readonly ILogger logger; + private readonly RustService rustService; + + /// + /// The settings manager. + /// + public SettingsManager(ILogger logger, RustService rustService) + { + this.logger = logger; + this.rustService = rustService; + this.logger.LogInformation("Settings manager created."); + } + /// /// The directory where the configuration files are stored. /// diff --git a/app/MindWork AI Studio/Tools/PluginSystem/I18N.cs b/app/MindWork AI Studio/Tools/PluginSystem/I18N.cs new file mode 100644 index 00000000..c327da48 --- /dev/null +++ b/app/MindWork AI Studio/Tools/PluginSystem/I18N.cs @@ -0,0 +1,30 @@ +namespace AIStudio.Tools.PluginSystem; + +public class I18N : ILang +{ + public static readonly I18N I = new(); + private static readonly ILogger LOG = Program.LOGGER_FACTORY.CreateLogger(); + + private ILanguagePlugin language = PluginFactory.BaseLanguage; + + private I18N() + { + } + + public static void Init(ILanguagePlugin language) => I.language = language; + + #region Implementation of ILang + + public string T(string fallbackEN) + { + LOG.LogWarning("Using I18N.I.T without namespace and type is probably wrong, because the I18N key collection process of the build system will not find those keys."); + return this.GetText(this.language, fallbackEN); + } + + public string T(string fallbackEN, string? typeNamespace, string? typeName) + { + return this.GetText(this.language, fallbackEN, typeNamespace, typeName); + } + + #endregion +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/PluginSystem/ILangExtensions.cs b/app/MindWork AI Studio/Tools/PluginSystem/ILangExtensions.cs index 1c9100a8..61abbf42 100644 --- a/app/MindWork AI Studio/Tools/PluginSystem/ILangExtensions.cs +++ b/app/MindWork AI Studio/Tools/PluginSystem/ILangExtensions.cs @@ -12,8 +12,8 @@ public static class ILangExtensions typeName ??= type.Name; typeNamespace ??= type.Namespace!; - // When the type's name ends with `1 or 2`, etc. (i.e., generic classes), remove it: - if(typeName.Contains("`")) + // When the type's name ends with `1 or `2, etc. (i.e., generic classes), remove it: + if(typeName.Contains('`')) typeName = typeName[..typeName.IndexOf('`')]; var ns = $"{typeNamespace}::{typeName}".ToUpperInvariant().Replace(".", "::"); diff --git a/app/MindWork AI Studio/wwwroot/changelog/v0.9.42.md b/app/MindWork AI Studio/wwwroot/changelog/v0.9.42.md index ef529ad5..ae842aac 100644 --- a/app/MindWork AI Studio/wwwroot/changelog/v0.9.42.md +++ b/app/MindWork AI Studio/wwwroot/changelog/v0.9.42.md @@ -1,10 +1,12 @@ # v0.9.42, build 217 (2025-05-xx xx:xx UTC) - Added the writing style "Changelog" to the rewrite & improve text assistant. This helps to create changelogs for your projects. - Added an option to load PDF files directly into the translation, text summarization, and legal check assistants as a preview prototype for testing before release. +- Added more text content to the localization system. - Improved the model selection for OpenAI by removing all `o1-pro` models. These models cannot be used right now, since OpenAI introduced a new API, which is not yet supported by MindWork AI Studio. - Improved the internal plugin maintenance so that removed resources are now removed from the file system. - Improved the app settings to apply the chosen language immediately. - Improved chat name generation to prevent the inclusion of line breaks, tabs, and other special characters. - Fixed an issue where empty lines in source code were being ignored by the Markdown renderer. Thanks My Nihongo for fixing this bug in the `MudBlazor.Markdown` repository. - Fixed the localization assistant not being able to load the localization file when used in the release app. +- Fixed the localization of the navigation component. - Upgraded Rust & .NET dependencies. \ No newline at end of file