From 153d8870c4f1de3d8cb8a0d92111ac331c49677b Mon Sep 17 00:00:00 2001 From: maliming Date: Tue, 2 Jan 2024 14:31:31 +0800 Subject: [PATCH] Add `verify` feature to `translate` command. --- .../Volo.Abp.Cli.Core.csproj | 1 + .../Volo/Abp/Cli/AbpCliCoreModule.cs | 4 +- .../Volo/Abp/Cli/Commands/TranslateCommand.cs | 60 +++++++++++++++---- 3 files changed, 54 insertions(+), 11 deletions(-) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj b/framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj index 589509bd22..a27f26562d 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj +++ b/framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj @@ -32,6 +32,7 @@ + diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs index e7289b7edd..90c95d18be 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs @@ -10,6 +10,7 @@ using Volo.Abp.Domain; using Volo.Abp.Http; using Volo.Abp.IdentityModel; using Volo.Abp.Json; +using Volo.Abp.Localization; using Volo.Abp.Minify; using Volo.Abp.Modularity; @@ -20,7 +21,8 @@ namespace Volo.Abp.Cli; typeof(AbpJsonModule), typeof(AbpIdentityModelModule), typeof(AbpMinifyModule), - typeof(AbpHttpModule) + typeof(AbpHttpModule), + typeof(AbpLocalizationModule) )] public class AbpCliCoreModule : AbpModule { diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/TranslateCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/TranslateCommand.cs index 73b6a74421..cb85b37e17 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/TranslateCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/TranslateCommand.cs @@ -11,6 +11,7 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Volo.Abp.Cli.Args; using Volo.Abp.DependencyInjection; +using Volo.Abp.Localization.Json; namespace Volo.Abp.Cli.Commands; @@ -23,6 +24,14 @@ public class TranslateCommand : IConsoleCommand, ITransientDependency public async Task ExecuteAsync(CommandLineArgs commandLineArgs) { var currentDirectory = Directory.GetCurrentDirectory(); + + // Verify + if (commandLineArgs.Options.ContainsKey(Options.Verify.Long)) + { + await VerifyJsonAsync(currentDirectory); + return; + } + var referenceCulture = commandLineArgs.Options.GetOrNull(Options.ReferenceCulture.Short, Options.ReferenceCulture.Long) ?? "en"; var allValues = commandLineArgs.Options.ContainsKey(Options.AllValues.Short) || commandLineArgs.Options.ContainsKey(Options.AllValues.Long); @@ -368,20 +377,22 @@ public class TranslateCommand : IConsoleCommand, ITransientDependency return Task.CompletedTask; } - private static IEnumerable GetCultureJsonFiles(string path, string cultureName) + private static IEnumerable GetCultureJsonFiles(string path, string cultureName = null) { var excludeDirectory = new List() - { - "node_modules", - Path.Combine("bin", "debug"), - Path.Combine("obj", "debug") - }; - - var allCultureInfos = CultureInfo.GetCultures(CultureTypes.AllCultures); + { + "node_modules", + "wwwroot", + ".git", + "bin", + "obj" + }; + var allCultureNames = CultureInfo.GetCultures(CultureTypes.AllCultures).Where(x => !x.Name.IsNullOrWhiteSpace()).Select(x => x.Name).ToList(); return Directory.GetFiles(path, "*.json", SearchOption.AllDirectories) .Where(file => excludeDirectory.All(x => file.IndexOf(x, StringComparison.OrdinalIgnoreCase) == -1)) - .Where(jsonFile => allCultureInfos.Any(culture => jsonFile.EndsWith($"{cultureName}.json", StringComparison.OrdinalIgnoreCase))); + .Where(file => allCultureNames.Any(x => Path.GetFileName(file).Equals($"{x}.json", StringComparison.OrdinalIgnoreCase))) + .WhereIf(!cultureName.IsNullOrWhiteSpace(), jsonFile => Path.GetFileName(jsonFile).Equals($"{cultureName}.json", StringComparison.OrdinalIgnoreCase)); } private AbpLocalizationInfo GetAbpLocalizationInfoOrNull(string path) @@ -468,6 +479,29 @@ public class TranslateCommand : IConsoleCommand, ITransientDependency return translateInfo; } + private Task VerifyJsonAsync(string currentDirectory) + { + var jsonFiles = GetCultureJsonFiles(currentDirectory); + var hasInvalidJsonFile = false; + foreach (var jsonFile in jsonFiles) + { + try + { + var jsonString = File.ReadAllText(jsonFile); + _ = JsonLocalizationDictionaryBuilder.BuildFromJsonString(jsonString); + } + catch (Exception e) + { + Logger.LogError($"Invalid json file: {jsonFile}"); + hasInvalidJsonFile = true; + } + } + + Logger.LogInformation(!hasInvalidJsonFile ? "All json files are valid." : "Some json files are invalid."); + + return Task.CompletedTask; + } + private static AbpLocalizationInfo SortLocalizedKeys(AbpLocalizationInfo targetLocalizationInfo, AbpLocalizationInfo referenceLocalizationInfo) { var sortedLocalizationInfo = new AbpLocalizationInfo @@ -503,8 +537,9 @@ public class TranslateCommand : IConsoleCommand, ITransientDependency sb.AppendLine("--all-values|-all Include all keys. Default false"); sb.AppendLine("--apply|-a Creates or updates the file for the translated culture."); sb.AppendLine("--file|-f Default: abp-translation.json"); - sb.AppendLine("--online|-o Translate online."); + sb.AppendLine("--online Translate online."); sb.AppendLine("--deepl-auth-key DeepL auth key for online translation."); + sb.AppendLine("--verify Verify that all localized files are correct JSON format."); sb.AppendLine(""); sb.AppendLine("Examples:"); sb.AppendLine(""); @@ -572,6 +607,11 @@ public class TranslateCommand : IConsoleCommand, ITransientDependency { public const string Short = "deepl-auth-key"; } + + public static class Verify + { + public const string Long = "verify"; + } } public class AbpTranslateInfo