diff --git a/DotNetResxUtils/.vscode/launch.json b/DotNetResxUtils/.vscode/launch.json new file mode 100644 index 0000000..d89c191 --- /dev/null +++ b/DotNetResxUtils/.vscode/launch.json @@ -0,0 +1,26 @@ +{ + "version": "0.2.0", + "configurations": [ + { + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + "name": ".NET Core Launch (console)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + // If you have changed target frameworks, make sure to update the program path. + "program": "${workspaceFolder}/bin/Debug/net6.0/DotNetResxUtils.dll", + "args": [], + "cwd": "${workspaceFolder}", + // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console + "console": "internalConsole", + "stopAtEntry": false + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach" + } + ] +} \ No newline at end of file diff --git a/DotNetResxUtils/.vscode/tasks.json b/DotNetResxUtils/.vscode/tasks.json new file mode 100644 index 0000000..c25d850 --- /dev/null +++ b/DotNetResxUtils/.vscode/tasks.json @@ -0,0 +1,41 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/DotNetResxUtils.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/DotNetResxUtils.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "--project", + "${workspaceFolder}/DotNetResxUtils.csproj" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git a/DotNetResxUtils/Commands/GenerationCommand.cs b/DotNetResxUtils/Commands/GenerationCommand.cs new file mode 100644 index 0000000..e6f6f23 --- /dev/null +++ b/DotNetResxUtils/Commands/GenerationCommand.cs @@ -0,0 +1,86 @@ +using System.Collections.Generic; +using System.IO; +using System.CommandLine; +using System.Text.Json; +using System.Threading.Tasks; +using System.Resources.NetStandard; + +namespace DotNetResxUtils.Commands +{ + internal class GenerationCommand + { + const string NAME = "generate"; + const string DESC = "Generate a .resx file."; + + public GenerationCommand(RootCommand rootCmd) + { + Command cmd = new Command(NAME, DESC); + rootCmd.AddCommand(cmd); + + Option fromOpt = new Option("--from", "Generates a .resx file from the given file."); + + Argument destArg = new Argument("destination", "The destination path to store this file. If no extension is given, .resx will automatically be concatenated."); + + cmd.AddOption(fromOpt); + cmd.AddArgument(destArg); + + cmd.SetHandler(CommandHandler, destArg, fromOpt); + } + private async void CommandHandler(FileInfo to, FileInfo? from) + { + IDictionary flattened = new Dictionary(); + if (from != null) + { + flattened = await FlattenJson(from); + } + using (ResXResourceWriter resxWriter = new ResXResourceWriter(to.FullName)) + { + foreach (KeyValuePair keyVal in flattened) + { + resxWriter.AddResource(keyVal.Key, keyVal.Value); + } + } + } + + private async Task> FlattenJson(FileInfo jsonFile) + { + JsonElement jsonObj; + using (FileStream readStream = jsonFile.OpenRead()) + { + jsonObj = await JsonSerializer.DeserializeAsync(readStream); + } + Dictionary result = new Dictionary(); + FlattenJsonElement(result, jsonObj, ""); + return result; + } + + private void FlattenJsonElement(IDictionary flattened, JsonElement jsonElement, string namepath) + { + if (jsonElement.ValueKind == JsonValueKind.Array) + { + int itemIndex = 0; + foreach (JsonElement item in jsonElement.EnumerateArray()) + { + FlattenJsonElement(flattened, item, namepath + $"[{itemIndex}]"); + } + } + else if (jsonElement.ValueKind == JsonValueKind.Object) + { + foreach (JsonProperty item in jsonElement.EnumerateObject()) + { + FlattenJsonElement(flattened, item.Value, namepath + $".{item.Name}"); + } + } + else + { + string? stored = jsonElement.GetString(); + if (stored != null) + { + flattened[namepath] = stored; + } + } + } + } + + +} \ No newline at end of file diff --git a/DotNetResxUtils/DotNetResxUtils.csproj b/DotNetResxUtils/DotNetResxUtils.csproj index bae1248..8fe51e0 100644 --- a/DotNetResxUtils/DotNetResxUtils.csproj +++ b/DotNetResxUtils/DotNetResxUtils.csproj @@ -1,14 +1,21 @@ + exe true true true true + true net6.0 disable enable + + + + + \ No newline at end of file diff --git a/DotNetResxUtils/Program.cs b/DotNetResxUtils/Program.cs index 3d0b61c..d217a3f 100644 --- a/DotNetResxUtils/Program.cs +++ b/DotNetResxUtils/Program.cs @@ -1,4 +1,6 @@ -using System; +using System.IO; +using System; +using System.CommandLine; namespace DotNetResxUtils { @@ -6,8 +8,20 @@ namespace DotNetResxUtils { static void Main(string[] args) { - Console.WriteLine("Hello, World!"); + RootCommand rootCmd = new RootCommand(".Net Resx Utils provides tools for generating, and editing .resx files."); + Command genCmd = new Command("gen", "Generate a .resx file."); + rootCmd.AddCommand(genCmd); + // See: Collection organizers - https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/object-and-collection-initializers + + Option convertOpt = new Option("--convert", "Generates a .resx file from the given file. Currently only supports .json files."); + genCmd.AddOption(convertOpt); + + Argument destArg = new Argument("destination", "The destination path to store this file. If no extension is given, .resx will automatically be concatenated."); + genCmd.AddArgument(destArg); + + + genCmd.SetHandler(async (string dst, FileInfo? from)) } } } \ No newline at end of file