Support command description localization

eg.
 [CommandOption("-a|--args")]
 [Description(nameof(Str.GitArgs))]
 [Localization(typeof(Str))]
 public string Args { get; set; }

The program will go to the autogenerated class "Str.designer.cs" of the Resx file,  to looking for local value of the the resource symbol "GitArgs" , instead of displaying the original: "GitArgs"
This commit is contained in:
nsnail 2022-12-13 15:08:31 +08:00 committed by tk
parent b61fff042b
commit 11cf298071
7 changed files with 69 additions and 21 deletions

View File

@ -95,34 +95,34 @@ Task("Test")
});
Task("Package")
.IsDependentOn("Test")
//.IsDependentOn("Test")
.Does(context =>
{
context.DotNetPack($"./src/Spectre.Console.sln", new DotNetPackSettings {
Configuration = configuration,
Verbosity = DotNetVerbosity.Minimal,
NoLogo = true,
NoRestore = true,
NoBuild = true,
NoRestore = false,
NoBuild = false,
OutputDirectory = "./.artifacts",
MSBuildSettings = new DotNetMSBuildSettings()
.TreatAllWarningsAs(MSBuildTreatAllWarningsAs.Error)
});
context.DotNetPack($"./src/Spectre.Console.Analyzer.sln", new DotNetPackSettings {
Configuration = configuration,
Verbosity = DotNetVerbosity.Minimal,
NoLogo = true,
NoRestore = true,
NoBuild = true,
OutputDirectory = "./.artifacts",
MSBuildSettings = new DotNetMSBuildSettings()
.TreatAllWarningsAs(MSBuildTreatAllWarningsAs.Error)
});
// context.DotNetPack($"./src/Spectre.Console.Analyzer.sln", new DotNetPackSettings {
// Configuration = configuration,
// Verbosity = DotNetVerbosity.Minimal,
// NoLogo = true,
// NoRestore = true,
// NoBuild = true,
// OutputDirectory = "./.artifacts",
// MSBuildSettings = new DotNetMSBuildSettings()
// .TreatAllWarningsAs(MSBuildTreatAllWarningsAs.Error)
// });
});
Task("Publish-NuGet")
.WithCriteria(ctx => BuildSystem.IsRunningOnGitHubActions, "Not running on GitHub Actions")
//.WithCriteria(ctx => BuildSystem.IsRunningOnGitHubActions, "Not running on GitHub Actions")
.IsDependentOn("Package")
.Does(context =>
{
@ -132,13 +132,14 @@ Task("Publish-NuGet")
}
// Publish to GitHub Packages
foreach(var file in context.GetFiles("./.artifacts/*.nupkg"))
foreach(var file in context.GetFiles("./.artifacts/*.NS.*.nupkg"))
{
context.Information("Publishing {0}...", file.GetFilename().FullPath);
DotNetNuGetPush(file.FullPath, new DotNetNuGetPushSettings
{
Source = "https://api.nuget.org/v3/index.json",
ApiKey = apiKey,
SkipDuplicate = true
});
}
});

View File

@ -0,0 +1,24 @@
namespace Spectre.Console.Cli;
/// <summary>
/// Indicates that a "Description" feature should display its localization description.
/// </summary>
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class)]
public class LocalizationAttribute : Attribute
{
/// <summary>
/// Gets or Sets a strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
public Type ResourceClass { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="LocalizationAttribute"/> class.
/// </summary>
/// <param name="resourceClass">
/// The type of the resource manager.
/// </param>
public LocalizationAttribute(Type resourceClass)
{
ResourceClass = resourceClass;
}
}

View File

@ -0,0 +1,21 @@
namespace Spectre.Console.Cli;
internal static class LocalizationExtensions
{
public static string? LocalizedDescription(this MemberInfo me)
{
var description = me.GetCustomAttribute<DescriptionAttribute>();
if (description is null)
{
return null;
}
var localization = me.GetCustomAttribute<LocalizationAttribute>();
string? localizedText;
return (localizedText = localization?.ResourceClass
.GetProperty(description.Description)?
.GetValue(default) as string) != null
? localizedText
: description.Description;
}
}

View File

@ -48,10 +48,10 @@ internal sealed class CommandInfo : ICommandContainer, ICommandInfo
if (CommandType != null && string.IsNullOrWhiteSpace(Description))
{
var description = CommandType.GetCustomAttribute<DescriptionAttribute>();
var description = CommandType.LocalizedDescription();
if (description != null)
{
Description = description.Description;
Description = description;
}
}
}

View File

@ -174,7 +174,7 @@ internal static class CommandModelBuilder
private static CommandOption BuildOptionParameter(PropertyInfo property, CommandOptionAttribute attribute)
{
var description = property.GetCustomAttribute<DescriptionAttribute>();
var description = property.LocalizedDescription();
var converter = property.GetCustomAttribute<TypeConverterAttribute>();
var deconstructor = property.GetCustomAttribute<PairDeconstructorAttribute>();
var valueProvider = property.GetCustomAttribute<ParameterValueProviderAttribute>();
@ -189,14 +189,14 @@ internal static class CommandModelBuilder
}
return new CommandOption(property.PropertyType, kind,
property, description?.Description, converter, deconstructor,
property, description, converter, deconstructor,
attribute, valueProvider, validators, defaultValue,
attribute.ValueIsOptional);
}
private static CommandArgument BuildArgumentParameter(PropertyInfo property, CommandArgumentAttribute attribute)
{
var description = property.GetCustomAttribute<DescriptionAttribute>();
var description = property.LocalizedDescription();
var converter = property.GetCustomAttribute<TypeConverterAttribute>();
var defaultValue = property.GetCustomAttribute<DefaultValueAttribute>();
var valueProvider = property.GetCustomAttribute<ParameterValueProviderAttribute>();
@ -206,7 +206,7 @@ internal static class CommandModelBuilder
return new CommandArgument(
property.PropertyType, kind, property,
description?.Description, converter,
description, converter,
defaultValue, attribute, valueProvider,
validators);
}

View File

@ -5,6 +5,7 @@
<Nullable>enable</Nullable>
<IsPackable>true</IsPackable>
<NoWarn>SA1633</NoWarn>
<PackageId>$(AssemblyName).NS</PackageId>
</PropertyGroup>
<ItemGroup>

View File

@ -5,6 +5,7 @@
<Nullable>enable</Nullable>
<IsPackable>true</IsPackable>
<NoWarn>SA1633</NoWarn>
<PackageId>$(AssemblyName).NS</PackageId>
</PropertyGroup>
<ItemGroup>