From 6158ec78caabb4598d76b35c3a7ba51c146fa0c6 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Thu, 17 Apr 2025 09:48:24 +0200 Subject: [PATCH] Create Lua code from collected I18N keys and texts --- app/Build/Commands/CollectI18NKeysCommand.cs | 150 ++++++++++++++++++- 1 file changed, 144 insertions(+), 6 deletions(-) diff --git a/app/Build/Commands/CollectI18NKeysCommand.cs b/app/Build/Commands/CollectI18NKeysCommand.cs index 8b2554bf..de69de9a 100644 --- a/app/Build/Commands/CollectI18NKeysCommand.cs +++ b/app/Build/Commands/CollectI18NKeysCommand.cs @@ -25,8 +25,8 @@ public sealed partial class CollectI18NKeysCommand var wwwrootPath = Path.Join(cwd, "wwwroot"); var allFiles = Directory.EnumerateFiles(cwd, "*", SearchOption.AllDirectories); var counter = 0; - var sb = new StringBuilder(); + var allI18NContent = new Dictionary(); foreach (var filePath in allFiles) { counter++; @@ -47,16 +47,154 @@ public sealed partial class CollectI18NKeysCommand var ns = this.DetermineNamespace(filePath); var fileInfo = new FileInfo(filePath); var name = fileInfo.Name.Replace(fileInfo.Extension, string.Empty); - var langNamespace = $"{ns}::{name}".ToUpperInvariant().Replace(".", "::"); + var langNamespace = $"{ns}.{name}".ToUpperInvariant(); foreach (var match in matches) { - var key = $"root::{langNamespace}::T{match.ToFNV32()}"; - + // The key in the format A.B.C.D.T{hash}: + var key = $"UI_TEXT_CONTENT.{langNamespace}.T{match.ToFNV32()}"; + allI18NContent.TryAdd(key, match); } } - Console.WriteLine($" {counter:###,###} files processed."); - Console.WriteLine(); + Console.WriteLine($" {counter:###,###} files processed, {allI18NContent.Count:###,###} keys found."); + + Console.Write("- Creating Lua code ..."); + var luaCode = this.ExportToLuaTable(allI18NContent); + + // Build the path, where we want to store the Lua code: + var luaPath = Path.Join(cwd, "Assistants", "I18N", "allTexts.lua"); + + // Store the Lua code: + await File.WriteAllTextAsync(luaPath, luaCode, Encoding.UTF8); + + Console.WriteLine(" done."); + } + + private string ExportToLuaTable(Dictionary keyValuePairs) + { + // Collect all nodes: + var root = new Dictionary(); + + // + // Split all collected keys into nodes: + // + foreach (var key in keyValuePairs.Keys.Order()) + { + var path = key.Split('.'); + var current = root; + for (var i = 0; i < path.Length - 1; i++) + { + // We ignore the AISTUDIO segment of the path: + if(path[i] == "AISTUDIO") + continue; + + if (!current.TryGetValue(path[i], out var child) || child is not Dictionary childDict) + { + childDict = new Dictionary(); + current[path[i]] = childDict; + } + + current = childDict; + } + + current[path.Last()] = keyValuePairs[key]; + } + + // + // Inner method to build Lua code from the collected nodes: + // + void ToLuaTable(StringBuilder sb, Dictionary innerDict, int indent = 0) + { + sb.AppendLine("{"); + var prefix = new string(' ', indent * 4); + foreach (var kvp in innerDict) + { + if (kvp.Value is Dictionary childDict) + { + sb.Append($"{prefix} {kvp.Key}"); + sb.Append(" = "); + + ToLuaTable(sb, childDict, indent + 1); + } + else if (kvp.Value is string s) + { + sb.AppendLine($"{prefix} -- {s.Trim().Replace("\n", " ")}"); + sb.Append($"{prefix} {kvp.Key}"); + sb.Append(" = "); + sb.Append($""" + "{s}" + """); + sb.AppendLine(","); + sb.AppendLine(); + } + } + + sb.AppendLine(prefix + "},"); + sb.AppendLine(); + } + + // + // Write the Lua code: + // + var sbLua = new StringBuilder(); + + // To make the later parsing easier, we add the mandatory plugin + // metadata: + sbLua.AppendLine( + """ + -- The ID for this plugin: + ID = "77c2688a-a68f-45cc-820e-fa8f3038a146" + + -- The icon for the plugin: + ICON_SVG = "" + + -- The name of the plugin: + NAME = "Collected I18N keys" + + -- The description of the plugin: + DESCRIPTION = "This plugin is not meant to be used directly. Its a collection of all I18N keys found in the project." + + -- The version of the plugin: + VERSION = "1.0.0" + + -- The type of the plugin: + TYPE = "LANGUAGE" + + -- The authors of the plugin: + AUTHORS = {"MindWork AI Community"} + + -- The support contact for the plugin: + SUPPORT_CONTACT = "MindWork AI Community" + + -- The source URL for the plugin: + SOURCE_URL = "https://github.com/MindWorkAI/AI-Studio" + + -- The categories for the plugin: + CATEGORIES = { "CORE" } + + -- The target groups for the plugin: + TARGET_GROUPS = { "EVERYONE" } + + -- The flag for whether the plugin is maintained: + IS_MAINTAINED = true + + -- When the plugin is deprecated, this message will be shown to users: + DEPRECATION_MESSAGE = "" + + -- The IETF BCP 47 tag for the language. It's the ISO 639 language + -- code followed by the ISO 3166-1 country code: + IETF_TAG = "en-US" + + -- The language name in the user's language: + LANG_NAME = "English (United States)" + + """); + + sbLua.Append("UI_TEXT_CONTENT = "); + if(root["UI_TEXT_CONTENT"] is Dictionary dict) + ToLuaTable(sbLua, dict); + + return sbLua.ToString(); } private List FindAllTextTags(ReadOnlySpan fileContent)